测试 · fixture · CI 门禁 · 本地工程模式

Jev 回归测试:确定性 fixture、概率容差与 CI 门禁

一份可落地的 Jev 回归测试指南:冻结可重放 fixture,断言 schema、决策和副作用,用有依据的容差比较概率,在 CI 中拦截有意义的 diff,诊断漂移,并保留人工审核。

先说结论

有用的 Jev 回归测试不是保存一段 prompt,而是保存一台有版本的“测量仪器”。重放同一份脱敏 state、问题、criteria、provider 路径和解析后的模型;精确断言类型化决策与必需副作用;概率用区间或差值比较;CI 只按你在看到候选结果前就写好的策略阻断。红色构建是诊断请求,不是让你反复调用直到出现想要答案的许可。

本文描述的是应用侧的测试模式,不是 provider 的保证。冻结完整的评测工件,保留原始响应与失败记录,根据有标签数据和重复运行结果选择容差,并为每次 baseline 变化安排审核。本文不使用月搜索量估计。

先画边界:哪些属于 provider,哪些属于应用

每个承诺都有明确负责人,回归测试才有可信度。

本地 fixture 契约

冻结测量仪器

把 state 投影、问题文本、criteria、provider 路径、解析后的模型标识和决策规则放在同一份记录里。即使业务代码没动,别名解析结果或问题文本变了,也说明测量仪器变了。

本地发布策略

断言行为,不要迷信浮点数

对有标签的决策和必需副作用做精确断言。概率用事先声明的容差或区间比较;不要因为浮点数从 0.873 变成 0.871 就阻断发布。

人工决策

保留人工审核环节

红色 diff 是证据,不是“安全/不安全”的自动结论。保留本次运行,检查受影响切片;接受新 baseline 或放宽容差前,必须有明确的人工审核者。

构建确定性的可重放 fixture

fixture 是一份最小但完整的记录:另一位工程师可以用它重现决策,也能解释 diff 为什么出现。

fixture_id

稳定 ID;不要用行号当身份。

state

脱敏后的证据,移除不稳定时间戳和密钥。

questions

运行时使用的精确 type、instructions 和 criteria。

expected

人工标签与本地通过/复核策略,不是 provider 承诺。

instrument

投影、问题、provider 和解析后的模型版本。

下面的 JSON 是说明性的 manifest,不是 Jev 的配置格式。把 provider 原始响应、请求元数据和 adapter hash 放在旁边。如果模型别名解析到了不同版本,应记录为测量仪器变化,而不是静默重写 baseline。

fixture.json
{
  "suite": "refund_completion_v3",
  "fixture_id": "completed-017",
  "input": {
    "state": "Order ORD-1042 was delivered. The refund was issued in full.",
    "questions": {
      "completed": {
        "type": "noul",
        "instructions": "Decide whether the refund process is complete.",
        "criteria": {
          "true": "The evidence says the refund was issued in full.",
          "false": "The refund is pending, partial, or not evidenced."
        }
      }
    }
  },
  "expected": {
    "decision": "true",
    "pass_min": 0.82,
    "review_min": 0.55
  },
  "instrument": {
    "provider": "your-provider",
    "model": "pinned-model-id",
    "projection_version": "refund-trace-v2",
    "question_version": "completion-v3"
  }
}

同时断言 schema、决策和副作用

类型化输出可以缩小断言面,但不能代替普通测试代码。

信号要断言什么建议的门禁
Noul / boolean有标签的结果必须是 true 或 false,并且概率位于声明的通过/复核区间内。决策精确匹配;概率使用区间或容差。
Choice选中的选项必须是预期标签。如果接近并列会带来风险,再检查前两项的差距。标签精确匹配;只有任务确实需要时才设置 margin 阈值。
Score / rubric分数必须落在接受区间内,同时保留原始分数供趋势分析。使用区间或聚合指标差异;不要对单个样例过拟合。
应用状态工作流确实创建了要求的记录、工具调用、队列项或状态。说得像做过,不代表副作用真的发生。由普通测试代码精确断言数据库、API 或 UI 状态。

无效响应必须 fail closed。超时、分布格式错误或字段缺失,不等于负面决策。报告中保留这种区别,避免把基础设施失败污染语义指标。

assertions.ts
const PROBABILITY_TOLERANCE = 0.05;

function checkCase(baseline, current, expected) {
  const decisionChanged = baseline.decision !== current.decision;
  const probabilityDelta = Math.abs(
    baseline.probability - current.probability,
  );

  if (current.decision !== expected.decision) {
    return { status: 'fail', reason: 'decision changed against the label' };
  }

  if (decisionChanged && probabilityDelta > PROBABILITY_TOLERANCE) {
    return { status: 'fail', reason: 'decision flip exceeded tolerance' };
  }

  if (probabilityDelta > PROBABILITY_TOLERANCE) {
    return { status: 'review', reason: 'probability moved beyond tolerance' };
  }

  return { status: 'pass', probabilityDelta };
}

概率容差:比较变化,不要比较噪声

使用与风险匹配的最小策略。下面的数字只是示例,不是通用默认值。

先看决策

对于有标签的 fixture,选中的 choice 或 boolean 通常是硬断言。概率从 0.873 变成 0.871 本身不是回归;决策翻转才是另一种信号。

明确区间

