LangChain 输出解析器:把模型回复变成你要的数据
读完你会什么
上一篇学了 Input(模板拼接) 和 Model(invoke / stream / batch)。大模型返回的是 AIMessage 对象,业务里往往要 字符串、JSON、结构化对象。
本文讲 Model I/O 的第三环 ------ Output 输出解析器:它是什么、为什么要用、常用有哪些、各自怎么用。
记忆口诀 :模型吐
AIMessage→ 解析器.invoke()→ 得到str/dict/ Pydantic 对象。结构化输出还可直接用llm.with_structured_output(),跳过 Parser 这一步。
注意先 申请大模型的秘钥和配置环境(与系列前文相同)。
一、总览:输出解析器是什么?为什么要用?
它在 Model I/O 里扮演什么角色?
LangChain 把调大模型拆成三段:
css
Input(Prompt 模板) → Model(LLM) → Output(输出解析器)
拼问题 生成回复 转成可用数据
输出解析器(Output Parser) 负责最后一步:把 AIMessage 转成程序方便用的 字符串、字典、强类型对象。
python
response = llm.invoke(messages) # AIMessage
text = parser.invoke(response) # str / dict / Pydantic 对象
解析器 = 模型输出 → 业务数据的适配器。 价值不只是少写一行 .content,而是 统一接口、可替换、可接 chain。
常用解析器一览
| 解析器 / 方式 | 产出类型 | 常用度 | 典型场景 |
|---|---|---|---|
StrOutputParser |
str |
⭐⭐ 必学 | 聊天、摘要、任何要纯文本 |
JsonOutputParser |
dict / list |
⭐ 常用 | 抽信息、对接 API 的 JSON |
PydanticOutputParser |
Pydantic 模型 | ⭐ 常用 | 固定字段 + 类型校验(学习用) |
with_structured_output |
Pydantic 模型 | ⭐ 生产推荐 | 同上,由 API 约束 schema |
CommaSeparatedListOutputParser |
list[str] |
✓ 特定 | Prompt 要求「逗号分隔列表」 |
XMLOutputParser 等 |
XML / 工具 JSON | 了解即可 | 老 Prompt、Agent |
学习路径 :StrOutputParser → JsonOutputParser → PydanticOutputParser + Field → with_structured_output。
二、分述:各解析器怎么用?
以下示例均省略环境变量配置。硅基流动可先配置:
python
import os
from langchain.chat_models import init_chat_model
os.environ["OPENAI_API_KEY"] = os.getenv("SILICON_KEY")
os.environ["OPENAI_BASE_URL"] = os.getenv("SILICON_BASE_URL")
llm = init_chat_model("openai:deepseek-ai/DeepSeek-V3")
2.1 StrOutputParser --- 拿纯文本(默认首选)
场景 :聊天、问答、写文章------下游只要 字符串。
python
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "你现在是一个小学{subject}老师,尽量用两三句话解释"),
("human", "请介绍{question}"),
]).invoke({"subject": "数学", "question": "数独是啥"})
answer = llm.invoke(prompt)
answerFormated = StrOutputParser().invoke(answer) # 等同于 answer.content
print(answerFormated)
流式:
python
for chunk in StrOutputParser().transform(llm.stream(prompt)):
print(chunk, end="")
2.2 JsonOutputParser --- 拿 JSON 字典或数组
场景 :下游要 dict 或 list,不是字符串。
python
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "你只输出 JSON 不要 markdown 不要解释。"),
("human", "用 JSON 描述城市,字段:name, population。城市:{city}"),
]).invoke({"city": "北京"})
data = JsonOutputParser().invoke(llm.invoke(prompt))
print(data) # {'name': '北京', 'population': '2189万'}
关键点:
- Prompt 必须约束 JSON------解析器只负责解析,不能保证模型不乱写。
- 自动处理 markdown 代码块 ------包了 ```````json```` 通常仍能解析。
- 不做类型校验 ------要强校验用 Pydantic 或
with_structured_output。
2.3 PydanticOutputParser --- 强类型结构化
场景 :字段固定、要 类型校验 ------下游要 Pydantic 对象 ,不是裸 dict。
标准三步
python
from pydantic import BaseModel, Field, RootModel
from langchain_core.output_parsers import PydanticOutputParser
from langchain_core.prompts import ChatPromptTemplate
# ① 定义 schema
class Animal(BaseModel):
name: str = Field(description="动物中文名称,不超过8个字", min_length=1, max_length=8)
emoji: str = Field(description="单个 emoji 表情")
age: int = Field(default=0, ge=0, le=150, description="年龄,0~150 整数")
class AnimalArray(RootModel[list[Animal]]):
pass
# ② 先建 parser,注入 format_instructions
parser = PydanticOutputParser(pydantic_object=AnimalArray)
prompt = ChatPromptTemplate.from_messages([
("system", "只输出 JSON,不要 markdown。\n{format_instructions}"),
("human", "用 JSON 数组描述三个动物"),
]).invoke({"format_instructions": parser.get_format_instructions()})
# ③ 调模型 → 解析
result = parser.invoke(llm.invoke(prompt))
print(result.model_dump())
get_format_instructions() 是什么?
把 Pydantic 模型的 JSON Schema 自动生成 成说明文字,塞进 Prompt 的 {format_instructions}。
易错点 :必须先建 parser,再传入 get_format_instructions();顺序反了或传空字典,模型看不到 schema。
解析结果怎么用?
python
result.root[0].name # RootModel:数组在 .root 里
result.model_dump() # 转 list[dict],方便打印/存库
result.model_dump_json() # 转 JSON 字符串
Field 常规用法
Field 必须从 pydantic 导入(不是 dataclasses.Field)。做两件事:
- 写给模型看 ------
description进入format_instructions - 写给程序看 ------ 类型、范围、默认值用于解析后校验
| 参数 | 用途 | 建议 |
|---|---|---|
description |
字段说明 → 进 Prompt | ⭐ 每个字段都写 |
default / default_factory |
缺字段时的默认值 | 可选字段时用 |
ge / le / min_length / max_length |
解析后硬校验 | 配合 description 一起写 |
python
name: str = Field(description="动物中文名称,不超过8个字", min_length=1, max_length=8)
age: int = Field(default=0, ge=0, le=150, description="年龄,0~150 整数")
对比 Json:Json 在 Prompt 里手写字段名;Pydantic 把说明写在 Field 里,不用维护两套文案。
接 chain
python
chain = prompt.partial(format_instructions=parser.get_format_instructions()) | llm | parser
result = chain.invoke({"city": "上海"}) # 按你的 prompt 变量调整
2.4 with_structured_output --- 生产更推荐
场景 :和 Pydantic 一样要结构化输出,但 不想手写 format_instructions。
python
from pydantic import BaseModel, Field, RootModel
# Animal / AnimalArray 定义同上一节,此处省略
llm_struct = llm.with_structured_output(AnimalArray)
result = llm_struct.invoke("用 JSON 数组描述三个动物,每项含名称、emoji 和年龄")
print(result.model_dump())
和 PydanticOutputParser 的对比:
| 维度 | PydanticOutputParser |
with_structured_output |
|---|---|---|
| 原理 | 模型输出文本 → 后解析 | 模型/API 按 schema 约束输出 |
| Prompt | 必须注入 {format_instructions} |
不用 |
| 典型写法 | parser.invoke(llm.invoke(prompt)) |
llm_struct.invoke(prompt) |
| chain | `prompt | llm |
| 适用 | 学习 Output 环、兼容弱 API | 生产环境优先 |
硅基等 OpenAI 兼容接口一般可用。若报 tool/schema 错误,试
method="json_mode",或退回PydanticOutputParser。
常见失败
| 现象 | 处理 |
|---|---|
忘了传 format_instructions |
检查 Prompt;或改用 with_structured_output |
| 字段缺失 / 类型错误 | 加强 Field(description=...);降低 temperature |
| Prompt 手写 JSON 又用了 Pydantic | 统一用 {format_instructions} 或改用 with_structured_output |
with_structured_output 报 schema 错误 |
method="json_mode" 或退回 Parser |
2.5 CommaSeparatedListOutputParser --- 逗号分隔列表
场景:Prompt 明确要求「用逗号分隔返回多个词」。
python
from langchain_core.output_parsers import CommaSeparatedListOutputParser
items = CommaSeparatedListOutputParser().invoke(llm.invoke(messages))
print(items) # ['苹果', '香蕉', '橙子']
适合标签、关键词;结构复杂时用 Json 或 Pydantic。
三、总结
3.1 选型决策
javascript
只要文字? → StrOutputParser ⭐ 默认
要 JSON / dict? → JsonOutputParser + Prompt 约束
要固定字段 + 校验? → 学习:PydanticOutputParser + Field
生产:with_structured_output ⭐ 推荐
逗号分隔列表? → CommaSeparatedListOutputParser
| 你的目标 | 用哪个 |
|---|---|
| 聊天、日志、纯文本 | StrOutputParser |
| 抽实体、对接 API JSON | JsonOutputParser |
| 结构化 + 校验(学习) | PydanticOutputParser |
| 结构化 + 校验(生产) | with_structured_output |
| 标签 / 关键词 | CommaSeparatedListOutputParser |
3.2 记住这些
python
模板 → llm.invoke → parser.invoke → str / dict / Model
模板 → llm.with_structured_output(...).invoke → Model(跳过 Parser)
新手路径:Str 跑通 → Json → Pydantic + Field → with_structured_output。