05 - 输出解析(Parsers):结构化输出
约 1064 字大约 4 分钟
LangChainOutput Parsers结构化输出
2026-03-08
第 05 课:输出解析(Parsers)- 结构化输出
课程目标
通过本节课,你将学到:
- ✅ 为什么需要输出解析
- ✅ 常用 Parser 类型
- ✅ Pydantic 数据验证
- ✅ 自定义 Parser
一、为什么需要输出解析?
1.1 问题场景
LLM 默认输出是字符串,但我们需要结构化数据:
# LLM 输出(字符串)
response = "张三,25岁,Python工程师"
# 我们需要(结构化数据)
{
"name": "张三",
"age": 25,
"job": "Python工程师"
}1.2 解决方案
使用 Output Parsers 将 LLM 输出转换为结构化数据:
from langchain.output_parsers import PydanticOutputParser
from pydantic import BaseModel
# 定义数据模型
class Person(BaseModel):
name: str
age: int
job: str
# 创建解析器
parser = PydanticOutputParser(pydantic_object=Person)
# 解析输出
data = parser.parse(response)
print(data.name) # "张三"二、常用 Parser 类型
2.1 PydanticOutputParser(推荐)
特点:类型安全、自动验证
from langchain.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field
# 定义模型
class CodeReview(BaseModel):
rating: int = Field(description="代码质量评分(1-10)")
issues: list[str] = Field(description="发现的问题列表")
suggestions: list[str] = Field(description="改进建议")
# 创建解析器
parser = PydanticOutputParser(pydantic_object=CodeReview)
# 获取格式说明
format_instructions = parser.get_format_instructions()
print(format_instructions)使用示例:
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
# 初始化
llm = ChatOpenAI(model="gpt-3.5-turbo")
parser = PydanticOutputParser(pydantic_object=CodeReview)
# 创建提示词
template = ChatPromptTemplate.from_messages([
("system", "你是一个代码审查专家。"),
("human", "{code}\n\n{format_instructions}")
])
# 调用
messages = template.format_messages(
code="def add(a, b): return a + b",
format_instructions=parser.get_format_instructions()
)
response = llm.invoke(messages)
result = parser.parse(response.content)
print(f"评分: {result.rating}")
print(f"问题: {result.issues}")2.2 JsonOutputParser
特点:简单灵活,不要求 Pydantic
from langchain.output_parsers import JsonOutputParser
parser = JsonOutputParser()
# 获取格式说明
format_instructions = parser.get_format_instructions()
# 解析输出
json_data = parser.parse('{"name": "张三", "age": 25}')
print(json_data["name"]) # "张三"2.3 ListParser
特点:解析列表格式
from langchain.output_parsers import CommaSeparatedListOutputParser
parser = CommaSeparatedListOutputParser()
# 解析
items = parser.parse("苹果, 香蕉, 橘子")
print(items) # ["苹果", "香蕉", "橘子"]2.4 DatetimeParser
特点:解析日期时间
from langchain.output_parsers import DatetimeOutputParser
parser = DatetimeOutputParser()
# 解析
date = parser.parse("2024-01-15 14:30:00")
print(date) # datetime对象三、Pydantic 数据验证
3.1 基础用法
from pydantic import BaseModel, Field, validator
class User(BaseModel):
name: str = Field(description="用户名")
age: int = Field(ge=0, le=150, description="年龄(0-150)")
email: str = Field(description="邮箱地址")
@validator("email")
def validate_email(cls, v):
if "@" not in v:
raise ValueError("邮箱格式不正确")
return v
# 创建实例(自动验证)
user = User(name="张三", age=25, email="zhangsan@example.com")
print(user.name) # "张三"
# 错误示例
try:
user = User(name="李四", age=200, email="invalid")
except ValueError as e:
print(e) # 验证失败3.2 嵌套模型
from typing import List
class Address(BaseModel):
city: str
street: str
class Person(BaseModel):
name: str
age: int
address: Address
skills: List[str]
# 使用
parser = PydanticOutputParser(pydantic_object=Person)四、自定义 Parser
4.1 继承 BaseOutputParser
from langchain.schema import BaseOutputParser
class CustomParser(BaseOutputParser):
def parse(self, output: str) -> dict:
"""自定义解析逻辑"""
lines = output.strip().split("\n")
result = {}
for line in lines:
if ":" in line:
key, value = line.split(":", 1)
result[key.strip()] = value.strip()
return result
@property
def _type(self) -> str:
return "custom_parser"
# 使用
parser = CustomParser()
data = parser.parse("姓名: 张三\n年龄: 25")
print(data) # {"姓名": "张三", "年龄": "25"}4.2 错误处理
from langchain.output_parsers import OutputFixingParser
# 创建修复解析器
parser = PydanticOutputParser(pydantic_object=User)
fixing_parser = OutputFixingParser.from_llm(
parser=parser,
llm=ChatOpenAI()
)
# 自动修复格式错误
try:
result = fixing_parser.parse("invalid json")
except Exception as e:
print(f"修复失败: {e}")五、实战案例
5.1 情感分析
from langchain.output_parsers import PydanticOutputParser
from pydantic import BaseModel
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
# 定义模型
class Sentiment(BaseModel):
sentiment: str # positive/negative/neutral
confidence: float # 0-1
keywords: list[str]
# 初始化
llm = ChatOpenAI(model="gpt-3.5-turbo")
parser = PydanticOutputParser(pydantic_object=Sentiment)
# 创建提示词
template = ChatPromptTemplate.from_messages([
("system", "你是一个情感分析专家。"),
("human", "{text}\n\n{format_instructions}")
])
# 分析
messages = template.format_messages(
text="今天天气真好,心情特别愉快!",
format_instructions=parser.get_format_instructions()
)
response = llm.invoke(messages)
result = parser.parse(response.content)
print(f"情感: {result.sentiment}") # positive
print(f"置信度: {result.confidence}") # 0.95
print(f"关键词: {result.keywords}") # ["好", "愉快"]六、本课小结
核心要点
- 为什么需要解析:将字符串转为结构化数据
- 常用 Parser:
- PydanticOutputParser(推荐)
- JsonOutputParser
- ListParser
- Pydantic 验证:类型安全、自动验证
- 自定义 Parser:继承 BaseOutputParser
下节预告
下一课,我们将学习 链(Chains),包括:
- LCEL(LangChain Expression Language)
- 链式调用
- 复杂流程编排
🎯 课后练习
- Pydantic 模型:定义一个"书籍信息"模型,包含书名、作者、出版年份、标签。
- 解析器:使用 PydanticOutputParser 解析书籍信息。
- 错误修复:尝试使用 OutputFixingParser 修复格式错误的输出。