对阈值自动化,保存通过、复核和失败区间。用留出标签或重复运行拟合边界,并把公式和分母放在门禁旁边。不要把一次好看的运行结果包装成保证。

升级边界样例

接近阈值的案例应进入复核或重复运行,而不是自动放宽容差。高风险决策要记录翻转率、前两项差距和切片影响。

谨慎做聚合

比较均值、错误率或校准指标时,同时写清样本量和切片定义。如果多个事件来自同一会话或客户,应按独立单位重采样。

把 diff 变成 CI 门禁

每次变更都跑小型确定性契约套件,再把有限的 live provider 预算留给受控 smoke 或 release 套件。

.github/workflows/jev-regression.yml
name: Jev regression suite

on:
  pull_request:
  push:
    branches: [main]

jobs:
  jev-regression:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: pnpm install --frozen-lockfile
      - run: pnpm eval:jev --           --fixtures evals/fixtures.jsonl           --baseline evals/baseline.json           --tolerance 0.05           --write-current artifacts/jev-current.json           --markdown artifacts/jev-regression.md
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: jev-regression-report
          path: artifacts/

工作流里的 `eval:jev` 是你仓库自有 wrapper 的占位名。社区 harness 可能提供相似的 baseline 和 tolerance 参数,但它们都不是 provider 的官方接口。让 wrapper 只在预先声明的关键案例或聚合门禁失败时返回非零,并在成功和失败时都上传完整报告。

先诊断红色构建,再动 baseline

好的失败报告会直接指向下一步,也能阻止“重试到绿色”。

失败类别保留的证据下一步
请求格式错误或解析失败载荷 hash、schema 错误、响应体和 adapter 版本。修复契约;在打分前拒绝不兼容的 provider 响应。
超时、限流或认证失败HTTP 状态码、request ID、尝试次数、退避记录和 provider/模型身份。先归类为基础设施问题;不要把“没有结果”转换成错误决策。
测量仪器相同,但有标签决策变了旧/新成对输出、概率差、fixture 标签和受影响切片。在审核者解释变化前,按语义回归处理。
fixture 或标签本身有问题脱敏 diff、来源引用、标签溯源和审核历史。带着溯源信息修正,并保留旧记录;不要为了让 CI 变绿而删除历史。

打印旧/新分布、模型和 provider 身份、fixture 标签、request ID、延迟和重试元数据。把无结果案例与错误决策分开,并把 baseline 更新保留为有理由的审核变更。

人工审核是测试设计的一部分

自动化采集和比较;把风险判断交给真正负责的人。

  1. 1

    确认 fixture 仍然具有代表性且脱敏正确。如果产品行为是有意改变的,更新需求和溯源,而不是只改 expected label。

  2. 2

    检查成对证据,而不是只看聚合分数。对关键失败读取 state 投影、问题、criteria 和原始响应。

  3. 3

    判断变化是孤立的,还是集中在某个切片:语言、来源、严重程度、证据完整度、选项数量或距离阈值的远近。

  4. 4

    只选择一个明确结果:修 adapter、重试合资格的基础设施失败、带溯源修 fixture、阻断发布,或由指定审核者接受新 baseline 并设置复查日期。

  5. 5

    保留旧工件和新工件。baseline 是决策记录,不是可以随手丢弃的缓存。

不要把概率阈值说成安全证书。本地门禁只说明:在这组 fixture、这台测量仪器和这套策略下,这个仓库如何处理结果。它不能证明 provider 的准确率、未来稳定性或测量范围之外的业务安全。

Jev 回归测试常见问题

Jev 回归测试 fixture 应该包含什么?

至少包括稳定的 fixture ID、脱敏 state、精确的 typed questions 和 criteria、人工标签或接受条件、本地决策策略,以及 provider/模型/测量仪器版本。把原始响应和请求元数据放在旁边,这样结果变化可以被诊断,而不是只显示为红色。

应该断言 Jev 的精确概率吗?

通常不应该。对 typed decision 和必需副作用做精确断言,再用声明的容差或区间比较概率变化。精确浮点快照很脆弱。容差应来自留出标签、重复运行波动和错误成本;本文示例中的 0.05 不是通用默认值。

如何在 CI 中设置 Jev 回归门禁?

每个 pull request 跑不调用 provider 的契约套件,再用固定 fixture 跑受控的 live provider smoke 或 release 套件。保存当前运行,与经过审核的 baseline 比较;只在预先声明的关键案例或聚合门禁失败时阻断,并在失败时也上传报告。把 wrapper 放在仓库里,让策略可审查。

决策发生变化说明了什么?

可能是语义回归、需求有意变化、问题或 state 投影变化、provider/模型变化、fixture 缺陷,或被误归类为决策的基础设施失败。先比较完整测量仪器和原始响应。审核者说清原因和动作之前,不要更新 baseline。

Jev 回归套件能证明系统安全吗?

不能。它只能为实际测量过的 fixture、标签、测量仪器和门禁提供可重复证据,不能建立 provider 保证,也不能覆盖未代表的流量。加入关键案例硬门禁、切片分析、延迟人工标签和生产监控,并明确每个结论的范围。

什么时候必须人工审核 Jev 结果?

关键案例失败、接近阈值的样例、新增或删除 fixture、集中在某个切片的回归、baseline 变化,以及 provider 或模型版本变化导致的结果,都应该审核。尤其要注意:聚合指标稳定,不代表高后果案例没有翻转。