问题与目标
自然语言适合阅读,不适合直接驱动数据库和业务流程。即使 Prompt 要求“返回 JSON”,模型仍可能增加代码围栏、漏字段、写错枚举,或者返回语法正确但业务无效的数据。
本篇把一条事件整理成固定 Schema,区分提供商原生约束、工具式结构化输出和手工解析。完成标准是有效结果得到类型对象,无效结果保留原文与错误原因,重试次数有上限。
核心概念
三条实现路径
- 提供商原生结构化输出:由模型 API 按 JSON Schema 约束,通常最稳定,但能力因服务商和模型而异。
- 工具式结构化输出:把 Schema 作为工具参数,读取模型提出的参数;仍要在应用侧校验。
- 手工解析:从文本提取 JSON 再校验,兼容面广但最脆弱。
Pydantic 校验的是结构,不会证明事实正确。device_id="不存在的设备" 可以通过字符串类型检查,业务层仍要查询设备白名单。
可运行实现
先用纯 Pydantic 验证,确保不依赖模型也能复现错误处理:
python -m pip install "pydantic>=2,<3"
import json
from typing import Literal
from pydantic import BaseModel, Field, ValidationError
class EventSummary(BaseModel):
device_id: str = Field(min_length=1, max_length=32)
level: Literal["info", "warning", "critical"]
summary: str = Field(min_length=1, max_length=60)
needs_review: bool
def parse_result(raw: str) -> dict:
try:
data = json.loads(raw)
value = EventSummary.model_validate(data)
return {"ok": True, "value": value.model_dump(), "raw": raw, "error": None}
except (json.JSONDecodeError, ValidationError) as error:
return {"ok": False, "value": None, "raw": raw, "error": str(error)}
print(parse_result(
'{"device_id":"AX-3","level":"warning",'
'"summary":"温度偏高,等待复核","needs_review":true}'
))
print(parse_result('{"device_id":"AX-3","level":"high"}'))
模型支持结构化输出时,可以让 LangChain 返回同一个类型:
from langchain_openai import ChatOpenAI
model = ChatOpenAI(model="provider-model-name")
structured_model = model.with_structured_output(EventSummary)
result = structured_model.invoke("设备 AX-3 温度偏高,尚未复核。")
print(result.model_dump())
具体使用原生还是工具策略,应查看集成和模型能力。生产代码可以把失败结果保存为:
{"ok":false,"raw":"...","error_type":"schema_validation","attempt":1}
若需要修复,最多进行一到两次,并把具体校验错误反馈给模型;每次都重新校验,不能因为是“修复结果”就直接信任。
常见问题与排查
JSON 能解析就直接执行
依次检查 JSON 语法、Pydantic 类型、枚举与长度,再检查设备、用户和状态是否符合业务规则。四层不能合并成一次 json.loads()。
校验失败后无限让模型自我修复
限制尝试次数,保留每次原文和错误。反复失败通常说明 Schema 太复杂、提示不清或模型不支持,而不是需要更多循环。
Schema 字段又多又深
删掉当前流程不需要的字段,使用明确名称、描述和枚举。复杂对象可拆成两步提取,减少一次生成同时满足的约束。
日志只保存异常字符串
异常需要与请求 ID、模型、Schema 版本、尝试次数和脱敏原文关联,否则无法判断是模型退化还是契约升级造成的回归。
小结
结构化输出把模型文本变成候选数据,Schema 和 Pydantic 再把候选数据变成类型安全的结果。它解决格式稳定性,不解决事实、权限和业务合法性;后几层校验必须继续由应用负责。
许可协议:CC BY-NC 4.0
更新于 1 小时前
觉得文章有帮助?点个赞吧!
0 条评论


