我靠数据吃饭,所以有个条件反射:一个数字你要是拆不开、对不上、经不起追问,我一个字都不信。偏偏眼下人人都在琢磨怎么让大模型“当裁判”——也就是 LLM‑as‑a‑judge 那套东西。不管是做医疗合规的逐条检查,还是翻 Claude Code 会话里哗啦啦滚过去的终端日志,你总得找个能“打分”的脑子来处理这些乱糟糟的非结构化数据。大厂的前沿模型靠这套评估体系给自己标质量,可如果你既想数据不离开本地,又想把账单压到骨头里,你只能驱着小尺寸的离线模型干这活。
然后现实就劈头盖脸地拍过来:模型越小,幻觉越疯。一样的转录,一样的评分表,每次跑出来都是新得数。不是误差,是直接抽风。想让这种小裁判正经干活,你得给它套一副铁打的缰绳。我这次的活儿就很具体:拿一段对话录音转成的文字,对着品控表逐条打分。品控表是真人专家提前写死的,三十六条,全是可以明确答“是”或“否”的硬杠杠,比如“说话人有没有确认 X”“步骤 Y 有没有覆盖到”。最理想的对话能拿三十六分,这数完全取决于表单有多长,模型要做的只是给每条勾上状态,没让它自己重写规则。
可当我真把离线小模型放上去当裁判,那种不信任感直接炸了。随便一个语言模型,你让它“自由打分”,它就开始演你了。演法还有四五种,招招踩在评估的命门上。
第一招,偷换分母。它碰见拿不准的条目,连招呼都不打,直接从清单里悄悄摘掉,分母一缩,最后那个百分比蹭地就上去了,看着挺唬人,实际上就是个注水肉。第二招,无凭无据画勾。它敢在没有任何原文引用的情况下,理直气壮地把某项标成“已完成”,硬是把胡乱一猜打扮成分内之责。第三招,凭空塞结构。返回的所谓“准则编号”或者“规则文本”,你在那张三十六条的表里搜穿屏幕也找不着,纯属它即兴创作。第四招,一跑一个样。同一条对话,你跑十次,它给你吐出不同的分数,等于你亲手搭了个乱数生成器,还管它叫“测量”。
既然小裁判内建了个戏精模式,我索性把打分的权利从它手里完全剥掉。整条管线里,所有冒出来的数字,通通由代码掌管;模型只负责回答一个个刨根问底的小问题,而且每个回答都得能被当场抓住证据。这么一来,它就没法顾左右而言他,也没法悄悄修改题目。
把框架摊开看,处理一通记录下来差不多是二十二个小调用,中间插着大段大段的确定性代码。真正能左右最终得分的,全管线只有两个环节动刀子,其他所有的步骤都是只读操作。先是抽取阶段,把对话的头部信息和一些关键事实摘出来,接着——结构上不允许模型替你决定一条准则是过是挂,它只能为你扒出用来判断的那几句原始文本来,再由外头不憨不傻的比对逻辑去下定论。同时,管线里灌进了语法约束,每一个输出都得落在预先划好的格式里,出格就当场报错;数数全是代码在数,模型那张嘴在计数这件事上根本没有表决权;再加上 CI 强制的不变量,每次提交,如果跑出来的核查记录不是所见即所得、不能逐条回溯,构建直接爆红灯。
回头看一眼这条铁的缰绳为什么非得这么打。如果你贪图省事,一个 prompt 里塞满转录和三十六条准则,指望模型一口报个数,那它背地里干的那些偷鸡摸狗的事——偷减条目、闭眼画勾、编造规则、漂移结果——你连抓都抓不住。而现在这套设计,本质上就是用二十二道小锁,把模型的每一个判断动作都锁在可验证的格子间里。它没法在你不注意的时候悄悄降低分母,因为每一条准则到底有没有参考到原文、参考的是哪几句,全都明明白白摊在遥测记录里。它也没法换个 run 就改口,因为只要是同一份输入,管线里的确定性部分会把随机性压到最低,输出的计分还是那个计分。
至于为什么非得选本地、离线、小尺寸的模型?数据隐私和成本是明账。不连外网,对话录音、医疗核查、编码日志就趴在自家机器上,不用给第三方过一手;跑小的也不用按 token 烧钱。只是小模型的脆弱得用工程手段兜回来,所以才有了三层技术骨架:语法约束堵住格式乱跳,代码驱动计数逼退数字造假,CI 不变量让每一次改动都带着全量回溯。就好像一个做事毛躁的下属,你让他在带防呆卡的流水线上打螺丝,他能拧错螺帽的概率就断崖式跌下去了。
这套思路最反直觉的地方在于:想拿到一个牢靠的分数,最不该做的就是让模型自己算分。不让它沾计分的事,它反而变得可靠起来——每一句借来的证据、每一次被代码逮住的勾选,都能让你在跑完那二十二圈之后,指着手里的评估报告说,这每一个数我都能找到出处。
热门跟贴