🎯 课程主题
通过构建虚拟服务器故意返回不匹配的字段,验证 Pydantic、TypedDict、JSON Schema、@dataclass 四种格式在数据格式不匹配时的处理行为差异。
📝 核心知识点
1. 实验设计:Fake Server
- 概念说明:构建一个虚拟的 DeepSeek 服务器,故意让服务端返回的字段名与客户端声明的字段名不一致,以验证四种格式的校验行为。
- 关键细节:
- 服务端返回
title1、year2(故意加了数字后缀),而客户端声明title、year - 通过 Fake Server 模拟大模型的响应,可控地制造格式不匹配场景
- 正常使用大模型时几乎不会出现此类问题(大模型能力足够强)
- 服务端返回
2. Pydantic:严格校验,不匹配即报错
- 概念说明:Pydantic 是唯一在字段不匹配时抛出异常的格式,体现了其运行时强校验特性。
- 关键细节:
- 服务端返回
title1,客户端要求title→ Pydantic 直接报错 - 错误信息会明确指出缺失的属性和多余的字段
- 实际开发中推荐使用 Pydantic,严格的校验能尽早暴露问题
- 服务端返回
3. TypedDict / JSON Schema / @dataclass:不报错,以服务端为准
- 概念说明:这三种格式在校验上表现一致——即使字段名不匹配,也不会报错,直接以服务端返回的结构为准。
- 关键细节:
- 服务端返回什么字段名,客户端就原样输出什么字段名
- 这意味着这三种格式在运行时没有类型校验机制
- 数据不正确时不会主动提示,可能埋下隐患
🏗️ 架构与工作流
┌─────────────┐ 请求(要求title/year...) ┌──────────────┐
│ 客户端 │ ─────────────────────────────> │ Fake Server │
│ (定义结构) │ │ (故意返回 │
│ │ <───────────────────────────── │ title1/year2)│
└─────────────┘ 响应(实际返回title1/year2) └──────────────┘
│
▼
Pydantic → 报错(字段不匹配)
TypedDict → 不报错(原样输出 title1, year2)
JSON Schema → 不报错(原样输出)
@dataclass → 不报错(原样输出)
💻 代码实战
# --- Fake Server 端 (fake_server.py) ---
# 构建虚拟 DeepSeek 服务器,故意返回不匹配字段
# 服务端返回: title1, year2, director, rating
# 客户端声明: title, year, director, rating
# --- 客户端验证 ---
# 1. Pydantic 格式验证
from pydantic import BaseModel
class MoviePydantic(BaseModel):
"""电影信息"""
title: str
year: int
director: str
rating: float
structured_model = model.with_structured_output(MoviePydantic)
response = structured_model.invoke("介绍星际穿越")
# 结果:报错!因为服务端返回 title1 而不是 title
# ValidationError: Missing required fields...
# 2. TypedDict 格式验证
class MovieTypedDict(TypedDict):
title: str
year: int
director: str
rating: float
structured_model = model.with_structured_output(MovieTypedDict)
response = structured_model.invoke("介绍星际穿越")
# 结果:不报错,输出 {'title1': '星际穿越', 'year2': 2014, ...}
# 3. JSON Schema 格式验证
structured_model = model.with_structured_output(json_schema, method="json_schema")
response = structured_model.invoke("介绍星际穿越")
# 结果:不报错,同 TypedDict
# 4. @dataclass 格式验证
@dataclass
class MovieDataclass:
title: str
year: int
director: str
rating: float
structured_model = model.with_structured_output(MovieDataclass)
response = structured_model.invoke("介绍星际穿越")
# 结果:不报错,同 TypedDict
⚠️ 常见问题与避坑指南
- 只有 Pydantic 做运行时校验:TypedDict、JSON Schema、@dataclass 均不做强校验,字段不匹配时静默通过。
- 严格校验是好事:数据不一致时不报错可能埋下生产隐患,因此生产环境首推 Pydantic。
- 正常使用大模型时几乎不会出现不匹配:大模型能力足够强,能精准匹配声明格式。本实验仅为验证性质,通过 Fake Server 人为制造问题。
💡 个人总结与延伸
这节通过实验清晰地展示了四种格式在校验机制上的本质差异:Pydantic 是唯一的强校验方案。在实际项目中,结构化输出不仅是为了格式化,更是为了保障数据一致性,因此应首选 Pydantic。如果场景只需简单 dict 且对准确性要求不高,TypedDict 足够;JSON Schema 和 @dataclass 则不推荐在 LangChain 的结构化输出中使用。