阶段:G4-工具与外部生态 | 预计耗时:60 分钟 | 前置:G3 全部验收通过 代码:要你自己敲成
langgraph-learn/examples/g4_structured.py为什么重要:S2 发票 OCR 项目的字段提取全靠本篇——"从一段乱文本里抽出规范字段"是结构化输出的看家戏
学习目标
- 掌握
with_structured_output(Pydantic模型):让模型回答直接变成程序可用的对象 - 学会写好的工具 docstring(工具选择率的关键)
- 会做"提取失败兜底":字段缺了怎么办
核心知识
1. 聊天输出 vs 结构化输出
普通 invoke 返回一段自由文本,程序没法可靠地抠字段;结构化输出让模型按你定义的 schema 填空:
from pydantic import BaseModel, Field
class Invoice(BaseModel):
invoice_no: str = Field(description="发票号码,8-20位数字")
amount: float = Field(description="价税合计(元)")
date: str | None = None # 允许缺失——模型抽不到就 None
structured_llm = llm.with_structured_output(Invoice)
inv = structured_llm.invoke("发票文本:今天开出 №24310066,金额 3580.00 元,2026年11月3日")
print(inv.invoice_no, inv.amount) # 直接当对象用!
- Field 的
description是写给模型的填写说明——写越具体,抽得越准 - 类型即约束:
float违约时框架帮你报错或重试
2. 工具 docstring 的三要素(决定模型选不选它)
- 干什么(动词开头)2. 什么时候用/不用(边界)3. 参数含义
反例:
"""加法"""——模型在 10 个工具里根本分不清;正例:"""两数相加。任何数值求和都用它;不要用于字符串拼接"""
3. OCR 场景的骨架(G7 项目直接复用)
RapidOCR 识别出原始文本 → 结构化输出节点抽字段 → 校验节点(金额>0?号码合法?)→
字段缺失/校验不过 → 允许重问一次(带错误提示)→ 再不过 → interrupt 人工复核(G3 的能力)
实验任务
任务 1:发票字段提取(25 分钟)
把上面骨架敲成 g4_structured.py,用 3 段不同风格的"发票文本"(正常/字段缺失/格式怪异)测试:
- 正常段全字段抽出;缺字段段 date 应为 None
- 记录每次抽取结果
任务 2:schema 迭代(20 分钟)
第一版抽不准的字段,改 Field description 再测——写进观察笔记:哪个字段靠"说明写清楚"救回来的。这就是 prompt 工程的日常。
任务 3:失败兜底链(15 分钟)
给提取节点加重试:第一次失败后,把"上次失败原因"附在提问里再抽一次——成功率提升了吗?
验收标准
衔接下一阶段
字段抽得准了 → G4-02 RAG 检索节点:给 Agent 接上你的私有知识。