LangChain 核心组件 [ 4 ]

输出解析器(Output parsers)

概念

**负责获取模型的输出,并将输出转换为更结构化的格式。**当使用 LLM 生成结构化数据或规范化聊天模型和 LLM 的输出时,这很有用。

大型语言模型(LLM)的输出本质上是非结构化的文本 。但在构建应用程序时,我们通常希望得到结构化的、机器可读的数据,这样可以将其转换为更适合下游任务的格式,比如:

  • JSON 对象
  • Python 字典或列表
  • 一个特定的 Pydantic 模型实例
  • 一个简单的布尔值或字符串枚举

输出解析器的作用就是架起这座桥梁: 它们将 LLM 的非结构化文本输出转换为结构化格式。这使得与 LLM 的交互从 "模糊的文本对话" 变成了 "精确的数据 API 调用",是构建可靠、高效 LLM 应用不可或缺的组件。


和 with_structured_output()的区别

他们都实现了相同的功能,但

  • 维度不同 :输出解析器是 LangChain 中的一个功能性组件,with_structured_output() 是聊天模型的一个方法。

  • 用法不同 :输出解析器的工作流程可以是链式的,可以将 Prompt、LLM 和 Parser 像管道一样连接起来:chain = prompt | llm | parser。而 with_structured_output(schema) 却不行,只能手动调用,返回一个新的、具备了结构化输出能力的 Runnable(可运行对象)

可以根据自己的使用场景选择,如果想使用链式就选择输出解析器


解析文本输出

其实对于使用 StrOutputParser 输出解析器输出文本,我们已经使用过多次了。对于 StrOutputParser,它也实现了标准的 Runnable 接口。示例如下:

python 复制代码
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

model = ChatOpenAI(model="gpt-4o-mini")
chain = model | StrOutputParser()
for chunk in chain.stream("写一首夏天的诗词,50字以内。"):
    print(chunk, end="|")

输出如下:

python 复制代码
|炎|夏|骄|阳|照|,|绿|树|映|蓝|天|。|
|蝉|鸣|声|声|烈|,|荷|塘|映|清|鲜|。|
|微|风|拂|面|过|,|凉|意|透|心|间|。|
|烦|忧|随|汗|去|,|畅|享|此|夏|欢|。||

若是不使用输出解析器,而是直接得到聊天模型返回的 AIMessage,文本内容则需要从消息中的 content 字段获取。

解析结构化对象输出

要输出结构化对象,需要用到的输出解析器是 PydanticOutputParser。

class langchain_core.output_parsers.pydantic.PydanticOutputParser 类,其参数如下:

  • pydantic_object:要解析的 pydantic 模型。

内置方法:

invoke():将单个输入转换为输出。

get_format_instructions() -> str:重要!!

  • 作用:生成一个指令字符串,这个字符串会被添加到发送给 LLM 的提示(Prompt)的末尾。
  • 目的:告诉 LLM 应该以什么样的格式返回它的响应。例如,"请将你的回复封装在 XML 标签中" 或 "请以 JSON 格式输出,包含 name 和 age 两个字段"。

代码示例如下:

python 复制代码
# 导入OpenAI聊天模型对接库,用于调用GPT-4o-mini等大模型
from langchain_openai import ChatOpenAI

# 导入Pydantic输出解析器:用于把LLM返回的文本,自动解析成结构化对象
from langchain_core.output_parsers import PydanticOutputParser

# 导入提示词模板:用于构建固定格式的提问模板
from langchain_core.prompts import PromptTemplate

# 导入可选类型:用于定义可以为None的字段
from typing import Optional

# 导入Pydantic基类与字段校验工具:用于定义结构化输出格式
from pydantic import BaseModel, Field

# ===================== 1. 初始化大模型 =====================
# 创建大模型实例,指定使用 gpt-4o-mini 模型
model = ChatOpenAI(model="gpt-4o-mini")

# ===================== 2. 定义输出数据结构 =====================
# 继承 BaseModel,定义一个结构化输出类,告诉LLM要输出什么格式
class Joke(BaseModel):
    """给用户讲一个笑话。"""  # 类注释:给模型看的功能说明

    # 笑话开头(问题/铺垫)
    # Field:给字段加描述,帮助LLM理解每个字段含义
    setup: str = Field(description="这个笑话的开头")

    # 笑话包袱(笑点/反转)
    punchline: str = Field(description="这个笑话的妙语")

    # 笑话评分(可选,可为空)
    # Optional[int]:表示这个字段可以是 int 或 None
    # default=None:默认值为空
    rating: Optional[int] = Field(
        default=None, description="从1到10分,给这个笑话评分"
    )

# ===================== 3. 创建输出解析器 =====================
# 创建解析器,绑定上面定义的 Joke 结构
# 作用:让LLM输出符合这个结构的内容,并自动解析成对象
parser = PydanticOutputParser(pydantic_object=Joke)

