LangChain Output Parser 输出解析器完全指南
目录
-
[什么是 Output Parser](#什么是 Output Parser)
-
[为什么需要 Output Parser](#为什么需要 Output Parser)
-
[StrOutputParser 字符串解析器](#StrOutputParser 字符串解析器)
-
[JsonOutputParser JSON解析器](#JsonOutputParser JSON解析器)
-
[PydanticOutputParser Pydantic解析器](#PydanticOutputParser Pydantic解析器)
-
[with_structured_output 结构化输出](#with_structured_output 结构化输出)
-
[Annotated 类型注解](#Annotated 类型注解)
-
[get_format_instructions 格式化指令](#get_format_instructions 格式化指令)
什么是 Output Parser
Output Parser 是 LangChain 中用于将大模型自由文本输出转换为结构化数据的工具。
问题
大模型输出的是自由文本:
"好的,我给你返回一个JSON:{"name": "华为", "price": 9999}"
但程序需要的是结构化数据:
{"name": "华为", "price": 9999} # dict 类型,可以直接使用
解决方案
大模型自由文本 → Output Parser → 结构化数据
Output Parser 就像一个"翻译器",把 AI 说的话转成程序能理解的数据格式。
为什么需要 Output Parser
场景对比
| 场景 | 没有 Parser | 有 Parser |
|---|---|---|
| 获取用户名 | "用户名为:张三" |
{"name": "张三"} |
| 获取商品信息 | "商品:电脑,价格:5999元" |
{"product": "电脑", "price": 5999} |
| 获取列表 | "1. 苹果 2. 香蕉 3. 橙子" |
["苹果", "香蕉", "橙子"] |
优势
-
程序化处理 :直接用
.name、.price访问数据 -
减少错误:不用手动解析字符串
-
类型安全:Pydantic 等支持数据校验
-
API对接:直接返回 JSON 给前端或 API
StrOutputParser 字符串解析器
什么是 StrOutputParser
最简单、最基础的输出解析器。从结果中提取 content 字段转换为字符串输出。
from langchain_core.output_parsers import StrOutputParser
parser = StrOutputParser()
result = parser.invoke(ai_message)
# result 现在是字符串类型
工作原理
AIMessage 对象
├── content: "这是AI的回答内容"
├── additional_kwargs: {}
└── ...
↓ StrOutputParser.invoke()
"这是AI的回答内容" # 字符串
完整示例
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain.chat_models import init_chat_model
import os
from dotenv import load_dotenv
load_dotenv(encoding='utf-8')
# 创建提示模板
chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是一个{role},请简短回答我的问题"),
("human", "请回答:{question}")
])
# 初始化模型
model = init_chat_model(
model="qwen-plus",
model_provider="openai",
api_key=os.getenv("aliQwen-api"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
# 调用模型
prompt = chat_prompt.invoke({"role": "AI助手", "question": "什么是LangChain?"})
result = model.invoke(prompt)
print(f"原始输出类型: {type(result)}") # AIMessage
print(f"原始输出: {result}")
# 使用 StrOutputParser 解析
parser = StrOutputParser()
response = parser.invoke(result)
print(f"解析后类型: {type(response)}") # str
print(f"解析后内容: {response}")
使用场景
-
简单问答,直接获取文本回答
-
不需要结构化数据时
-
作为其他 Parser 的基础
JsonOutputParser JSON解析器
什么是 JsonOutputParser
将大模型的自由文本输出转换为结构化 JSON 数据(dict 类型)。
基本用法
from langchain_core.output_parsers import JsonOutputParser
parser = JsonOutputParser()
result = parser.invoke(ai_message)
# result 现在是 dict 类型
方法1:提示词指定格式
在提示词中直接指定返回 JSON 格式:
chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是一个{role},请简短回答我的问题,结果返回json格式,q字段表示问题,a字段表示答案。"),
("human", "请回答:{question}")
])
prompt = chat_prompt.invoke({"role": "AI助手", "question": "什么是LangChain?"})
result = model.invoke(prompt)
parser = JsonOutputParser()
response = parser.invoke(result)
print(response) # {'q': '什么是LangChain?', 'a': 'LangChain是一个...'}
方法2:使用 Pydantic 模型 + get_format_instructions(推荐)
from langchain_core.output_parsers import JsonOutputParser
from pydantic import BaseModel, Field
# 定义数据结构
class Person(BaseModel):
time: str = Field(description="时间")
person: str = Field(description="人物")
event: str = Field(description="事件")
# 创建解析器
parser = JsonOutputParser(pydantic_object=Person)
# 获取格式化指令(让模型知道如何输出)
format_instructions = parser.get_format_instructions()
print(format_instructions)
# The output format must be a JSON object...
# {"time": "...", "person": "...", "event": "..."}
# 在提示词中使用
chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是一个AI助手,你只能输出结构化JSON数据。"),
("human", "请生成一个关于{topic}的新闻。{format_instructions}")
])
prompt = chat_prompt.format_messages(
topic="小米SU7发布",
format_instructions=format_instructions
)
result = model.invoke(prompt)
response = parser.invoke(result)
print(response) # {'time': '2024年', 'person': '雷军', 'event': '发布小米SU7...'}
get_format_instructions 的作用
这个方法生成格式说明,告诉大模型应该如何输出 JSON:
The output format must be a JSON object...
Parrot must adhere to the following schema:
{"time": "<time>", "person": "<person>", "event": "<event>"}
模型会根据这个指令来格式化输出,确保能被正确解析。
PydanticOutputParser Pydantic解析器
什么是 PydanticOutputParser
基于 Pydantic 模型的结构化输出解析器,功能最强,支持:
-
类型校验
-
数据转换
-
复杂嵌套结构
-
运行时验证
Pydantic 模型基础
from pydantic import BaseModel, Field
class Product(BaseModel):
name: str = Field(description="产品名称")
price: float = Field(description="产品价格")
description: str = Field(description="产品描述")
完整示例
from langchain_core.output_parsers import PydanticOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain.chat_models import init_chat_model
from pydantic import BaseModel, Field, field_validator
import os
from dotenv import load_dotenv
load_dotenv(encoding='utf-8')
# 定义数据结构
class Product(BaseModel):
name: str = Field(description="产品名称")
category: str = Field(description="产品类别")
description: str = Field(description="产品简介")
@field_validator("description")
def validate_description(cls, value):
"""验证产品简介长度必须 >= 10"""
if len(value) < 10:
raise ValueError('产品简介长度必须大于等于10')
return value
# 创建解析器
parser = PydanticOutputParser(pydantic_object=Product)
# 获取格式化指令
format_instructions = parser.get_format_instructions()
# 创建提示模板
prompt_template = ChatPromptTemplate.from_messages([
("system", "你是一个AI助手,你只能输出结构化的json数据\n{format_instructions}"),
("human", "请你输出标题为:{topic}的新闻内容")
])
# 格式化提示词
prompt = prompt_template.format_messages(
topic="华为Mate X7",
format_instructions=format_instructions
)
# 调用模型
model = init_chat_model(
model="qwen-plus",
model_provider="openai",
api_key=os.getenv("aliQwen-api"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
result = model.invoke(prompt)
# 解析结果
response = parser.invoke(result)
# 访问结构化数据
print(response.name) # 产品名称
print(response.category) # 产品类别
print(response.description) # 产品描述
Pydantic 字段验证器
from pydantic import BaseModel, Field, field_validator
class Product(BaseModel):
name: str = Field(description="产品名称")
price: float = Field(description="价格,必须大于0")
description: str = Field(description="描述,长度10-100")
@field_validator("price")
def validate_price(cls, value):
if value <= 0:
raise ValueError("价格必须大于0")
return value
@field_validator("description")
def validate_description(cls, value):
if len(value) < 10 or len(value) > 100:
raise ValueError("描述长度必须在10-100之间")
return value
JsonOutputParser vs PydanticOutputParser
| 特性 | JsonOutputParser | PydanticOutputParser |
|---|---|---|
| 返回类型 | dict |
Pydantic Model 实例 |
| 类型校验 | 无 | 有(运行时验证) |
| 嵌套结构 | 支持 | 支持(更强大) |
| 自定义验证 | 不支持 | 支持(@field_validator) |
| 使用难度 | 简单 | 中等 |
| 推荐场景 | 简单结构 | 复杂结构、强类型需求 |
with_structured_output 结构化输出
什么是 with_structured_output
直接让模型输出结构化数据,不需要 Parser,更简洁:
# 使用 with_structured_output
llm_with_structured_output = llm.with_structured_output(Schema)
result = llm_with_structured_output.invoke(messages)
TypedDict 版本
from typing import TypedDict, Annotated
from langchain.chat_models import init_chat_model
import os
from dotenv import load_dotenv
load_dotenv(encoding='utf-8')
llm = init_chat_model(
model="qwen-plus",
model_provider="openai",
api_key=os.getenv("aliQwen-api"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
# 定义数据结构
class Animal(TypedDict):
animal: Annotated[str, "动物名称"]
emoji: Annotated[str, "动物表情"]
class AnimalList(TypedDict):
animals: Annotated[list[Animal], "动物与表情列表"]
# 使用 with_structured_output
llm_with_structured = llm.with_structured_output(AnimalList)
messages = [{"role": "user", "content": "任意生成三种动物,以及他们的emoji表情"}]
result = llm_with_structured.invoke(messages)
print(result)
# {'animals': [{'animal': '猫', 'emoji': '🐱'}, {'animal': '狗', 'emoji': '🐶'}, {'animal': '兔子', 'emoji': '🐰'}]}
Pydantic 版本
from pydantic import BaseModel
from typing import List
class Animal(BaseModel):
animal: str
emoji: str
class AnimalList(BaseModel):
animals: List[Animal]
llm_with_structured = llm.with_structured_output(AnimalList)
result = llm_with_structured.invoke(messages)
print(result.animals[0].animal) # 猫
对比
| 方式 | 优点 | 缺点 |
|---|---|---|
| with_structured_output | 代码简洁,不需要Parser | 只能用于结构化输出 |
| OutputParser | 灵活,可组合 | 代码较多 |
Annotated 类型注解
什么是 Annotated
Annotated[T, metadata] 是 Python 的类型注解扩展,用于给类型添加元数据(描述信息)。
from typing import Annotated
Age = Annotated[int, "年龄,范围0-150"]
-
int- 基础类型 -
"年龄,范围0-150"- 元数据/描述
Annotated + Field
from typing import Annotated
from pydantic import Field
# 用 Annotated 结合 Field 设置范围约束
Age = Annotated[int, Field(ge=0, le=150, description="年龄,范围0-150")]
class Person(BaseModel):
name: str
age: Age
Annotated 在 LangChain 中的作用
在 with_structured_output 和 TypedDict 中,Annotated 用于给模型提供字段描述:
class Animal(TypedDict):
animal: Annotated[str, "动物名称"] # 告诉模型这个字段的含义
emoji: Annotated[str, "动物表情"] # 描述越详细,模型理解越准确
Annotated vs 普通类型
# 普通类型 - 无描述
class Animal(TypedDict):
animal: str
emoji: str
# Annotated - 有描述
class Animal(TypedDict):
animal: Annotated[str, "动物名称"]
emoji: Annotated[str, "动物表情"]
描述信息会帮助模型更准确地理解需要输出什么内容。
注意事项
Annotated 本身不具备运行时校验能力
from typing import Annotated, TypedDict
Age = Annotated[int, "年龄,范围0-150"]
class Person(TypedDict):
name: str
age: Age
# 这不会报错!Annotated 只是描述,Python 不会校验范围
p = Person(name="z3", age=188)
如果需要运行时校验,必须使用 Pydantic:
from pydantic import BaseModel, Field, ValidationError
from typing import Annotated
# Pydantic + Field 才能真正校验
Age = Annotated[int, Field(ge=0, le=150, description="年龄,范围0-150")]
class Person(BaseModel):
name: str
age: Age
try:
p = Person(name="z3", age=188) # 会报错!
except ValidationError as e:
print("数据校验失败:", e)
get_format_instructions 格式化指令
什么是格式化指令
告诉大模型应该如何格式化输出的指令字符串。
parser = JsonOutputParser(pydantic_object=Person)
format_instructions = parser.get_format_instructions()
输出示例
The output format must conform to the following schema:
{"name": "<name>", "age": "<age>"}
Parrot must adhere to the following strict JSON format and return ONLY the JSON object.
在提示词中使用
chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是一个AI助手,你只能输出JSON格式。"),
("human", "请生成用户信息:{format_instructions}")
])
prompt = chat_prompt.format_messages(
format_instructions=format_instructions
)
工作流程
1. 定义 Pydantic 模型
↓
2. 创建 Parser,传入模型
↓
3. get_format_instructions() 生成格式化指令
↓
4. 将指令嵌入提示词
↓
5. 模型根据指令输出 JSON
↓
6. Parser 解析 JSON 为程序数据
总结
Output Parser 分类
| Parser | 返回类型 | 特点 | 使用场景 |
|---|---|---|---|
| StrOutputParser | str |
最简单 | 纯文本提取 |
| JsonOutputParser | dict |
JSON转换 | 简单JSON结构 |
| PydanticOutputParser | Model |
强类型校验 | 复杂结构验证 |
选择指南
简单文本输出 → StrOutputParser
JSON结构(简单) → JsonOutputParser
JSON结构(复杂/需验证) → PydanticOutputParser
不想用Parser → with_structured_output
完整调用链
PromptTemplate
↓ format_messages()
Messages
↓ model.invoke()
AIMessage
↓ parser.invoke()
结构化数据(dict / Pydantic Model)