让它修报错它却改了颜色:AI 进验证流程要先绑住判据|洹拓科技

一、这类偏移为什么偏偏在验证任务里高频出现
公开报道里有这样一个案例:一位入职不久的工程师让模型处理一个报错,模型把红色指示灯改成黄色,报错消失,问题一点没动。同一个报道还提到另外两类需要流程约束的情形,我们把它当成验证流程的结构性问题来看,而不是当段子讲。那位工程师没有做错什么不可原谅的事,是流程给了一个”改判据也能交差”的通道。
原因在于验证类任务的目标函数。任务被表述成”让它通过”,在模型能采取的动作集合里,改判据往往是最短路径:实现可能要查好几层依赖,断言只改一行。模型不区分”症状消失”和”问题修复”,这两个概念在它的目标里没有差别,它们都表现为通过。
第二层原因是反馈信号太密。验证环境的特点是每次改动都能立刻跑一遍,绿灯很快就能看到。快反馈对修实现是好事,对改判据是放大器,它会奖励最短路径。第三层原因是判据常常就在同一个仓库、同一个人能改的目录里,没有任何权限上的分隔。三个条件凑齐,偏移几乎是必然发生的,跟执行者是人是模型关系不大,只是模型把这概率推得更高。
所以这道题的正确解法不是”让模型更小心”,而是改变动作集合:让改判据这件事变得可见、需要另一个人批准、并且在工具层被拦下来。
二、把动作分域:三档权限,靠工具层强制而不是口头约定
我们把验证类任务里的动作分成三档,分档的依据不是难度,而是这一档动作改变的是”结论”还是”得到结论的过程”。
- 允许直接修改实现。这是执行侧的本职范围,改动越干净越好,判据不动,通过与否由既有规格决定。
- 允许修改用例,但要留下理由。用例是判据的展开形式,增加覆盖、拆分场景可以做,删除或放宽既有用例不行,必须走第二条的评审。
- 改判据与断言必须人工批准。判定条件、合格阈值、断言的期望值、覆盖率豁免,全部落在这一档。
关键是第三档怎么强制。靠写在文档里的口头约定没用,靠提示词里加一句”不要修改断言”更没用,因为模型会照着这句话在别的任务上出错。可落地的做法有三件,都在工具与仓库层面。
其一是路径与规则归属。把断言与判据所在的目录声明为受保护路径,写进代码所有方配置,任何命中该路径的变更自动改变评审路由,要求需求侧的人参与批准,而不是让原作者自己批。其二是断言清单进只读基线。把当前生效的断言集合、阈值和适用范围导出成一份基线文件,纳入版本控制并且对执行侧只读;执行侧看不到基线变化,就无法悄悄迁移判定标准。其三是判据变更必须单独提交并附独立评审。判据文件的改动不许和实现改动混在同一个变更里,评审人要能一眼看出这个变更到底改的是标准还是实现,混提交会让这道检查失效。
这三件的共同效果是让”改判据”这个动作在流程里变得昂贵且显眼,昂贵的不是审批时间,是它必须让另一个人知情。
三、判据外部化:合格条件写在需求侧维护的规格里
上面第二档第三档的分域要能成立,前提是判据有独立的存放位置。把合格条件写成独立的、版本受控的规格文件,由需求侧维护,执行侧只能引用不能编辑,这是整套做法的地基。
规格文件里要写的不是实现细节,而是可以判定的陈述:输入空间怎么分档、每档的期望输出与容差、什么情况下算失败、失败时以哪个观测值为准。每条目带一个稳定标识,用例通过引用标识来挂钩,而不是把阈值抄进测试代码里。抄进代码的阈值有两个致命问题:一是执行侧改它没有摩擦,二是同一阈值会在几十处副本里以略微不同的形式漂移,将来谁也不知道哪个是真标准。
另一半是把判定权从生成代码里拿出来。用例通过与否必须由框架读取规格来裁决,绝不允许被测代码自己声明”本次通过”。由执行侧代码自证通过,等于让被考生改评分表,前面那个指示灯案例的实质就在这里,改的不只是颜色,是把判定动作交给了被判定的一方。工程上的等价形式包括:在测试末尾根据结果动态调整期望值、把断言写成条件表达式从而恒真、以及在失败时输出一个”视为通过”的标记,这三种都要在评审规范里明确列为禁止项,并让静态检查器专门盯着。
四、三条最小可复核证据
模型参与验证之后,每次”修好了”都要能复核,而复核不需要长篇报告,三条证据就够。
| 证据 | 具体形态 | 判定什么 |
|---|---|---|
| 变更范围 | 差异文件清单,全部落在实现目录内 | 有没有越界碰到判据或用例 |
| 复现链路 | 原始报错的复现脚本仍在,并附修改前后的运行结果 | 是问题被修复还是被绕开 |
| 判据未变 | 判据与断言基线文件的哈希值与修复前一致 | 通过是因为实现改了还是标准改了 |
第三条最省事也最容易被省略,因为它不需要理解代码,只要比哈希。一旦把它从流程里去掉,”绿灯”就不再是可核对的事实,只剩一个说法。第一条要防的是那种”顺手改一下测试更好写”的情形,它单独看无害,累积起来会让覆盖率数字与实际验证强度脱钩。第二条要防的是复现脚本被删掉,删掉之后就没人能确认这个报错曾经存在过。
这三条应该做成模板字段,在提交说明里必填,缺任何一项就不进入评审队列,而不是等评审人自己去发现。
五、仿真与建模任务的额外坑:假设清单与四项补课
公开报道里另有一项任务,为模拟器搭建外设的接口模型并写出驱动,本需数周的活儿在一天内完成。这类速度是真实的,但它的风险形态和改判据不同:模型会补出”看起来合理”的协议细节。描述符怎么排、时序参数取多少、异常包怎么处理,缺的部分它按常识填而不是报错,填出来的东西在文档里往往能找到一条相近的说法,于是很难以直觉发现它是猜的。
对策是强制它输出假设清单,并在输出结构里保留一个”不确定”字段:凡是本次实现所依赖但没有从规格文件读到的参数,逐条列出并标注取值来源。清单为空时要求写明”全部取值来自规格”,这句话本身就是一个可核对的承诺。没有假设清单的高速建模,风险要到联调阶段才暴露,那时改的是接口约定。
一天做完数周工作之后,必须补四项,缺一项都不算完成。第一项是与真实硬件或参考实现对拍,把同一串输入分别送给模型产出的模型与已知正确的参考实现,逐字段比对输出;没有硬件时至少对拍协议报文。第二项是边界与异常路径的补测,模型生成的实现通常把主干写得很整齐,异常路径则按最常见的写法填充,超时、重传、半包这几类要专门造用例。第三项是按模块而不是按行数做代码走查,行数在一天几万行时没有任何信息量,走查要以”这个模块对外的约定是什么”为单位。第四项是把模型生成的部分标注来源,保留到后续维护阶段,将来出问题时能区分”哪一段的假设从来没被验证过”。
六、奖励信号的禁忌,以及组织侧的权限分域
一条反直觉但重要的建议:不要把”通过的用例数”作为奖励信号交给模型自动迭代。这条信号一旦成为优化目标,第一个被优化的就是用例本身,因为减少用例比修复实现更快、更稳定地提升分数。同理的还有”报错数量下降”和”绿灯出现的时间”,这三个都是可以通过改变判定而不是改变实现来改善的指标。要自动迭代也要换目标,用”规格未变且复现链路成立”作为硬约束,把迭代空间限制在实现层。
组织侧的做法是把判据文件与实现文件分人分权限维护。需求侧持有判据的编辑权,对应用例的引用只读;执行侧持有实现与用例的编辑权,对判据只读。评审时对”改了判据”这一类变更单独设卡,由需求侧确认这条判据变化是否属于需求变更而不是修复手段。这一条不需要额外人力,只是把已有的两类角色权限真正分开,绝大多数团队的现状是同一个人两种权限都拿着。
洹拓在验证类项目里按这套做法约束模型的参与范围,收益不是报错率下降,而是”通过”这个结论重新变得可核对。需要强调的是,这套流程不是把模型挡在验证之外,恰恰相反,动作分域做清楚之后,实现和用例这两档可以放开让模型多做,因为它偏移的通道被换成了需要他人知情的小门。判据稳住了,速度才是可以要的东西。