Files
story/docs/agent-evaluation.md
T

177 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Agent固定评测集与发布门禁
## 1. 目的和需求对应
本文落实原需求 `P0252`“建立可重复的评测集和质量指标”。评测执行器把固定测试集、脱敏观测结果、评分规则、阈值、Agent版本和模型配置版本组合成一份可重复生成的JSON报告。相同评测集既可用于模拟供应商,也可用于真实账号;两种环境使用同一评分口径,但报告必须明确标记`mock`或`real`,不得用模拟结果代替真实账号验收。
评测报告可以直接转换为运营配置接口所需的登记正文,并固定标记为`AGENT_QUALITY_V1`。运营配置发布仍由既有双人审批、资源引用和评测门禁控制;`AGENT_BUNDLE`只有登记了`PASSED`标准Agent质量证据才可以发布,普通手工`GENERIC`证据不能绕过该门禁。
## 2. 交付组成
| 文件 | 作用 |
|---|---|
| `cmd/agent-eval` | 读取评测集和观测结果,生成报告;退化时返回非零退出码 |
| `cmd/agent-eval-collect` | 通过受权限控制的SaaS接口读取每个用例的通话状态和最终话轮,自动生成脱敏观测文件 |
| `cmd/agent-eval-register` | 校验评测集和报告完整性,使用确定性幂等键把证据登记到指定运行配置版本 |
| `internal/agenteval` | 输入校验、逐用例评分、聚合指标、阈值判断和登记正文生成 |
| `testdata/agent-eval-suite.v1.json` | 首版固定评测集、预期结果和评分规则引用 |
| `testdata/agent-eval-collection.example.v1.json` | 用例、唯一通话编号和脱敏评分卡的采集清单示例 |
| `testdata/agent-eval-observations.mock.v1.json` | 可重复执行的模拟供应商脱敏观测样例 |
| `artifacts/agent-eval-report.mock.v1.json` | 当前模拟基线报告和可登记正文 |
测试集与观测文件只保存合成用例编号、时延、回答长度、布尔评分和计数,不保存完整对话、姓名、录音、提示词或供应商长期凭证。真实试点问题应先脱敏并分配稳定用例编号,再进入评测集。
## 3. 固定覆盖范围
评测集缺少以下任一类别时,执行器直接判定输入无效,不生成“通过”结论:
1. 正常闲聊 `normal_chat`;
2. 长停顿 `long_pause`;
3. 重复表达 `repeated_expression`;
4. 姓名和日期歧义 `name_date_ambiguity`;
5. 冲突事实 `conflicting_fact`;
6. 情绪话题 `emotional_topic`;
7. 用户打断 `user_interruption`;
8. 网络波动 `network_fluctuation`;
9. 记忆召回 `memory_recall`;
10. 敏感信息 `sensitive_information`。
每个用例必须声明预期通话结果、首个回答时延上限、回答长度上限、虚构事实数量上限、至少一个评分标志和版本化评分规则引用。观测结果必须与评测集中的用例一一对应,不能缺失、重复或混入未知用例。
## 4. 质量指标
执行器同时执行“逐用例门禁”和“整套指标门禁”。逐用例失败能够定位到具体用例;聚合指标用于识别Agent版本整体退化。
| 指标 | 计算方式 | 默认基线用途 |
|---|---|---|
| 通话成功率 | 成功用例数 ÷ 全部用例数 | 检查完整对话是否可用 |
| 首个回答P95时延 | 全部用例首个回答时延的最近秩P95 | 检查回答等待时间退化 |
| 打断恢复率 | 打断用例中通过`interruption_recovered`的比例 | 检查打断后能否继续交流 |
| 平均回答长度 | 全部用例回答字符数平均值 | 防止回答变得过长 |
| 称呼准确率 | 要求`salutation_correct`的用例通过比例 | 检查长者称呼使用 |
| 记忆准确率 | 要求`memory_correct`的用例通过比例 | 检查是否使用正确长者记忆 |
| 虚构事实数 | 全部用例虚构事实计数之和 | 阻止无来源事实进入内容闭环 |
| 故事来源完整率 | 要求`story_source_complete`的用例通过比例 | 检查候选内容可追溯性 |
| 敏感信息处理率 | 敏感信息用例通过比例 | 检查敏感内容不进入普通故事或记忆 |
阈值保存在评测集文件中并随版本提交。修改阈值必须创建新的`suite_version`,不能覆盖已经用于发布结论的旧版本。
## 5. 自动采集与评分边界
每个用例完成一次独立通话后,采集清单把`case_id`关联到唯一`conversation_id`,并填写人工评分器或经过批准的自动评分器产生的脱敏评分标志。一个通话编号不能复用于多个用例。
采集器通过当前登录用户的OIDC访问令牌调用:
```text
GET /api/v1/conversations/{id}
GET /api/v1/conversations/{id}/turns?limit=100
```
服务端继续执行客户组织、家庭、长者和资源权限检查。采集器自动计算以下机器可观察结果:
- 通话状态为`COMPLETED`且存在有效长者—智能体话轮时,判定控制和内容链路成功;
- 从第一条长者话轮结束到随后第一条智能体话轮开始计算首答时延;
- 使用本通话最长的智能体最终话轮字符数作为回答长度,避免多个短回答掩盖单条过长回答;
- 观测文件只保留`conversation:<id>`证据引用,不复制最终字幕正文。
称呼是否准确、记忆是否正确、是否虚构、故事来源是否完整、敏感信息是否正确处理属于语义判断。采集器要求评分卡显式提供这些字段,但不会因为通话完成而自动写成`true`。缺少任一用例、重复使用同一通话或缺少必需评分字段时,采集直接失败。
准备一个权限受控且只包含一行OIDC访问令牌的临时文件,然后执行:
```powershell
$env:GOCACHE = (Resolve-Path '.').Path + '\.gocache'
go run ./cmd/agent-eval-collect `
-suite ./testdata/agent-eval-suite.v1.json `
-manifest ./testdata/agent-eval-collection.example.v1.json `
-api http://127.0.0.1:58080 `
-access-token-file <临时令牌文件> `
-out ./artifacts/agent-eval-observations.current.json
```
示例清单中的通话编号仅为格式占位,执行前必须替换为本次十个独立用例产生且当前账号有权读取的真实编号。访问令牌不会写入观测文件、报告或日志;执行后应删除临时令牌文件。
## 6. 生成评测报告
在项目根目录执行:
```powershell
$env:GOCACHE = (Resolve-Path '.').Path + '\.gocache'
go run ./cmd/agent-eval `
-suite ./testdata/agent-eval-suite.v1.json `
-observations ./testdata/agent-eval-observations.mock.v1.json `
-report-ref 'artifact://agent-eval-report.mock.v1.json' `
-out ./artifacts/agent-eval-report.mock.v1.json
```
退出码含义:
- `0`:输入完整且所有用例和聚合阈值通过;
- `1`:评测正常完成但存在退化,报告仍会写出;
- `2`:评测集、观测结果、报告引用或文件格式无效,不能形成质量结论。
真实账号评测只需把观测文件的`environment`改为`real`,填写实际Agent版本、同一模型配置引用和真实执行时间,并用同一套用例编号记录脱敏评分。真实观测不得复制完整个人对话;需要人工复核时,报告仅保存受控证据系统中的引用。
## 7. 登记到配置发布流程
报告中的`registration_payload`是以下接口的JSON正文:
```text
POST /api/v1/ops/config-versions/{id}/evaluations
Idempotency-Key: <稳定且唯一的评测登记键>
If-Match: "<配置版本行版本>"
```
推荐流程如下:
1. 固定Agent版本、模型配置引用和评测集版本;
2. 在模拟供应商环境执行,修复输入、流程和明显质量问题;
3. 在真实账号环境执行同一评测集,形成独立的`real`报告;
4. 将真实报告存入受控交付位置,使用其引用和`registration_payload`登记评测证据;
5. 由非配置创建人完成发布审批;
6. 任一关键指标低于阈值时保持`FAILED`,不得手工改写为`PASSED`;修复后使用新的Agent或配置版本重新执行。
登记前先执行只读校验:
```powershell
go run ./cmd/agent-eval-register `
-suite ./testdata/agent-eval-suite.v1.json `
-observations ./testdata/agent-eval-observations.mock.v1.json `
-report ./artifacts/agent-eval-report.mock.v1.json `
-tenant <客户组织UUID> `
-config <运行配置版本UUID> `
-dry-run
```
只读校验会用评测集和观测文件重新计算完整报告,再检查评测集SHA-256、版本、模型配置引用、用例数量、通过/失败结论和`registration_payload`是否逐项一致,并显示本次登记的确定性幂等键。评测集、观测、报告或登记正文任一项被单独修改,命令都会拒绝发送。
确认无误后,使用运营人员OIDC令牌登记:
```powershell
go run ./cmd/agent-eval-register `
-suite ./testdata/agent-eval-suite.v1.json `
-observations ./testdata/agent-eval-observations.mock.v1.json `
-report ./artifacts/agent-eval-report.mock.v1.json `
-tenant <客户组织UUID> `
-config <运行配置版本UUID> `
-api http://127.0.0.1:58080 `
-access-token-file <临时令牌文件>
```
同一配置版本和同一报告正文始终生成相同的`Idempotency-Key`。登记器发送前会复制指标并注入目标`config_version_id`,不修改磁盘上的原始报告。第一次成功返回HTTP 201,响应丢失后重试返回同一评测记录和HTTP 200,不会重复产生发布证据。服务端还会复核`evidence_type`、报告结构、评测集摘要、用例计数、结论一致性和全部必需指标;标准证据只能属于`AGENT_BUNDLE`,且`model_config_ref`必须严格等于`runtime-config-version:<该组合的model_version_id>`,防止把另一模型或另一组合的报告误作当前发布证据。访问令牌不进入命令输出、报告或幂等键。
因此,执行候选组合评测前应从固定评测集复制一个本次运行文件,只把`model_config_ref`设为目标组合模型组件的规范引用;用例、分类、预期、评分规则和阈值保持不变。观测文件必须使用同一引用。仓库中的模拟基线报告用于证明工具链可运行,不应直接登记到模型组件编号不同的候选组合。
`FAILED`报告默认拒绝登记,防止操作人员误把调试产物当成发布证据。如果项目需要保留失败历史,必须显式增加`-allow-failed`;它只登记`FAILED`证据,仍不能满足配置发布门禁。
模拟报告证明评测工具和评分闭环可运行,不证明真实语音质量、真实首包时延、真实打断体验或供应商配额已经验收。
阶段8使用[真实Agent模型质量一致性证据](real-agent-models-evidence.md)把本报告与Embedding六类召回/隔离、内容安全六类策略、数据条款和额度证据绑定到同一候选。`agent-eval`报告仍是内容生成质量的唯一评分来源;聚合门禁会重新计算它,不接受只复制结论的手工摘要。
## 8. 扩展规则
- 新增用例可以扩展类别,但不能删除十类强制覆盖。
- 自动评分器和人工评分器都必须输出相同的脱敏观测结构。
- 评分标志的含义发生变化时,必须更新`scoring_rule_ref`和评测集版本。
- 同一报告必须能够追溯`suite_sha256`、Agent版本、模型配置引用、运行环境和执行时间。
- 发布候选只执行一遍完整固定集;普通功能子批次只运行受影响用例,符合项目“功能完整、验证精简”的测试策略。