首页/新闻资讯/正文详情

【LangChain框架入门级】4. 结构化输出

发布时间:2026/9/27 20:27:06 来源:云帆数科 栏目:资讯中心
【LangChain框架入门级】4. 结构化输出
结构化输出with_structured_output 详解普通调用大模型返回的是一段自由文本字符串。这段文字对人类很友好但对程序不友好——想从中提取「公司名、日期、价格」就得写复杂又容易出错的解析代码。结构化输出让我们事先定义好期望的数据结构强制模型按这个结构返回信息。本篇讲清楚它的用法、三种定义方式、联合类型以及两个实用场景。目录什么是结构化输出为什么需要它with_structured_output() 方法返回 Pydantic 对象返回 TypedDict字典返回 JSON选择输出格式Union 联合类型实用场景一信息提取器实用场景二与工具结合本篇小结1. 什么是结构化输出为什么需要它结构化输出是一种使聊天模型以结构化格式如 JSON进行响应的技术。典型场景希望把模型输出存进数据库并确保输出符合数据库的模式Schema。核心是一次从「字符串」到「对象」的范式转换。没有这个功能时modelChatOpenAI()responsemodel.invoke(告诉我关于苹果公司的最新消息。)print(response.content)# 苹果公司于昨日发布了新款iPhone...其股价上涨了2%...这段文本对人类友好但如果程序想提取「公司名」和「股价变化」就得写正则表达式等复杂、易错的解析代码。而聊天模型的with_structured_output方法允许我们预先定义期望的数据结构要求大模型必须按这个结构返回信息。2. with_structured_output() 方法使用分三步# 1. 定义输出结构schema{foo:bar}# 2. 绑定 schema得到支持结构化返回的 Runnable 实例model_with_structuremodel.with_structured_output(schema)# 3. 执行输出与结构对应的对象structured_outputmodel_with_structure.invoke(user_input)这是获得结构化输出最简单、最可靠的方法。返回的是一个类似 model 的 Runnable不同之处在于执行后输出的不是字符串或消息而是与给定结构对应的对象。2.1 方法参数with_structured_output(schema,# 输出结构JSON、TypedDict、Pydantic 等*,methodjson_schema,# 生成方式include_rawFalse,# 是否同时返回原始消息strictNone,# 是否严格匹配 schema**kwargs)参数说明schema输出结构可以传 JSON Schema、TypedDict、Pydantic 类。methodLLM 的生成方式json_schema默认使用 OpenAI 的结构化输出 API。function_calling使用 OpenAI 的工具调用旧称函数调用。json_mode使用 OpenAI 的 JSON mode此时必须在提示中包含把输出格式化为所需 schema 的说明。include_rawFalse默认只返回解析后的结构化输出解析出错则抛错。True返回带raw原始 BaseMessage、parsed解析结果、parsing_error解析错误三个键的字典错误也会被捕获。strictTrue时保证模型输出与 schema 完全匹配并做校验。2.2 返回值规则schema是Pydantic 类→ 返回一个 Pydantic 对象。schema是TypedDict 或 JSON Schema→ 返回一个字典。include_rawTrue→ 返回带raw/parsed/parsing_error的字典。3. 返回 Pydantic 对象把输出结构定义为 Pydantic 类模型会返回一个 Pydantic 对象。收到响应后LangChain 提取代表该结构的 JSON用 Pydantic 解析、验证后返回fromlangchain_openaiimportChatOpenAIfromtypingimportOptionalfrompydanticimportBaseModel,Field modelChatOpenAI(modelgpt-4o-mini)# 定义输出结构classJoke(BaseModel):给用户讲一个笑话。setup:strField(description这个笑话的开头)punchline:strField(description这个笑话的妙语)rating:Optional[int]Field(defaultNone,description从1到10分给这个笑话评分)structured_modelmodel.with_structured_output(Joke)resultstructured_model.invoke(给我讲一个关于唱歌的笑话)print(result)打印结果setup为什么歌手总是喜欢在洗手间里唱歌 punchline因为那里有很好的回音和灵感 rating73.1 支持嵌套输出可以在一个结构里嵌套另一个结构、用 List 包含多个对象fromtypingimportOptional,ListfrompydanticimportBaseModel,FieldclassJoke(BaseModel):给用户讲一个笑话。setup:strField(description这个笑话的开头)punchline:strField(description这个笑话的妙语)rating:Optional[int]Field(defaultNone,description从1到10分给笑话评分)classData(BaseModel):获取关于笑话的数据。jokes:List[Joke]structured_modelmodel.with_structured_output(Data)resultstructured_model.invoke(分别讲一个关于唱歌和跳舞的笑话)print(result)打印结果简化jokes[ Joke(setup为什么唱歌的人总是很快乐, punchline因为他们总是「音」乐满满, rating8), Joke(setup一个跳舞的牛走进俱乐部为什么大家都不理它, punchline因为它总是「踏」错节拍, rating7) ]4. 返回 TypedDict字典TypedDict 用于给字典对象提供精确、结构化的类型提示指定字典里应该有哪些键、每个键的值类型还能捕捉键名拼写错误和类型错误。定义方式Python 3.8fromtypingimportTypedDictclassUser(TypedDict):name:strage:intemail:stris_active:boolTrue# 默认值它的一个重要作用是在开发阶段发现错误good:User{name:Bob,age:25,email:bobexample.com}# 正确bad:User{name:Dave,age:forty,# 错误应该是 intemial:daveexample.com,# 错误键名拼写错误}用 TypedDict 作为结构化输出的 schema模型会返回一个字典fromlangchain_openaiimportChatOpenAIfromtypingimportOptionalfromtyping_extensionsimportAnnotated,TypedDict modelChatOpenAI(modelgpt-4o-mini)classJoke(TypedDict):给用户讲一个笑话。setup:Annotated[str,...,这个笑话的开头]punchline:Annotated[str,...,这个笑话的妙语]rating:Annotated[Optional[int],None,从1到10分给这个笑话评分]structured_modelmodel.with_structured_output(Joke)resultstructured_model.invoke(给我讲一个关于唱歌的笑话)print(result)打印结果{setup:为什么歌手总是带一把伞,punchline:因为他们怕下雨时会错过音调,rating:7}4.1 include_rawTrue 的效果structured_modelmodel.with_structured_output(Joke,include_rawTrue)resultstructured_model.invoke(给我讲一个关于唱歌的笑话)返回一个字典包含三部分raw模型返回的原始 AIMessage。parsed解析后的字典解析失败则为 None。parsing_error解析错误没有则为 None。调试时建议用include_rawTrue可以同时看到原始响应和解析结果方便定位问题。5. 返回 JSON也可以直接用一个JSON Schema字典作为结构模型返回普通字典fromlangchain_openaiimportChatOpenAI modelChatOpenAI(modelgpt-4o-mini)json_schema{title:joke,description:给用户讲一个笑话。,type:object,properties:{setup:{type:string,description:这个笑话的开头,},punchline:{type:string,description:这个笑话的妙语,},rating:{type:integer,description:从1到10分给这个笑话评分,default:None,},},required:[setup,punchline],}structured_modelmodel.with_structured_output(json_schema)resultstructured_model.invoke(给我讲一个关于唱歌的笑话)print(result)打印结果{setup:为什么唱歌的人总是很开心,punchline:因为他们总是有很多音符可供选择,rating:7}6. 选择输出格式Union 联合类型有时候希望模型根据问题类型返回不同结构中的一种可以用Union联合类型定义父模式fromlangchain_openaiimportChatOpenAIfrompydanticimportBaseModel,FieldfromtypingimportOptional,Union modelChatOpenAI(modelgpt-4o-mini)classJoke(BaseModel):给用户讲一个笑话。setup:strField(description这个笑话的开头)punchline:strField(description这个笑话的妙语)rating:Optional[int]Field(defaultNone,description从1到10分给笑话评分)classConversationalResponse(BaseModel):以对话的方式回应。待人友善乐于助人。response:strField(description对用户查询的会话响应)classFinalResponse(BaseModel):final_output:Union[Joke,ConversationalResponse]structured_modelmodel.with_structured_output(FinalResponse)# 问笑话 → 返回 Jokeresultstructured_model.invoke(给我讲一个关于唱歌的笑话)print(result)# final_outputJoke(setup..., punchline..., rating7)# 普通问候 → 返回 ConversationalResponseresultstructured_model.invoke(你好)print(result)# final_outputConversationalResponse(response你好有什么我可以帮助你的吗)模型会自己判断该返回联合类型中的哪一种。7. 实用场景一信息提取器结构化输出最常见的用途是从一段文本中提取指定信息。关键技巧每个字段都设为Optional且默认 None——允许模型在不知道答案时输出 None而不是瞎编。每个字段都写description——模型靠这些描述来提高提取质量。用 SystemMessage 明确「只从文本提取不知道就返回 null」。fromlangchain_openaiimportChatOpenAIfromtypingimportOptionalfrompydanticimportBaseModel,Fieldfromlangchain_core.messagesimportHumanMessage,SystemMessage modelChatOpenAI(modelgpt-4o-mini)classPerson(BaseModel):一个人的信息。name:Optional[str]Field(defaultNone,description这个人的名字)hair_color:Optional[str]Field(defaultNone,description这个人头发的颜色)skin_color:Optional[str]Field(defaultNone,description这个人的肤色)height_in_meters:Optional[str]Field(defaultNone,description以米为单位的高度)structured_modelmodel.with_structured_output(schemaPerson)messages[SystemMessage(content你是一个提取信息的专家只从文本中提取相关信息。如果您不知道要提取的属性的值属性值返回null),HumanMessage(content史密斯身高6英尺金发。),]resultstructured_model.invoke(messages)print(result)打印结果name史密斯 hair_color金发 skin_colorNone height_in_meters1.83注意文本里没给肤色skin_color就是 None身高给的是英尺模型自动换算成了米。8. 实用场景二与工具结合重要提醒用聊天模型原生的工具搭配结构化输出并不好用更好的做法是用 LangGraph 的 Agent 能力。这里只是了解原理。8.1 方式一with_structured_output 的 tools 参数fromlangchain_openaiimportChatOpenAIfrompydanticimportBaseModel,Fieldfromlangchain_core.toolsimporttoolfromlangchain_core.messagesimportHumanMessage modelChatOpenAI(modelgpt-4o-mini)# 结构化结果对象classSearchResult(BaseModel):结构化搜索结果。query:strField(description搜索查询)findings:strField(description调查结果摘要)tooldefweb_search(query:str)-str:在网上搜索信息。 Args: query: 搜索查询 return西安今天多云转小雨气温18-23度东南风2级空气质量良好structured_search_modelmodel.with_structured_output(SearchResult,tools[web_search],strictTrue,include_rawTrue,)resultstructured_search_model.invoke(搜索当前最新的西安的天气)这种方式只会返回工具调用信息raw 里的 AIMessage并不会自动执行工具、也不会帮我们整合出 SearchResult。因为with_structured_output只是让模型知道有哪些工具不会自动执行。8.2 方式二拆解能力手动执行工具顺序很重要正确顺序是先绑定工具 → 执行工具、把结果加入消息 → 再加结构化输出。# 1. 先绑定工具model_with_toolsmodel.bind_tools([web_search])messages[HumanMessage(搜索当前最新的西安的天气)]# 2. 第一轮模型返回工具调用ai_msgmodel_with_tools.invoke(messages)messages.append(ai_msg)# 3. 手动执行工具把 ToolMessage 加入消息fortool_callinai_msg.tool_calls:tool_msgweb_search.invoke(tool_call)messages.append(tool_msg)# 4. 再加结构化输出处理包含工具结果的完整消息structured_search_modelmodel_with_tools.with_structured_output(SearchResult)resultstructured_search_model.invoke(messages)print(result)打印结果query西安天气 findings西安今天多云转小雨气温18-23度东南风2级空气质量良好。这个流程依然要调用两次模型、且比较繁琐。想一次自动完成「调用工具 结构化整合」就要靠后面学习的 LangGraph Agent。9. 本篇小结结构化输出让模型按预定义结构返回把「字符串」变成「对象」方便程序处理和入库。三步用法定义 schema →model.with_structured_output(schema)→ invoke。三种 schemaPydantic 类返回 Pydantic 对象TypedDict / JSON Schema 返回字典支持嵌套和 List。Union联合类型可让模型根据问题返回不同结构。信息提取场景字段设 Optional 默认 None、写好 description、用 SystemMessage 约束「不知道就返回 null」。结构化输出与工具结合时原生方式繁琐、不会自动执行工具推荐用 LangGraph Agent。下一篇我们讲**流式传输stream / astream**以及如何用 LangSmith 可视化跟踪整个调用过程。

