基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
  • 知识卡片碎片时间过考点
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
    • AI 热点每日 AI 资讯与动向
AI 工作台
简历
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-11-06 00:16

模型输出能解析,还需过类型与业务校验

dev.to · AI#结构化输出#数据校验#测试
Editor brief · 编辑速览

文章以数量字段类型错误导致下游订单异常为例,区分 JSON 可解析、模式合规与业务正确三个层次。建议保存原始响应并回放验证,覆盖类型漂移、金额不一致、非法状态和跨租户标识等问题。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

模型返回了合法 JSON,订单却照样出了错:作者的一次故障中,quantity 被写成字符串 '3',下游最终发出了 12 笔数量为零的订单。原文没有交代字符串如何变成零,但问题很明确:能解析,不等于能使用。

作者给出的办法是把输出依次送过解析、Schema、业务规则三道关,再保存原始响应做回放。这篇值得读的地方,是把「模型应该听懂了」变成可检查的契约;需要保留的疑问,则是作者没有公布失败率和对照数据。

合法 JSON 到底保证了什么

JSON mode 保证的是输出能被当作 JSON 解析,不保证字段符合业务要求。{"quantity": "3"} 是合法 JSON,但如果数量必须是整数,它就没有履行契约。

作者建议做一个小实验:保存 50 条原始响应,先用 json.loads 统计解析成功数,再交给真正的 Schema 校验器,比较两次通过数量。他预期两者会有差异,但没有公布这组实验的结果,不能把它当成已经证明的普遍比例。

三道关分别回答不同的问题:

  • Gate A 检查能不能解析,拦住语法错误。
  • Gate B 检查类型、必填字段、范围和枚举,拦住结构错误。
  • Gate C 检查跨字段关系和业务规则,拦住结构正确但业务不成立的数据。

解析通过,只说明数据进得了门,不说明它有资格执行后续操作。

例如,订单金额可能算错,状态可能违反状态机,订单 ID 可能属于另一个租户。这些问题不能只靠字段类型判断。尤其是租户归属,还需要结合请求身份或数据库记录,单独检查返回对象并不够。

Schema 管字段,业务代码管关系

作者的模板使用 jsonschema 库里的 Draft202012Validator,对应 JSON Schema draft 2020-12。订单必须包含 order_id、quantity、unit_cents、total_cents 和 status,并通过 additionalProperties: False 拒绝额外字段。

规则也写得很具体:order_id 匹配 ^ord_[0-9a-f]{8}$;quantity 是 1 到 999 的整数;两个金额字段是非负整数;status 只能是 new、paid、shipped。

这些限制仍然不能证明总金额正确。下面这段原始代码负责补上金额之间的关系:

def gate_c(obj):
    if obj['total_cents'] != obj['quantity'] * obj['unit_cents']:
        COUNT['gateC:arithmetic'] += 1
        return None, 'gateC:total-mismatch'
    return obj, None

要看的是乘法比较那一行:它假设订单总额就是数量乘单价。如果业务存在折扣、税费或运费,这条规则就得调整。Gate C 必须来自自己的领域规则,不能直接复制成通用答案。

作者随后又提出一个更省事的选择:只让模型返回 quantity 和 unit_cents,由代码计算总额。前面的检查适合验证已有输出,后面的设计则减少了模型需要负责的事情。

Strict mode 也不能让本地校验器退场。作者提醒,不同提供方对类型、正则、范围、跨字段运算的支持不同,但没有给出产品和版本对照,不能据此判断某个具体服务的能力。

还有两个容易漏掉的边界:字段缺失与 null 是否被区分,布尔值是否会被误认为整数。Python 中 isinstance(True, int) 为真,手写类型检查时尤其需要留意。

重试能救一次,回放才能看见问题

作者反对的是用重试掩盖失败。同一个提示词再请求一次,可能得到合格结果,却没有解释第一次为什么失败。

文中的「Gate B 失败率为 4%」是举例,不是作者公布的实测结果。它想说明:即使重试让最终请求成功,首次失败仍应被记录,否则提示词退化可能被成功率遮住。

作者的回放方法不依赖在线模型。先把原始输出存成 JSONL,每行包含 content,再由 replay.py 依次调用 gate_a、gate_b、gate_c;任一关失败就跳过,全部通过才增加 kept,最后打印通过数和 COUNT。

准备好原文的 gate.py、replay.py 与响应文件后,执行命令如下:

python -m venv .venv && . .venv/bin/activate
pip install jsonschema
python replay.py saved_responses.jsonl

最后一行使用的是已保存的响应,因此修改校验规则后可以重复检查同一批数据,不必重新消耗模型请求。

作者还建议在拒绝之前做类型转换,例如把 '3' 转成 3,同时记录转换次数。这里存在一个实现缺口:原文模板没有包含转换逻辑,照抄代码会直接在 Gate B 拒绝字符串。转换规则需要自己补,并限定适用字段。

Schema 也应和提示词一起进入版本控制。每次拒绝都记录 Schema 版本,才能判断失败来自模型输出,还是契约发生了变化。

我的判断

这套方法最有价值的是把失败分开统计,让团队知道问题发生在哪里。它适合接收模型结构化结果、还要继续写库或调用业务接口的流程。

但校验器只能证明「满足已写下的规则」。一个格式正确、确实存在的订单 ID,仍可能不是用户想查询的订单。作者也明确承认,三道关不能消除幻觉,且没有公开自己的回放数据。因此,这是一套可实践的工程经验,还不是可靠性提升的量化证明。

部署建议也要分开看。作者主张让校验与模型调用处于同一进程,避免额外网络跳转;随后推荐 MonkeyCode 的免费服务器方案,并披露文章属于产品推广。文中提到的额度是据转述的 1000 万 tokens,同时说明配额会变化。这不能当成当前承诺,更不能支持 p99 延迟结论,作者自己也反对这样推断。

对于已经端到端强制执行类型契约的 SDK,我倾向于复用已有校验入口,再补业务规则和观测。原文建议这类场景跳过三关设计,但类型契约是否覆盖跨字段规则,仍需确认。

能拿来做什么

  • 给前端或 Node 中接收 AI 结构化结果的位置补一份明确契约,先检查必填字段、数字类型和额外字段,再决定是否交给下游。
  • 保存首批 50 条原始响应作为回放样本,分别记录解析、Schema 和业务规则的失败数;允许重试时,也保留首次失败记录。
  • 从一个确定的业务关系开始写 Gate C,例如数量与单价的计算关系;能由代码推导的字段,优先交给代码计算。
  • 把提示词和 Schema 一起管理版本,明确哪些字段允许类型转换,并记录转换率,避免一次提示词修改悄悄改变接口行为。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
Langflow 高危漏洞暴露智能体执行风险
下一篇
用大模型为 Kubernetes 日志做初诊

资讯速览

dev.to · AI · 2026-11-06 00:16

AI 评分 8.0 / 10

相关标签

#结构化输出#数据校验#测试

继续阅读

  • 提示词技能何时有效:小样本对照实测
  • Langflow 高危漏洞暴露智能体执行风险
  • 用大模型为 Kubernetes 日志做初诊
  • 腾讯 Hy4 支持图像理解与自主操作软件
  • 用权限代理隔离智能体密钥与执行