LangChain 1.0 入门(八):结构化输出
前言
在大模型工程化落地过程中,自由文本输出是最大的工程痛点。自然语言回答灵活、拟人,但无法被程序直接解析、无法入库、无法对接接口、无法自动化流程。
LangChain 1.0 彻底重构了结构化输出体系,废弃了旧版本繁琐的解析器拼接写法,统一以 with_structured_output 为核心,搭配 Pydantic 强数据校验,支持普通模型、复杂嵌套结构、智能体 Agent、标准 JSON 解析等全场景能力。
本文为全新重写完整版,所有代码统一采用 python-dotenv + ChatOpenAI 标准加载方式,兼容 OpenAI、DeepSeek、通义千问、vLLM 本地私有化部署等所有兼容接口,所有案例可直接复制运行,适配生产环境。
一、前置环境配置(全文统一标准)
1.1 依赖安装
pip install langchain langchain-openai pydantic python-dotenv
1.2 环境变量文件 .env(生产通用)
项目根目录新建 .env 文件,统一管理模型参数,避免硬编码,适配多环境切换:
# 模型配置
BASIC_MODEL=gpt-4o-mini
API_KEY=sk-xxxxxx
BASE_URL=https://api.openai.com/v1
# 本地vLLM/私有化部署可替换为
# BASE_URL=http://127.0.0.1:8000/v1
# API_KEY=dummy
1.3 全局统一模型加载代码(全文通用)
所有案例统一使用这套模型初始化逻辑,保证项目代码风格统一、易于维护迁移:
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
# 加载环境变量
load_dotenv()
# 初始化大模型(兼容所有OpenAI兼容接口)
llm = ChatOpenAI(
model=os.getenv("BASIC_MODEL"),
api_key=os.getenv("API_KEY"),
base_url=os.getenv("BASE_URL"),
temperature=0 # 结构化输出必须置0,保证输出稳定
)
核心规范:结构化输出场景强制 temperature=0,消除模型随机性,避免格式错乱、字段缺失、数据抖动问题。
二、结构化输出核心原理与两大底层策略
2.1 核心价值
让大模型从「自由聊天」变成可编程、可校验、可入库、可自动化的工业级输出,彻底替代正则匹配、字符串截取等脏解析逻辑。
2.2 底层双策略(LangChain 1.0 核心优化)
-
ToolStrategy(通用兜底策略):兼容所有大小模型,通过工具调用格式约束强制结构化输出,兼容性100%,速度略低。
-
ProviderStrategy(厂商原生策略·推荐):调用模型原生JSON Schema能力,由模型底层强制格式合规,精度、速度、稳定性最优,适配 GPT 系列、DeepSeek、通义千问新版模型。
三、核心API:with_structured_output 完整详解
with_structured_output 是 LangChain 1.0 官方唯一主推的结构化API,统一替代所有旧式解析器组合写法,支持自动策略适配、自动重试、数据校验、原始日志留存。
3.1 API参数说明
-
schema:必填,Pydantic模型/JSON Schema字典,定义输出字段、类型、描述、校验规则;
-
method:可选,手动指定
tool_calling/json_schema,默认自动适配最优策略; -
include_raw:是否返回模型原始输出,调试必备;
-
strict:严格模式,强制字段完全匹配,禁止多余、缺失字段,生产推荐开启。
3.2 基础实战:单层实体信息抽取
实现人物信息结构化抽取,缺失字段自动填充空值,输出标准化实体对象:
from typing import List
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
load_dotenv()
llm = ChatOpenAI(
model=os.getenv("BASIC_MODEL"),
api_key=os.getenv("API_KEY"),
base_url=os.getenv("BASE_URL"),
temperature=0
)
# 1. 定义结构化数据模型
class Person(BaseModel):
"""青年用户基础信息实体"""
name: str = Field(description="用户姓名")
age: int = Field(description="用户年龄")
high: int = Field(description="用户身高(cm)")
hobbies: List[str] = Field(description="用户日常兴趣爱好列表")
# 2. 绑定结构化输出规则
structured_llm = llm.with_structured_output(Person)
# 3. 全新与时俱进提示词+现代化案例
prompt = """请严格按照要求抽取用户结构化信息,严格匹配指定字段:
1. 需要抽取的字段:姓名、年龄、身高、爱好;
2. 无对应信息的字段统一填充 0 或空数组,禁止省略字段;
3. 严格匹配字段类型:年龄、身高为数字,爱好为字符串数组。
待解析信息:小林今年24岁,身高178cm,日常喜欢短视频剪辑、AI绘画、户外露营和飞盘运动。
"""
result = structured_llm.invoke(prompt)
# 4. 直接取值,无需手动解析
print(f"姓名:{result.name}")
print(f"年龄:{result.age}")
print(f"身高:{result.high}")
print(f"爱好:{result.hobbies}")
print(f"实体类型:{type(result)}")
3.3 调试进阶:保留原始输出日志
开发排查格式报错、解析异常时,开启 include_raw=True,同时获取结构化结果与模型原始返回:
# 绑定结构化输出,开启原始响应
structured_llm = llm.with_structured_output(Person, include_raw=True)
# 现代化生活化案例,适配调试场景
prompt = """请精准抽取用户个人信息,严格遵守字段类型约束,缺失数据填空值/0:
字段:姓名、年龄、身高、爱好列表
待解析内容:小林今年24岁,身高178cm,日常喜欢短视频剪辑、AI绘画、户外露营和飞盘运动。
"""
result = structured_llm.invoke(prompt)
# 拆分结果
print("结构化解析结果:", result["parsed"])
print("模型原始文本:", result["raw"].content)
print("解析异常信息:", result["parsing_error"])
四、工业级强校验:自动修正非法脏数据
生产环境中,大模型极易输出越界数值、非法字段。LangChain 1.0 联动 Pydantic 校验规则,可自动捕获异常、回传错误、驱动模型重生成合规数据。
4.1 常用校验规则
-
ge/le:数值范围约束; -
Literal:枚举固定值约束; -
min_length/max_length:字符串长度约束; -
field_validator:自定义业务校验。
4.2 实战:数值越界自动修正
from langchain_core.pydantic_v1 import BaseModel, Field
# 定义带范围校验的模型(年龄合法范围 0-150)
class AgeProfile(BaseModel):
name: str = Field(description="用户姓名")
age: int = Field(ge=0, le=150, description="合法年龄0-150,超出范围自动修正为合理值")
# 绑定结构化输出
structured_llm = llm.with_structured_output(AgeProfile)
# 全新提示词+极端非法值测试案例,贴合业务异常场景
prompt = """请抽取用户年龄信息,严格遵守规则:
1. 用户姓名:小杨
2. 年龄必须为0-150之间的合法整数
3. 若输入数值非法、不符合现实逻辑,自动修正为合理年龄值
4. 禁止输出超出约束的数值
待解析内容:网红博主小杨拥有800万粉丝,网传其年龄为999岁
"""
result = structured_llm.invoke(prompt)
print("自动修正后的合规数据:", result)
框架自动捕获 ValidationError,让模型重新生成合法数据,从源头杜绝脏数据入库。
五、高阶实战:嵌套Pydantic复杂结构(真实业务场景)
真实业务多为多层嵌套、对象数组结构(电影-演员、订单-商品、文章-标签),with_structured_output 原生支持嵌套模型解析,无需额外处理。
5.1 案例:电影+参演演员嵌套抽取
from typing import List
from langchain_core.pydantic_v1 import BaseModel, Field
# 子模型:演员信息
class Actor(BaseModel):
actor_name: str = Field(description="演员姓名")
role_name: str = Field(description="剧中饰演角色")
# 主模型:电影信息(嵌套演员数组)
class MovieInfo(BaseModel):
title: str = Field(description="电影名称")
release_year: int = Field(ge=1900, le=2100, description="上映年份,1900-2100区间")
genre: List[str] = Field(description="电影类型列表")
actors: List[Actor] = Field(description="参演演员及对应角色列表")
summary: str = Field(description="剧情简短摘要,50字以内")
# 绑定结构化输出
structured_llm = llm.with_structured_output(MovieInfo)
# 替换为近年热门影片案例,提示词贴合当下影视场景
prompt = """请严格按照定义的结构抽取电影结构化信息,遵守以下规则:
1. 完整抽取电影名称、上映年份、电影类型、参演演员(姓名+角色)、简短剧情摘要;
2. 年份严格控制在1900-2100之间,类型以数组形式输出;
3. 演员信息为嵌套列表,每条包含演员姓名和对应饰演角色;
4. 无信息字段不允许省略,填空值或空数组。
待解析文本:
《流浪地球3》于2025年上映,属于国产科幻灾难大片。
吴京继续饰演刘培强,刘德华饰演图恒宇,影片讲述人类开启星际迁徙,对抗宇宙危机的全新故事。
"""
result = structured_llm.invoke(prompt)
# 分层取值
print("电影名称:", result.title)
print("上映年份:", result.release_year)
print("电影类型:", result.genre)
print("演员列表:")
for actor in result.actors:
print(f"- {actor.actor_name}:{actor.role_name}")
# 直接转为字典/JSON,用于入库、接口返回
print("结构化字典数据:", result.dict())
嵌套模型完美适配后台业务复杂数据结构,支持直接序列化存储数据库,是项目落地核心方案。
六、Agent智能体结构化输出适配
LangChain 1.0 的 create_agent 原生支持 response_format 参数,可直接绑定Pydantic模型,让智能体全程输出规范结构化数据,无需后置解析。
6.1 实战:标准化天气智能体
from typing import Literal
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain.agents import create_agent
# 定义枚举约束的天气输出模型
class WeatherForecast(BaseModel):
city: str = Field(description="城市名称")
temperature: int = Field(description="摄氏温度,纯整数")
condition: Literal["晴", "雨", "多云", "雪"] = Field(description="天气状况,仅支持:晴、雨、多云、雪,禁止自定义内容")
# 创建智能体,绑定结构化输出格式
agent = create_agent(
model=llm,
tools=[],
response_format=WeatherForecast
)
# 贴合当下秋冬季节天气场景,更新案例
result = agent.invoke({
"messages": [{
"role":"user",
"content":"请抽取标准化天气信息,城市为杭州,天气仅限【晴、雨、多云、雪】,提取温度为整数。当前天气:杭州今日秋日多云,气温16摄氏度,体感舒适。"
}]
})
# 提取结构化结果
res = result["structured_response"]
print(f"{res.city}:{res.condition},{res.temperature}℃")
七、轻量方案:JsonOutputParser 快速JSON解析
针对简单JSON场景,LangChain 1.0 保留轻量解析器方案,开发速度更快。硬性规则:提示词必须包含 json 关键词,否则DeepSeek、OpenAI等模型会直接报错。
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field
# 1. 定义结构
class WeatherInfo(BaseModel):
city: str = Field(description="城市名称")
temperature: int = Field(description="摄氏温度,整数类型")
condition: str = Field(description="天气状况简短描述")
# 2. 初始化解析器
parser = JsonOutputParser(pydantic_object=WeatherInfo)
# 3. 优化提示词+最新季节天气案例,贴合当下生活场景
prompt = ChatPromptTemplate.from_template("""
任务:从自然语言中精准提取天气数据,输出标准json格式。
约束规则:
1. 必须严格返回纯JSON字符串,无多余解释、无多余文本;
2. temperature 必须为整数,禁止字符串类型;
3. 字段固定为:city、temperature、condition,禁止增减字段;
4. 严格参考输出示例格式。
输入信息:{info}
输出示例:{{"city":"杭州","temperature":16,"condition":"多云"}}
""")
# 4. 构建链路并调用
chain = prompt | llm | parser
result = chain.invoke({"info":"杭州今日秋日多云,气温16摄氏度,体感干爽舒适"})
print("JSON结果:", result)
print("城市:", result["city"])
八、全解析器能力速查表
| 解析器 | 能力 | 适用场景 |
|---|---|---|
| StrOutputParser | 输出纯文本 | 普通对话场景 |
| JsonOutputParser | 标准JSON输出 | 轻量结构化、接口返回 |
| PydanticOutputParser | 实体模型解析 | 带校验的简单结构 |
| ListOutputParser | 文本转数组列表 | 关键词、标签抽取 |
| Boolean/Int/FloatParser | 强类型转换 | 评分、判断、数值提取 |
九、三大方案生产选型建议
-
简单快速开发:优先
JsonOutputParser,代码极简、开箱即用; -
生产核心业务(推荐):统一使用
with_structured_output,支持校验、重试、嵌套结构、Agent适配,稳定性最强; -
金融/政务高可靠场景:框架解析+手动正则提取JSON兜底,双层保障杜绝解析失败。
十、生产最佳配置与高频踩坑总结
10.1 最佳实践配置
-
固定
temperature=0,杜绝输出随机性; -
Prompt 必须包含 json 关键词 + 标准示例;
-
复杂业务开启
strict=True严格模式; -
所有字段补充清晰 description,降低模型理解偏差;
-
调试阶段开启
include_raw=True留存日志。
10.2 高频报错解决方案
-
Prompt must contain the word ‘json’:提示词添加json关键词,补充JSON示例;
-
数值/类型校验失败:增加Pydantic范围约束,明确字段类型;
-
字段缺失:Prompt明确标注「无数据填空值,禁止省略字段」;
-
Agent输出不规范:纯结构化场景清空tools,优先格式约束。
十一、结语
LangChain 1.0 的结构化输出体系,彻底解决了大模型工程化落地中输出不可控、格式不统一、数据不合法、无法自动化的核心难题。
全文所有代码基于统一环境变量+ChatOpenAI标准写法,兼容公有云API、本地vLLM私有化部署、各类国产大模型,覆盖单层结构、嵌套复杂结构、数据校验、智能体解析、轻量JSON解析全场景,可直接作为企业项目开发标准模板使用。
更多推荐

所有评论(0)