
LangChain 学习记录 04Output Parser 输出解析器详解告别模型乱返回本文重点讲为什么需要输出解析器StrOutputParser如何提取普通字符串JsonOutputParser如何解析 JSONPydanticOutputParser如何做字段级校验with_structured_output()为什么更适合生产环境项目中如何选择不同解析方案一句话概括Prompt 负责约束模型怎么写Parser 负责把模型写出来的内容变成程序能用的数据。文章目录LangChain 学习记录 04Output Parser 输出解析器详解告别模型乱返回一、为什么需要 Output Parser二、Output Parser 的底层逻辑三、StrOutputParser最常用的字符串解析器适合场景四、JsonOutputParser把模型输出转成字典JsonOutputParser 的本质可以配合格式说明五、PydanticOutputParser让输出带类型校验为什么 Pydantic 更适合工程项目六、with_structured_output更工程化的结构化输出七、几种方案的对比八、常见坑1. 只在 Prompt 里写“请输出 JSON”2. 字段名不统一3. 把 Parser 当成万能修复器4. Pydantic 校验失败没有处理九、小结参考资料一、为什么需要 Output Parser假设你让模型返回 JSON请提取姓名、职业、城市并用 JSON 返回。理想情况下模型返回{name:张三,job:后端开发工程师,city:杭州}但是现实中模型可能返回当然可以下面是提取结果 { name: 张三, job: 后端开发工程师, city: 杭州 }人看起来没问题但程序解析时可能直接炸。再比如模型可能返回{姓名:张三,职业:后端开发工程师,城市:杭州}字段含义没错但你的后端代码要的是result[name]这时字段名对不上也会出问题。所以结构化输出不是“让模型尽量听话”这么简单而是工程稳定性问题。Output Parser 解决的就是把模型输出转换为稳定的数据结构。二、Output Parser 的底层逻辑先看图。大模型输出一般有几种形态AIMessage普通字符串JSON 字符串Markdown 包裹的 JSON半结构化自然语言Output Parser 的职责是模型输出 ↓ 解析器提取、转换、校验 ↓ Python 字符串 / 字典 / Pydantic 对象这就是 AI 应用和普通后端开发的一个重要区别。传统后端里我们处理的大多是确定输入前端 JSON → 后端 dict → 数据库AI 应用里我们面对的是概率输出模型自然语言 → 尽量转成稳定结构 → 程序继续处理所以 Parser 是大模型应用工程化的重要组件。三、StrOutputParser最常用的字符串解析器StrOutputParser是最简单、最常用的输出解析器。它的作用把模型返回的 AIMessage 提取成普通字符串。示例fromlangchain_openaiimportChatOpenAIfromlangchain_core.promptsimportChatPromptTemplatefromlangchain_core.output_parsersimportStrOutputParser promptChatPromptTemplate.from_messages([(system,你是一个耐心的技术导师。),(human,请用一句话解释{topic})])llmChatOpenAI(modelgpt-4o-mini)chainprompt|llm|StrOutputParser()resultchain.invoke({topic:LangChain 的 Output Parser})print(result)这里的链路是输入 dict ↓ prompt 生成消息 ↓ llm 返回 AIMessage ↓ StrOutputParser 提取 content ↓ 得到普通字符串如果不加StrOutputParser()你拿到的可能是一个AIMessage对象。加了之后后续处理更方便。比如print(result[:20])就可以像普通字符串一样切片、保存、展示。适合场景场景是否适合聊天回复适合简单解释适合文案生成适合前端直接展示文本适合需要字段校验不够如果你只是要一段自然语言回答StrOutputParser基本够用。四、JsonOutputParser把模型输出转成字典如果你希望模型输出结构化 JSON可以使用JsonOutputParser示例fromlangchain_openaiimportChatOpenAIfromlangchain_core.promptsimportChatPromptTemplatefromlangchain_core.output_parsersimportJsonOutputParser parserJsonOutputParser()promptChatPromptTemplate.from_messages([(system,你是一个信息抽取助手。请严格输出 JSON不要添加额外解释。),(human,从下面文本中提取 name、job、city\n{text})])llmChatOpenAI(modelgpt-4o-mini)chainprompt|llm|parser resultchain.invoke({text:张三是一名后端开发工程师目前在杭州工作。})print(result)print(result[name])期望结果{name:张三,job:后端开发工程师,city:杭州}JsonOutputParser 的本质它不是让模型天然变稳定而是先要求模型输出 JSON再尝试把返回内容解析成 Python dict。所以它依赖两件事Prompt 对格式约束足够清楚模型真的按格式输出这意味着它比纯文本好但还不是最强约束。可以配合格式说明有些解析器可以提供格式提示告诉模型应该怎么输出。思路大概是parser 生成格式要求 ↓ 把格式要求放进 Prompt ↓ 模型更容易输出合法结构 ↓ parser 再解析这其实是一种“前后夹击”前面用 Prompt 约束 后面用 Parser 校验五、PydanticOutputParser让输出带类型校验JsonOutputParser返回的是普通字典。但有时候我们希望字段类型也被严格检查。比如评分必须是整数 范围必须是 1 到 10 关键词必须是列表这时可以用PydanticOutputParser先定义数据模型fromtypingimportListfrompydanticimportBaseModel,FieldclassMovieReview(BaseModel):title:strField(description电影名称)rating:intField(description评分范围 1 到 10,ge1,le10)tags:List[str]Field(description电影标签)summary:strField(description一句话短评)然后创建解析器fromlangchain_core.output_parsersimportPydanticOutputParser parserPydanticOutputParser(pydantic_objectMovieReview)完整示例fromtypingimportListfrompydanticimportBaseModel,Fieldfromlangchain_openaiimportChatOpenAIfromlangchain_core.promptsimportChatPromptTemplatefromlangchain_core.output_parsersimportPydanticOutputParserclassMovieReview(BaseModel):title:strField(description电影名称)rating:intField(description评分范围 1 到 10,ge1,le10)tags:List[str]Field(description电影标签)summary:strField(description一句话短评)parserPydanticOutputParser(pydantic_objectMovieReview)promptChatPromptTemplate.from_messages([(system,你是一个电影评论信息抽取助手。\n{format_instructions}),(human,请从下面文本中提取电影评论信息\n{text})])promptprompt.partial(format_instructionsparser.get_format_instructions())llmChatOpenAI(modelgpt-4o-mini)chainprompt|llm|parser reviewchain.invoke({text:《星际穿越》非常震撼我给 10 分关键词是科幻、亲情、宇宙。})print(review.title)print(review.rating)print(review.tags)print(review.summary)这里最关键的是parser.get_format_instructions()它会生成一段格式说明告诉模型应该输出什么结构。为什么 Pydantic 更适合工程项目因为它能做校验。比如rating:intField(ge1,le10)如果模型返回{rating:99}Pydantic 会认为不合法。这对项目很重要。因为你不能指望模型永远听话后端必须有自己的防线。六、with_structured_output更工程化的结构化输出在新版 LangChain 里很多模型支持with_structured_output()它的思路是直接把结构化 schema 绑定到模型上让模型按这个结构返回。示例fromtypingimportListfrompydanticimportBaseModel,Fieldfromlangchain_openaiimportChatOpenAIclassStudyCard(BaseModel):title:strField(description学习卡片标题)explanation:strField(description概念解释)key_points:List[str]Field(description关键点列表)quiz:strField(description自测题)llmChatOpenAI(modelgpt-4o-mini)structured_llmllm.with_structured_output(StudyCard)resultstructured_llm.invoke(请为 LangChain Output Parser 生成一张学习卡片。)print(result.title)print(result.key_points)和PydanticOutputParser相比with_structured_output()更像是从模型接口层面要求结构化输出。在支持该能力的模型上它通常更稳。不过也要注意不同模型厂商对结构化输出的支持程度可能不同。所以生产项目里要结合具体模型测试。七、几种方案的对比方案返回结果约束强度适合场景StrOutputParser字符串弱聊天、解释、文案JsonOutputParser字典中通用 JSON 提取PydanticOutputParserPydantic 对象较强字段类型校验with_structured_output()Pydantic 对象或结构化数据强生产级结构化输出我的个人建议简单文本StrOutputParser 通用结构化JsonOutputParser 需要类型校验PydanticOutputParser 模型支持原生结构化优先 with_structured_output八、常见坑1. 只在 Prompt 里写“请输出 JSON”这不够。模型可能仍然返回下面是 JSON ...更好的做法Prompt 约束 Parser 解析 必要时 Pydantic 校验2. 字段名不统一如果你的代码要result[name]就不要让模型自由发挥成{姓名:张三}Prompt 里要明确字段名请输出 JSON字段必须为 name、job、city。3. 把 Parser 当成万能修复器Parser 不是万能的。如果模型输出完全不是目标格式Parser 也救不了。所以要同时做好Prompt 设计模型选择Parser 校验错误处理重试机制这才是工程化思路。4. Pydantic 校验失败没有处理如果校验失败程序可能抛异常。生产项目里最好配合chain.with_retry(...)或者在业务代码中捕获异常。不要让一个格式错误直接把用户请求打崩。九、小结这一篇讲的是 LangChain 的输出解析器。可以这样记StrOutputParser把 AIMessage 转成字符串。 JsonOutputParser把 JSON 文本转成 dict。 PydanticOutputParser把模型输出转成带校验的数据对象。 with_structured_output利用模型原生能力做结构化输出。底层逻辑是大模型负责生成内容 输出解析器负责把内容变成程序可用的数据。如果说 Prompt Template 解决的是如何稳定地问模型那么 Output Parser 解决的是如何稳定地使用模型的回答下一篇继续学习Chains 与 LCEL 管道语法。也就是把 Prompt、Model、Parser 串成一条真正的 AI 工作流。参考资料LangChain Python 官方文档https://docs.langchain.com/oss/python/langchainLangChain Core Output Parsershttps://reference.langchain.com/python/langchain-core/output_parsers/Pydantic 官方文档https://docs.pydantic.dev/