
🔥草莓熊Lotso: 个人主页
❄️个人专栏: 《C++知识分享》 《Linux 入门到实践:零基础也能懂》
✨生活是默默的坚持,毅力是永久的享受!
🎬 博主简介:

文章目录
- 前言
- [一. 输出解析器核心概念](#一. 输出解析器核心概念)
-
- [1.1 什么是输出解析器?](#1.1 什么是输出解析器?)
- [1.2 与 with_structured_output() 的关键区别](#1.2 与 with_structured_output() 的关键区别)
- [二. 常用输出解析器实战](#二. 常用输出解析器实战)
-
- [2.1 StrOutputParser:解析文本输出](#2.1 StrOutputParser:解析文本输出)
- [2.2 PydanticOutputParser:解析为结构化对象](#2.2 PydanticOutputParser:解析为结构化对象)
- [2.3 JsonOutputParser:解析为 JSON 格式](#2.3 JsonOutputParser:解析为 JSON 格式)
- [三. 核心考点与最佳实践](#三. 核心考点与最佳实践)
-
- [3.1 核心考点总结](#3.1 核心考点总结)
- [3.2 最佳实践](#3.2 最佳实践)
- 结尾:
前言
在构建大语言模型(LLM)应用时,我们经常会遇到一个核心矛盾:大模型最擅长生成自然流畅的文本,但程序只能处理结构化的数据 。想象一下这个场景:你正在开发一个天气查询应用,用户问 "北京今天天气怎么样?",大模型返回了一段非常友好的回答:"北京今天晴转多云,最高气温 28℃,最低气温 18℃,风力 3 级,适合外出活动。" 如果没有输出解析器,你只能用正则表达式或者字符串匹配来提取这些字段,不仅代码复杂易出错,而且大模型输出格式稍有变化就会导致程序崩溃。LangChain 的 输出解析器(Output Parsers) 正是为了解决这个问题而生的。它提供了一套标准化的接口,能够将大模型的非结构化文本输出,自动转换为 JSON、Pydantic 对象、列表等机器可读的格式,是连接大模型和业务系统的关键桥梁。
一. 输出解析器核心概念
1.1 什么是输出解析器?
输出解析器是 LangChain 中的一个功能性组件,负责接收大模型的输出(通常是AIMessage对象),并将其转换为更结构化、更适合下游任务处理的格式。
它的核心价值在于:
- 标准化:提供统一的接口处理不同模型的输出
- 可靠性:通过格式指令和类型验证,确保输出符合预期
- 易用性:无需手动编写复杂的字符串解析代码
- 可扩展性:支持自定义解析器,满足各种特殊需求
1.2 与 with_structured_output() 的关键区别
很多初学者会混淆输出解析器和聊天模型的with_structured_output()方法,它们虽然都能实现结构化输出,但有本质区别:
| 维度 | 输出解析器(Output Parsers) | with_structured_output() |
||
|---|---|---|---|---|
| 本质 | LangChain 的功能性组件 | 聊天模型的内置方法 | ||
| 用法 | 支持链式调用:`prompt | model | parser` | 返回一个新的 Runnable 对象 |
| 灵活性 | 更高,可以组合多个解析器 | 相对固定,只能返回指定结构 | ||
| 适用场景 | 需要复杂的输出处理流程 | 简单的结构化输出需求 |
简单来说:如果你想使用 LCEL(LangChain 表达式语言)构建链式流程,优先使用输出解析器;如果你只是想让模型直接返回结构化对象,可以使用 **with_structured_output()**。


二. 常用输出解析器实战
LangChain 提供了多种内置的输出解析器,覆盖了绝大多数常见的结构化输出场景。下面我们逐一讲解最常用的三种。
2.1 StrOutputParser:解析文本输出
StrOutputParser是最简单也是最常用的输出解析器,它的作用非常纯粹:从 **AIMessage对象中提取 content**字段,返回纯文本字符串。
虽然看起来简单,但它是几乎所有 LangChain 链的标配,因为大模型的原始输出是AIMessage对象,而我们通常只需要其中的文本内容。
完整代码示例
python
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
# 1. 初始化大模型
model = ChatOpenAI(model="gpt-4o-mini")
# 2. 定义输出解析器
parser = StrOutputParser()
# 3. 构建链:模型 -> 解析器
chain = model | parser
# 4. 调用链并流式输出
print("生成一首夏天的诗词:")
for chunk in chain.stream("写一首夏天的诗词,50字以内。"):
print(chunk, end="|")
代码解读
- 第 7 行:创建
StrOutputParser实例,无需任何参数 - 第 10 行:使用 LCEL 的管道符
|将模型和解析器连接成一个链 - 第 14 行:调用链的
stream()方法进行流式输出,每个chunk都是解析后的纯文本字符串
输出结果
Plain
生成一首夏天的诗词:
|炎|夏|骄|阳|照|,|绿|树|映|蓝|天|。|
|蝉|鸣|声|声|烈|,|荷|塘|映|清|鲜|。
|微|风|拂|面|过|,|凉|意|透|心|间|。|
|烦|忧|随|汗|去|,|畅|享|此|夏|欢|。||
如果不使用StrOutputParser,你需要手动从AIMessage中提取content字段:
python
# 不使用解析器的写法
result = model.invoke("写一首夏天的诗词,50字以内。")
print(result.content) # 手动提取文本内容

2.2 PydanticOutputParser:解析为结构化对象
PydanticOutputParser是功能最强大的输出解析器,它可以将大模型的输出直接转换为 Pydantic 对象,并自动进行类型验证。
Pydantic 是 Python 中最流行的数据验证库,它允许你定义数据模型,指定每个字段的类型、描述和默认值,然后自动验证输入数据是否符合模型要求。
完整代码示例
python
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import PydanticOutputParser
from langchain_core.prompts import PromptTemplate
from typing import Optional
from pydantic import BaseModel, Field
# 1. 初始化大模型
model = ChatOpenAI(model="gpt-4o-mini")
# 2. 定义输出结构:Pydantic 类
class Joke(BaseModel):
"""给用户讲一个笑话。"""
setup: str = Field(description="这个笑话的开头")
punchline: str = Field(description="这个笑话的妙语")
rating: Optional[int] = Field(
default=None, description="从1到10分,给这个笑话评分"
)
# 3. 设置解析器
parser = PydanticOutputParser(pydantic_object=Joke)
# 4. 提示词模板:必须包含格式指令
prompt = PromptTemplate(
template="Answer the user query.\n{format_instructions}\n{query}\n",
input_variables=["query"],
# partial_variables:提前绑定固定的变量,无需每次调用都传入
partial_variables={"format_instructions": parser.get_format_instructions()},
)
# 5. 构建链:提示词 -> 模型 -> 解析器
chain = prompt | model | parser
# 6. 调用链
result = chain.invoke({"query": "给我讲一个关于唱歌的笑话"})
print(result)
print(f"\n笑话开头:{result.setup}")
print(f"笑话妙语:{result.punchline}")
print(f"笑话评分:{result.rating}")
关键知识点解读
- Pydantic 模型定义
- 每个字段都使用
Field()添加描述,大模型会根据这些描述生成正确的输出 Optional[int]表示该字段是可选的,可以为None- 类的文档字符串会被解析器用作整体描述
- 每个字段都使用
- **
get_format_instructions()**方法- 这是
PydanticOutputParser最重要的方法,它会自动生成一段详细的格式指令,告诉大模型应该如何输出 - 生成的指令会包含 JSON 格式要求、字段说明和示例
- 必须将这段指令添加到提示词中,否则大模型不知道应该按照什么格式输出
- 这是
- **
partial_variables**参数- 提示词模板中的
format_instructions是固定不变的,不需要每次调用链都传入 - 使用
partial_variables可以提前将这个变量绑定到模板上,简化调用代码
- 提示词模板中的
输出结果
Plain
setup='为什么歌手总是带着铅笔去演出?' punchline='因为他们想要不断调整音调!' rating=7
笑话开头:为什么歌手总是带着铅笔去演出?
笑话妙语:因为他们想要不断调整音调!
笑话评分:7
可以看到,返回的result是一个Joke对象,我们可以直接通过属性访问各个字段,非常方便。


2.3 JsonOutputParser:解析为 JSON 格式
JsonOutputParser用于将大模型的输出解析为 Python 字典(JSON 格式)。它有两种使用方式:
- 不带 Pydantic 模型:大模型输出自由格式的 JSON
- 带 Pydantic 模型:输出严格符合 Pydantic 模型结构的 JSON,并进行验证
方式一:不带 Pydantic 模型
python
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplate
# 1. 初始化大模型
model = ChatOpenAI(model="gpt-4o-mini")
# 2. 设置解析器(不带 Pydantic 模型)
parser = JsonOutputParser()
# 3. 提示词模板
prompt = PromptTemplate(
template="Answer the user query.\n{format_instructions}\n{query}\n",
input_variables=["query"],
partial_variables={"format_instructions": parser.get_format_instructions()},
)
# 4. 构建链
chain = prompt | model | parser
# 5. 调用链
result = chain.invoke({"query": "给我讲一个关于唱歌的笑话"})
print(result)
print(f"\n笑话内容:{result['joke']}")
输出结果
Plain
{'joke': '为什么歌手总是带着梯子?\n因为他们想要在音乐会上达到更高的层次!'}
笑话内容:为什么歌手总是带着梯子?
因为他们想要在音乐会上达到更高的层次!
方式二:带 Pydantic 模型
python
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplate
from typing import Optional
from pydantic import BaseModel, Field
# 1. 初始化大模型
model = ChatOpenAI(model="gpt-4o-mini")
# 2. 定义 Pydantic 模型
class Joke(BaseModel):
"""给用户讲一个笑话。"""
setup: str = Field(description="这个笑话的开头")
punchline: str = Field(description="这个笑话的妙语")
rating: Optional[int] = Field(
default=None, description="从1到10分,给这个笑话评分"
)
# 3. 设置解析器(带 Pydantic 模型)
parser = JsonOutputParser(pydantic_object=Joke)
# 4. 提示词模板
prompt = PromptTemplate(
template="Answer the user query.\n{format_instructions}\n{query}\n",
input_variables=["query"],
partial_variables={"format_instructions": parser.get_format_instructions()},
)
# 5. 构建链
chain = prompt | model | parser
# 6. 调用链
result = chain.invoke({"query": "给我讲一个关于唱歌的笑话"})
print(result)
print(f"\n笑话开头:{result['setup']}")
print(f"笑话妙语:{result['punchline']}")
print(f"笑话评分:{result['rating']}")
输出结果
Plain
{'setup': '为什么歌手从不在森林里唱歌?', 'punchline': '因为他们会被树木的'静'止住!', 'rating': 7}
笑话开头:为什么歌手从不在森林里唱歌?
笑话妙语:因为他们会被树木的'静'止住!
笑话评分:7


- 不带 Pydantic 模型:输出结构灵活,但没有类型验证,大模型可能会输出不符合预期的字段
- 带 Pydantic 模型:输出严格符合 Pydantic 模型结构,会自动进行类型验证,可靠性更高
三. 核心考点与最佳实践
3.1 核心考点总结
- 输出解析器的核心作用:将大模型的非结构化文本输出转换为机器可读的结构化数据
- 与 **
with_structured_output()**的区别 :输出解析器是组件,支持链式调用;with_structured_output()是模型方法,返回 Runnable - 常用解析器的选择 :
- 纯文本输出:使用
StrOutputParser - 需要强类型验证:使用
PydanticOutputParser - 需要 JSON 格式:使用
JsonOutputParser
- 纯文本输出:使用
- 格式指令的重要性:必须将解析器生成的格式指令添加到提示词中,否则大模型不知道应该按照什么格式输出
- Pydantic 模型的设计:每个字段都应该添加清晰的描述,这直接影响大模型输出的准确性
3.2 最佳实践
- 总是使用 Pydantic 进行类型验证 :即使你只需要 JSON 格式,也建议使用带 Pydantic 模型的
JsonOutputParser,这样可以确保输出的可靠性 - 优化格式指令:如果大模型输出的格式不符合预期,可以手动修改提示词中的格式指令,使其更清晰
- 处理解析错误:在生产环境中,应该添加异常处理逻辑,捕获解析失败的情况,并进行重试或降级处理
- 流式输出注意事项 :
PydanticOutputParser和JsonOutputParser的流式输出会返回部分对象,直到最后一个 chunk 才会生成完整的对象
除了本文介绍的三种常用解析器,LangChain 还提供了更多类型的解析器,包括:
XMLOutputParser:解析 XML 格式输出YamlOutputParser:解析 YAML 格式输出CommaSeparatedListOutputParser:解析逗号分隔的列表EnumOutputParser:解析枚举类型输出DatetimeOutputParser:解析日期时间格式输出
结尾:
html
🍓 我是草莓熊 Lotso!若这篇技术干货帮你打通了学习中的卡点:
👀 【关注】跟我一起深耕技术领域,从基础到进阶,见证每一次成长
❤️ 【点赞】让优质内容被更多人看见,让知识传递更有力量
⭐ 【收藏】把核心知识点、实战技巧存好,需要时直接查、随时用
💬 【评论】分享你的经验或疑问(比如曾踩过的技术坑?),一起交流避坑
🗳️ 【投票】用你的选择助力社区内容方向,告诉大家哪个技术点最该重点拆解
技术之路难免有困惑,但同行的人会让前进更有方向~愿我们都能在自己专注的领域里,一步步靠近心中的技术目标!
结语:输出解析器是 LangChain 应用开发中不可或缺的组件,它解决了大模型输出与程序处理之间的格式不匹配问题。你可以根据自己的业务需求选择合适的解析器,甚至可以自定义解析器来满足特殊的输出格式要求。在下一篇文章中,我们将进入 RAG(检索增强生成)的世界,学习如何使用 LangChain 的文档加载器加载各种类型的文档,为构建智能知识库问答系统打下基础。
✨把这些内容吃透超牛的!放松下吧✨ ʕ˘ᴥ˘ʔ づきらど
