模型返回 NaN 和 Infinity,怎样在 JSON 数据入口拒绝非有限数
模型文本中出现 NaN,未必会让 Python 的 JSON 解码报错;1e400 也可能在解析后成为无穷大。它们进入评分、向量或统计字段后,常常直到排序与聚合才显露异常。入口应同时检查解码常量和实际数值,出口再禁止产生非标准的 JSON 数字。
常量钩子不是全部边界
parse_constant 可以拒绝 NaN、Infinity 和 -Infinity 这些扩展常量。它不会收到每一个普通数字字面量,所以不能靠这个钩子拦住巨大指数。样本 {"score":1e400} 在默认浮点解析下会得到非有限值,必须用第二层检查发现。
本文先严格解码常量,再递归走过对象和数组中的值,对浮点数使用 math.isfinite。字符串 "NaN" 是普通文本,不自动转为数值;布尔值则保持布尔类型。Python 中布尔值与整数存在继承关系,若业务字段只允许数字,应显式排除布尔,而不是让一个宽泛的整数判断把 true 当作一分。
正常数据应原样保留
附件正常项含嵌套小数、整数、布尔和空值,预期全部保真。异常项分别使用 NaN、Infinity、负无穷与巨大指数,预期拒收并区分发生在常量读取还是递归有限性阶段。这样故障报告才不会把所有问题都写成“JSON 格式不对”,也便于确认第二道防线确实运行过。
失败反例是在统计前用零替换 NaN。零是一个合法测量值,替换会改变均值与排序,而且丢掉异常来源。另一个反例是只检查最外层 score,嵌套列表里的坏数仍会进入下游。检查器覆盖嵌套结构,并在结果中标明拒绝样本编号。
出口也需要同样严格
Python 序列化使用 allow_nan=False 可以阻止非有限浮点以扩展文本输出。入口严格并不能保证中间计算永远有限,例如除法、累加或指数操作可能产生新的异常。因此输出之前再检查,是对数据流的约束,而不是重复一遍读取步骤。
本例使用常规浮点类型,不能代表金融小数精度或任意大整数在所有语言中都可无损往返。若业务需要十进制定点,应另设字段合同和编码方式,不要用“有限”这个判断替代“精确”。数字是有限的,也仍然可能超出业务量程。
实际部署时把语法错误、非有限数、类型错误和业务范围错误分别编号。前者回答是否能读取,后者回答是否能采用,日志只存必要上下文。本文运行的是本地合成输入,没有调用任何模型,也不把这组防御性夹具当作某家接口的输出质量评测。
配套文件与依据
本文的合成输入和参考结果可下载独立样本 a010.json,离线检查器 a010.py与样本放在同一目录后运行。检查器不调用模型接口。 使用 Python 3.12 或兼容版本,将上述文件下载到同一目录,执行 python a010.py。
留言讨论
评论发布后会被人工复核,违规内容将被删除。
如果发表没有反应,可以前往联系我们告诉我们。