在LangChain中一些模型提供者通过其 API 原生支持结构化输出(例如 OpenAI、Grok、Gemini)。这是最可靠的方法。当对于不支持原生结构化输出的模型,LangChain 使用工具调用来实现相同的结果。这种方法适用于所有支持工具调用的模型,而大多数现代模型都支持工具调用。下面是LangChain所提供的两种结构化输出的核心策略对比:
| 策略 | 适用场景 | 原理 |
|---|---|---|
ProviderStrategy |
模型原生支持结构化输出(如 OpenAI GPT-4o/GPT-5、Grok) | 利用模型 API 的 response_format={ "type": "json_schema" } 等机制,由模型提供商强制约束输出格式 |
ToolStrategy |
其他支持工具调用的模型(如 Claude、Llama 3 via API) | 将你的 schema 包装成一个"虚拟工具",模型通过 tool call 返回结构化参数 |
一、with_structured_output方法让模型能够结构化输出
python
from langchain.chat_models import init_chat_model
# 初始化一个支持结构化输出的大语言模型(此处使用 DeepSeek)
# 注意:DeepSeek 官方 API 是否原生支持结构化输出需确认;
# 若不支持,LangChain 会自动回退到 ToolStrategy(工具调用)方式实现结构化输出。
model = init_chat_model("deepseek-chat")
# 自定义结构化输出的数据模式(Schema)
# 使用 Pydantic BaseModel 定义期望的输出结构,字段带描述可显著提升模型理解准确性
from pydantic import BaseModel, Field
class MovieInput(BaseModel):
"""从文本中提取的电影信息结构"""
name: str = Field(..., description="电影的名字")
publish: str = Field(..., description="电影上映时间,格式如 '2009' 或 '2009年'")
director: str = Field(..., description="电影的导演姓名")
# 使用 .with_structured_output() 方法将原始模型包装为结构化输出模型
# 该方法会根据模型能力自动选择最佳实现策略:
# - 若模型原生支持 JSON Schema(如 GPT-4o),则使用 ProviderStrategy;
# - 否则,通过工具调用(Tool Calling)模拟结构化输出(ToolStrategy)。
# 包装后的 structured_model.invoke() 将直接返回 MovieInput 类型的实例,而非字符串。
structured_model = model.with_structured_output(MovieInput)
# 输入一段包含电影信息的非结构化文本
text = "《阿凡达》(Avatar, 2009)导演:詹姆斯·卡梅隆。在不远的未来,地球资源枯竭,人类将目光投向4.4光年外的潘多拉星球。一颗蕴藏稀有矿产"难得素"的神秘世界。为开采资源,人类启动"阿凡达计划",通过基因技术创造出可由人类意识操控的纳美人混血躯体。"
# 调用结构化模型,自动从 text 中提取并返回符合 MovieInput 模式的对象
result = structured_model.invoke(text)
# result 是一个 MovieInput 实例,可直接访问属性或转为 JSON
print(result)
# 示例输出:MovieInput(name='阿凡达', publish='2009', director='詹姆斯·卡梅隆')
对于 DeepSeek ,目前其开源模型(如通过 vLLM 部署)通常不原生支持 JSON Schema 输出 ,因此 LangChain 会采用 ToolStrategy ------ 这意味着模型实际是通过"调用一个虚拟工具"来返回结构化参数,效果依然可靠。
二、response_format参数直接让Agent具备结构化输出能力
在 LangChain 1.0 中,最直接、最推荐的方式 让 Agent 具备结构化输出能力,就是在调用 create_agent 时通过 response_format 参数指定你期望的输出结构。
python
# 导入核心模块
from langchain.agents import create_agent
from pydantic import BaseModel, Field
# 定义你期望的结构化输出格式
# 使用 Pydantic BaseModel 是最佳实践:支持类型校验、字段描述、嵌套等
class MovieInfo(BaseModel):
"""从文本中提取的电影基本信息"""
name: str = Field(..., description="电影的中文或英文名称")
publish_year: str = Field(..., description="电影上映年份,例如 '2009'")
director: str = Field(..., description="导演全名")
# 创建具备结构化输出能力的智能体
# 关键点:在 create_agent 中直接传入 response_format=MovieInfo
# LangChain 会根据模型能力自动选择 ProviderStrategy 或 ToolStrategy
agent = create_agent(
model="deepseek-chat", # 使用 DeepSeek 模型(不支持原生 JSON Schema)
response_format=MovieInfo # ← 直接声明期望的输出结构
# 注意:无需手动导入或指定 ToolStrategy,LangChain 自动处理!
)
# 准备输入文本
text = "《阿凡达》(Avatar, 2009)导演:詹姆斯·卡梅隆。故事发生在潘多拉星球......"
# 调用智能体
# 输入必须是标准消息格式:{"messages": [{"role": "user", "content": "..."}]}
result = agent.invoke({
"messages": [{"role": "user", "content": text}]
})
# 提取结构化结果
# 所有结构化输出统一存放在 result["structured_response"] 中
movie: MovieInfo = result["structured_response"]
# 打印结果(movie 是 MovieInfo 实例,支持属性访问)
print(f"片名: {movie.name}")
print(f"上映年份: {movie.publish_year}")
print(f"导演: {movie.director}")
# 也可转为字典或 JSON
print(movie.model_dump()) # {'name': '阿凡达', 'publish_year': '2009', 'director': '詹姆斯·卡梅隆'}
当你在 create_agent(..., response_format=YourSchema) 中传入一个 Pydantic 模型(或其它 schema 类型) 时:
LangChain 会自动分析所用模型的能力:
- 如果模型原生支持结构化输出 ,则使用 ProviderStrategy;
- 否则,自动降级为 ToolStrategy。
最终,Agent 的执行结果中会包含一个 structured_response 字段,其值就是你定义的结构化对象实例。
三、Provider Strategy
利用模型原生支持的结构化输出能力,通过 API 层面直接约束模型输出格式(如 JSON Schema),由模型提供商(Provider)保证输出合规。
(1)自动触发使用
直接在实例化创建Agent的时候,传入参数response_format=MovieInput
python
from langchain.chat_models import init_chat_model
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
model = init_chat_model("openai:gpt-4o")
structured = model.with_structured_output(User) # ← 自动使用 ProviderStrategy
四、Tool Strategy
将你的数据结构伪装成一个工具 ,利用模型的 工具调用能力来返回结构化参数。工作原理:
- LangChain 将你的 Pydantic 模型转换为一个虚拟工具(例如叫
return_structured_data)。 - 请求时附带该工具的定义(含参数 schema)。
- 模型如果支持工具调用,会主动调用这个工具,并将提取的数据作为工具参数传回。
- LangChain 拦截该工具调用,提取参数并验证,最终返回结构化对象。
(1)显式的去调用
实例化ToolStrategy并传入你自定义的输出格式,就被称为显示的使用。
python
# 导入 ToolStrategy:用于在模型不支持原生结构化输出时,
# 通过"工具调用"(Tool Calling)机制模拟结构化输出行为。
from langchain.agents.structured_output import ToolStrategy
# 创建一个具备结构化输出能力的智能体(Agent)
# - model="deepseek-chat":指定使用 DeepSeek 的聊天模型
# (注意:DeepSeek 目前不支持 OpenAI 风格的原生 JSON Schema 输出,
# 因此必须通过 ToolStrategy 实现结构化提取)
# - response_format=ToolStrategy(MovieInput):
# 显式声明期望的输出结构为 MovieInput 类型,
# 并强制使用工具调用策略来引导模型返回符合该 schema 的参数。
agent = create_agent(
model="deepseek-chat",
response_format=ToolStrategy(MovieInput)
)
# 调用智能体,传入用户输入消息
# 格式遵循标准聊天消息结构:列表 of {"role": "...", "content": "..."}
# 此处将待解析的电影文本作为用户消息传入
result = agent.invoke({
"messages": [{"role": " user ", "content": text}]
})
# 从结果中提取结构化数据
# LangChain 将模型通过工具调用返回的参数自动验证并转换为 MovieInput 实例,
# 存放在 result["structured_response"] 字段中。
# 该对象可直接访问属性(如 .name, .publish),也可调用 .model_dump() 转为字典。
print(result["structured_response"])