ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

【LangChain组件04:Structured output】—— LangChain 结构化输出:从 Pydantic 模型到三种输出策略实战

【LangChain组件04:Structured output】—— LangChain 结构化输出:从 Pydantic 模型到三种输出策略实战 LangChain 结构化输出从 Pydantic 模型到三种输出策略实战大多数时候你需要的不是一段自由文本而是结构化的数据——比如一个 JSON 对象。LangChain 的**结构化输出Structured Output**让 Agent 按照你指定的格式返回结果省去从文本里解析数据这一步让 AI 的输出可以直接被程序使用。本文基于 LangChain 官方文档Python与菜鸟教程 LangChain 系列沿材料分类组件04Structured output的路径组织覆盖从最简的 Pydantic 模型用法、与工具共存、复杂嵌套结构到三种输出策略ToolStrategy / ProviderStrategy / AutoStrategy的原理与选型。一、先厘清为什么需要结构化输出假设你需要从一段用户描述中提取姓名、年龄和职业方式输出格式后续处理普通回复“张三今年28岁是一名工程师”需要正则或再次调用模型来解析结构化输出{name: 张三, age: 28, job: 工程师}直接作为 Python 对象使用一句话结论结构化输出把模型返回文本 → 程序解析变成模型直接给你可用的结构体省掉了解析步骤还顺带做了字段校验。LangChain 的create_agent()会自动处理结构化输出你设置好期望的 Schema当模型生成结构化数据时它会被捕获、校验并存到 Agent 状态的structured_response键里。二、最简单的用法传入 Pydantic 模型把 Pydantic 模型传给response_format参数即可fromdotenvimportload_dotenv load_dotenv()frompydanticimportBaseModel,Fieldfromlangchain.agentsimportcreate_agentfromlangchain.chat_modelsimportinit_chat_modelfromlangchain.messagesimportHumanMessageclassCourseInfo(BaseModel):菜鸟教程 RUNOOB 课程提取结果course_name:strField(description课程名称)difficulty:strField(description难度入门/进阶/高级)estimated_hours:intField(description预计学习时长小时)is_free:boolField(description是否免费)modelinit_chat_model(deepseek:deepseek-v4-flash,temperature0)agentcreate_agent(modelmodel,response_formatCourseInfo,# 传入 Pydantic 模型system_prompt你是菜鸟教程 RUNOOB 的课程助手从用户描述中提取课程信息。,)resultagent.invoke({messages:[HumanMessage(content我最近在学习 Python3 基础教程是入门级别的大概要学 20 个小时而且是完全免费的)]})ifstructured_responseinresult:courseresult[structured_response]print(f课程名:{course.course_name})print(f难度:{course.difficulty})print(f预计时长:{course.estimated_hours}小时)print(f免费:{是ifcourse.is_freeelse否})print(f对象类型:{type(course)})运行结果课程名: Python3 基础教程 难度: 入门 预计时长: 20 小时 免费: 是 对象类型: class __main__.CourseInfo✅ 成功标志返回的structured_response是Pydantic 模型实例而不是普通字典。这意味着你可以用.course_name等属性访问IDE 也能提供自动补全。三、与工具共存先查再输出response_format和tools可以同时使用——Agent 在需要时调用工具最终输出结构化数据frompydanticimportBaseModel,Fieldfromlangchain.agentsimportcreate_agentfromlangchain.chat_modelsimportinit_chat_modelfromlangchain.messagesimportHumanMessagefromlangchain.toolsimporttooltooldefsearch_course(keyword:str)-str:在菜鸟教程 RUNOOB 搜索课程信息courses{python:Python3 基础教程 | 入门 | 免费 | 30章 | 约20小时,java:Java 基础教程 | 入门 | 免费 | 35章 | 约25小时,}returncourses.get(keyword.lower(),f未找到 {keyword} 相关课程)classCourseRecommendation(BaseModel):课程推荐结果course_name:strField(description推荐课程名称)reason:strField(description推荐理由)difficulty:strField(description难度入门/进阶/高级)modelinit_chat_model(deepseek:deepseek-v4-flash,temperature0)agentcreate_agent(modelmodel,tools[search_course],response_formatCourseRecommendation,system_prompt你是菜鸟教程 RUNOOB 的课程顾问。先查询课程再给出推荐。,)resultagent.invoke({messages:[HumanMessage(content我想学 Python有什么推荐)]})recresult[structured_response]print(f推荐课程:{rec.course_name})print(f推荐理由:{rec.reason})print(f难度:{rec.difficulty})# 查看完整过程print(\n 执行过程 )formsginresult[messages]:ifmsg.typetool:print(f 调用{msg.name}:{msg.content})运行结果推荐课程: Python3 基础教程 推荐理由: 该课程免费且适合Python初学者学习时长约20小时 难度: 入门 执行过程 调用 search_course: Python3 基础教程 | 入门 | 免费 | 30章 | 约20小时四、复杂嵌套结构Pydantic 支持嵌套、列表、枚举等复杂结构frompydanticimportBaseModel,FieldfromtypingimportLiteralfromlangchain.agentsimportcreate_agentfromlangchain.chat_modelsimportinit_chat_modelfromlangchain.messagesimportHumanMessageclassTopic(BaseModel):知识点name:strField(description知识点名称)order:intField(description学习顺序从 1 开始)minutes:intField(description建议学习分钟数)classLearningPlan(BaseModel):学习计划goal:strField(description学习目标概述)level:Literal[入门,进阶,高级]Field(description难度级别)total_hours:floatField(description总时长小时)topics:list[Topic]Field(description知识点列表)modelinit_chat_model(deepseek:deepseek-v4-flash,temperature0)agentcreate_agent(modelmodel,response_formatLearningPlan,system_prompt你是菜鸟教程 RUNOOB 的学习规划师。,)resultagent.invoke({messages:[HumanMessage(content帮我制定一个 Python 入门学习计划总时长控制在 10 小时以内)]})planresult[structured_response]print(f目标:{plan.goal})print(f难度:{plan.level})print(f总时长:{plan.total_hours}小时)print(f\n知识点列表 ({len(plan.topics)}个):)fortopicinplan.topics:print(f{topic.order}.{topic.name}({topic.minutes}分钟))运行结果展示了完整的嵌套结构——topics是一个Topic列表每个元素有order、name、minutes字段。五、不需要 Agent直接用模型提取如果你的场景是信息提取而非多步骤推理可以直接用模型的with_structured_output()不需要 Agent更简洁高效frompydanticimportBaseModel,Fieldfromlangchain.chat_modelsimportinit_chat_modelclassSentimentResult(BaseModel):情感分析结果sentiment:strField(description积极/消极/中性)score:floatField(description情感强度 0~1)keywords:list[str]Field(description关键情感词)modelinit_chat_model(deepseek:deepseek-v4-flash,temperature0)# 直接在模型上使用 with_structured_output()不需要 Agentstructured_modelmodel.with_structured_output(SentimentResult)texts[菜鸟教程 RUNOOB 真的太好用了强烈推荐,这个教程内容太少了不太值。,今天天气不错。,]fortextintexts:resultstructured_model.invoke(text)print(f文本:{text[:30]}...)print(f 情感:{result.sentiment}, 强度:{result.score}, 关键词:{result.keywords})with_structured_output()是 model 的方法不需要 Agent。信息提取类任务用它就够了多步骤推理才用create_agent()。六、三种输出策略原理与选型LangChain 提供三种结构化输出策略理解它们的区别能帮你在不同场景下做出最佳选择。6.1 策略总览策略原理模型支持响应速度ToolStrategy将 Schema 伪装成工具模型调用这个工具来输出结构化数据所有支持 function calling 的模型较慢多一次工具调用ProviderStrategy使用模型原生的结构化输出能力如 OpenAI 的 response_format部分模型GPT-4o、Claude 3等较快直接输出AutoStrategy自动检测模型能力选择最佳策略自动适配自动选择最优6.2 ToolStrategy工具调用模式ToolStrategy 是兼容性最好的方式。它将 Schema 转换为一个假工具模型通过调用这个工具来输出结构化数据frompydanticimportBaseModel,Fieldfromlangchain.agentsimportcreate_agentfromlangchain.agents.structured_outputimportToolStrategyfromlangchain.chat_modelsimportinit_chat_modelfromlangchain.messagesimportHumanMessageclassWeatherReport(BaseModel):天气报告city:strField(description城市名称)temperature:floatField(description温度摄氏度)condition:strField(description天气状况)humidity:intField(description湿度百分比)modelinit_chat_model(deepseek:deepseek-v4-flash,temperature0)agentcreate_agent(modelmodel,response_formatToolStrategy(schemaWeatherReport),system_prompt你是天气助手根据用户描述生成结构化天气报告。,)resultagent.invoke({messages:[HumanMessage(content杭州今天晴天温度25度湿度60%)]})reportresult[structured_response]print(f城市:{report.city}| 温度:{report.temperature}°C)print(f状况:{report.condition}| 湿度:{report.humidity}%)# 查看执行过程——多了一条工具调用的消息print(f\n消息总数:{len(result[messages])})formsginresult[messages]:print(f [{msg.type}],end)ifhasattr(msg,tool_calls)andmsg.tool_calls:print(f 调用:{[tc[name]fortcinmsg.tool_calls]})elifmsg.typetool:print(f{msg.content[:60]})运行结果揭示了 ToolStrategy 的内部机制——多了一个工具调用步骤调用名为 WeatherReport 的假工具然后才有结构化输出城市: 杭州 温度: 25.0°C 状况: 晴天 湿度: 60% 消息总数: 4 [human] 杭州今天晴天温度25度湿度60% [ai] 调用: [WeatherReport] [tool] Returning structured response: ... [ai]handle_errors错误重试。ToolStrategy 支持在结构化输出出错时自动重试fromlangchain.agents.structured_outputimportToolStrategy# handle_errorsTrue输出格式错误时将错误信息反馈给模型重试strategy_with_retryToolStrategy(schemaWeatherReport,handle_errorsTrue,# 默认 False)# handle_errors 也可以是一个自定义错误消息模板strategy_custom_errorToolStrategy(schemaWeatherReport,handle_errors格式有误请按 {error} 修正后重新输出,)6.3 ProviderStrategy原生结构化输出ProviderStrategy 使用模型提供商的原生能力如 OpenAI 的response_format参数跳过工具调用环节速度更快frompydanticimportBaseModel,Fieldfromlangchain.agentsimportcreate_agentfromlangchain.agents.structured_outputimportProviderStrategyfromlangchain.chat_modelsimportinit_chat_modelfromlangchain.messagesimportHumanMessageclassCourseInfo(BaseModel):课程信息name:strField(description课程名称)level:strField(description难度入门/进阶/高级)price:strField(description价格信息)modelinit_chat_model(deepseek:deepseek-v4-flash,temperature0)agentcreate_agent(modelmodel,response_formatProviderStrategy(schemaCourseInfo),system_prompt你是菜鸟教程 RUNOOB 的课程助手。,)resultagent.invoke({messages:[HumanMessage(contentPython3 基础教程是入门级的免费课程)]})courseresult[structured_response]print(f课程:{course.name}| 难度:{course.level}| 价格:{course.price})print(f消息数:{len(result[messages])})# 比 ToolStrategy 少运行结果消息数 2比 ToolStrategy 的 4 条少因为它不需要额外的工具调用步骤。ProviderStrategy 主要被 OpenAI 的 GPT-4o 及以上和 Claude 3 及以上支持。如果模型不支持LangChain 会自动降级到 ToolStrategy。检查模型是否支持可以用model.profile查看。6.4 AutoStrategy自动选择最推荐直接传入 Pydantic 模型而不是策略对象LangChain 会自动选择最佳策略frompydanticimportBaseModel,Fieldfromlangchain.agentsimportcreate_agentfromlangchain.chat_modelsimportinit_chat_modelfromlangchain.messagesimportHumanMessageclassAnalysis(BaseModel):分析结果summary:strField(description一句话总结)score:intField(description评分 1~10)pros:list[str]Field(description优点列表)cons:list[str]Field(description缺点列表)modelinit_chat_model(deepseek:deepseek-v4-flash,temperature0)agentcreate_agent(modelmodel,response_formatAnalysis,# 直接传模型自动选择策略system_prompt你是课程评估专家评估用户描述的课程。,)resultagent.invoke({messages:[HumanMessage(content菜鸟教程 RUNOOB 的 Python 课程内容系统全面实例丰富而且完全免费。但视频教程较少高级内容覆盖不够。)]})analysisresult[structured_response]print(f总结:{analysis.summary})print(f评分:{analysis.score}/10)print(f优点:{, .join(analysis.pros)})print(f缺点:{, .join(analysis.cons)})6.5 三种策略选择指南场景推荐策略原因不确定模型是否支持原生输出AutoStrategy直接传 Pydantic自动选择最优策略需要兼容各种模型ToolStrategy所有支持 function calling 的模型都可用追求极致性能ProviderStrategy跳过工具调用环节速度更快需要错误重试ToolStrategy(handle_errorsTrue)只有 ToolStrategy 支持 handle_errors大多数情况下直接传入 Pydantic 模型即使用 AutoStrategy就够了。只有在需要错误重试或明确控制策略行为时才需要显式指定 ToolStrategy 或 ProviderStrategy。七、总结你真正需要记住的 N 件事结构化输出 模型直接给你可用的结构体省去文本解析还顺带做字段校验。最简单用法是传 Pydantic 模型response_formatCourseInfo返回的是 Pydantic 实例可属性访问。可以搭配工具response_formattools同时用Agent 先查再结构化输出。支持复杂嵌套Pydantic 的列表、嵌套、枚举Literal都能直接用。不需要 Agent 就直接用模型信息提取场景用model.with_structured_output()更简洁。三种策略AutoStrategy默认推荐/ ToolStrategy兼容所有 function-calling 模型/ ProviderStrategy原生、更快但有模型门槛。只有 ToolStrategy 支持 handle_errors需要错误重试时显式指定。验证清单我定义了 Pydantic 模型并用response_format传入create_agent()我能用.属性访问structured_response里的字段我的场景需要工具时tools和response_format同时配了纯信息提取场景我用了with_structured_output()而不是 Agent我清楚 AutoStrategy / ToolStrategy / ProviderStrategy 三者的适用场景需要错误重试时我显式用ToolStrategy(handle_errorsTrue)参考资源LangChain 官方文档Structured output——https://docs.langchain.com/oss/python/langchain/structured-outputLangChain Referencecreate_agent / response_format——https://reference.langchain.com/python/langchain/agents/factory/create_agent菜鸟教程 LangChain 系列——https://www.runoob.com/langchain/
返回列表