事情本身不复杂,线索都在日志里。结构化抽取里 is_refund 字段在 schema 里是 boolean,模型返回字符串 true,pydantic 2 的严格模式直接抛 ValidationError,一批 3000 条里有 217 条挂掉。
第一反应是「schema 描述没有限定取值」,验证下来不成立。
排查方向其实有限,先把可能性排一排。模型倾向把布尔值写成带引号的字符串。还有一种是strict 模式不做隐式类型转换。
不容易想到的是,部分样本本身就是「是」与「否」。
第一件事是统计失败样本里该字段的取值分布
python -c "import json;from collections import Counter;print(Counter(json.loads(l).get('is_refund') for l in open('out.jsonl')))"
再往下用 field_validator 做一次宽松转换
python -c "print([{'true':True,'false':False,'是':True,'否':False}])"
随后在字段描述里写清只接受 true 或 false
python -c "import json;s=json.load(open('schema.json'));s['properties']['is_refund']['description']='布尔值 不要加引号';json.dump(s,open('s2.json','w'))"
末了把转换后的结果重新校验并统计通过率
python revalidate.py --in out.jsonl --schema s2.json
改完先别撤,确认这几项。3000 条全部通过校验,布尔字段的类型分布里只剩 True 与 False,没有字符串。
这里还有个坑。模型输出类型漂移很常见,入口按宽松解析加字段级转换,比把校验调严更实用。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
