← 返回目录
ap5.5实操⏱ 约 11 分钟

回归门禁:分数跌了,不许上线

实测拦截一次"更便宜但更差"的改动——全课最该抄走的 50 行

🔎 最后验证 2026-08📚 来源:本节门禁演示为 ECS 实测(2026-08,deepseek-chat,基线 17.0 拦截 14.0,脚本与原始输出见本节代码)🧰 Python、DeepSeek API、CI
为什么学这个

前面几章你建了评测集、学会了判分。但评测只有变成"卡住上线的闸门",才真正产生价值——否则它只是一个"改完可以跑一下、忘了也没人管"的脚本。

这一节把评测做成门禁:分数跌了,退出码非零,CI 直接红灯

实测里它立刻救了一次场:一个"看起来更灵活、成本还低了 52%"的提示词改动,被门禁拦下了——因为分数从 17.0 掉到了 14.0

💡 打个比方

体检报告放在抽屉里,和体检不合格不许开车,是两种东西。

前者是"信息",后者是"制度"。AP5 前四节给你信息,这一节把它变成制度。

实测:门禁拦了一次"看起来更好"的改动

基线(v2):规则版提示词,20 条评测集跑 3 轮

✅ 已写入基线:17.0/20(版本 v2)
   错例 3 条(正品质疑判成商品咨询、医保卡问题、温和抱怨)

改动(bad):把优先级规则删掉,换成"请综合考虑用户的整体意图和情绪,灵活判断"——听起来更聪明、提示词更短更便宜

  本次得分:14.0/20(标准差 0.00)
  平均 token:1330 | 耗时 12s
  错例(6 条):
    「我买的鞋子小了,能换个大一码吗?」 应=退款 实=商品咨询
    「收到的杯子碎了!!!要求赔偿」   应=投诉 实=退款
    …

门禁判定
  基线(v2):17.0/20   本次(bad):14.0/20
  分差:-3.0   噪声地板:0.50   token 变化:-52%

  ❌ 拦截:分数下跌 3.0 超过噪声地板 —— 不许上线

注意那个 -52%:这次改动便宜了一半。如果只看成本仪表(ap1.6),你会以为这是一次成功的优化。只有评测门禁能告诉你:你用 3 分准确率换了这一半成本。

门禁的核心逻辑(50 行)

base = json.load(open("eval_baseline.json"))      # 基线快照
mean, sd, tok, errs = run_eval(rounds=3)          # 本次跑分(多轮取均值)
noise = max(base["sd"], sd, 0.5)                  # 噪声地板(ap2.5)
delta = mean - base["mean"]

if delta < -noise:
    print("❌ 拦截:分数下跌超过噪声地板")
    sys.exit(1)                                   # ← CI 因非零退出码而红灯
elif delta > noise:
    print("✅ 放行:真提升")
    if tok/base["tok"] - 1 > 0.2:
        print("⚠️ 但成本涨了 20% 以上,确认划算吗?")
else:
    print("⚖️ 打平")                              # 打平时看成本决定去留

四个设计要点:

  1. 多轮取均值(3 轮):单轮波动会误伤(ap2.5 的噪声地板);
  2. 噪声地板兜底(至少 0.5):防止基线记录的标准差偏小导致误拦;
  3. 同时看成本:分数持平但成本涨 20%,应该回退(ap2.4 的教训);
  4. sys.exit(1):这一行才是"门禁"——没有它,就只是个报告

挂进 CI

# .github/workflows/eval.yml(示意)
- name: 运行评测门禁
  env:
    DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
  run: python3 evals/gate.py        # 分数跌了 → 非零退出 → PR 红灯

配套的三条团队规矩(比技术更重要):

  • 改提示词/换模型/改检索参数的 PR,必须跑门禁;
  • 基线更新要单独提交(--update-baseline),并在 commit message 里写清"为什么允许这次变化";
  • 门禁红了不许强行合并——要么修,要么明确说明为何可接受(比如"用 3 分准确率换 50% 成本,产品决定接受")并记录在案

门禁要卡哪些指标