# ===================== 4. 构建提示词模板 =====================
# 定义提示词模板,固定格式
prompt = PromptTemplate(
    # 模板内容:
    # 1. 告诉模型回答用户问题
    # 2. 插入 format_instructions(格式要求)
    # 3. 插入用户真正的 query(问题)
    template="Answer the user query.\n{format_instructions}\n{query}\n",

    # 声明模板中需要动态传入的变量:这里只有用户问题 query
    input_variables=["query"],

    # partial_variables:预先传入固定不变的变量,不用每次调用都传
    # parser.get_format_instructions() 自动生成格式说明文本,告诉LLM怎么输出
    partial_variables={"format_instructions": parser.get_format_instructions()},
)

# ===================== 5. 构建链式调用 =====================
# LangChain 链式语法:
# 提示词 → 大模型生成回答 → 解析成结构化对象
chain = prompt | model | parser

# ===================== 6. 流式调用并输出 =====================
# stream:流式输出,一边生成一边返回,不用等全部完成
for chunk in chain.stream({"query": "给我讲一个关于唱歌的笑话"}):
    # chunk 就是解析后的 Joke 对象,流式逐块输出
    print(chunk, end="|")

结果如下:

python 复制代码
setup='为什么歌手总是带着铅笔去演出?' punchline='' rating=None|
setup='为什么歌手总是带着铅笔去演出?' punchline='因为' rating=None|
setup='为什么歌手总是带着铅笔去演出?' punchline='因为他们' rating=None|
setup='为什么歌手总是带着铅笔去演出?' punchline='因为他们想' rating=None|
setup='为什么歌手总是带着铅笔去演出?' punchline='因为他们想要' rating=None|
setup='为什么歌手总是带着铅笔去演出?' punchline='因为他们想要不断' rating=None|
setup='为什么歌手总是带着铅笔去演出?' punchline='因为他们想要不断调整' rating=None|
setup='为什么歌手总是带着铅笔去演出?' punchline='因为他们想要不断调整音' rating=None|
setup='为什么歌手总是带着铅笔去演出?' punchline='因为他们想要不断调整音调' rating=None|
setup='为什么歌手总是带着铅笔去演出?' punchline='因为他们想要不断调整音调!' rating=None

解析 JSON 输出

要输出 JSON 格式,需要用到的输出解析器是 JsonOutputParser

class langchain_core.output_parsers.json.JsonOutputParser 类,其参数如下:

  • pydantic_object:用于验证的 Pydantic 对象。如果为空,则不执行任何验证。

内置方法:

invoke():将单个输入转换为输出。

get_format_instructions() -> str:重要!!

  • 作用:生成一个指令字符串,这个字符串会被添加到发送给 LLM 的提示(Prompt)的末尾。
  • 目的:告诉 LLM 应该以什么样的格式返回它的响应。例如,"请将你的回复封装在 XML 标签中" 或 "请以 JSON 格式输出,包含 name 和 age 两个字段"。

代码示例如下,这将提示模型返回 JSON:

python 复制代码
# 导入 LangChain 对接 OpenAI 大模型的类,用于创建聊天模型实例
from langchain_openai import ChatOpenAI

# 导入 Json 输出解析器:
# 作用 → 把大模型返回的字符串自动转成 Python 字典(JSON 对象)
from langchain_core.output_parsers import JsonOutputParser

# 导入提示词模板:用于拼接固定格式的提示词
from langchain_core.prompts import PromptTemplate

# ===================== 1. 初始化大模型 =====================
# 创建大模型对象,指定使用 gpt-4o-mini 模型
model = ChatOpenAI(model="gpt-4o-mini")

# ===================== 2. 创建 JSON 解析器 =====================
# 创建一个通用的 JSON 解析器
# 它不需要定义 Pydantic 类,直接让模型返回 JSON 格式字符串,然后自动转字典
parser = JsonOutputParser()

# ===================== 3. 构建提示词模板 =====================
prompt = PromptTemplate(
    # 模板内容:
    # 1. 告诉模型:回答用户问题
    # 2. 插入 {format_instructions}:告诉模型必须按 JSON 格式输出
    # 3. 插入 {query}:用户真正的问题
    template="Answer the user query.\n{format_instructions}\n{query}\n",

    # 声明需要动态传入的变量:只有用户问题 query
    input_variables=["query"],

    # partial_variables:预先传入固定不变的变量
    # parser.get_format_instructions() 会自动生成一段文字,告诉模型:
    # "请返回 JSON 格式,不要多余内容"
    partial_variables={"format_instructions": parser.get_format_instructions()},
)

# ===================== 4. 构建执行链 =====================
# LangChain 链式调用语法:
# 提示词 → 大模型生成内容 → JSON 解析器解析成字典
chain = prompt | model | parser

# ===================== 5. 执行并输出结果 =====================
# invoke:一次性调用,等待模型全部生成完成后返回结果
# 传入用户问题:给我讲一个关于唱歌的笑话
result = chain.invoke({"query": "给我讲一个关于唱歌的笑话"})

