LangChain之核心组件(输出解析器)

4. 输出解析器(Output parsers)

快速简单的解释一下输出解析器到底解决什么问题:

你调模型拿到的 result 是一个 AIMessage 对象,不是纯字符串:

python 复制代码
result = model.invoke(messages)
print(type(result))   # <class 'langchain_core.messages.AIMessage'>
print(result.content) # "你好!"

每次都要 .content 很烦,而且如果你想把模型输出传给下一个环节(比如存入数据库),你需要的是纯字符串。

输出解析器就是:把 AIMessage 对象 → 纯字符串。

4.1 概念

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

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

• JSON 对象

• Python 字典或列表

• 一个特定的 Pydantic 模型实例

• 一个简单的布尔值或字符串枚举

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

4.1.1 与with_structured_output() 的区别

两个都能实现结构化输出,但维度不同:

python 复制代码
# 解析器方式:可以链式
chain = prompt | model | parser
result = chain.invoke(input)

# with_structured_output 方式:不能链式
structured_model = model.with_structured_output(Schema)
result = structured_model.invoke(input)   # 必须手动调用

可以根据自己的使用场景选择,想用链式调用就选输出解析器。两种都能达到目的,写法不同而已。

4.2 解析文本输出 --- StrOutputParser

StrOutputParser --- 最常用的输出解析器

它就是把 AIMessage 的 .content 取出来。

python 复制代码
from langchain_core.output_parsers import StrOutputParser
from langchain_deepseek import ChatDeepSeek

model = ChatDeepSeek(model="deepseek-v4-flash")
chain = model | StrOutputParser()

for chunk in chain.stream("写一首夏天的诗词,50字以内。"):
    print(chunk, end="|")

不用 parser :输出是 AIMessage,需要 .content ,流式时收到 AIMessageChunk

用 parser: 输出直接是 str, 流式时直接收到字符串 token

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

content 字段获取。

为什么 parser 也能 .invoke()?

因为 StrOutputParser 也实现了 Runnable 接口,和聊天模型一样。所有实现了 Runnable 接口的组件,都可以:

4.3 解析结构化对象输出 --- PydanticOutputParser

如果你想拿到的不是字符串,而是一个带字段的 Python 对象(像之前 test23.py 那样),就用 PydanticOutputParser。

