ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

AI Agent白手起家37: LangChain 输出解析器实战:文本、JSON、XML 与 Pydantic

2026/8/7 1:08:04 拓冰建站 浏览量
AI Agent白手起家37: LangChain 输出解析器实战:文本、JSON、XML 与 Pydantic

内容纲要

  • 输出解析器核心作用:将大模型自然语言输出转换为结构化数据
  • 常用解析器类型
    • StrOutputParser:提取纯文本,无需格式指令
    • PydanticOutputParser:基于 Pydantic 数据模型,精确控制字段和验证
    • JsonOutputParser:自由 JSON 或结合 Pydantic 生成严格 JSON
    • XMLOutputParser:输出字典,可指定标签约束
  • 关键技术点
    • 格式指令注入:get_format_instructions()必须嵌入提示词
    • Pydantic v2 版本变化及验证器用法
    • 流式输出中的 JSON 完整性保护
  • 完整可运行代码:使用模拟模型演示四种解析器,无需外部 API Key

引言

大模型输出的本质是自然语言文本,但实际应用需要结构化数据(如 JSON 对象、表格、特定字段)传递给下游服务。早期做法是用正则表达式从文本中抽取信息,但模型输出的随机性常导致匹配失败。LangChain 的输出解析器(Output Parsers)提供了一个标准化方案:通过将格式要求预先注入提示词,并结合解析器自动转换,可稳定获得结构化的 Python 对象。本文通过可运行代码演示文本、JSON、Pydantic 和 XML 四种常见解析器的用法。

输出解析器在 IO 管道中的定位

LangChain 的核心数据流由三部分组成:提示词模板、大模型、输出解析器,它们通过 LCEL 管道串联:

用户输入

提示词模板

大模型

输出解析器

结构化数据

下游应用

解析器的作用是将模型输出的自由文本转换为机器易处理的格式,同时保证与 LangChain 生态的其他组件无缝对接。

四种解析器一览

解析器输出类型是否需格式指令典型场景
StrOutputParser字符串简单问答、文本摘要
PydanticOutputParserPydantic BaseModel 实例精准字段控制、数据验证
JsonOutputParser字典 (dict)通用 JSON 数据交互
XMLOutputParser字典 (dict)兼容 XML 的老系统

使用结构化解析器时,务必通过get_format_instructions()获取格式指令并嵌入提示词,否则模型可能不遵守格式约定。

环境准备

安装依赖:

pipinstalllangchain langchain-core langchain-community pydantic

以下代码使用FakeListChatModel模拟模型输出,因此无需任何 API Key 即可运行。如果希望接入真实模型(如 OpenAI、DeepSeek),只需替换模型初始化部分。

完整可运行代码

