Files
zk-data-agent/docs/technical-architecture/13-skill-evaluation-workbench.md
T
2026-07-23 16:49:53 +08:00

452 lines
13 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.
# 13. Skill 评测实验台设计
## 1. 背景
当前快慢分流优化需要完成一条完整链路:
```text
已有评测集
-> 使用现成 Skill 判断快慢
-> 支持单条和批量运行
-> 对比人工标签和模型判断
-> 查看分歧及判定依据
-> 更新 Skill 或切换模型
-> 重新评测并比较变化
```
这里讨论的是离线优化和评估场景。评测过程允许 Agent 使用完整 Agent Loop,重点是判断质量、依据可追溯和标准持续收敛。线上快慢路由的耗时、成本和部署形态属于后续独立问题。
本设计假设快慢分流 Skill 已经存在。实验台负责稳定调用和评估 Skill,不负责定义 Skill 内部的分类标准。
## 2. 目标
实验台需要支持:
- 单条输入调用指定 Skill,返回判断、理由和执行记录。
- 上传 CSV、XLSX 或 JSONL,配置字段映射后批量运行。
- 选择模型和不可变的 Skill 版本。
- 后台并发执行,支持暂停、继续、取消和失败重试。
- 自动计算总体、分类别和分垂域指标。
- 集中查看人工与模型分歧,并进行人工复核。
- 查看模型声明的 Skill 判定依据和实际访问记录。
- 对比不同 Skill 版本或模型版本的修正与退化。
- 导出原始结果、复核结果和版本对比结果。
实验台不承担:
- 在线请求的实时路由。
- 快系统能力或分类原则的编写。
- 将每个普通 Skill 自动转成页面应用。
- 修改现有聊天 Agent 的会话和运行流程。
## 3. 总体架构
```mermaid
flowchart LR
UI["快慢分流评测页面"] --> EXP["Evaluation Service"]
API["Skill Run API"] --> EXP
EXP --> MAP["Dataset Mapping"]
EXP --> SNAP["Skill Snapshot"]
EXP --> SCHED["Batch Scheduler"]
SCHED --> RUNNER["Headless Skill Runner"]
RUNNER --> AGENT["LocalCodingAgent"]
RUNNER --> MODEL["指定模型"]
RUNNER --> SKILL["固定 Skill 快照"]
EXP --> STORE["Evaluation Store"]
STORE --> RESULT["指标 / 分歧 / 复核 / 版本对比"]
```
新增能力由五个部分组成:
1. `Evaluation Service`:管理数据集、实验配置、运行和结果。
2. `Dataset Mapping`:把不同格式的数据转换为统一 case。
3. `Skill Snapshot`:固定每次实验使用的 Skill 内容。
4. `Headless Skill Runner`:使用现有 Agent Core 在后台执行指定 Skill。
5. `Batch Scheduler`:拆分、并发和恢复批量任务。
## 4. 与现有 Agent 的隔离
现有聊天链路保持不变:
```text
/api/chat
-> AgentState
-> account/session-scoped LocalCodingAgent
-> 聊天 session 和活动流
```
评测链路新增独立入口:
```text
/api/evaluations
-> EvaluationRuntime
-> evaluation-scoped LocalCodingAgent
-> 评测任务、case 结果和内部执行记录
```
两条链路可以复用:
- `LocalCodingAgent`
- `ModelConfig`
- Skill loader
- Tool handler
- `OutputSchemaConfig`
- 模型兼容层
评测链路必须独立管理:
- Agent 实例。
- Session 命名空间。
- 数据库记录。
- 运行队列。
- 并发和资源配额。
- Skill 快照。
评测产生的内部 Agent session 不进入左侧聊天会话列表,也不读取聊天历史、用户记忆或当前聊天 session 状态。
代码隔离只能保证功能不互相污染。批量任务仍可能争用模型服务资源,因此评测任务需要独立 worker pool、并发上限和低于聊天请求的调度优先级。有条件时可以为评测配置独立模型地址。
## 5. 数据集字段映射
评测文件格式由数据来源决定,不应写进 Skill,也不应要求用户临时组织成提示词。
上传文件后,系统先读取表头和样本,用户把源字段映射到统一字段:
| 统一字段 | 说明 | 必填 |
|---|---|---|
| `case_id` | case 唯一标识 | 否,可自动生成 |
| `query` | 当前用户 query | 是 |
| `gold_route` | 人工快慢标签 | 评测时必填 |
| `history` | 对话历史 | 否 |
| `context` | 设备、位置等上下文 | 否 |
| `domain` | 垂域 | 否 |
| `request_id` | 线上 RID | 否 |
| `metadata` | 其他保留字段 | 否 |
| `source_row` | 原始行 | 自动保留 |
页面需要支持:
- 列名自动推荐。
- 手动选择源字段。
- JSON path,例如 `data.query`
- 标签值转换,例如 `快/慢``0/1``fast/slow`
- 必要的字段组合和简单转换。
- 转换后样本预览。
- 缺失字段、非法标签和重复 ID 校验。
确认后的映射保存为可复用的 `Dataset Mapping Profile`。Skill Runner 只接收统一 case,不感知原始文件的列名和格式。
统一 case 示例:
```json
{
"case_id": "001",
"query": "到目的地电量够不够",
"gold_route": "fast",
"history": [],
"context": {},
"domain": "地图导航",
"request_id": "",
"metadata": {},
"source_row": {}
}
```
## 6. Skill 版本与快照
实验不能只记录 Skill 名称。Skill 内容会持续更新,同一个名称在不同时间可能代表不同标准。
每次创建实验时生成不可变快照,并记录:
```json
{
"skill_name": "fast-slow-routing",
"repository": "zk-data-agent",
"git_commit": "abc1234",
"content_hash": "sha256:...",
"snapshot_id": "skill_snapshot_xxx",
"status": "committed"
}
```
版本来源可以是:
- 当前部署版本。
- 指定 Git commit。
- 指定 Git tag。
- 尚未提交的草稿快照。
快照建议存放在:
```text
.port_sessions/evaluations/skill_snapshots/
<skill-name>/
<commit-or-content-hash>/
```
运行旧版本时不能切换当前项目分支,也不能覆盖线上 Skill。对于 Git 中的历史版本,可以通过 `git archive` 提取单个 Skill 目录到快照缓存。
草稿版本允许参与实验,但页面必须明确标记“未提交”,并使用内容哈希保证同一次实验可复现。
评测 Agent 始终从快照加载 Skill;聊天 Agent 继续从当前部署目录加载 Skill,两者互不影响。
## 7. Headless Skill Runner
`Headless` 表示没有聊天页面,不表示减少 Agent 能力。
Runner 接收:
```json
{
"skill_snapshot_id": "skill_snapshot_xxx",
"model_id": "model_xxx",
"case": {
"case_id": "001",
"query": "到目的地电量够不够"
}
}
```
Runner 的执行过程:
1. 从快照读取指定 Skill。
2. 创建独立的评测 Agent 实例和 session。
3. 直接把指定 Skill 注入当前任务,不等待模型自行召回 Skill。
4. 把统一 case 作为任务输入。
5. 按 Skill 约定执行完整 Agent Loop。
6. 保存最终结果、执行事件、工具调用和用量。
7. 将最终输出归一化为评测结果。
统一评测结果至少包含:
```json
{
"case_id": "001",
"prediction": "fast",
"reason": "当前快系统已有对应能力",
"confidence": 0.95,
"evidence_refs": [
"knowledge/地图能力.md#到达电量预估"
],
"status": "completed",
"raw_output": "",
"agent_session_id": ""
}
```
单条判断创建一个 Agent Run。批量判断把每条 case 拆成独立 Agent Run,避免样本间上下文污染。
## 8. 批量调度
批量调度器负责:
- 把数据集拆成独立 case 任务。
- 使用受控并发执行。
- 保存每条 case 的状态和重试次数。
- 单条失败不终止整个实验。
- 支持暂停、继续和取消。
- 服务重启后从数据库恢复未完成任务。
- 只重跑失败项、分歧项或用户选中的 case。
任务状态:
```text
pending
running
completed
failed
cancelled
```
聊天请求和评测请求需要独立并发池。评测批量任务默认低优先级,避免影响当前在线使用者。
## 9. 判定依据与可追溯性
页面需要回答“模型依据 Skill 的哪部分作出判断”,但不能把完整模型思考当作可靠因果证据。
实验台展示两类事实:
1. **实际访问记录**Agent 读取了哪些 Skill 文件、知识文件和章节。
2. **模型声明的判定依据**:最终结果中的 `evidence_refs`
生成 Skill 快照时,系统为 Markdown 标题和知识文件建立稳定引用,例如:
```text
SKILL.md#判断流程
knowledge/地图能力.md#到达电量预估
knowledge/边界.md#开放式行程规划
```
评测 Runner 的统一任务约定要求最终结果返回引用。页面将引用解析为可点击的原文片段。
如果模型没有引用明确规则,页面展示“未引用具体依据”,并允许按此条件筛选。这类 case 本身就是标准缺失或模型未正确使用 Skill 的候选问题。
## 10. 页面信息架构
页面采用“实验配置、结果页签、单条详情”三层结构。
### 10.1 实验配置
顶部配置区包含:
- 数据集。
- 字段映射。
- Skill 和版本。
- 模型。
- case 数量。
- 并发配置。
- 开始、暂停、继续、取消、克隆实验。
运行开始后配置区折叠,避免占用结果空间。
### 10.2 结果页签
| 页签 | 主要内容 |
|---|---|
| 概览 | 运行进度、总体指标、混淆矩阵、快慢分布、分垂域指标 |
| 分歧 | 人工标签与模型判断不一致、低置信、无明确依据的 case |
| 全部 Case | 全量结果、状态、筛选、排序和导出 |
| 版本对比 | 不同 Skill 或模型实验之间的修正、退化和指标变化 |
### 10.3 单条详情抽屉
点击一条 case 后展示:
1. 原始数据和统一后的输入。
2. 人工标签、模型判断、置信度和理由。
3. Skill 判定依据及原文片段。
4. 实际读取文件和工具调用。
5. 默认折叠的完整 Agent 执行记录。
6. 人工复核结果和备注。
人工复核至少支持:
- 人工原标签正确。
- 模型判断正确。
- 分类标准存在歧义。
- 快系统能力信息缺失。
- 暂不确定。
## 11. 实验与版本对比
一个实验由以下对象共同确定:
```text
数据集版本
+ 字段映射版本
+ Skill 快照
+ 模型版本
+ 执行参数
```
同一数据集可以克隆实验并替换 Skill 或模型:
```text
实验 ASkill abc1234 + 模型 A
实验 BSkill def5678 + 模型 A
实验 CSkill def5678 + 模型 B
```
版本对比需要展示:
- 总体指标变化。
- 各垂域指标变化。
- 从错误变正确的 case。
- 从正确变错误的 case。
- 判断未变化但理由变化的 case。
- 新增或消失的无依据结果。
这样才能形成“评测、发现分歧、更新 Skill、重新评测”的优化闭环。
## 12. 数据存储
评测运行状态适合使用独立 SQLite 数据库,例如:
```text
.port_sessions/evaluations/evaluations.db
```
核心实体:
```text
evaluation_datasets
dataset_mapping_profiles
skill_snapshots
evaluation_experiments
evaluation_cases
evaluation_case_runs
evaluation_results
evaluation_reviews
```
数据库保存可查询状态、关系和人工复核结果。上传原文件、Skill 快照、导出文件和较大的 Agent transcript 保存在实验目录,数据库记录路径和摘要。
## 13. API 轮廓
```text
POST /api/evaluations/datasets
POST /api/evaluations/datasets/{id}/mapping
POST /api/evaluations/skill-snapshots
GET /api/evaluations/skill-snapshots
POST /api/evaluations
GET /api/evaluations/{id}
POST /api/evaluations/{id}/start
POST /api/evaluations/{id}/pause
POST /api/evaluations/{id}/resume
POST /api/evaluations/{id}/cancel
GET /api/evaluations/{id}/results
POST /api/evaluations/{id}/retry
POST /api/evaluations/{id}/reviews
GET /api/evaluations/{id}/export
POST /api/evaluations/compare
```
API 同时服务 Web 页面和外部批量调用。单条调用可以创建只包含一个 case 的轻量实验,复用相同运行与记录机制。
## 14. 实施顺序
### P1:后台单条运行
- Skill 快照。
- Headless Skill Runner。
- 单条输入和统一结果。
- 独立于聊天 session 的运行记录。
### P2:数据集与批量调度
- 文件上传和字段映射。
- 批量拆分、并发、暂停、恢复和重试。
- 基础指标和导出。
### P3:评测页面
- 实验配置。
- 概览、分歧、全部 Case。
- 单条详情和人工复核。
- Skill 依据引用。
### P4:版本对比
- 克隆实验。
- Skill 和模型版本矩阵。
- 修正、退化和理由变化分析。
## 15. 验收标准
- 开启评测任务后,现有聊天 Agent 可以正常创建、继续和停止会话。
- 600 条批量任务不会出现在聊天会话列表。
- 不同输入格式可以通过字段映射转换为统一 case。
- 每次实验可以确认具体 Skill commit 或内容哈希。
- Skill 更新后,历史实验仍能读取原快照并复现配置。
- 单条失败不会中断全量任务,服务重启后可以恢复。
- 页面可以定位人工与模型分歧,并查看简短理由和 Skill 引用。
- 可以比较两个实验的修正项和退化项。
- 批量评测的并发不会明显拖慢聊天 Agent。