在 LangChain 的开发流程中,模型调用结果解析(Output Parsers) 是至关重要的一环。
大模型生成的原始输出通常是长篇文本或特定的对象(如 AIMessage),但在实际业务中,我们往往需要结构化的数据(如 JSON、列表或特定的 Python 对象),以便程序进一步处理。
以下是关于 LangChain 结果解析的详细介绍及代码示例。
一、 为什么需要结果解析器?
- 格式化数据 :将模型生成的非结构化文本转为结构化格式(如从一段话中提取出
{"name": "张三", "age": 25})。 - 去除冗余:模型有时会输出"好的,这是你要的结果:"等废话,解析器可以直接提取核心内容。
- 自动提示(Instructions):解析器不仅负责"解析",还能自动在 Prompt 中生成"请按以下格式输出..."的指令。
二、 常用解析器类型及代码示例
1. 字符串解析器 (StrOutputParser)
最简单的解析器,用于从 AIMessage 对象中直接提取出文本字符串。
python
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
model = ChatOpenAI(model="gpt-3.5-turbo")
# 未使用解析器:返回的是 AIMessage 对象
# 使用解析器:返回的是纯字符串
chain = model | StrOutputParser()
result = chain.invoke("讲个冷笑话")
print(result) # 输出:为什么企鹅只有肚皮是白的?因为手短洗不到后背。
2. 列表解析器 (CommaSeparatedListOutputParser)
用于将逗号分隔的文本解析为 Python 列表。
python
from langchain_core.output_parsers import CommaSeparatedListOutputParser
from langchain_core.prompts import PromptTemplate
output_parser = CommaSeparatedListOutputParser()
# 获取格式化指令
format_instructions = output_parser.get_format_instructions()
prompt = PromptTemplate(
template="列出5种{subject}.\n{format_instructions}",
input_variables=["subject"],
partial_variables={"format_instructions": format_instructions}
)
chain = prompt | model | output_parser
print(chain.invoke({"subject": "常见的水果"}))
# 输出: ['苹果', '香蕉', '橘子', '西瓜', '葡萄']
3. 结构化 JSON 解析器 (PydanticOutputParser) ------ 最常用且最强大
通过定义一个 Pydantic 类(数据模型),强制要求 AI 返回符合该模型结构的 JSON 数据。
python
from typing import List
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_core.output_parsers import PydanticOutputParser
# 1. 定义期望的数据结构
class Joke(BaseModel):
setup: str = Field(description="笑话的铺垫")
punchline: str = Field(description="笑话的笑点")
tags: List[str] = Field(description="笑话的标签,如'冷笑话'、'幽默'等")
# 2. 初始化解析器
parser = PydanticOutputParser(pydantic_object=Joke)
# 3. 将解析指令注入 Prompt
prompt = PromptTemplate(
template="回答用户的问题。\n{format_instructions}\n{query}",
input_variables=["query"],
partial_variables={"format_instructions": parser.get_format_instructions()}
)
# 4. 构建链
chain = prompt | model | parser
# 5. 调用
result = chain.invoke({"query": "给我讲一个关于程序员的笑话"})
print(f"铺垫: {result.setup}")
print(f"笑点: {result.punchline}")
print(f"标签: {result.tags}")
三、 结果解析的核心原理
LangChain 的解析过程通常分为三个阶段:
- 指令注入 (Instructions) :通过
parser.get_format_instructions(),LangChain 会自动生成一段复杂的提示词(例如:"Your response must be a JSON object that conforms to the schema below..."),并拼接到你的 Prompt 里。 - 模型生成:模型读取到格式要求,尽量输出符合规范的 JSON 文本。
- 转换与验证 (Parsing):解析器接收到字符串,尝试将其转化为 Python 对象。如果结果不符合 Pydantic 定义的校验规则,解析器会抛出异常。
四、 进阶:如何处理解析错误?
大模型并不总是 100% 遵守格式。如果解析失败(比如模型输出了错误的 JSON),LangChain 提供了重试机制:
OutputFixingParser:当第一个解析器失败时,它会将错误信息和原始输出发回给 LLM,让 LLM 自己修复格式。RetryOutputParser:更强大的修复工具,将 Prompt 和错误信息同时发回模型重试。
python
from langchain.output_parsers import OutputFixingParser
# 如果上面的 parser 失败了,使用 OutputFixingParser 自动修复
fixing_parser = OutputFixingParser.from_llm(parser=parser, llm=model)
fixed_result = fixing_parser.parse("这里是模型错误的输出文本")
五、 总结
| 解析器名称 | 适用场景 | 输出类型 |
|---|---|---|
| StrOutputParser | 提取纯文本,去掉对象封装 | str |
| JsonOutputParser | 简单的 JSON 提取,不强制校验 | dict |
| PydanticOutputParser | 严格的结构化数据提取与校验 | Pydantic Object |
| ListOutputParser | 处理列表、逗号分隔数据 | list |
建议 :在生产环境中,尽量使用 PydanticOutputParser 。它不仅能帮你解析数据,还能利用 Pydantic 的类型检查确保数据的可靠性,配合 LCEL (|) 管道语法,可以让你的 AI 应用逻辑非常清晰。