# 打印最终结果(已经是 Python 字典格式)
print(result)

结果如下:

python 复制代码
{'joke': '为什么歌手总是带着梯子?\n因为他们想要在音乐会上达到更高的层次!'}

也可以使用带 Pydantic 情况下的 JsonOutputParser,如下所示:

python 复制代码
# 导入OpenAI聊天模型,用于调用GPT系列大模型
from langchain_openai import ChatOpenAI
# 导入JSON输出解析器:可以根据Pydantic模型,约束大模型输出标准JSON并自动转为字典
from langchain_core.output_parsers import JsonOutputParser
# 导入提示词模板,用来统一构造固定格式的用户提示
from langchain_core.prompts import PromptTemplate
# 导入Optional:标识字段可以为整型,也可以为None空值
from typing import Optional
# 导入Pydantic基类BaseModel和字段描述工具Field
from pydantic import BaseModel, Field

# 1. 初始化大模型实例
# 指定使用 gpt-4o-mini 模型
model = ChatOpenAI(model="gpt-4o-mini")

# 2. 用Pydantic定义结构化输出模型
# 继承BaseModel,强制约束大模型返回的数据结构、字段含义、类型
class Joke(BaseModel):
    """给用户讲一个笑话。"""  # 类注释会一并传给大模型,作为功能说明

    # 笑话铺垫/开头,字符串类型,附带字段描述给大模型参考
    setup: str = Field(description="这个笑话的开头")
    # 笑话笑点/包袱,字符串类型
    punchline: str = Field(description="这个笑话的妙语")
    # 笑话评分:可为整数或为空,默认值None
    rating: Optional[int] = Field(
        default=None,
        description="从1到10分,给这个笑话评分"
    )

# 3. 创建JSON解析器,并绑定自定义Pydantic结构
# 作用:
# 1. 自动生成格式要求提示词,告诉大模型必须按Joke结构输出JSON
# 2. 把大模型返回的JSON字符串,自动解析为Python字典
parser = JsonOutputParser(pydantic_object=Joke)

# 4. 构造提示词模板
prompt = PromptTemplate(
    # 模板句式:
    # 先要求回答用户问题,再插入自动生成的JSON格式要求,最后接入用户提问
    template="Answer the user query.\n{format_instructions}\n{query}\n",
    # 声明模板里需要动态传入的变量名
    input_variables=["query"],
    # 预填充固定变量:把解析器生成的格式说明提前注入模板
    partial_variables={"format_instructions": parser.get_format_instructions()},
)

# 5. 构建LangChain链式流水线
# 流程:提示词构造 → 大模型生成 → JSON结构化解析
chain = prompt | model | parser

# 6. 同步调用链,传入用户问题,打印解析后的结构化字典结果
print(chain.invoke({"query": "给我讲一个关于唱歌的笑话"}))

结果如下:

python 复制代码
{'setup': '为什么歌手从不在森林里唱歌?', 'punchline': '因为他们会被树木的'静'止住!', 'rating': None}

除了上面讲的文本、对象、JSON 解析器,其实 LangChain 官方还提供了更多类型的解析器,如:

  • XML 解析器:XMLOutputParser
  • Yaml 解析器:YamlOutputParser
  • CSV 解析器:CommaSeparatedListOutputParser
  • 枚举解析器:EnumOutputParser
  • 日期解析器:DatetimeOutputParser 等等,更多类型参考这里。

除此之外,LangChain 还支持我们自定义输出解析器,以将模型输出结构化为自定义格式,详细情况参考这里。

相关推荐
戋风2 小时前
从源码到实战:LangChain4j 1.14 完整学习指南(14 课全解)
langchain
老陈说编程2 小时前
12. LangChain 6大核心调用方法:invoke/stream/batch同步异步全解析,新手也能轻松学会
开发语言·人工智能·python·深度学习·机器学习·ai·langchain
网络工程小王5 小时前
【LangChain Output Parser 输出解析器】输出篇
人工智能·学习·langchain
Zfox_7 小时前
【LangChain】核心组件(上)
后端·langchain·ai编程
yanghuashuiyue7 小时前
Deep Agents 框架-开发部署
langchain·langgraph·deepagents
FrontAI7 小时前
深入浅出 LangGraph —— 第12章:多Agent系统架构
人工智能·langchain·ai agent·langgraph
狐狐生风7 小时前
LangChain实现简易版-----PDF 文档问答机器人
人工智能·langchain·机器人·pdf·prompt
测试员周周7 小时前
【AI测试系统】第5篇:AI 编码工具抛硬币?我们用 LangGraph 做了个“确定性+AI”的测试系统(附自愈架构)
人工智能·python·功能测试·测试工具·架构·langchain·单元测试
H_unique7 小时前
LangChain:创建工具Ⅰ
python·langchain