摘要
日志读取器对每一行战斗日志做三次 OCR(整图原尺寸、面板原尺寸、面板放大 1.5 倍),三次足够一致才输出这行文字,否则留“未知”。之前有一个私有的候选版本:它在很窄的条件下,把一部分“未知”行提升为输出。问题是——怎么确认候选版本只做了它声称的事,而没有悄悄改动别的行、改写原文、拼接文字或编造身份?
本实验不看任何图片,也不重新计算准确率,只写一个校验器,比较“基线版本保存的 JSON”和“候选版本保存的 JSON”之间的关系是否合法。第一版校验器在 6 对真实保存结果中判定 2 页无效;排查后发现是校验器自己没考虑到生产代码已有的 Unicode 规范化。保留第一版和它的结论,另立一个兼容版后,6 页全部通过。
要回答的问题
候选版本相对于基线,是否只把符合条件的“未知”行提升为输出,并且提升的文字恰好是原始 OCR 读到的第一条完整文字?
数据与来源
- 6 对已保存的 JSON:基线(A31)与候选(A31R)各 6 页,包括 3 页含日志的截图和 3 页没有日志的负例(战场、英雄、说明文字)。
- 不读取原图、原始 OCR 中间文件或评分参考。
方法
运行前先冻结协议、合成测试期望、代码和测试,然后只审计一次。合法转换的要求:
- 候选的格式、用途、编号、零图像/零 OCR 计数和处理时间合法;来源路径和 2560×1440 原生尺寸与基线完全一致。
- 每一行、行顺序、行 ID、角色、原生框和三次原始尝试(顺序、变体、文字、分数)全部保留;类型敏感比较(
True、1、1.0不相等)。 - 基线行本身要合法:三次尝试按固定顺序、分数有限;“未知”行文字和声明都为空;已输出的日志行文字等于某次原始尝试,声明等于解析结果;表头永远不当日志事件。
- 未变的行无需提升也合法。变化的行只允许改文字、声明、状态和原因,而且基线必须是“未知”的日志行,并满足已冻结的窄资格条件(只看基线证据,不看候选改写后的证据)。
- 被提升的行,文字必须恰好是按保存顺序的第一条完整原始尝试,声明必须恰好等于解析这段原文的结果。不允许规范化、拼接、补标点或推断身份。
校验器只返回“是否合法”和失败原因,不输出候选文字、不修补证据。
设置
第一版:45 个合成案例(8 个合法对照、37 个应拒绝的违规,例如伪造伤害、伪造玩家、编造身份、挪动行框、改分数、丢弃或重排尝试、给表头提升等)。兼容版:56 个合成案例(11 个合法、45 个违规)。
结果
| 第一版 | 兼容版 | |
|---|---|---|
| 合成案例与期望不一致 | 0 | 0 |
| 6 页保存结果判为合法 | 4 | 6 |
| 验证的提升行 | 3 | 13 |
| 验证的未变行 | 3 | 29 |
| 保留的原生框 / 原始尝试 | 6 / 18 | 42 / 126 |
兼容版逐页:短日志页 6 行(3 提升、3 未变),长滚动页 29 行(10 提升、19 未变),洞穴页 7 行(7 未变),三个负例页 0 行。整个审计耗时约 0.013 秒,新的图像读取、解码、OCR、GPU 和评分参考读取都是 0。实验与此前相关测试合计 227 项通过。
作为背景(引自此前保存的评分,本轮没有重算):候选版本在可读完整行上 36/39 正确,可核验的输出 36/36 正确。
失败与负结果
第一版校验器把长滚动页和洞穴页判为“基线文字不是原文”。排查只用保存的 JSON 和生产代码:两页中有 8 行已经输出的基线文字,使用了生产代码记录在案的 NFKC 规范化(例如全角冒号变半角,死亡单位:7。 变成 死亡单位:7。),全部 24 条基线输出都等于“第一条原始尝试做 NFKC 再去首尾空白”。第一版假设“基线必须逐字等于原文”是错的。
处理方式:第一版的协议、代码和结论原样保留;另立兼容版协议,只修正对基线文字的要求,使之与生产代码一致;对新提升的行仍要求逐字等于原文(包括原始空格和标点),如果把基线的规范化用在新提升的行上就判无效。这是校验器的兼容性修正,用的是已曝光数据,不是新的识别方法或留出准确率提升。
局限
- 校验器只证明两份 JSON 之间的关系受约束,不证明它们来自可信的像素;两边共有的错误读数也能通过。
- 同一引擎的资格条件不是独立真值,也不是校准过的置信度。
- 它只支持这一份冻结的私有格式;新格式需要单独审阅的新版本。生产采纳前仍需主负责方独立验收(尚未记录)。
结论与下一步
在不读取任何像素的情况下,可以严格检查一个候选版本是否只做了它声称的“窄提升”。这次审计还顺带暴露了校验器自身的假设错误,并以保留原结论、另立兼容版的方式解决。生产代码没有改动;是否采纳候选版本等待独立验收。
Comments