LangChain 结构化输出实战:让大模型返回程序可直接调用的数据
一、为什么业务开发必须使用结构化输出举个简历信息抽取场景 大模型自然语言返回候选人张三拥有 10 年大模型开发经验掌握 Python、LangChain、FastAPI想要应聘智能体开发岗位。想要拿到姓名、工作年限、技能列表代码还需要额外做文本解析容错极差。如果返回结构化 JSONjson{ name: 张三, years_of_experience: 10, skills: [Python, LangChain, FastAPI], target_position: 智能体开发 }代码可以直接通过对象属性读取数据result.name、result.skills无需额外文本处理。结构化输出适用场景简历 / 文档信息抽取用户评论情感分析、关键词提取客服工单自动分类、优先级判定内容审核、数据清洗、结构化入库下游业务接口调用二、LangChain 三大输出方案总览LangChain 提供分层的输出处理能力日常开发最常用三类组件StrOutputParser统一获取字符串文本适配 Runnable 管道PydanticOutputParser基于 Prompt 约束 JSON解析为 Pydantic 实体with_structured_output模型原生结构化输出封装代码更简洁三、StrOutputParser基础字符串解析核心作用model.invoke()返回的是AIMessage对象.content可以拿到文本。 但在 LangChain 的 Runnable 管道|链式语法中不能直接调用属性。StrOutputParser实现 Runnable 协议作为管道标准组件统一将各类消息对象转为字符串。误区区分 单独调用resp.content和StrOutputParser打印结果一致一旦使用链式编排prompt | model | parser必须使用解析器。实战案例文本摘要python运行from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate from utils.model_factory import get_deepSeek_model model get_deepSeek_model() chat_prompt ChatPromptTemplate.from_messages([ (system, 你是内容编辑将文本提炼成一句话摘要不超过50字), (human, 待总结内容{content}) ]) # 链式标准写法 chain chat_prompt | model | StrOutputParser() res chain.invoke({ content: LangChain是大模型应用开发框架支持模型调用、提示词管理、RAG检索、工具调用等功能。 }) print(res)适合文案生成、文本总结、普通问答等只需要纯文本的场景。四、PydanticOutputParser经典结构化解析方案实现思路使用 PydanticBaseModel定义期望输出结构标注字段类型与描述初始化PydanticOutputParser绑定模型通过get_format_instructions()自动生成 JSON 格式约束将格式指令注入 Prompt要求模型输出符合 Schema 的 JSON解析模型返回文本自动实例化为 Pydantic 对象。实战案例简历信息抽取python运行from langchain_core.output_parsers import PydanticOutputParser from langchain_core.prompts import ChatPromptTemplate from pydantic import BaseModel, Field from utils.model_factory import get_deepSeek_model model get_deepSeek_model() # 定义输出结构 class ResumeInfo(BaseModel): name: str Field(description候选人姓名) years_of_experience: int Field(description工作年限) skills: list[str] Field(description掌握的技术技能) target_position: str Field(description目标应聘岗位) parser PydanticOutputParser(pydantic_objectResumeInfo) format_instructions parser.get_format_instructions() prompt_template ChatPromptTemplate.from_messages([ (system, 你是招聘信息分析助手严格按照格式指令返回JSON。\n{format_instructions}), (human, 简历文本{resume_content}) ]) prompt prompt_template.invoke({ format_instructions: format_instructions, resume_content: 我叫张三拥有10年大模型开发经验擅长python、langchain、fastapi想要寻找智能体开发相关工作。 }) response model.invoke(prompt) result parser.invoke(response) print(result.name) print(result.skills)⚠️ 常见坑DeepSeek 等国产模型常会用json包裹内容旧版本解析器会直接报错生产环境需要做好兼容。五、with_structured_output更简洁的结构化方案with_structured_output直接给模型绑定输出 Schema不需要手动拼接格式指令到 Prompt。 对接 DeepSeek OpenAI 兼容接口时推荐指定methodjson_mode开启模型 JSON 强制输出模式。实战案例商品评论情感分析使用Literal字面量类型严格限制字段可选值相当于轻量枚举约束。python运行from typing import Literal from langchain_core.prompts import ChatPromptTemplate from pydantic import BaseModel, Field from utils.model_factory import get_deepSeek_model model get_deepSeek_model() class ReviewAnalysis(BaseModel): sentiment: Literal[正面, 负面, 中性] Field(description评论情感) keywords: list[str] Field(description核心关键词) summary: str Field(description一句话总结评论) needs_reply: bool Field(description商家是否需要跟进回复) prompt_template ChatPromptTemplate.from_messages([ (system, 评论分析专家只输出合法JSON不要额外解释、markdown标记。), (human, 分析评论{review}) ]) # 绑定结构化输出 structured_llm model.with_structured_output(ReviewAnalysis, methodjson_mode) prompt prompt_template.invoke({review: 鼠标手感安静但是使用两周滚轮出现异响。}) result structured_llm.invoke(prompt) print(result.sentiment) print(result.needs_reply)答疑代码看不到 JSON 字符串json_mode是底层行为模型输出 JSON 字符串 → LangChain 内部自动解析成 Pydantic 实例。你拿到的是对象原始 JSON 被框架封装不会直接暴露。六、两种结构化方案如何选择表格方案原理优缺点适用场景PydanticOutputParserPrompt 告知 Schema本地解析文本通用性最强所有模型都能用需要手动管理格式指令学习底层原理、不支持原生 JSON 模式的模型with_structured_output模型层绑定 SchemaAPI 强制 JSON代码简洁依赖模型服务商接口支持DeepSeek、GPT 等兼容 OpenAI 接口的模型新项目首选学习建议先吃透PydanticOutputParser理解结构化输出底层原理项目开发优先使用with_structured_output。七、实战案例客服工单自动分类 异常捕获生产环境中大模型输出具有不确定性随时可能解析失败必须捕获异常保存原始响应用于排查问题。python运行from typing import Literal from langchain_core.output_parsers import PydanticOutputParser from langchain_core.prompts import ChatPromptTemplate from langchain_core.exceptions import OutputParserException from pydantic import BaseModel, Field from utils.model_factory import get_deepSeek_model model get_deepSeek_model(temperature0) class TicketResult(BaseModel): category: Literal[订单, 物流, 退款, 产品, 其他] Field(description工单分类) priority: Literal[低, 中, 高] Field(description优先级) reason: str Field(description分类依据) parser PydanticOutputParser(pydantic_objectTicketResult) format_instructions parser.get_format_instructions() prompt_template ChatPromptTemplate.from_messages([ (system, 客服工单分类助手。{format_instructions}), (human, 用户问题{question}) ]) prompt prompt_template.invoke({ format_instructions: format_instructions, question: 订单显示已签收但我没有收到包裹请尽快处理 }) response model.invoke(prompt) try: result parser.invoke(response) print(工单分类, result.category) print(优先级, result.priority) if result.priority 高: print(自动流转人工优先处理) except OutputParserException as e: print(解析失败原始模型输出, response.content) print(错误详情, str(e))抽取、分类任务建议设置temperature0降低随机性保证输出稳定。八、生产环境避坑要点不要信任大模型输出即便使用结构化输出关键业务建议增加二次代码校验异常处理必不可少捕获解析异常记录原始返回文本方便调优 PromptLiteral 限制可选值情感、分类场景尽量使用字面量类型避免模型随意生成文本两种方案按需取舍老旧模型使用PydanticOutputParser新模型优先with_structured_output解析频繁报错时优化 Prompt明确禁止模型输出 markdown、多余解释语句。九、本章核心总结自然语言面向人阅读结构化数据面向程序自动化处理StrOutputParser标准 Runnable 组件链式管道获取文本Pydantic BaseModel 用来定义强类型输出结构PydanticOutputParser经典解析方案通用性拉满with_structured_output代码简洁新项目首选线上业务务必捕获解析异常做好日志留存。