指标来源建议阈值
主任务准确率ap2.4 评测集不得低于基线 - 噪声地板
检索命中率(RAG)ap4.4同上
幻觉率ap5.4只许降不许升
格式合格率ap3.2 校验器应接近 100%,跌破即红灯
单次成本ap1.6 流水涨幅超过 20% 需人工确认
P95 延迟ap1.6 流水超阈值告警(不一定拦截)

别一次性卡太多:先卡 1-2 个核心指标(准确率 + 成本),跑顺了再加——门禁误报太多,大家就会开始绕过它

🔧 动手做:给你的项目装上门禁(15 分钟)

  1. 跑本节代码:先 python3 gate.py --update-baseline 建基线,再 PROMPT_VERSION=bad python3 gate.py 看它拦截。
  2. 换成你的评测集和提示词,建立你的基线快照(提交进 Git,基线是代码的一部分)。
  3. 故意做一次坏改动(删掉一条关键规则),跑门禁——它拦住了吗?
  4. 挂进 CI:GitHub Actions / GitLab CI 里加一步跑门禁(key 走 secrets,ap1.5 的规矩)。
  5. 写进项目 README:"改提示词的 PR 必须门禁绿灯"——把制度写下来。

做到这里你应该有:一个会 exit(1) 的门禁脚本 + 提交进 Git 的基线快照 + CI 配置 + 一条写下来的团队规矩。

为什么:🎯 这是全课最该抄走的 50 行代码。它把前面所有章节的努力(评测集、判分、指标)变成不可绕过的制度——从此"我觉得这样更好"必须先过一遍数字。

本课两次"白改"教训(ap2.4 加规则没用、ap2.5 加步骤没用)+ 这次"更便宜但更差"的拦截,合起来就是门禁存在的全部理由。

❓ 测验
实测中被拦截的改动,token 成本降了 52%。这说明门禁只看成本会怎样?
⚠️ 避坑基线不能随便更新——那等于把门拆了

最常见的门禁失效方式:门禁红了,开发者顺手跑一下 --update-baseline,红灯变绿灯,继续合并。这就是把门拆了

三条防御:① 基线文件的改动必须单独 PR 并有人审(和代码一样);② commit message 里必须写清为什么允许这次下跌;③ 定期回看基线历史——如果你的基线一路在降,说明你在温水煮青蛙。技术上再完善的门禁,也挡不住一个决定绕过它的团队;制度和技术要一起立

🤖 让 AI 帮你写门禁脚本
我的评测集在【路径/格式】,主要指标有【准确率/幻觉率/成本】。请帮我写一个可挂进 CI 的门禁脚本:1) 多轮跑分取均值 + 噪声地板判定;2) 与 Git 里的基线快照比较;3) 分数跌了 exit(1),打平时看成本给建议;4) 输出适合 CI 日志的摘要(含错例);5) 给出 GitHub Actions 配置示例(key 走 secrets)。
✅ 小结

门禁三句话:分数跌了 exit(1)(这一行才是门禁)、多轮取均值 + 噪声地板防误伤、成本和质量一起卡;基线更新要单独审——别自己把门拆了

AP5 最后一节讲评测体系的"活水":线上真实的失败样本怎么回流进评测集——让你的评测越用越准,而不是停留在上线那天的想象。

下一节 → 线上回流:让真实失败样本喂养评测集
🔎 来源与核验· 1 条,点开核对
本节每个关键论断都对应一个可追溯的来源 —— 这是本课程"靠谱、不过时"的底线。
「门禁实测:基线版提示词 20 条评测集 3 轮均分 17.0;改为「灵活判断」版后均分 14.0、token 下降 52%,门禁判定分差 -3.0 超过噪声地板 0.50,拦截并以非零退出码结束」
📚 ECS 实测 gate.py(2026-08,deepseek-chat,temperature=0)✓ 已核验 2026-08
智图软件的赞赏码
都看到这了,打个赏呗!
接下来 · ap5.6
线上回流:让真实失败喂养你的评测集
继续读下一节 →