相关推荐

深度拆解 AI Agent:从 ChatGPT 到智能体的进化之路,TaoToken 统一 Key 配置实战
深度拆解 AI Agent:从 ChatGPT 到智能体的进化之路,TaoToken 统一 Key 配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 20:27:06

嵌入式固件烧录版本管理:构建-烧录-验证全链路管控方案
嵌入式固件烧录版本管理:构建-烧录-验证全链路管控方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 20:27:06

开发企业网站多少钱?5年运维老兵揭秘价格与防黑最佳实践
开发企业网站多少钱?5年运维老兵揭秘价格与防黑最佳实践

开发企业网站多少钱?5年运维老兵揭秘价格与防黑最佳实践 昨晚凌晨两点,我盯着后台告警急得冒汗:客户官网首页突然挂了非法链接,打开全是赌博广告。这就是很多老板问“开发企业网站多少钱”时,最容易忽略的隐形成本——安全。很多人以为建站就是写代码、… · 2026/9/27 20:27:00

Vue3 开发提效:Vscode 插件配 TaoToken 的 settings.json 骨架与验证
Vue3 开发提效:Vscode 插件配 TaoToken 的 settings.json 骨架与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 21:04:44

学习观深度解读:从认知科学到输出式学习实践
学习观深度解读:从认知科学到输出式学习实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 21:04:38

已有 Hermes Agent?7 分钟让 Agent 自主装好 hermes-web-ui + SenseNova Skill
已有 Hermes Agent?7 分钟让 Agent 自主装好 hermes-web-ui + SenseNova Skill

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 21:04:38

STM32CubeMX 6.14安装与配置避坑指南
STM32CubeMX 6.14安装与配置避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 21:04:38

STM32F407+LAN8720以太网调试全指南:从CubeMX配置到LWIP与FreeRTOS实战
STM32F407+LAN8720以太网调试全指南:从CubeMX配置到LWIP与FreeRTOS实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 21:04:32

OpenMontage 日增 3400+ Star 背后:用 TaoToken 统一 Key 打通 AI Agent 视频生产工具链
OpenMontage 日增 3400+ Star 背后:用 TaoToken 统一 Key 打通 AI Agent 视频生产工具链

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 21:04:32

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码