第 4 章:Skill 质量评估体系
本章目标: 建立完整的 Skill 评估框架,掌握测试方法和正确率追踪
预计阅读时间: 30 分钟
难度等级: ⭐⭐⭐☆☆(进阶)
📖 目录
- 评估维度概览
- 触发准确性评估
- 任务完成率评估
- 上下文效率评估
- 用户满意度评估
- 维护成本评估
- 自动化测试框架
- 正确率追踪机制
- A/B 测试设计
- 本章实践
评估维度概览
五维评估框架
| ┌─────────────────┐
│ Skill 质量 │
└────────┬────────┘
┌─────────────────┼─────────────────┐
│ │ │
↓ ↓ ↓
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 触发准确性 │ │ 任务完成率 │ │ 上下文效率 │
│ (Trigger) │ │ (Completion) │ │ (Context) │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
└─────────────────┼─────────────────┘
│
┌─────────────────┼─────────────────┐
↓ ↓ ↓
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 用户满意度 │ │ 维护成本 │ │ 综合评分 │
│ (Satisfaction)│ │ (Cost) │ │ (Score) │
└──────────────┘ └──────────────┘ └──────────────┘
|
评估指标总览
| 维度 | 核心指标 | 测量方法 | 目标值 |
| 触发准确性 | 误触发率、漏触发率 | 日志分析 | <5% / <5% |
| 任务完成率 | 成功率、一次通过率 | 用户反馈 | >90% / >80% |
| 上下文效率 | Token 使用量、加载文件数 | 会话分析 | <5KB / <3 文件 |
| 用户满意度 | NPS、重复使用率 | 调查问卷 | >8 / >60% |
| 维护成本 | 更新频率、问题报告数 | 版本追踪 | <1 次/月 / <5% |
触发准确性评估
指标定义
误触发率(False Positive Rate):
| 误触发率 = 误触发次数 / 总触发次数 × 100%
误触发:Skill 在不应该触发时触发
例:用户说"我会用 PDF",pdf-tools 错误触发
|
漏触发率(False Negative Rate):
| 漏触发率 = 漏触发次数 / 应触发次数 × 100%
漏触发:Skill 在应该触发时未触发
例:用户说"分析这个 PDF",pdf-tools 未触发
|
触发准确率(Accuracy):
| 准确率 = (正确触发次数) / (总触发机会) × 100%
= 100% - 误触发率 - 漏触发率
|
数据收集方法
方法 1:会话日志分析
| # 分析会话日志
def analyze_triggers(session_logs):
results = {
'correct_triggers': 0,
'false_positives': 0,
'false_negatives': 0
}
for log in session_logs:
# 检查 Skill 是否触发
triggered = check_skill_triggered(log)
# 检查是否应该触发
should_trigger = check_should_trigger(log)
if triggered and should_trigger:
results['correct_triggers'] += 1
elif triggered and not should_trigger:
results['false_positives'] += 1
elif not triggered and should_trigger:
results['false_negatives'] += 1
return results
|
方法 2:用户反馈收集
| 在 Skill 使用后询问(可选):
"这个 Skill 的触发是否符合您的预期?"
- ✅ 是,正是我需要的
- ❌ 否,不应该触发
- ❌ 否,应该触发但没有
记录反馈用于计算准确率
|
方法 3:测试用例
| # 测试用例集
test_cases = [
# (用户输入,应该触发,说明)
("分析这个 PDF", True, "明确触发"),
("我会用 PDF 工作", False, "提及但不需要处理"),
("提取 PDF 文本", True, "明确功能"),
("PDF 是什么", False, "知识问题"),
("帮我看看这个文档", True, "隐式触发"),
# ... 更多用例
]
def evaluate_trigger_accuracy(test_cases):
correct = 0
for user_input, should_trigger, description in test_cases:
triggered = test_skill_trigger(user_input)
if triggered == should_trigger:
correct += 1
return correct / len(test_cases) * 100
|
目标值
| 指标 | 优秀 | 良好 | 需改进 |
| 误触发率 | <3% | <5% | >10% |
| 漏触发率 | <3% | <5% | >10% |
| 触发准确率 | >95% | >90% | <85% |
改进策略
误触发高 → 收紧触发条件:
| # 修改前(太宽泛)
description: 处理文档
# 修改后(更精确)
description: PDF 文件处理:提取文本、编辑、分析。
当用户需要处理 PDF 文件内容时使用
|
漏触发高 → 扩展触发词:
| # 添加更多触发场景
description: |
PDF 处理。当用户需要:
(1) 提取文本,(2) 编辑 PDF,(3) 分析内容,
(4) 转换格式,(5) 合并拆分,
或说"这个文档"、"这个文件"(上下文中是 PDF)时使用
|
任务完成率评估
指标定义
成功率(Success Rate):
| 成功率 = 成功完成的任务数 / 总任务数 × 100%
成功:用户目标达成,无需人工干预
|
一次通过率(First Pass Yield):
| 一次通过率 = 一次成功的任务数 / 总任务数 × 100%
一次成功:无需重试、无需纠正
|
平均重试次数(Average Retries):
| 平均重试 = 总重试次数 / 总任务数
重试:用户需要重复指令或纠正
|
数据收集方法
方法 1:任务完成标记
| # 在 Skill 中标记任务完成
def mark_task_completion(task_id, success, retries=0):
log_entry = {
'task_id': task_id,
'success': success,
'retries': retries,
'timestamp': datetime.now().isoformat()
}
save_to_log(log_entry)
# 使用时
if task_completed_successfully():
mark_task_completion(task_id, True)
elif task_failed():
mark_task_completion(task_id, False)
|
方法 2:用户确认
| 任务完成后询问:
"任务完成!结果是否符合预期?"
- ✅ 是,完全符合
- ⚠️ 部分符合,需要调整
- ❌ 否,需要重做
记录用户确认
|
方法 3:会话分析
| # 分析会话中的纠正模式
def analyze_correction_patterns(session):
corrections = 0
for message in session.messages:
if contains_correction(message):
# "不对"、"错了"、"应该是"等
corrections += 1
return corrections
# 纠正次数多 = 任务完成率低
|
目标值
| 指标 | 优秀 | 良好 | 需改进 |
| 成功率 | >95% | >90% | <80% |
| 一次通过率 | >85% | >75% | <60% |
| 平均重试 | <0.3 | <0.5 | >1.0 |
改进策略
成功率低 → 分析失败原因:
| 失败原因分类:
1. 理解错误 → 改进触发条件
2. 执行错误 → 修复脚本/逻辑
3. 输出错误 → 调整输出格式
4. 边界情况 → 添加异常处理
|
一次通过率低 → 优化工作流:
| 常见问题:
- 步骤遗漏 → 添加检查清单
- 参数错误 → 添加验证
- 格式不对 → 提供模板
|
上下文效率评估
指标定义
平均 Token 使用量:
| 平均 Token = 总 Token 数 / 会话数
包括:元数据 + SKILL.md + 加载的参考文档
|
加载文件数:
| 平均加载文件数 = 总加载文件数 / 会话数
包括:SKILL.md + references 文件
|
上下文密度:
| 上下文密度 = 有用信息量 / 总 Token 数
有用信息:直接用于任务的内容
|
测量方法
方法 1:会话分析工具
| def analyze_context_usage(session_id):
session = get_session(session_id)
# 统计加载的文件
loaded_files = session.loaded_files
total_tokens = session.total_tokens
# 统计有用内容
useful_tokens = count_useful_tokens(session)
return {
'files_loaded': len(loaded_files),
'total_tokens': total_tokens,
'useful_tokens': useful_tokens,
'density': useful_tokens / total_tokens
}
|
方法 2:Skill 自检
| 在 Skill 中添加自检(定期):
"检查上下文使用:
- 当前加载文件数:X
- 估计 Token 数:Y
- 是否超过阈值:是/否
如果超过,考虑:
1. 能否精简 SKILL.md?
2. 能否延迟加载某些文件?
3. 能否移到 scripts/执行?"
|
目标值
| 指标 | 优秀 | 良好 | 需改进 |
| 平均 Token | <3KB | <5KB | >10KB |
| 加载文件数 | <2 | <3 | >5 |
| 上下文密度 | >70% | >50% | <30% |
改进策略
Token 过多 → 精简内容:
| 1. 删除冗余解释
2. 缩短示例
3. 移到 references/
4. 使用更简洁的表达
|
加载文件多 → 优化结构:
| 1. 合并相关文件
2. 使用渐进式披露
3. 延迟非必要加载
4. 脚本执行代替加载
|
用户满意度评估
指标定义
净推荐值(NPS):
| NPS = 推荐者比例 - 贬损者比例
推荐者:评分 9-10
被动者:评分 7-8
贬损者:评分 0-6
目标:NPS > 50
|
重复使用率:
| 重复使用率 = 重复使用的用户数 / 总用户数 × 100%
重复使用:7 天内使用 2+ 次
|
用户留存率:
| 7 日留存 = 7 天后仍使用的用户数 / 初始用户数 × 100%
30 日留存 = 30 天后仍使用的用户数 / 初始用户数 × 100%
|
数据收集方法
方法 1:满意度调查
| 定期询问(每 10 次使用后):
"请评价这个 Skill:
⭐⭐⭐⭐⭐ 非常满意
⭐⭐⭐⭐ 满意
⭐⭐⭐ 一般
⭐⭐ 不满意
⭐ 非常不满意
改进建议:[开放文本]"
|
方法 2:使用频率分析
| def analyze_usage_frequency(user_id):
usage = get_user_usage(user_id)
# 计算使用频率
days_with_usage = len(set(u.date for u in usage))
total_days = (usage[-1].date - usage[0].date).days + 1
return {
'frequency': days_with_usage / total_days,
'total_uses': len(usage),
'avg_per_day': len(usage) / total_days
}
|
方法 3:反馈分析
| def analyze_feedback(feedbacks):
sentiments = {
'positive': 0,
'neutral': 0,
'negative': 0
}
for feedback in feedbacks:
sentiment = classify_sentiment(feedback.text)
sentiments[sentiment] += 1
return sentiments
|
目标值
| 指标 | 优秀 | 良好 | 需改进 |
| NPS | >50 | >30 | <0 |
| 重复使用率 | >70% | >50% | <30% |
| 7 日留存 | >60% | >40% | <20% |
维护成本评估
指标定义
更新频率:
| 更新频率 = 更新次数 / 时间(月)
包括:Bug 修复、功能更新、文档更新
|
问题报告率:
| 问题报告率 = 问题报告数 / 使用次数 × 100%
问题:Bug、错误、困惑
|
平均修复时间(MTTR):
| MTTR = 总修复时间 / 问题数
修复时间:从报告到解决
|
目标值
| 指标 | 优秀 | 良好 | 需改进 |
| 更新频率 | <1/月 | <2/月 | >4/月 |
| 问题报告率 | <2% | <5% | >10% |
| MTTR | <24h | <48h | >1 周 |
自动化测试框架
测试类型
1. 单元测试:
| # 测试单个函数
def test_extract_text():
result = extract_text('fixtures/sample.pdf')
assert len(result) > 0
assert isinstance(result, str)
|
2. 集成测试:
| # 测试完整工作流
def test_full_workflow():
# 1. 触发 Skill
# 2. 执行任务
# 3. 验证输出
output = run_skill('pdf-tools', 'extract', 'sample.pdf')
assert output.success
assert output.text is not None
|
3. 回归测试:
| # 确保更新不破坏现有功能
def test_regression():
for test_case in regression_suite:
result = run_skill(test_case.input)
assert result == test_case.expected
|
测试框架示例
| # tests/test_skill.py
import pytest
from skill_runner import SkillRunner
class TestSkillTrigger:
@pytest.mark.parametrize("input,should_trigger", [
("分析 PDF", True),
("我会 PDF", False),
("提取文本", True),
("PDF 是什么", False),
])
def test_trigger(self, input, should_trigger):
runner = SkillRunner('pdf-tools')
triggered = runner.check_trigger(input)
assert triggered == should_trigger
class SkillTaskCompletion:
def test_extract_text(self):
runner = SkillRunner('pdf-tools')
result = runner.run('extract', 'fixtures/sample.pdf')
assert result.success
assert len(result.text) > 0
def test_rotate(self):
runner = SkillRunner('pdf-tools')
result = runner.run('rotate', 'fixtures/sample.pdf', 90)
assert result.success
assert result.output_file.exists()
if __name__ == '__main__':
pytest.main()
|
持续集成
| # .github/workflows/skill-test.yml
name: Skill Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run Tests
run: |
pip install -r requirements.txt
pytest tests/
- name: Validate Skill
run: |
python scripts/package_skill.py skills/my-skill
|
正确率追踪机制
日志格式
| {
"timestamp": "2026-03-26T10:30:00Z",
"skill": "pdf-tools",
"task": "extract_text",
"input": "sample.pdf",
"success": true,
"duration_ms": 1500,
"tokens_used": 3500,
"user_feedback": "positive",
"retries": 0
}
|
追踪仪表板
| # Skill 性能仪表板
## 触发准确性
- 误触发率:2.3% ✅
- 漏触发率:1.8% ✅
- 准确率:95.9% ✅
## 任务完成率
- 成功率:94.2% ✅
- 一次通过率:87.5% ✅
- 平均重试:0.18 ✅
## 上下文效率
- 平均 Token:3.2KB ✅
- 加载文件:2.1 ✅
- 上下文密度:68% ⚠️
## 用户满意度
- NPS: 52 ✅
- 重复使用率:65% ✅
- 7 日留存:58% ✅
|
告警机制
| def check_alerts(metrics):
alerts = []
if metrics['false_positive_rate'] > 0.10:
alerts.append("误触发率过高")
if metrics['success_rate'] < 0.80:
alerts.append("成功率过低")
if metrics['avg_tokens'] > 10000:
alerts.append("Token 使用过多")
if metrics['nps'] < 0:
alerts.append("NPS 为负")
return alerts
|
A/B 测试设计
测试场景
场景 1:触发词优化
| A 组:当前 description
B 组:优化后 description
测量:触发准确率、漏触发率
|
场景 2:工作流优化
| A 组:当前工作流
B 组:优化后工作流
测量:成功率、一次通过率、用户满意度
|
场景 3:输出格式优化
| A 组:当前输出格式
B 组:新输出格式
测量:用户满意度、重复使用率
|
实施方法
| def run_ab_test(skill_name, variant_a, variant_b, duration_days=7):
# 随机分配用户
users = get_all_users()
group_a = random_sample(users, 0.5)
group_b = [u for u in users if u not in group_a]
# 部署变体
deploy_variant(skill_name, 'A', variant_a, group_a)
deploy_variant(skill_name, 'B', variant_b, group_b)
# 收集数据
metrics_a = collect_metrics(group_a, duration_days)
metrics_b = collect_metrics(group_b, duration_days)
# 统计分析
result = statistical_test(metrics_a, metrics_b)
return {
'winner': 'A' if result.a_better else 'B',
'confidence': result.confidence,
'improvement': result.improvement_pct
}
|
本章实践
练习 1:设计评估框架
任务: 为你的 Skill 设计完整的评估框架
输出:
| ## Skill 评估框架
### 评估维度
| 维度 | 指标 | 目标值 | 测量方法 |
|------|------|-------|---------|
| 触发准确性 | ... | ... | ... |
| 任务完成率 | ... | ... | ... |
| ... | ... | ... | ... |
### 数据收集计划
1. ...
2. ...
3. ...
### 改进循环
[描述如何根据评估结果改进]
|
练习 2:编写测试用例
任务: 为你的 Skill 编写 10+ 个测试用例
输出:
| # tests/test_my_skill.py
import pytest
class TestTrigger:
@pytest.mark.parametrize("input,should_trigger", [
# 至少 5 个用例
("...", True),
("...", False),
# ...
])
def test_trigger(self, input, should_trigger):
...
class TaskCompletion:
def test_task_1(self):
...
def test_task_2(self):
...
|
本章总结
核心要点
- 五维评估框架:
- 触发准确性
- 任务完成率
- 上下文效率
- 用户满意度
-
维护成本
-
关键指标:
- 触发准确率 >90%
- 成功率 >90%
- Token <5KB
-
NPS >30
-
自动化测试:
- 单元测试
- 集成测试
- 回归测试
-
CI/CD
-
持续追踪:
- 日志记录
- 仪表板
- 告警机制
- A/B 测试
检查清单
评估 Skill 时检查:
| □ 触发准确率 >90%
□ 成功率 >90%
□ Token 使用 <5KB
□ NPS >30
□ 有自动化测试
□ 有日志追踪
□ 有改进循环
|
第 4 章完
下一章:第 5 章:Skill 进化与持续优化