关于 AI、软件、系统与持续思考的个人笔记

知乎姨姨

AI 返回了合法 JSON,为什么还要用 JSON Schema 检查

JSON 能解析,只能说明语法正确。用 Python jsonschema 检查必填字段、类型、枚举与额外字段,再把格式错误和业务错误分开处理。

文章目录

让 AI 从工单里提取编号、优先级和摘要,返回内容能被 json.loads 读出来,仍可能不能直接入库:编号少了一位,优先级写成自由文本,或者多出了调用程序没准备接收的字段。解析 JSON 和接受业务数据之间,需要一道明确的校验。

把输出约定写成 Schema

以下工单结构是示例。安装 Python 的 jsonschema 库后,将代码保存为 validate_ticket.py。虚拟环境可避免改动系统 Python:

python3 -m venv .venv
. .venv/bin/activate
python -m pip install jsonschema

Schema 中把编号、优先级和摘要设为必填,并拒绝未约定的字段:

import json
from jsonschema import Draft202012Validator

schema = {
    "type": "object",
    "properties": {
        "ticket_id": {"type": "string", "pattern": "^T-[0-9]{6}$"},
        "priority": {"enum": ["low", "normal", "high"]},
        "summary": {"type": "string", "minLength": 1, "maxLength": 200}
    },
    "required": ["ticket_id", "priority", "summary"],
    "additionalProperties": False
}
Draft202012Validator.check_schema(schema)
validator = Draft202012Validator(schema)
raw = '{"ticket_id":"T-000123","priority":"urgent","summary":"无法登录"}'
item = json.loads(raw)
for error in validator.iter_errors(item):
    print(list(error.absolute_path), error.message)

这组输入的 priority 不在枚举中。properties 只声明字段规则,不自动要求字段出现,所以还需要 required;只写 type: object 也不会禁止未知字段。正则两端的锚点用来限制整个编号,避免只匹配字符串中间一段。

分清三种失败

如果 json.loads 抛出异常,是语法或包装问题,例如回复外面多了一段说明。Schema 校验失败,则属于缺字段、类型不符或取值超出约定。两者都应在入库前拒绝,不要把“urgent”悄悄改成“high”,除非产品规则明确允许这种映射。

第三种更隐蔽:格式全部通过,但工单编号不存在,摘要也没有准确反映原文。Schema 不能判断这些事实。程序还要查询编号、核对权限、保留原始工单与提取结果之间的关系。让模型输出一个合法结构,不等于获得了正确结论。

对于日期、邮箱等 format,也别只写关键字就假定库会检查。jsonschema 的格式检查需要显式启用相应 FormatChecker,有些格式还依赖额外安装项。没有需求时,优先使用容易核对的类型、枚举和长度规则。

重试要有边界

可以把“priority 必须属于哪三个值”这类结构错误交回模型修正,并限制次数。每次保留原回复、错误位置和修正回复,超过上限进入人工队列。不要把异常原文连同密钥、内部路径或整份客户材料原样拼进重试提示。

收到结果后先校验,再计算、写库或调用工具。代码中的 Schema 也应纳入版本管理;字段改名时同步消费者,而不是让新旧客户端猜测。规则含义见 JSON Schema 对象文档,Python 的校验与格式检查行为见 jsonschema 文档。

继续阅读 · AI 与 Agent 返回顶部