第二十一节 — 评估闭环
这一节回答:FinBayes 的认知质量怎么衡量?怎么形成"评估 → 改进 → 再评估"的闭环?
为什么评估测试不等于普通测试
普通测试用 assert expected == actual,但 LLM 输出没有唯一正确答案。一个分析 ETH 走势的认知任务可以有多种合理输出 —— 不是 string 比对能判定。
评估测试用统计指标 + 数据集衡量质量趋势,而非单点断言:
| 维度 | 普通测试 | 评估测试 |
|---|---|---|
| 期望值 | 单一确定 | 一组合格输出(rubric) |
| 通过判据 | assert | 指标聚合 + 阈值 |
| 失败处理 | 修代码 | 修代码 / 修 Prompt / 修工具 / 标 case 入回归集 |
| 频率 | 每次 PR | 周期跑(nightly + release)+ 关键变更跑 |
| 数据规模 | 个位数 fixture | 几十到几百条评估样本 |
评估闭环的工程结构
这张图表达什么:评估数据集 → 跑 → 判定 → 报告 → 改进 → 失败 case 入回归集 → 再评估,是个闭环。每次改进都更新评估集,避免回归。
这张图特意不表达什么:具体评估工具实现(在工程实现仓);评估的真 LLM 成本(在 CHAP-18 成本指标)。
评估数据集(Eval Set)
数据集分层
| 层 | 用途 | 规模 | 跑频率 |
|---|---|---|---|
| 冒烟集 | 关键场景快速验证 | 10-20 条 | 每次 PR |
| 回归集 | 已发现失败 case 的固化 | 持续累积,初始 30-50 条 | nightly + release |
| 场景集 | CHAP-06 9 个场景的覆盖 | 每场景 5-10 条 = 50-100 条 | release |
| 抗扰集 | Prompt 注入 / 边界 case / 异常输入 | 持续累积 | release |
约束:
- 评估数据集进 Git + Review gate 覆盖(不能有 PR 偷偷删 case)
- 评估数据集不含真实用户数据(用脱敏 / 合成数据)
- 评估数据集不含凭证类样式(凭证不变量延伸到测试资产)
评估样本的结构
每条样本含:
| 字段 | 含义 |
|---|---|
sample_id | 全局唯一 |
scenario | 关联 CHAP-06 场景 |
input | 用户输入 + 上下文(如 Session 历史 / 画像 / Watchlist 状态) |
expected_capabilities | 期望具备的能力(如"必须给出反方" / "必须标失效条件" / "不应给方向性结论 if 数据缺失") |
negative_constraints | 不应出现(如"不能给执行类建议" / "不能输出凭证样式") |
rubric | 质量评分维度(见下) |
tags | 任务类型 / 难度 / 来源 / 等 |
评分 Rubric
每个样本对应一组评分维度:
| 维度 | 评分方法 |
|---|---|
| 反方覆盖完整度 | LLM-as-judge:检查输出是否含反方 + 反方质量打分 |
| 失效条件清晰度 | LLM-as-judge + 规则:必须含可观测的失效条件 |
| 证据归因 | 规则:输出中的关键结论必须有证据指向 |
| 信息缺口诚实度 | 规则 + 人工:缺数据时应该明示,不应硬编 |
| 输出格式契约 | 规则:综合层 schema 校验通过 |
| 表达密度匹配画像 | LLM-as-judge:是否过密 / 过疏 |
| 第一屏命中题眼 | LLM-as-judge:首屏是否回答用户主要疑问 |
| 边界约束遵守 | 规则 + grep:不出现禁词 / 不给执行类建议 |
每个维度独立打分(0-5)+ 汇总加权。
评估运行器
评估流程
关键约束:
- 评估运行器与 runtime 解耦 —— 运行器通过 runtime 公开 API 调用(CLI / Web API),不直接 import
- 每次评估记录 LLM 版本 + Prompt 版本 + Provider + 工具版本(可追溯哪次评估对应哪个组合)
- 评估结果库长期保留(看趋势 + 看回归)
质量判定方法
三种判定手段
| 手段 | 适用维度 | 优点 | 缺点 |
|---|---|---|---|
| 规则判定 | 格式 / 字段存在 / 禁词 / 边界 | 快 / 稳 / 便宜 | 难判语义质量 |
| LLM-as-judge | 反方质量 / 表达匹配 / 题眼命中 | 能判语义 | 贵 / 慢 / 自身有偏 |
| 人工抽检 | 关键 case / 争议结果 / 新数据集校准 | 真正可靠 | 极贵 / 不可大规模 |
LLM-as-judge 的工程约束
LLM-as-judge 是评估的核心手段之一,需要专门工程:
- judge LLM 与被评估 LLM 不同(避免自评偏见)—— 例如 GPT 评估 Claude 输出,反之亦然
- judge Prompt 本身是 Prompt 资产(详见 CHAP-19 Prompt 版本化)+ 与 rubric 同步演化
- judge 评分校准:用人工抽检的样本回头校准 judge 准确度(如 100 条人工标注 vs judge 判定的相关度)
- 高分歧 case(多 judge 不收敛)走人工
评估指标聚合
单次评估的核心指标
| 指标 | 含义 |
|---|---|
overall_score | 所有样本加权平均分 |
pass_rate | 总分 >阈值的样本比例 |
per_dimension_score | 各 rubric 维度的均分 |
per_scenario_score | CHAP-06 各场景的均分 |
regression_failures | 历史 pass 但本次 fail 的样本 |
boundary_violations | 边界约束违反次数(严重失败,单条即阻断) |
阈值与门禁
| 阈值类型 | 第一阶段建议 | 用途 |
|---|---|---|
overall_score >= 3.5/5 | 软阈值 | 看趋势,下滑明显需排查 |
pass_rate >= 80% | 软阈值 | 同上 |
regression_failures == 0 | 硬阈值 | 回归集必须全过,否则 release 阻断 |
boundary_violations == 0 | 硬阈值 | 边界违反 = release 阻断 |
关键约束:
- 软阈值用于趋势监控,不作 PR 门禁(避免 Goodhart's law —— 优化指标牺牲真实质量)
- 硬阈值仅限回归集 + 边界违反 —— 这两类是不可妥协的
- 评估结果不直接喂回 LLM 训练 / Prompt 自动优化(避免反馈循环失控)—— 改进需要人工分析 + 工程决策
离线评估 vs 在线评估
离线评估
| 何时跑 | 跑什么 |
|---|---|
| 每次 Prompt 变更 PR | 冒烟集 + 该 Prompt 关联的子集 |
| nightly | 回归集 + 抗扰集 |
| release 前 | 全部数据集 + 性能基线对比 |
| 重要架构变更 | 全部数据集 + 人工抽检 |
在线评估
第一阶段单机部署,"在线"指用户真实使用过程中的质量信号:
| 信号 | 采集方式 |
|---|---|
| 用户对候选状态的接受率 | candidate → confirmed / rejected / edited 的比例 |
| 用户对 Judgment 的"赞 / 否 / 编辑" | UI 提供反馈按钮(可选) |
| 用户主动重提问的频率 | 同一会话内连续多次提问 = 上一轮没满足 |
| 用户取消任务的频率 | 高 = 任务质量或速度问题 |
| 触发 clarify 的频率 | 高 = 意图识别不准 / 输入难懂 |
约束:
- 在线评估信号严格 per-user 隔离(不跨用户聚合 —— 隐私)
- 用户显式同意才上报到 FinBayes 团队(默认仅本地审计 trail)
- 上报仅含统计数据(不含具体输入输出 / 用户画像)
评估驱动改进
改进类型
| 评估发现的问题 | 改进路径 |
|---|---|
| 某场景反方覆盖不足 | 调综合层 Prompt + 加 fixture |
| 某任务类型表达过密 | 调表达密度模板 + 与画像联动 |
| 某 Provider 在特定任务上质量差 | task_routing.yaml 调路由 |
| 某工具调用频次过低 | 工具描述优化 + LLM Function Calling 测试 |
| 某边界 case 被识别成正常输入 | 边界 hook 规则增强 + 加边界测试集 |
| 信息缺口未明示 | 综合层 schema 强约束 + Prompt 加固 |
改进流程
约束:
- 改进不绕过评估闭环 —— 改完必须重跑评估
- 失败 case 进回归集避免反复跌入同一坑(这是 case library 的真正用途,详见下文)
- 每次重要改进记 ADR 或工程日志
Case Library 的角色(澄清)
战略层提到"Case Library"作为认知质量的回归追踪 —— 工程层的承接:
| Case Library 是 | Case Library 不是 |
|---|---|
| 评估数据集中的"回归集" | release 门禁的强制清单 |
| 历史失败 case 的累积 + 复测 | 测试覆盖率的代名词 |
| 看"质量是否退步"的趋势 | "0 命中 = 完美"的 KPI |
| 工程与战略层共同维护的资产 | 工程一方说了算的工具 |
详见 CHAP-03 架构目标与质量取舍。
评估资产的演化
评估数据集 / rubric / judge prompt 本身也需要演化(详见 CHAP-19 Prompt 版本化):
| 资产 | 演化策略 |
|---|---|
| 评估样本 | 累积 + 标过期 + 不强行删除(历史可追溯) |
| Rubric 维度 | 加 minor / 改语义 major + 重跑历史样本生成新基线 |
| Judge Prompt | semver + 切换时记录"哪一时点起用新 judge" |
| 阈值 | 可调,但每次调整记录理由(避免悄悄放水) |
第一阶段不做的评估能力
明示不做:
- 真实用户 A/B 实验(单机部署不需要)
- 自动 Prompt 优化(如 DSPy 等)—— 评估反馈喂回 Prompt 优化器,第一阶段不引入
- 多用户聚合趋势报表(隐私 + 第一阶段单用户)
- 实时质量监控告警(评估周期跑足够)
这些都不是不可演化(评估接口契约不变),只是第一阶段不抢答。
与其他章节的关系
- 评估覆盖的场景 → CHAP-06 关键业务场景
- 评估依赖的可观测性 → CHAP-18 可观测性
- 评估驱动 Prompt 演化 → CHAP-19 演化与版本管理(ADR-009 待写)
- 评估资产的 Review gate → CHAP-17 边界与安全
- 评估如何接入 CI → CHAP-20 测试体系
- Case Library 的战略来源 → CHAP-03 架构目标与质量取舍