fromlangchain_core.promptsimportChatPromptTemplatefromlangchain_core.output_parsersimport(StrOutputParser,JsonOutputParser,PydanticOutputParser,XMLOutputParser,)fromlangchain_community.chat_models.fakeimportFakeListChatModelfrompydanticimportBaseModel,Field,model_validator# ======================== 1. 文本解析器 ========================# 模型预设回复str_model=FakeListChatModel(responses=[" LangChain 是一个用于构建大语言模型应用的开源框架。"])str_prompt=ChatPromptTemplate.from_template("用一句话介绍{subject}")str_chain=str_prompt|str_model|StrOutputParser()result_str=str_chain.invoke({"subject":"LangChain"})print("StrOutputParser 结果:",result_str)print()# ======================== 2. Pydantic 解析器 ========================classJoke(BaseModel):setup:str=Field(description="笑话的铺垫,必须以问号结尾")punchline:str=Field(description="笑话的包袱,回答铺垫问题")@model_validator(mode='before')@classmethoddefcheck_setup_ends_with_question(cls,values:dict)->dict:setup=values.get('setup','')ifnotsetup.endswith('?'):raiseValueError(f'setup 必须以问号结尾,当前为:{setup}')returnvalues# 模拟模型返回严格符合 Pydantic 的 JSON 字符串pyd_model_response='{"setup": "为什么鸡不能过马路?", "punchline": "因为它会被机动车撞到。"}'pyd_model=FakeListChatModel(responses=[pyd_model_response])pyd_parser=PydanticOutputParser(pydantic_object=Joke)format_instructions=pyd_parser.get_format_instructions()pyd_prompt=ChatPromptTemplate.from_template("回答用户的查询\n{format_instructions}\n用户输入:{query}")pyd_prompt=pyd_prompt.partial(format_instructions=format_instructions)pyd_chain=pyd_prompt|pyd_model|pyd_parser joke_obj=pyd_chain.invoke({"query":"给我讲一个笑话"})print("PydanticOutputParser 结果:",joke_obj)print("字段 setup:",joke_obj.setup)print("字段 punchline:",joke_obj.punchline)print()# ======================== 3. JSON 解析器(自由格式) ========================json_model_response='{"joke": "为什么鸡不能过马路?因为它会被机动车撞到。"}'json_model=FakeListChatModel(responses=[json_model_response])json_parser=JsonOutputParser()json_format=json_parser.get_format_instructions()json_prompt=ChatPromptTemplate.from_template("请以 JSON 格式返回一个笑话\n{format_instructions}\n用户输入:{input}")json_prompt=json_prompt.partial(format_instructions=json_format)json_chain=json_prompt|json_model|json_parser json_result=json_chain.invoke({"input":"讲个笑话"})print("JsonOutputParser 结果:",json_result)print("类型:",type(json_result))print()# ======================== 4. XML 解析器(指定标签) ========================xml_model_response="""<movies> <movie> <title>阿甘正传</title> <year>1994</year> <actor>汤姆·汉克斯</actor> </movie> <movie> <title>荒岛余生</title> <year>2000</year> <actor>汤姆·汉克斯</actor> </movie> </movies>"""xml_model=FakeListChatModel(responses=[xml_model_response])# 指定顶层标签和内部字段xml_parser=XMLOutputParser(tags=["movies","movie","title","year","actor"])xml_format=xml_parser.get_format_instructions()xml_prompt=ChatPromptTemplate.from_template("根据用户查询生成 XML 列表\n{format_instructions}\n{query}")xml_prompt=xml_prompt.partial(format_instructions=xml_format)xml_chain=xml_prompt|xml_model|xml_parser xml_result=xml_chain.invoke({"query":"列出汤姆·汉克斯的电影"})print("XMLOutputParser 结果 (字典):",xml_result)print("第一标题:",xml_result["movies"][0]["movie"][0]["title"][0])print()# ======================== 5. 流式 JSON 演示(模拟) ========================# 为演示流式解析,使用一个分段返回的模拟模型# 由于 FakeListChatModel 不支持 streaming,此处仅给出概念说明。# 在实际应用中,可使用支持流式的模型替换,解析器会自动处理部分 JSON。print("流式 JSON 解析概念:解析器在接收到不完整的 JSON 片段时,会等待字段完整再输出。")

结果解读

  • StrOutputParser直接返回去除多余空白的纯文本。
  • PydanticOutputParser将模型返回的 JSON 反序列化为Joke对象,并执行验证器检查setup是否以问号结尾,失败则抛出异常。
  • JsonOutputParser返回普通字典,适合无需强类型校验的场景;若结合 Pydantic,可生成更严格的 JSON。
  • XMLOutputParser默认将 XML 转为多层嵌套字典,通过tags参数可约束输出结构,避免无关字段。

Pydantic 版本注意事项

LangChain 在不同版本中使用的 Pydantic 版本不同:v0.1 之前同时兼容 Pydantic v1/v2,v0.2 起默认 v2,v0.3 完全弃用 v1。代码示例基于 Pydantic v2,语法与 v1 差异较大(如model_validator替代root_validator),若使用旧版 LangChain 需调整导入和验证器写法。

最佳实践

  • 始终将get_format_instructions()注入提示词,否则模型可能自由发挥。
  • 需要严格字段验证时首选PydanticOutputParser,其错误处理机制能与 LangChain 的OutputFixingParser结合自动修复。
  • 处理 XML 时注意解析结果是嵌套字典,访问路径较深,可编写辅助函数提取。
  • 流式场景下,JsonOutputParser能保证任意截断时刻的 JSON 仍为合法片段,便于前端实时渲染。

总结

输出解析器是 LangChain 从模型“模糊输出”到“精确数据”的关键桥梁。文本解析器简单直接,Pydantic 提供强类型保障,JSON 和 XML 覆盖了主流数据交换格式。

使用框架封装好的解析器,不仅能减少重复造轮子,还能充分利用其与模型、提示词模板的深度集成,大幅提升 LLM 应用的工程化水平。