🎯 抓出指令缺陷(第二层)
官方任务二的字数约束 vs 参考话术冲突、任务一的业务规则自相矛盾——若直接上线,质检数据全失真。指令体检在评测前就能拦下。
runs/ 下找到产物文件逐一复核
美团履约数字人每天产生大规模外呼。指令包含复杂流程分支和多重合规约束,人工抽听无法全量覆盖、标准因人而异。但「做一个自动评测器」不是难点——难的是凭什么信它:
裁判自己会误判,谁来评测评测系统?模型分数低,是模型差还是指令本身写得自相矛盾?模拟器说「测得充分」,充分到什么程度?
EvalCall 的回答是三层质量闭环:不仅评测模型,还审计指令本身,并量化校准自己的裁判。每一层都在官方脱敏数据上实测落地。
下面三层依次回答三个问题:模型守不守指令(评模型)→ 指令本身可不可信(审指令)→ 我凭什么信自己的裁判(校裁判)。
| 任务(官方指令) | Persona | 原始分(n=3,均值±标准差) | pass^3 | 结论 |
|---|---|---|---|---|
| 任务一 · 骑手合同生效通知 | 配合型 | 50.6 ± 6.8 | 0.00 | 两任务全部轨迹均触发 critical 否决,pass^3=0。注:pass^3=0 表示无一条轨迹做到零 critical 完美通过——是结论,不是 bug(详见报告)。体检器给出归因:任务一开场白塞 5 项信息必丢项、任务二字数与信息量物理冲突——低分主因在指令,报告自动挂归因警示 |
| 不耐烦型 | 41.2 ± 12.1 | |||
| 任务二 · 低延迟直播升级通知 | 配合型 | 58.7 ± 3.3 | 0.00 | |
| 不耐烦型 | 60.5 ± 2.9 |
分数为否决前原始分(critical 否决后计 0 分另列);±为 3 条独立轨迹的标准差——单样本是观测值,带方差才是测量。每条 fail 附对话原文证据与指令原文引用,点开报告逐条可审计。(产物:runs/official01_n3/ runs/official02_n3/)
受控消融实验:同一被测模型、同一任务(体检修复版指令)、同一把固化的检查点尺子,唯一变量是被测模型「看得见 vs 看不见」指令中的约束段。规模声明:每组 2 条轨迹,属可行性演示而非统计结论——分离方向清晰(71/63 个百分点),置信区间未估。
| 维度 | 看得见约束 | 看不见约束 | 解读 |
|---|---|---|---|
| 约束遵循(constraint) | 100% | 28.6% | 看得见约束的模型严格守住了约束与话术——+71 / +63 个百分点的分离度,评测系统精确检测到了行为差异 |
| 话术合规(style) | 62.5% | 0% | |
| 流程完整(flow) | 26.3% | 83.3% | 守约束的代价:短句+频繁暂停挤掉了流程信息量——指令的「字数 vs 信息量」张力仍残留(体检→修复→实测是迭代循环) |
| 标量总分 | 0(critical 否决) | 68.2 | 标量分会撒谎:只看总分会得出「守约束的模型更差」的荒谬结论——这正是报告必须输出分维度画像、不依赖单一分数的原因 |
(产物:runs/discriminant_constraints_on|off/)实验另一收获:首跑时两组各自重新编译检查点导致「不同尺」(LLM 编译器非确定性),结论无效——已修复为 --checklist 固化复用机制并重判。比较实验必须同尺,这条工程教训已产品化进 CLI。
同任务、同固化尺子、同跨模型裁判团,被测模型换成两个真实档位:
| 维度 | Sonnet(大模型)被测 | Haiku(小模型)被测 | 解读 |
|---|---|---|---|
| 约束遵循(constraint) | 66.7% | 100% | 反直觉但机制清晰:强字数约束的外呼场景下,小模型天然简短的输出更守「极简话术」,大模型信息越丰富越易超限——能力越强 ≠ 越守指令 |
| 话术合规(style) | 50.0% | 87.5% | |
| 违规率 / 百判定 | 47.0 | 38.5 |
(产物:runs/modelcmp_sonnet|haiku/)这正是美团需要这类评测的原因:外呼模型选型若按通用能力榜单挑最大的模型,约束遵循反而可能更差——必须用任务指令实测。EvalCall 的模型对比报告直接服务选型决策,每个差异都附逐检查点证据。
实测中任务二被一票否决——深挖发现根因不在模型。EvalCall 内置指令体检器,自动检测指令的自相矛盾 / 不可行约束 / 歧义表述 / 缺失分支,并给出可直接照改的修订建议。以下全部是体检器在两条官方指令上的自主发现(提示词只教方法论,无任何硬编码结论):
指令要求「每次回复极简——最多15-20个字」,但 Step1 参考话术约 43 字、Step2 询问语约 38 字——官方提供的参考话术自己就是上限的两倍以上。任何模型都无法同时满足,实测被一票否决归零。
✏️ 建议:字数上限改为「单句不超过20字、单轮可多句」,或将参考话术拆为 ≤20 字短句分轮发出。
Call Flow 第 2 步说「单日合同需要连续 Y 天完成配送」,Knowledge Points 却写「单日合同在生效当天完成 X 单即可」——同一合同类型的履约周期在指令内部互相打架,模型说哪个都算错。
✏️ 建议:确认业务实际规则后统一表述;若是笔误,将 Call Flow 第 2 步改为「多日合同需连续 Y 天」。
整个流程没有商家明确拒绝(「不需要了解」「以后别打了」)时的退出路径。执行者无脚本可循,可能继续硬推,直接引发客诉与合规风险。同时缺失:负责人不在场、说「就1分钟」后仍被拒等路径。
✏️ 建议:补通用退出规则——商家明确拒绝时立即致歉挂断,不得再说任何产品内容。
X/Y/Z/W/$ 全部是未填充的占位符且无注入说明,模型只能照念「X单」;其中 Y 在开场白指「每日单数」、在第 2 步又指「连续天数」——同一个变量两种语义。
✏️ 建议:指令顶部增加「系统变量注入」区块,逐一注明变量含义与来源。
两条官方指令各检出 11 条问题,指令可行性分均为 0(确定性公式计算,可复现)。具体到美团运营的工位:写完一条新外呼指令,提交前跑一遍 lint_instruction.py,几十秒拿到「3 处冲突、1 个缺失退出分支」和照改建议——把一次潜在的全量客诉挡在上线之前。先治指令,再评模型,质检数据才有意义。
审完指令、评完模型,最后一个问题反噬自己——上面所有结论都依赖 LLM 裁判,可裁判自己也会错。谁来评测评测者?EvalCall 用「已知答案注入」校准自己:向系统投放人工构造、真值已知的合成对话(埋好各类违规、补救、未触发分支等难判情形),跑完整裁判流程,输出裁判的查准率/查全率/混淆矩阵。我们把自己裁判的准确率印在报告上——这是评测结果可以被信任的前提。
当前口径产物:runs/calibration/calibration_32case_gpt56sol_xhigh_v1.json。下方 92.1% 为此前跨 Claude 裁判团 v3 的历史对照,仍保留以展示提示词演进证据,不与当前模型口径混写。
所有标题数字统一用全量集口径;fail 查准 76.7%(误报偏多)原样披露。下表为跨模型机制的小样本探索记录(12 例),仅证方向:
| 指标 | 同模型 3 票(12 例探索性小样本) | 跨模型裁判团(同 12 例;样本小、差异未做显著性检验,结论为方向性而非定论) | 含义 |
|---|---|---|---|
| 整体准确率 | 86.5% | 94.2%(宏 F1 0.887→0.947;12 例小样本,方向性参考) | 裁判与已知真值的一致程度 |
| 违规查全率(fail Recall) | 100% | 100% | 一个违规都不漏——质检底线两种配置下都守住 |
| 违规查准率(fail Precision) | 61.1%(7 误报) | 78.6%(3 误报) | 不好看的数字我们直接印出来,然后用实验修它:偏严误报近乎减半 |
| pass 查全率 | 82.1% | 92.3% | flow 类「偏严误杀」显著缓解 |
| 置信度校准 | 判对 0.953 vs 判错 0.876(gap +0.077,有效) | 判对 0.951 vs 判错 0.950(gap ≈0,失效) | 跨模型混投的副作用,我们主动披露:不同模型的置信度不在同一刻度,混在一起即失去分层能力。结论:准确率用跨模型投票,可信度分层需按模型分别校准(路线图) |
| 指标 | 12 例基础集(跨模型裁判团) | 32 例对抗集(同为跨模型裁判团;难度 3 倍:引用脏话陷阱 / 违规后自纠 / 方言+ASR噪声多违规并发 / 流程乱序) |
|---|---|---|
| 整体准确率 | 94.2% | 90.3%(165 判定,fail support 11→36) |
| 违规查全率 | 100% | 88.9%(4 个刁钻违规漏判:自纠洗白、噪声掩护类) |
| 分类型 | — | constraint 100% · flow 90.4% · style 80% · forbidden 62.5% |
我们主动把考题加难、把回落的数字原样印出来:扩容集专门设计了「引用用户脏话钓关键词误判」「违规后立即自纠诱导洗白」这类陷阱,钓到裁判 4 次漏判——每次漏判都有逐条真值对照可审计(runs/calibration/)。同源声明(最重要的局限,我们自己先说):①真值为作者标注,属 known-answer self-check 而非独立 held-out 验证;②裁判判定准则与黄金集陷阱同源迭代——准确率应理解为「同源考题上的上界」。治理方案见仓库 GOVERNANCE.md。
针对「真值自标注+准则同源迭代」这一根本性质疑,我们构造了盲标注 held-out 集:标注者与裁判调优链严格隔离(不接触既有考题与裁判提示词),22 例 / 94 真值,专门埋入 8 种「绕过禁语」对抗手法(不说"验证码"改说"短信里那串6位数字"、反讽式贬损、利诱念码…)和 4 条反向陷阱(字面像违规实则合规:引用、否定句式、培训例句)。
| 指标 | 同源集(32例) | Held-out 盲标注集(22例) | 含义 |
|---|---|---|---|
| 整体准确率 | 90.3% | 94.7%(宏F1 0.845;本集「全判pass」平凡基线 74.5%;95% CI [88.0, 98.3]) | 独立集未崩盘且量级一致——初步缓解同源过拟合担忧。同集对照已补:v1 与 v3 在 held-out 上完全持平(94.7%=94.7%,逐类一致)——v3 准则的收益集中在同源对抗难例(92.1 vs 90.3),不损害泛化;「v3 更泛化」的说法不成立,我们如实不说 |
| 违规查全率 | 88.9% | 100% | 本集 20 个违规检查点 0 漏判,含 8 种禁语规避手法(每种 1-3 例,n 小:100% 召回的 95% CI 下界约 83%)——双判合议对规避话术的有效性获初步验证,非鲁棒性证明 |
| 反向陷阱误杀 | — | 0(pass 查准率 1.0) | 引用/否定句式/培训例句不被冤枉——归属判定准则起效 |
| forbidden / style 类准确率 | 62.5% / 80% | 100% / 100% | 合规质检最关键的两类在独立集上满分 |
| 残余弱点 | — | na 类 n=4(召回 2/4,95% CI [7%,93%]——样本不足以评估)、fail 查准率 0.80 | na 维度本集无法下结论;误报仍需复核——原样披露 |
完整产物:runs/calibration/heldout_v3.json(meta 含裁判团配置自证)、data/calibration/heldout_set.json(22 例全文+标注理由可审计)。诚实边界:盲标注者是与裁判调优链隔离的 AI 二次标注(同属 Claude 家族——共享先验可能系统性抬高一致率,94.7% 应视为上界);人类标注一致率(Cohen's Kappa)与异源家族交叉标注是生产前必做项。
| 裁判提示词版本 | 32 例对抗集成绩 | 说明 |
|---|---|---|
| v1(基础版) | 90.3% | 原基线 |
| v2(加 4 条防误判准则) | 73.3%(崩盘) | 改动前按预注册协议落盘了预测(fail 查全 ≥94%)——实测全面失败:谨慎准则诱发「na 逃避」(na 查准率仅 0.238,裁判拿不准就弃权)。预注册机制按设计拦截了这次倒退,它没有上线 |
| v3(4 准则 + na 纪律 + 双判合议) | 92.1%(宏F1 0.892;forbidden 类 62.5%→100%) | 按预注册决策规则正式采用为投稿版——升级有预测、倒退有拦截、采纳有数据,每一步留档可查 |
意外收获:v2 配置下置信度校准 gap 从 0.043 暴涨至 0.67(按模型分别校准:haiku 0.64 / sonnet 0.69 / opus 0.81)——裁判弃权或犯错时置信度显著更低,置信度过滤从「失效」变为「可用」,且 per-model 校准数据证实了「跨模型置信度必须分别校准」的判断。完整预测-对账记录见 runs/calibration/PREREGISTRATION_v2.md(预测原文未改,错在哪如实写)。
这组对照本身就是方法论结论:同一个模型连投 3 票只能消随机噪声,错会 3:0 一起错(实测 7 个误判全是全票一致地错);换 3 个不同模型投票才消得掉系统性偏见——准确率 +7.7 个百分点,误报近乎减半,漏判保持为零。剩余误判集中在「合理转述的开场白该不该算合规」这类口径分歧——正是校准要暴露给质检负责人拍板的。完整混淆矩阵见 runs/calibration/calibration.json(基线留档 calibration_samemodel_baseline.json)。
裁判提示词携带每条检查点的 source_quote 指令原文。开发中实测:不带原文时裁判对「应当以指定开场白开启」类检查点只能臆测(3 票 2:1 分裂);带原文后 3 票全对,整体投票一致率 88.9%。
每条 LLM 判定投 3 票取多数,报告同时公布一致率与分裂条目——分裂项自动标记建议人工复核,评测结论自带可信度分层。
被测模型与模拟器在干净上下文中运行,杜绝宿主环境信息泄入对话轨迹。开发中实测抓到一例轨迹污染(模拟模型拒演并泄露宿主信息),已通过隔离机制根除。
官方指令含英文引号时,小模型输出 JSON 必带未转义裸引号。内置裸引号修复器(实测失败样本单测覆盖),编译/判定链路对脏输出免疫。
质检团队要的不是分数,是能拍板的结论。三层闭环之上,评测出口落到「可上线 / 打回 / 无法判定」的门禁决策——2026-07-02 用门禁版流水线全量真实重跑:官方任务一(12 通 · 打回 · 履约 20%) · 官方任务二(打回 · 0 分挂指令归因警示) · 无冲突对照任务(分数正常分布,证明 0 分是检出不是失灵)。
任一 P0(安全红线/critical)失败 → 整体打回;报告头条直接给决策徽章 + 触发红线明细。裁判通道故障导致大面积「无法判定」时如实输出「无法判定」——绝不把「没判成」包装成「通过」(fail-closed 设计)。
辱骂、歧视、隐私泄露、未告知 AI 身份、诱导——独立于任务指令的全局 P0 红线轨(policy 单一规则源),业务分级 P0/P1/P2 对应打回/扣分/复核。
「这通电话到底有没有把活办成」——真实外呼第一 KPI。从任务 goal 生成 outcome 检查点,报告头条直接给履约达成率。判据口径可按业务定义一行替换。
用户质疑「你是不是机器人」时被测客服是否稳健应对、该表明身份时如实表明——合规导向实现(藏身份骗用户在履约场景反而可能踩线)。
模型改一版,同尺 checklist 下自动对比哪些检查点变好/变差;规则轨结论确定、LLM 轨标注「需复测确认」——真实对比产物:Haiku→Sonnet 3 好 7 差 22 不变。
从真实对话暴露的盲区挖「指令要求了但清单漏了」的候选检查点——溯源硬闸:source_quote 必须逐字回指指令原文,防「用模型输出反推评判标准」的循环论证;只进待人工确认区。
「模拟器测得充分」不能靠形容词。EvalCall 把每个检查点是否被轨迹实际检验(pass/fail vs na)汇总成触达率,并列出测试盲区清单:
| 任务 | 无反馈环(被动统计) | coverage-guided 反馈环开启后 |
|---|---|---|
| 任务一 · 骑手合同通知 | 94.4%(1 个盲区) | 100%(0 盲区) |
| 任务二 · 低延迟直播 | 77.8%(6 个盲区) | 100%(0 盲区) |
反馈环已实现且实证有效(任务二 +22.2 个百分点、盲区清零):每条轨迹判定完成后,仍未触达的检查点被标记为「优先攻击目标」注入下一条轨迹的对抗模拟器,主动制造触发场景——商家开车要挂断、Web控制台兜底引导这些此前测不到的分支被逐一逼出(绝对量:两任务合计补上 7 个盲区检查点——演示规模下绝对量小,机制价值在检查点数百条的生产规模显现;机制对标 coverage-guided behavioral fuzzing,evalcall/cli.py 主循环可查证)。触达口径已收紧:fail 须附原文证据才计触达,收紧后两任务仍保持 100%。评测系统不仅打分,还告诉你测试差什么、并主动补上。
官方任务二的字数约束 vs 参考话术冲突、任务一的业务规则自相矛盾——若直接上线,质检数据全失真。指令体检在评测前就能拦下。
被测模型一字不差说出指定开场白,单票裁判却判 fail——根因是裁判没拿到指令原文只能臆测。修复后 3 票全对。这正是「校裁判」层存在的意义。
被动统计模式下任务一有 1 个、任务二有 6 个条件分支从未被触达;开启 coverage-guided 反馈环后两任务触达率均达 100%、盲区清零——发现盲区到消灭盲区,闭环实证有效。
判别力实验首跑时两组各自重新编译检查点(LLM 编译器非确定性),对照失效——已产品化为 --checklist 固化复用机制并同尺重判。比较实验必须同尺,这条教训写进了 CLI。
| 指标 | 说明 |
|---|---|
| 约束违反数 / 百次对话 | 核心量化产出,可按 task / persona / severity 三维切片 |
| 四维能力画像 | 流程完整度 · 约束遵循率 · 异常处理 · 话术合规 |
| 检查点触达率 + 盲区清单 | 测试充分性的量化表达,反哺模拟器调度 |
| 裁判查准率 / 查全率 / 混淆矩阵 | 已知答案注入校准,评测结果自带误差棒 |
| 投票一致率 / 双轨冲突率 | 逐条结论的可信度分层,分裂项标记人工复核 |
| 指令可行性分 + 缺陷清单 | 指令体检产出,附可直接照改的修订建议 |
| EvalCall 设计 | 对应研究脉络 | 对照结论 |
|---|---|---|
| 指令→检查点编译 | TICK(ICLR'25)的 checklist 分解评测 | 同范式,但我们自动从指令编译且用对抗模拟器动态触发,而非静态评既有文本 |
| 规则+LLM 双轨 | IFEval(可程序化验证约束)+ MT-Bench 系 LLM-judge | IFEval 只覆盖可正则验证的约束,我们把语义约束一并纳入 |
| 对抗式用户模拟器 | τ-bench / τ²-bench(NeurIPS'24,Sierra)的 LLM 用户模拟 | τ 系列追求「像真人」(fidelity),我们追求「专挑指令崩溃路径」(adversarial coverage) |
| 裁判自校准 | JudgeBench(ICLR'25)的 meta-evaluation with verifiable ground truth | 同方法论,落到外呼质检场景 |
| 覆盖率反馈环 | FLARE 的 coverage-guided behavioral fuzzing(此前只用于代码/MAS 测试) | 此前公开应用集中在代码/MAS 测试,对话指令遵循质检方向未检索到先例 |
| 指令体检器 | —— | 公开文献空白:IFEval/ComplexBench/FollowBench 都假设指令是好的、只测模型;没有公开工作检测「指令本身是否自相矛盾/不可行/缺分支」 |
一句话定位:把 IFEval 的可验证约束、τ-bench 的用户模拟、JudgeBench 的裁判元评测,首次合成一个面向外呼 agent 的上线前主动压测闭环——并新增「指令体检」这个文献空白维度。「对抗式 × 覆盖率引导 × 外呼指令遵循」三元交集在我们的检索范围内未见公开先例(检索截至 2026-06,欢迎指正)。
| 测算项 | 数字与依据 |
|---|---|
| 质检单通调用量(评既有录音转写,无需模拟) | 32 检查点 ÷ 6/批 × 3 票 ≈ 18 次裁判调用 ≈ 4.5 万 token;规则轨前置零成本过滤可再省 30% |
| 质检单通成本(生产后端 qwen/deepseek 档 ≈¥0.002/千token) | ≈ ¥0.1–0.2 / 通 |
| 人工抽听对照 | 听录音+填质检表 10–15 分钟 ≈ ¥7–12 / 通(含人力综合成本) |
| 百万通/天规模的两种方案对账 | 现状·人工抽检 3%:3 万通 × ¥10 = ¥30 万/天,覆盖率 3% |
| EvalCall 全量:100 万通 × ¥0.15 = ¥15 万 + fail 标记复核(标记率按14%、附证据复核 1-2 分钟/条 ≈¥1.5)14 万 × ¥1.5 = ¥21 万 → ¥36 万/天,覆盖率 100% | |
| 结论 | 同量级预算下覆盖率 3% → 100%(33 倍);且复核不用重听录音——报告附对话原文+指令原文双重证据,单条复核从 10 分钟降到 1-2 分钟。fail 查准率(当前 76.7%)每提升 10 个百分点,复核账单再降约 ¥3 万/天——这正是「校裁判」层持续迭代的直接金钱价值 |
| 延迟与扩展性 | 演示通道 claude-cli 单案 165s 是本地子进程的限制;生产为批量 API——单通质检各自独立、可无限水平并行,墙钟由并发度决定而非架构。裁判升级后用重判工具从既有轨迹回溯,无需重跑对话 |
当前被测与裁判同为 Claude 家族,存在 self-enhancement bias。已实现跨档位裁判团(haiku/sonnet/opus 每票不同模型),生产部署将换异构家族(GPT/Qwen/Claude 交叉)+ 人工抽检锚点。
检查点编译靠 source_quote 溯源兜底,但「抽得全不全、severity 标得准不准」无金标准校验。路线图:把校准黄金集扩展到编译层(人工标注的标准检查点清单)。
演示规模下分数为观测值而非统计估计。已支持多轨迹 + pass^k 可靠性口径(对标 τ-bench),生产建议每 persona ≥20 条轨迹。
被测模型为通用 LLM 扮演(官方未提供真实外呼模型,所有参赛队同此约束);persona 为手工设计+盲区驱动补充。真实脱敏轨迹接入有现成格式适配层。
evalcall run --task task.yaml --personas all 编译指令 → 对抗模拟 → 双轨判定
evalcall report --run runs/xxx 生成可交互 HTML 报告
python3 lint_instruction.py task.yaml 指令体检:冲突 / 不可行 / 歧义 / 缺失分支
python3 calibrate.py 裁判自校准:已知答案注入 → 查准率 / 查全率
python3 rejudge_checkpoint.py runs/xxx all 3 裁判升级后从既有轨迹全量重判(无需重跑对话)