类别 项目 详细说明
类基本信息 完整路径 langchain_core.output_parsers.pydantic.PydanticOutputParser
核心作用 将大语言模型(LLM)的非结构化文本输出解析为强类型的 Pydantic 模型对象。利用 Pydantic 的数据验证机制,确保输出符合预定义的结构和类型约束,并自动处理格式错误。
适用场景 • 需要结构化 JSON 或类 JSON 输出的场景• 对字段类型有严格要求(如必须整数、枚举值、必填字段)• 希望利用 IDE 类型提示和自动补全进行下游开发• 需要优雅地处理 LLM 输出中的格式偏差或遗漏字段
初始化参数 pydantic_object 类型Type[PydanticModel](继承自 BaseModel的类)作用:指定目标数据模型。Parser 会根据该类的定义(字段类型、描述、默认值、验证器)来:1. 生成格式指令(Format Instructions)2. 解析并验证 LLM 输出3. 实例化最终的对象
核心方法 invoke(input: Union[str, dict, BaseMessage]) -> Any 功能 :执行解析逻辑,将 LLM 的原始输出转换为结构化对象输入 :可以是字符串(LLM 纯文本响应)、字典(已部分解析)或 BaseMessage 对象输出 :解析后的 Pydantic 模型实例异常处理 :若输出无法解析或验证失败,会抛出 OutputParserException,包含原始输出和错误详情
get_format_instructions() -> str 功能关键! ​ 生成自然语言指令,指导 LLM 如何格式化输出返回 :包含 JSON 模式(JSON Schema)的字符串,描述了期望的输出结构典型用法 :必须将返回的字符串追加到 Prompt 的末尾 ,例如:```prompt = ChatPromptTemplate.from_template("请回答问题:{question}\n{format_instructions}")parser = PydanticOutputParser(pydantic_object=MyModel)chain = prompt
底层机制 Schema 生成 自动从 Pydantic 模型的字段类型(如 str, int, List[float], Literal['A','B'])生成对应的 JSON Schema,包含在 format instructions 中
容错处理 当 LLM 输出格式不匹配时(如缺少必填字段、类型错误、额外字段),默认行为取决于配置:• 严格模式:直接报错• 宽松模式:尝试提取可用字段,或填充默认值
与 LLM 的交互 通常与 ChatPromptTemplate配合使用,将 get_format_instructions()的结果作为占位符注入提示,形成自描述的提示链(Self-describing Prompt)
  • vs JsonOutputParserPydanticOutputParser基于类型系统,提供更强的类型安全和验证;JsonOutputParser仅确保输出是合法 JSON,不验证字段结构。

  • vs StrOutputParser:后者直接返回字符串,不做任何结构化处理,适用于纯文本回答。

  • 依赖 :需要安装 pydantic库(pip install pydantic

案例代码:

python 复制代码
from langchain_core.output_parsers import PydanticOutputParser
from langchain_core.prompts import PromptTemplate
from typing import Optional
from langchain_deepseek import ChatDeepSeek
from pydantic import BaseModel, Field

#1:定义你想要的输出结构(Pydantic 类)
class Joke(BaseModel):
    """给用户讲一个笑话。"""
    setup: str = Field(description="这个笑话的开头")
    punchline: str = Field(description="这个笑话的妙语")
    rating: Optional[int] = Field(
        default=None, description="从1到10分,给这个笑话评分"
    )
# Field(description=...) 是给模型看的,告诉它每个字段什么意思

# 2:创建解析器
parser = PydanticOutputParser(pydantic_object=Joke)

#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()},
)
# partial_variables 是什么?
# → 不需要每次 invoke 都传的"固定变量"。这里 format_instructions 只取决于 parser,
#   不随每次 query 变化,所以用 partial_variables 预先绑定,调用时只传 query 就行。

#4:串链
model = ChatDeepSeek(model="deepseek-v4-flash")
chain = prompt | model | parser
# 流程:模板填值 → 模型生成 JSON 字符串 → parser 把 JSON 转成 Joke 对象

# 步骤 5:流式调用
for chunk in chain.stream({"query": "给我讲一个关于唱歌的笑话"}):
    print(chunk, end="|")

可以看到流式输出(逐 token 打出 Pydantic 对象的字段值)。注意流式时的特点: punchline 一开始是空字符串 '',然后一个字一个字地"长出来"------这就是流式解析的体现。

输出太长了,我复制换行下来看就明显了:

数据流:

{query: "给我讲一个笑话"}

PromptTemplate → "Answer the user query.\n{format_instructions}\n给我讲一个笑话\n"

│ format_instructions = parser.get_format_instructions()(JSON schema 指令)

model → AIMessage(content='{"setup": "...", "punchline": "...", "rating": 5}')

│ 模型遵照 format_instructions 输出了 JSON 字符串

PydanticOutputParser → Joke(setup="...", punchline="...", rating=5)

│ parser 把 JSON 字符串反序列化成 Joke 对象

你的代码可以直接 joke.setup, joke.punchline, joke.rating

和 with_structured_output() 的对比

PydanticOutputParser 的优势在于它不依赖模型的 tool calling 能力------它只是在提示词里强行要求模型输出 JSON,然后解析。即使模型不支持 function calling,这套也能工作。

4.4 解析 JSON 输出 --- JsonOutputParser

PydanticOutputParser 把模型输出转成 Pydantic 对象。JsonOutputParser 把模型输出转成 Python 字典。

类别 项目 详细说明
类基本信息 完整路径 langchain_core.output_parsers.json.JsonOutputParser
核心作用 将 LLM 的输出解析为 JSON 格式 (Python dictlist)。相比 PydanticOutputParser更轻量,专注于 JSON 语法解析,不强制依赖 Pydantic 模型进行类型验证(除非显式传入)。
适用场景 • 需要灵活的 JSON 输出,结构可能随查询变化• 只需要基础的 JSON 解析,不需要严格的类型检查或数据验证• 作为 PydanticOutputParser的轻量级替代方案• 处理非严格的 JSON(如允许单引号、无引号键等宽松模式,取决于底层实现)
初始化参数 pydantic_object 类型Optional[Type[PydanticModel]]]作用 :用于验证的 Pydantic 对象。如果为空(None ,则不执行 任何数据验证,仅做 JSON 语法解析和字典转换;如果提供,则在解析后会用该模型验证数据结构并返回模型实例。
核心方法 invoke(input: Union[str, dict, BaseMessage]) -> Any 功能 :执行解析逻辑,将 LLM 输出转换为 Python 字典/列表或 Pydantic 对象输入 :LLM 的响应字符串(通常为 JSON 格式)、字典或 BaseMessage输出 :解析后的 Python 数据结构(若未传 pydantic_object)或 Pydantic 模型实例(若传入)异常处理 :若 JSON 语法错误或验证失败,抛出 OutputParserException
get_format_instructions() -> str 功能关键! ​ 生成指导 LLM 输出 JSON 的自然语言指令返回 :包含 JSON 结构描述(或 JSON Schema)的字符串典型用法 :必须将返回的字符串追加到 Prompt 末尾,明确告知模型:"请以 JSON 格式输出,包含 'name' 和 'age' 字段"
与 PydanticOutputParser 对比 验证机制 JsonOutputParser:基础 JSON 语法检查,可选 Pydantic 验证(非必需)PydanticOutputParser:强制 Pydantic 验证,强类型约束
灵活性 JsonOutputParser:更高,适合动态结构PydanticOutputParser:更低,结构固定且严格
性能开销 JsonOutputParser:更轻量,解析更快PydanticOutputParser:需实例化模型,验证开销略大

4.4.1 不带 Pydantic(纯字典)

和 PydanticOutputParser 的区别: 输出是 dict 不是 Pydantic 对象,字段名由模型自己决定(这里是 joke)。

python 复制代码
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_deepseek import ChatDeepSeek

# 创建解析器(不传 pydantic_object,纯输出 dict)
parser = JsonOutputParser()

prompt = PromptTemplate(
    template="Answer the user query.\n{format_instructions}\n{query}\n",
    input_variables=["query"],
    partial_variables={"format_instructions": parser.get_format_instructions()},
)
model = ChatDeepSeek(model="deepseek-v4-flash")
chain = prompt | model | parser
result = chain.invoke({"query": "给我讲一个关于唱歌的笑话"})
print(result)

4.4.2 带 Pydantic(有类型校验的字典)

带 Pydantic 时:

get_format_instructions() 会包含 Pydantic 定义的字段约束

输出虽然是 dict,但会按 Pydantic 定义的字段名和类型做校验

和 PydanticOutputParser 的区别:输出是 dict 而非 Joke 对象

python 复制代码
from typing import Optional
import Field
from pydantic import BaseModel, Field
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_deepseek import ChatDeepSeek

# 定义输出结构:Pydantic 类
class Joke(BaseModel):
    """给用户讲一个笑话。"""
    setup: str = Field(description="这个笑话的开头")
    punchline: str = Field(description="这个笑话的妙语")
    rating: Optional[int] = Field(
    default=None, description="从1到10分,给这个笑话评分"
)
parser = JsonOutputParser(pydantic_object=Joke)

prompt = PromptTemplate(
    template="Answer the user query.\n{format_instructions}\n{query}\n",
    input_variables=["query"],
    partial_variables={"format_instructions": parser.get_format_instructions()},
)

model = ChatDeepSeek(model="deepseek-v4-flash")
chain = prompt | model | parser
result = chain.invoke({"query": "给我讲一个关于唱歌的笑话"})
print(result)

对比

你要什么?

├─ 只要文字内容 → StrOutputParser

├─ 要带类型的 Python 对象 → PydanticOutputParser

└─ 要字典,不想定义 Pydantic 类 → JsonOutputParser

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

• XML 解析器: XMLOutputParser

• Yaml 解析器: YamlOutputParser

• CSV 解析器: CommaSeparatedListOutputParser

• 枚举解析器: EnumOutputParser

• 日期解析器: DatetimeOutputParser 等等,更多类型参考离线 |LangChain 参考文档

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

完毕,下一篇笔记文档加载器

相关推荐
Mac的实验室1 小时前
为什么用chatgpt账号登入一直提示需要电话号码, 要验证手机号怎么解决?
ai编程
沐泽__2 小时前
自注意力机制含义
ai编程
沐泽__2 小时前
Skill 如何实现(通用思路,可直接用)含义
ai编程
掘金酱3 小时前
📱 TRAE SOLO 移动端上线征文|“我的第一次移动端AI办公” 评测,赢机械键盘礼包+10w矿石!
openai·ai编程·trae
KaneLogger3 小时前
如何提升模型编码能力
agent·ai编程
louiX3 小时前
初级 AI Agent 工程师
langchain·agent·客户端
canonical_entropy4 小时前
Nop Chaos Flux:百度AMIS之后的下一代低代码渲染引擎
前端·低代码·ai编程
阿珊和她的猫4 小时前
从实践中提炼的架构设计与工程规范
ai·agent·llama·cli·mcp