结构化输出解析
大型语言模型能够生成任意文本,但这也带来了问题:
- 输出格式不统一,难以解析
- 难以存储到关系数据库
- 下游处理困难
结构化输出可以将模型输出限制为特定格式(通常是 JSON),便于后续处理。
方式一:with_structured_output()
使用 Pydantic 模型定义输出结构,返回一个字典或 Pydantic 对象。
基本用法
from typing import List
from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI
# 1. 定义数据结构
class Person(BaseModel):
"""人物信息"""
name: str = Field(description="姓名")
age: int = Field(description="年龄")
hobbies: List[str] = Field(description="爱好列表")
# 2. 初始化模型并绑定结构化输出
llm = ChatOpenAI(model="gpt-4o", temperature=0)
structured_llm = llm.with_structured_output(Person)
# 3. 调用
result = structured_llm.invoke("提取信息:他叫张三,30岁,喜欢阅读和音乐。")
print(result.name) # 张三
print(result.age) # 30
print(result.hobbies) # ['阅读', '音乐']
print(type(result)) # <class '__main__.Person'>
组合提示词模板
# 提示词模板可以随意组合
from langchain_core.prompts import PromptTemplate
prompts = (
PromptTemplate.from_template("帮我生成一个关于{topic}的笑话。")
+ '要求:1、内容搞笑一点;'
+ '要求:2、输出的内容采用{language}'
)
chain = prompts | structured_llm
resp = chain.invoke({"topic": "猫", "language": "中文"})
print(resp)
print(resp.__dict__)
包含原始输出
# 返回原始响应 + 解析结果
structured_llm = llm.with_structured_output(Person, include_raw=True)
result = structured_llm.invoke("提取信息:他叫李四,25岁。")
# result 是字典
print(result["raw"]) # 原始 AIMessage
print(result["parsed"]) # 解析后的 Person 对象
print(result["parsing_error"]) # 解析错误(如果有)
工作原理
.with_structured_output() 内部会:
- 导入合适的输出解析器
- 将 Pydantic 模式格式化为模型所需的正确格式
- 返回一个 Runnable 对象,可用于 LCEL 链
方式二:JsonOutputParser
使用解析器将输出转为 JSON:
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 1. 定义数据结构
class WeatherInfo(BaseModel):
"""天气信息"""
city: str = Field(description="城市名称")
temperature: int = Field(description="温度(摄氏度)")
condition: str = Field(description="天气状况")
# 2. 创建解析器
json_parser = JsonOutputParser(pydantic_object=WeatherInfo)
# 3. 创建提示词(关键:必须包含 "json" 关键词)
prompt = ChatPromptTemplate.from_template(
"""请从以下信息提取天气数据,以 JSON 格式返回。
信息:{weather_info}
必须返回以下格式:{{"city": "城市", "temperature": 数字, "condition": "状况"}}
"""
)
# 4. 构建链
chain = prompt | model | json_parser
# 5. 调用
result = chain.invoke({"weather_info": "北京今天晴,温度25度"})
print(result) # {'city': '北京', 'temperature': 25, 'condition': '晴'}