基础篇第 03 篇

第 3 章:结构化输出

Pydantic schema 与 with_structured_output 的可控决策。

本站只展示学习文档。文中的 Python、模型、搜索和 MCP 命令均不会在构建或部署时执行;手动运行可能需要密钥并产生费用。

约 771 字·预计阅读 3 分钟
本页目录

学习目标

理解为什么当前项目不用模型随便回一段自然语言,而是让模型按 BaseModel 定义的字段返回对象。

它是什么

BaseModel 定义运行时可校验的数据契约,Field 给字段补默认值、说明和约束。with_structured_output(MyModel) 会让聊天模型按这个 schema 返回 MyModel 实例。它解决的问题是:后续代码可以读 response.research_brief、response.need_clarification 这种明确字段,而不是从一段文本里猜。

当前项目怎么用

模型 当前项目位置 用途
ClarifyWithUser state.py 让模型判断是否需要追问用户。
ResearchQuestion state.py 把用户消息转成研究 brief。
ConductResearch state.py 作为 supervisor 可调用的结构化工具 schema。
Summary state.py 约束网页摘要结果。
ResearcherOutputState state.py 限制 researcher 子图输出给父图的字段。

项目里的典型写法:

research_model = (
    configurable_model
    .with_structured_output(ResearchQuestion)
    .with_retry(stop_after_attempt=configurable.max_structured_output_retries)
    .with_config({
        "configurable": research_model_config,
        "tags": ["langsmith:nostream"],
    })
)
response = await research_model.ainvoke(
    [HumanMessage(content=prompt_content)],
    config=config,
)

注意这个顺序:先把模型包装成结构化输出,再加重试和运行时配置。返回值已经是 Pydantic 对象,不是 AIMessage。

最小真实 Agent

示例文件:03_structured_output.py。

class TopicBrief(BaseModel):
    title: str = Field(description="A short Chinese title.")
    research_question: str = Field(description="One focused research question.")
    needs_tools: bool = Field(description="Whether external tools are needed.")

节点调用真实模型:

structured_model = model.with_structured_output(TopicBrief)
brief = await structured_model.ainvoke([...])

然后把 brief.model_dump_json() 写回 messages,方便你直接看到 schema 约束后的结果。

BaseModel、Field 什么时候用

场景 选择
模型必须返回可被代码继续处理的字段 BaseModel + Field
工具参数需要让模型理解字段含义 BaseModel + Field
图内部状态只做读写和 reducer 合并 TypedDict
对话历史 MessagesState

Field 的 description 很重要,尤其给模型看的工具参数和结构化输出字段。别为了好看给所有普通状态字段都套 Field,那是噪音。

运行

uv run python docs/langgraph-learning/examples/03_structured_output.py

预期现象:终端输出一段 JSON,至少包含 title、research_question、needs_tools 三个字段。它不是 mock,是模型按 Pydantic schema 生成并通过解析后的对象。

常见误区

把结构化输出当成 100% 业务正确。 Pydantic 只保证形状和类型,不能保证模型判断一定对;当前项目因此加了 .with_retry(...),但业务质量仍要靠提示词、评估和后续节点约束。

以为结构化输出返回 AIMessage。 with_structured_output(TopicBrief) 返回的是 TopicBrief 实例;如果要放进 messages,需要自己转成字符串或重新包装成 AIMessage。

把工具 schema 和图状态混在一起。 ConductResearch 是工具/模型边界契约;ResearcherState 是图内部状态。一个强调校验和字段说明,一个强调状态合并。

本次真实验证

已使用默认 openai:gpt-5.5 运行一次。模型返回:

{"title":"LangGraph 状态管理机制研究","research_question":"LangGraph 如何通过状态模式(State Schema)、节点状态更新与检查点机制实现多轮工作流中的状态管理与恢复?","needs_tools":false}

参考资源与示例代码