oh-my-knowledge 0.0.1 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +537 -332
- package/dist/src/analysis/coverage-analyzer.d.ts +57 -0
- package/dist/src/analysis/coverage-analyzer.d.ts.map +1 -0
- package/dist/src/analysis/coverage-analyzer.js +262 -0
- package/dist/src/analysis/coverage-analyzer.js.map +1 -0
- package/dist/src/analysis/gap-analyzer.d.ts +114 -0
- package/dist/src/analysis/gap-analyzer.d.ts.map +1 -0
- package/dist/src/analysis/gap-analyzer.js +439 -0
- package/dist/src/analysis/gap-analyzer.js.map +1 -0
- package/dist/src/analysis/hedging-classifier.d.ts +34 -0
- package/dist/src/analysis/hedging-classifier.d.ts.map +1 -0
- package/dist/src/analysis/hedging-classifier.js +144 -0
- package/dist/src/analysis/hedging-classifier.js.map +1 -0
- package/dist/src/analysis/report-diagnostics.d.ts +9 -0
- package/dist/src/analysis/report-diagnostics.d.ts.map +1 -0
- package/dist/src/analysis/report-diagnostics.js +631 -0
- package/dist/src/analysis/report-diagnostics.js.map +1 -0
- package/dist/src/authoring/evolver.d.ts +64 -0
- package/dist/src/authoring/evolver.d.ts.map +1 -0
- package/dist/src/authoring/evolver.js +275 -0
- package/dist/src/authoring/evolver.js.map +1 -0
- package/dist/src/authoring/generator.d.ts +13 -0
- package/dist/src/authoring/generator.d.ts.map +1 -0
- package/dist/src/authoring/generator.js +60 -0
- package/dist/src/authoring/generator.js.map +1 -0
- package/dist/src/cli.d.ts +3 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +1004 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/eval-core/cache.d.ts +11 -0
- package/dist/src/eval-core/cache.d.ts.map +1 -0
- package/dist/src/eval-core/cache.js +53 -0
- package/dist/src/eval-core/cache.js.map +1 -0
- package/dist/src/eval-core/ci-gates.d.ts +17 -0
- package/dist/src/eval-core/ci-gates.d.ts.map +1 -0
- package/dist/src/eval-core/ci-gates.js +42 -0
- package/dist/src/eval-core/ci-gates.js.map +1 -0
- package/dist/src/eval-core/dependency-checker.d.ts +37 -0
- package/dist/src/eval-core/dependency-checker.d.ts.map +1 -0
- package/dist/src/eval-core/dependency-checker.js +280 -0
- package/dist/src/eval-core/dependency-checker.js.map +1 -0
- package/dist/src/eval-core/evaluation-execution.d.ts +26 -0
- package/dist/src/eval-core/evaluation-execution.d.ts.map +1 -0
- package/dist/src/eval-core/evaluation-execution.js +196 -0
- package/dist/src/eval-core/evaluation-execution.js.map +1 -0
- package/dist/src/eval-core/evaluation-job.d.ts +48 -0
- package/dist/src/eval-core/evaluation-job.d.ts.map +1 -0
- package/dist/src/eval-core/evaluation-job.js +112 -0
- package/dist/src/eval-core/evaluation-job.js.map +1 -0
- package/dist/src/eval-core/evaluation-reporting.d.ts +28 -0
- package/dist/src/eval-core/evaluation-reporting.d.ts.map +1 -0
- package/dist/src/eval-core/evaluation-reporting.js +123 -0
- package/dist/src/eval-core/evaluation-reporting.js.map +1 -0
- package/dist/src/eval-core/execution-strategy.d.ts +11 -0
- package/dist/src/eval-core/execution-strategy.d.ts.map +1 -0
- package/dist/src/eval-core/execution-strategy.js +121 -0
- package/dist/src/eval-core/execution-strategy.js.map +1 -0
- package/dist/src/eval-core/fact-checker.d.ts +25 -0
- package/dist/src/eval-core/fact-checker.d.ts.map +1 -0
- package/dist/src/eval-core/fact-checker.js +66 -0
- package/dist/src/eval-core/fact-checker.js.map +1 -0
- package/dist/src/eval-core/schema.d.ts +30 -0
- package/dist/src/eval-core/schema.d.ts.map +1 -0
- package/dist/src/eval-core/schema.js +195 -0
- package/dist/src/eval-core/schema.js.map +1 -0
- package/dist/src/eval-core/statistics.d.ts +86 -0
- package/dist/src/eval-core/statistics.d.ts.map +1 -0
- package/dist/src/eval-core/statistics.js +210 -0
- package/dist/src/eval-core/statistics.js.map +1 -0
- package/dist/src/eval-core/task-planner.d.ts +4 -0
- package/dist/src/eval-core/task-planner.d.ts.map +1 -0
- package/dist/src/eval-core/task-planner.js +33 -0
- package/dist/src/eval-core/task-planner.js.map +1 -0
- package/dist/src/eval-workflows/each-evaluation-workflow.d.ts +133 -0
- package/dist/src/eval-workflows/each-evaluation-workflow.d.ts.map +1 -0
- package/dist/src/eval-workflows/each-evaluation-workflow.js +169 -0
- package/dist/src/eval-workflows/each-evaluation-workflow.js.map +1 -0
- package/dist/src/eval-workflows/evaluation-pipeline.d.ts +38 -0
- package/dist/src/eval-workflows/evaluation-pipeline.d.ts.map +1 -0
- package/dist/src/eval-workflows/evaluation-pipeline.js +214 -0
- package/dist/src/eval-workflows/evaluation-pipeline.js.map +1 -0
- package/dist/src/eval-workflows/evaluation-preparation.d.ts +64 -0
- package/dist/src/eval-workflows/evaluation-preparation.d.ts.map +1 -0
- package/dist/src/eval-workflows/evaluation-preparation.js +90 -0
- package/dist/src/eval-workflows/evaluation-preparation.js.map +1 -0
- package/dist/src/eval-workflows/run-evaluation.d.ts +105 -0
- package/dist/src/eval-workflows/run-evaluation.d.ts.map +1 -0
- package/dist/src/eval-workflows/run-evaluation.js +264 -0
- package/dist/src/eval-workflows/run-evaluation.js.map +1 -0
- package/dist/src/executors/anthropic-api.d.ts +3 -0
- package/dist/src/executors/anthropic-api.d.ts.map +1 -0
- package/dist/src/executors/anthropic-api.js +43 -0
- package/dist/src/executors/anthropic-api.js.map +1 -0
- package/dist/src/executors/claude-cli.d.ts +3 -0
- package/dist/src/executors/claude-cli.d.ts.map +1 -0
- package/dist/src/executors/claude-cli.js +103 -0
- package/dist/src/executors/claude-cli.js.map +1 -0
- package/dist/src/executors/claude-sdk-trace.d.ts +10 -0
- package/dist/src/executors/claude-sdk-trace.d.ts.map +1 -0
- package/dist/src/executors/claude-sdk-trace.js +100 -0
- package/dist/src/executors/claude-sdk-trace.js.map +1 -0
- package/dist/src/executors/claude-sdk.d.ts +3 -0
- package/dist/src/executors/claude-sdk.d.ts.map +1 -0
- package/dist/src/executors/claude-sdk.js +160 -0
- package/dist/src/executors/claude-sdk.js.map +1 -0
- package/dist/src/executors/gemini.d.ts +3 -0
- package/dist/src/executors/gemini.d.ts.map +1 -0
- package/dist/src/executors/gemini.js +78 -0
- package/dist/src/executors/gemini.js.map +1 -0
- package/dist/src/executors/index.d.ts +7 -0
- package/dist/src/executors/index.d.ts.map +1 -0
- package/dist/src/executors/index.js +22 -0
- package/dist/src/executors/index.js.map +1 -0
- package/dist/src/executors/openai-api.d.ts +3 -0
- package/dist/src/executors/openai-api.d.ts.map +1 -0
- package/dist/src/executors/openai-api.js +40 -0
- package/dist/src/executors/openai-api.js.map +1 -0
- package/dist/src/executors/openai-cli.d.ts +3 -0
- package/dist/src/executors/openai-cli.d.ts.map +1 -0
- package/dist/src/executors/openai-cli.js +60 -0
- package/dist/src/executors/openai-cli.js.map +1 -0
- package/dist/src/executors/script.d.ts +3 -0
- package/dist/src/executors/script.d.ts.map +1 -0
- package/dist/src/executors/script.js +63 -0
- package/dist/src/executors/script.js.map +1 -0
- package/dist/src/executors/shared.d.ts +117 -0
- package/dist/src/executors/shared.d.ts.map +1 -0
- package/dist/src/executors/shared.js +49 -0
- package/dist/src/executors/shared.js.map +1 -0
- package/dist/src/grading/assertions.d.ts +18 -0
- package/dist/src/grading/assertions.d.ts.map +1 -0
- package/dist/src/grading/assertions.js +239 -0
- package/dist/src/grading/assertions.js.map +1 -0
- package/dist/src/grading/index.d.ts +26 -0
- package/dist/src/grading/index.d.ts.map +1 -0
- package/dist/src/grading/index.js +98 -0
- package/dist/src/grading/index.js.map +1 -0
- package/dist/src/grading/judge.d.ts +13 -0
- package/dist/src/grading/judge.d.ts.map +1 -0
- package/dist/src/grading/judge.js +98 -0
- package/dist/src/grading/judge.js.map +1 -0
- package/dist/src/grading/layered-scores.d.ts +13 -0
- package/dist/src/grading/layered-scores.d.ts.map +1 -0
- package/dist/src/grading/layered-scores.js +62 -0
- package/dist/src/grading/layered-scores.js.map +1 -0
- package/dist/src/inputs/eval-config.d.ts +13 -0
- package/dist/src/inputs/eval-config.d.ts.map +1 -0
- package/dist/src/inputs/eval-config.js +136 -0
- package/dist/src/inputs/eval-config.js.map +1 -0
- package/dist/src/inputs/load-samples.d.ts +16 -0
- package/dist/src/inputs/load-samples.d.ts.map +1 -0
- package/dist/src/inputs/load-samples.js +51 -0
- package/dist/src/inputs/load-samples.js.map +1 -0
- package/dist/src/inputs/mcp-resolver.d.ts +50 -0
- package/dist/src/inputs/mcp-resolver.d.ts.map +1 -0
- package/dist/src/inputs/mcp-resolver.js +307 -0
- package/dist/src/inputs/mcp-resolver.js.map +1 -0
- package/dist/src/inputs/skill-loader.d.ts +18 -0
- package/dist/src/inputs/skill-loader.d.ts.map +1 -0
- package/dist/src/inputs/skill-loader.js +222 -0
- package/dist/src/inputs/skill-loader.js.map +1 -0
- package/dist/src/inputs/url-fetcher.d.ts +19 -0
- package/dist/src/inputs/url-fetcher.d.ts.map +1 -0
- package/dist/src/inputs/url-fetcher.js +241 -0
- package/dist/src/inputs/url-fetcher.js.map +1 -0
- package/dist/src/observability/production-analyzer.d.ts +61 -0
- package/dist/src/observability/production-analyzer.d.ts.map +1 -0
- package/dist/src/observability/production-analyzer.js +183 -0
- package/dist/src/observability/production-analyzer.js.map +1 -0
- package/dist/src/observability/trace-adapter.d.ts +75 -0
- package/dist/src/observability/trace-adapter.d.ts.map +1 -0
- package/dist/src/observability/trace-adapter.js +341 -0
- package/dist/src/observability/trace-adapter.js.map +1 -0
- package/dist/src/renderer/html-renderer.d.ts +9 -0
- package/dist/src/renderer/html-renderer.d.ts.map +1 -0
- package/dist/src/renderer/html-renderer.js +338 -0
- package/dist/src/renderer/html-renderer.js.map +1 -0
- package/dist/src/renderer/layout.d.ts +13 -0
- package/dist/src/renderer/layout.d.ts.map +1 -0
- package/dist/src/renderer/layout.js +476 -0
- package/dist/src/renderer/layout.js.map +1 -0
- package/dist/src/renderer/skill-health-renderer.d.ts +20 -0
- package/dist/src/renderer/skill-health-renderer.d.ts.map +1 -0
- package/dist/src/renderer/skill-health-renderer.js +218 -0
- package/dist/src/renderer/skill-health-renderer.js.map +1 -0
- package/dist/src/renderer/summary.d.ts +21 -0
- package/dist/src/renderer/summary.d.ts.map +1 -0
- package/dist/src/renderer/summary.js +1072 -0
- package/dist/src/renderer/summary.js.map +1 -0
- package/dist/src/renderer/table.d.ts +3 -0
- package/dist/src/renderer/table.d.ts.map +1 -0
- package/dist/src/renderer/table.js +134 -0
- package/dist/src/renderer/table.js.map +1 -0
- package/dist/src/renderer/trends.d.ts +6 -0
- package/dist/src/renderer/trends.d.ts.map +1 -0
- package/dist/src/renderer/trends.js +127 -0
- package/dist/src/renderer/trends.js.map +1 -0
- package/dist/src/server/job-store.d.ts +4 -0
- package/dist/src/server/job-store.d.ts.map +1 -0
- package/dist/src/server/job-store.js +68 -0
- package/dist/src/server/job-store.js.map +1 -0
- package/dist/src/server/report-server.d.ts +16 -0
- package/dist/src/server/report-server.d.ts.map +1 -0
- package/dist/src/server/report-server.js +196 -0
- package/dist/src/server/report-server.js.map +1 -0
- package/dist/src/server/report-store.d.ts +44 -0
- package/dist/src/server/report-store.d.ts.map +1 -0
- package/dist/src/server/report-store.js +190 -0
- package/dist/src/server/report-store.js.map +1 -0
- package/dist/src/types.d.ts +553 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/package.json +44 -3
package/README.md
CHANGED
|
@@ -1,448 +1,653 @@
|
|
|
1
1
|
# oh-my-knowledge
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
知识载体评测工具 — 用客观数据衡量你的 artifact 质量。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**固定模型,只变知识载体,数据说话。**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## 为什么需要这个工具
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
做知识工程的团队会产出大量知识载体(当前常见是 skill,也包括 prompt、agent、workflow 等)。当被问到"v2 比 v1 好在哪"时,需要客观数据而非主观判断。`oh-my-knowledge` 通过控制变量实验解决这个问题:相同模型、相同测试样本,只改变知识载体。
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
## Quick Start
|
|
11
|
+
## 快速开始
|
|
14
12
|
|
|
15
13
|
```bash
|
|
16
|
-
#
|
|
17
|
-
npm i
|
|
14
|
+
# 安装
|
|
15
|
+
npm i oh-my-knowledge -g
|
|
18
16
|
|
|
19
|
-
#
|
|
17
|
+
# 生成评测项目脚手架
|
|
20
18
|
omk bench init my-eval
|
|
21
19
|
cd my-eval
|
|
22
20
|
|
|
23
|
-
#
|
|
21
|
+
# 把要对比的 artifact 放到 skills/ 目录
|
|
22
|
+
# 方式一:直接放 .md 文件(skills/v1.md, skills/v2.md)
|
|
23
|
+
# 方式二:放完整 artifact 目录(skills/my-skill-v1/SKILL.md, ...)
|
|
24
|
+
# 只放一个 artifact 也行,会自动加 baseline 对照
|
|
25
|
+
|
|
26
|
+
# 预览评测计划
|
|
24
27
|
omk bench run --dry-run
|
|
25
28
|
|
|
26
|
-
#
|
|
27
|
-
omk bench run
|
|
29
|
+
# 运行评测(自动发现 skills/ 目录下的所有 artifact)
|
|
30
|
+
omk bench run
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 在 Claude Code 中使用
|
|
28
34
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
35
|
+
安装 omk 后,在 Claude Code 中直接用自然语言交互:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
/omk eval # 评测当前项目的 artifact
|
|
39
|
+
/omk evolve # 自动迭代改进 artifact
|
|
40
|
+
/omk gen-samples # 生成测试用例
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
或直接说"帮我评测 v1 和 v2 的差异"、"改进一下这个 artifact",omk 会自动理解意图并调用对应命令。
|
|
44
|
+
|
|
45
|
+
## 特性
|
|
46
|
+
|
|
47
|
+
| 特性 | 说明 |
|
|
48
|
+
|------|------|
|
|
49
|
+
| **18 种断言** | 包含子串、正则、JSON Schema、语义相似度、自定义函数等 |
|
|
50
|
+
| **四维评估** | 质量、成本、效率、稳定性四个维度对比 |
|
|
51
|
+
| **多执行器** | 支持 Claude CLI / Claude SDK / OpenAI / Gemini 及自定义命令 |
|
|
52
|
+
| **MCP URL 获取** | 通过 MCP Server 获取私有文档 URL 内容(SSO 保护的知识库等) |
|
|
53
|
+
| **盲测 A/B** | `--blind` 隐藏变体名称,HTML 报告有揭晓按钮 |
|
|
54
|
+
| **并行执行** | `--concurrency N` 并行 N 个任务 |
|
|
55
|
+
| **多轮方差分析** | `--repeat N` 重复 N 次,计算均值/标准差/置信区间/t 检验 |
|
|
56
|
+
| **自动分析** | 检测低区分度断言、均匀分数、全通过/全失败、高成本样本 |
|
|
57
|
+
| **可追溯性** | 报告含 CLI 版本、Node 版本、artifact 哈希 |
|
|
58
|
+
| **中英切换** | HTML 报告右上角一键切换语言 |
|
|
59
|
+
|
|
60
|
+
## 工作原理
|
|
61
|
+
|
|
62
|
+
核心思路:**固定模型 + 固定样本,只变 artifact 和 runtime context**,通过交错调度消除时间漂移,用断言 + LLM 评委双通道评分,再叠加知识缺口信号量化风险敞口。
|
|
63
|
+
|
|
64
|
+
```mermaid
|
|
65
|
+
flowchart TD
|
|
66
|
+
subgraph Input["① 输入"]
|
|
67
|
+
S["eval-samples<br/>(JSON / YAML)"]
|
|
68
|
+
A["artifacts<br/>skills/*.md · SKILL.md<br/>baseline · git:name · @cwd"]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
subgraph Prep["② 预处理(解析与抓取)"]
|
|
72
|
+
V["变体解析<br/>variant → artifact + runtime context<br/>(cwd / 项目级 CLAUDE.md / 本地 skills)"]
|
|
73
|
+
U["URL 抓取<br/>prompt / context 中的 URL<br/>MCP Server(私有文档) → HTTP"]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
subgraph Schedule["③ 交错调度 + 并发"]
|
|
77
|
+
Q["s1-v1 → s1-v2 → s2-v1 → s2-v2 …<br/>--concurrency N · --repeat N"]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
subgraph Exec["④ 执行器(固定模型)"]
|
|
81
|
+
E["claude / claude-sdk / openai / gemini<br/>anthropic-api / openai-api / 自定义命令"]
|
|
82
|
+
T["claude-sdk 抽取<br/>turns / toolCalls trace"]
|
|
83
|
+
E -.-> T
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
subgraph Score["⑤ 双通道评分"]
|
|
87
|
+
AS["断言(18 种)<br/>内容 / 结构 / 成本 / 延迟<br/>agent: tools_called · turns_min …"]
|
|
88
|
+
LS["LLM 评委<br/>rubric · dimensions(多维独立打分)"]
|
|
89
|
+
CS["综合分数<br/>断言 & LLM 有则均值"]
|
|
90
|
+
AS --> CS
|
|
91
|
+
LS --> CS
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
subgraph Analyze["⑥ 自动分析 + 知识缺口"]
|
|
95
|
+
D["低区分度断言 / 均匀分 / 全通过全失败<br/>高成本样本 · 方差 · t 检验"]
|
|
96
|
+
G["知识缺口信号<br/>(风险敞口量化, 不证明完备)"]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
subgraph Report["⑦ 报告"]
|
|
100
|
+
R["四维: 质量 / 成本 / 效率 / 稳定性<br/>JSON + HTML · 盲测揭晓<br/>CLI/Node/artifact 哈希可追溯"]
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
S --> U
|
|
104
|
+
A --> V
|
|
105
|
+
V --> Q
|
|
106
|
+
U --> Q
|
|
107
|
+
Q --> E
|
|
108
|
+
T --> AS
|
|
109
|
+
E --> AS
|
|
110
|
+
E --> LS
|
|
111
|
+
CS --> D
|
|
112
|
+
CS --> G
|
|
113
|
+
D --> R
|
|
114
|
+
G --> R
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**关键设计:**
|
|
118
|
+
|
|
119
|
+
- **交错调度**消除时间漂移:同一样本的不同 variant 交替发出,而非 v1 全跑完再跑 v2,避免模型负载/网络波动被错误归因给 artifact。
|
|
120
|
+
- **variant = artifact + runtime context**:`name@cwd` 让对照组可以显式声明"项目目录"这个隐性输入,把"项目级沉淀"和"显式 artifact 注入"拆开测。
|
|
121
|
+
- **双通道评分互补**:断言抓确定性缺陷(必须调用某工具/必须包含某字段),LLM 评委抓主观质量(可读性/完整性),两者都存在时取均值。
|
|
122
|
+
- **知识缺口信号**不是评分的一部分,而是一个独立追踪项:它告诉你"这次评测覆盖了多少风险敞口",用于追踪收敛,而非断言知识"完备"。
|
|
123
|
+
|
|
124
|
+
## 评测样本格式
|
|
125
|
+
|
|
126
|
+
支持 JSON 和 YAML(`eval-samples.json`、`eval-samples.yaml`、`eval-samples.yml`)。
|
|
73
127
|
|
|
74
128
|
```json
|
|
75
129
|
[
|
|
76
130
|
{
|
|
77
131
|
"sample_id": "s001",
|
|
78
|
-
"prompt": "
|
|
132
|
+
"prompt": "审查这段代码的安全性",
|
|
79
133
|
"context": "function auth(u, p) { db.query('SELECT * FROM users WHERE name=' + u); }",
|
|
80
|
-
"rubric": "
|
|
134
|
+
"rubric": "应识别 SQL 注入风险并建议参数化查询",
|
|
81
135
|
"assertions": [
|
|
82
|
-
{ "type": "contains", "value": "SQL
|
|
83
|
-
{ "type": "contains", "value": "
|
|
84
|
-
{ "type": "not_contains", "value": "
|
|
85
|
-
{ "type": "json_valid" },
|
|
86
|
-
{ "type": "cost_max", "value": 0.01 },
|
|
87
|
-
{ "type": "custom", "fn": "my-assertion.mjs", "weight": 1 }
|
|
136
|
+
{ "type": "contains", "value": "SQL 注入", "weight": 1 },
|
|
137
|
+
{ "type": "contains", "value": "参数化", "weight": 1 },
|
|
138
|
+
{ "type": "not_contains", "value": "没有问题", "weight": 0.5 }
|
|
88
139
|
],
|
|
89
140
|
"dimensions": {
|
|
90
|
-
"security": "
|
|
91
|
-
"actionability": "
|
|
141
|
+
"security": "是否识别出注入漏洞",
|
|
142
|
+
"actionability": "是否给出可直接使用的修复代码"
|
|
92
143
|
}
|
|
93
144
|
}
|
|
94
145
|
]
|
|
95
146
|
```
|
|
96
147
|
|
|
97
|
-
###
|
|
148
|
+
### 字段说明
|
|
149
|
+
|
|
150
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
151
|
+
|------|------|------|------|
|
|
152
|
+
| `sample_id` | `string` | **是** | 样本唯一标识 |
|
|
153
|
+
| `prompt` | `string` | **是** | 发送给模型的用户提示词 |
|
|
154
|
+
| `context` | `string` | 否 | 附加上下文(代码片段等),会被包裹在代码块中拼接到 prompt 后。也支持 URL,运行时自动抓取内容 |
|
|
155
|
+
| `rubric` | `string` | 否 | LLM 评委的评分标准(1-5 分) |
|
|
156
|
+
| `assertions` | `array` | 否 | 断言检查列表,详见[断言类型](#断言类型) |
|
|
157
|
+
| `assertions[].type` | `string` | **是** | 断言类型 |
|
|
158
|
+
| `assertions[].value` | `string\|number` | 视类型 | 检查值(`contains`、`min_length`、`cost_max` 等必填) |
|
|
159
|
+
| `assertions[].values` | `array` | 视类型 | 字符串数组(`contains_all`、`contains_any` 必填) |
|
|
160
|
+
| `assertions[].pattern` | `string` | 视类型 | 正则表达式(`regex` 必填) |
|
|
161
|
+
| `assertions[].flags` | `string` | 否 | 正则标志(默认 `"i"`) |
|
|
162
|
+
| `assertions[].schema` | `object` | 视类型 | JSON Schema 对象(`json_schema` 必填,基于 [ajv](https://ajv.js.org/)) |
|
|
163
|
+
| `assertions[].reference` | `string` | 视类型 | 参考文本(`semantic_similarity` 必填) |
|
|
164
|
+
| `assertions[].threshold` | `number` | 否 | 语义相似度通过阈值(默认 3) |
|
|
165
|
+
| `assertions[].fn` | `string` | 视类型 | 自定义断言 JS 文件路径(`custom` 必填) |
|
|
166
|
+
| `assertions[].weight` | `number` | 否 | 权重(默认 1) |
|
|
167
|
+
| `dimensions` | `object` | 否 | 多维度评分,key 为维度名,value 为评分标准文本 |
|
|
168
|
+
|
|
169
|
+
### URL 自动抓取
|
|
170
|
+
|
|
171
|
+
`prompt` 和 `context` 中的 URL 会在评测前自动抓取内容并内联到文本中。适用于引用在线文档、API 文档等场景:
|
|
98
172
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
| `assertions` | `array` | No | List of deterministic and async checks applied to the model output. Each assertion is an object with a `type` field (see [Assertion Types](#assertion-types)). |
|
|
106
|
-
| `assertions[].type` | `string` | **Yes** | The assertion type (e.g., `"contains"`, `"json_valid"`, `"custom"`). See full list below. |
|
|
107
|
-
| `assertions[].value` | `string\|number` | Varies | The value to check against. Required for `contains`, `starts_with`, `equals`, `min_length`, `cost_max`, etc. |
|
|
108
|
-
| `assertions[].values` | `array` | Varies | Array of strings. Required for `contains_all` and `contains_any`. |
|
|
109
|
-
| `assertions[].pattern` | `string` | Varies | Regex pattern. Required for `regex` type. |
|
|
110
|
-
| `assertions[].flags` | `string` | No | Regex flags (default: `"i"`). Only used with `regex` type. |
|
|
111
|
-
| `assertions[].schema` | `object` | Varies | JSON Schema object. Required for `json_schema` type. Validated via [ajv](https://ajv.js.org/) (full JSON Schema spec). |
|
|
112
|
-
| `assertions[].reference` | `string` | Varies | Reference text for semantic comparison. Required for `semantic_similarity` type. |
|
|
113
|
-
| `assertions[].threshold` | `number` | No | Minimum score (1-5) to consider a semantic similarity match passing. Default: `3`. |
|
|
114
|
-
| `assertions[].fn` | `string` | Varies | Path to a `.mjs` file exporting the check function. Required for `custom` type. Resolved relative to the samples file directory. |
|
|
115
|
-
| `assertions[].weight` | `number` | No | Weight of this assertion in the composite score calculation. Default: `1`. Higher weight = more influence on the final assertion score. |
|
|
116
|
-
| `dimensions` | `object` | No | Key-value map for multi-dimensional LLM scoring. Each key is a dimension name (e.g., `"security"`), and the value is the rubric text the LLM judge uses to score that dimension (1-5). Scores are averaged into a single LLM score. |
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"sample_id": "s001",
|
|
176
|
+
"prompt": "请根据以下 PRD 文档生成测试用例:https://wiki.example.com/prd/feature-x"
|
|
177
|
+
}
|
|
178
|
+
```
|
|
117
179
|
|
|
118
|
-
|
|
180
|
+
运行时,URL 会被替换为实际文档内容。获取顺序:先通过 MCP Server 获取匹配的 URL(如 SSO 保护的私有文档),再通过 HTTP 获取剩余 URL。MCP 已成功的 URL 不会重复 HTTP 抓取。
|
|
119
181
|
|
|
120
|
-
|
|
182
|
+
**私有文档 URL**:在项目目录放一个 `.mcp.json` 配置文件,或通过 `--mcp-config` 指定路径:
|
|
121
183
|
|
|
122
|
-
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"mcpServers": {
|
|
187
|
+
"docs": {
|
|
188
|
+
"command": "npx",
|
|
189
|
+
"args": ["@example/docs-mcp-server"],
|
|
190
|
+
"env": { "DOCS_API_TOKEN": "xxx" },
|
|
191
|
+
"urlPatterns": ["docs.example.com"],
|
|
192
|
+
"fetchTool": {
|
|
193
|
+
"name": "fetch_doc",
|
|
194
|
+
"urlTransform": {
|
|
195
|
+
"regex": "docs\\.example\\.com/([^/]+/[^/]+)/([^/?#]+)",
|
|
196
|
+
"params": { "namespace": "$1", "slug": "$2" }
|
|
197
|
+
},
|
|
198
|
+
"contentExtract": "data.body"
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
123
204
|
|
|
124
|
-
|
|
205
|
+
**公网 URL**:直接 HTTP 获取,如果需要认证请确保命令行环境已配置好网络访问(VPN、代理等)。
|
|
125
206
|
|
|
126
|
-
|
|
207
|
+
### 评分策略
|
|
127
208
|
|
|
128
|
-
|
|
209
|
+
#### 1. 断言评分
|
|
129
210
|
|
|
130
|
-
|
|
211
|
+
基于规则的本地检查,每个断言产生通过/失败结果。
|
|
131
212
|
|
|
132
|
-
|
|
133
|
-
2. Sum the weights of all passing assertions → `passedWeight`
|
|
134
|
-
3. Sum the weights of all assertions → `totalWeight`
|
|
135
|
-
4. Compute ratio: `passedWeight / totalWeight` (0.0 ~ 1.0)
|
|
136
|
-
5. Normalize to 1-5 scale: **`score = 1 + ratio × 4`**
|
|
213
|
+
**计算方式:**
|
|
137
214
|
|
|
138
|
-
|
|
215
|
+
- 通过率 = 通过断言的权重之和 / 总权重(0~1)
|
|
216
|
+
- 分数 = 1 + 通过率 × 4(映射到 1~5 分)
|
|
217
|
+
- 示例:3 个断言(权重各 1),2 个通过 → 通过率 = 2/3 → 分数 = 1 + 0.67 × 4 = **3.67**
|
|
139
218
|
|
|
140
|
-
#### 2. Rubric
|
|
219
|
+
#### 2. Rubric / Dimensions 评分
|
|
141
220
|
|
|
142
|
-
|
|
221
|
+
评委模型(默认 `haiku`)按标准打 1-5 分。`dimensions` 模式下各维度独立评分后取平均。
|
|
143
222
|
|
|
144
|
-
|
|
223
|
+
#### 3. 综合分数
|
|
145
224
|
|
|
146
|
-
|
|
225
|
+
| 条件 | 公式 |
|
|
226
|
+
|------|------|
|
|
227
|
+
| 仅断言 | `assertionScore` |
|
|
228
|
+
| 仅 LLM | `llmScore` |
|
|
229
|
+
| 两者都有 | `(assertionScore + llmScore) / 2` |
|
|
230
|
+
| 都没有 | `0` |
|
|
147
231
|
|
|
148
|
-
|
|
232
|
+
### 断言类型
|
|
149
233
|
|
|
150
|
-
|
|
234
|
+
**确定性断言(18 种):**
|
|
151
235
|
|
|
152
|
-
|
|
236
|
+
| 类型 | 说明 |
|
|
237
|
+
|------|------|
|
|
238
|
+
| `contains` / `not_contains` | 包含/不包含子串 |
|
|
239
|
+
| `regex` | 正则匹配 |
|
|
240
|
+
| `min_length` / `max_length` | 长度范围 |
|
|
241
|
+
| `json_valid` / `json_schema` | JSON 校验 |
|
|
242
|
+
| `starts_with` / `ends_with` | 前缀/后缀匹配 |
|
|
243
|
+
| `equals` / `not_equals` | 精确匹配 |
|
|
244
|
+
| `word_count_min` / `word_count_max` | 词数范围 |
|
|
245
|
+
| `contains_all` / `contains_any` | 多值匹配 |
|
|
246
|
+
| `cost_max` / `latency_max` | 成本/延迟限制 |
|
|
247
|
+
| `semantic_similarity` | LLM 语义相似度 |
|
|
248
|
+
| `custom` | 自定义 JS 函数(30s 超时) |
|
|
153
249
|
|
|
154
|
-
|
|
155
|
-
|----------------|----------------------|
|
|
156
|
-
| Assertions only | `assertionScore` |
|
|
157
|
-
| LLM only (rubric or dimensions) | `llmScore` |
|
|
158
|
-
| Both | `(assertionScore + llmScore) / 2` |
|
|
159
|
-
| Neither | `0` |
|
|
250
|
+
### 自定义断言
|
|
160
251
|
|
|
161
|
-
|
|
252
|
+
```js
|
|
253
|
+
// my-assertion.mjs
|
|
254
|
+
export default function(output, { sample, assertion }) {
|
|
255
|
+
return { pass: output.includes('SQL'), message: '检查了 SQL 关键字' };
|
|
256
|
+
}
|
|
257
|
+
```
|
|
162
258
|
|
|
163
|
-
|
|
259
|
+
## 四维评估指标
|
|
164
260
|
|
|
165
|
-
|
|
261
|
+
评测报告从四个维度展示结果:
|
|
166
262
|
|
|
167
|
-
|
|
|
168
|
-
|
|
169
|
-
|
|
|
170
|
-
|
|
|
171
|
-
|
|
|
172
|
-
|
|
|
173
|
-
| `max_length` | `value`, `weight` | Output length <= value |
|
|
174
|
-
| `json_valid` | `weight` | Output is valid JSON |
|
|
175
|
-
| `json_schema` | `schema`, `weight` | Output matches JSON Schema (full spec via ajv) |
|
|
176
|
-
| `starts_with` | `value`, `weight` | Output starts with string (case-insensitive) |
|
|
177
|
-
| `ends_with` | `value`, `weight` | Output ends with string (case-insensitive) |
|
|
178
|
-
| `equals` | `value`, `weight` | Output exactly equals value (after trim) |
|
|
179
|
-
| `not_equals` | `value`, `weight` | Output does not equal value (after trim) |
|
|
180
|
-
| `word_count_min` | `value`, `weight` | Word count >= value |
|
|
181
|
-
| `word_count_max` | `value`, `weight` | Word count <= value |
|
|
182
|
-
| `contains_all` | `values`, `weight` | Output contains ALL substrings |
|
|
183
|
-
| `contains_any` | `values`, `weight` | Output contains at least one substring |
|
|
184
|
-
| `cost_max` | `value`, `weight` | Execution cost (USD) <= value |
|
|
185
|
-
| `latency_max` | `value`, `weight` | Execution latency (ms) <= value |
|
|
263
|
+
| 维度 | 指标 | 说明 |
|
|
264
|
+
|------|------|------|
|
|
265
|
+
| 📊 **质量** | 综合分数、断言分、LLM 评分、min/max | 基于断言和 LLM 评委的综合评分 |
|
|
266
|
+
| 💰 **成本** | 总成本、输入/输出 Token 数 | 基于 Token 消耗和模型定价的 API 费用 |
|
|
267
|
+
| ⚡ **效率** | 平均延迟 (ms) | 从发送请求到收到完整响应的端到端耗时 |
|
|
268
|
+
| 🛡️ **稳定性** | 成功率 (%) | 模型调用成功率,失败包括超时、API 错误等 |
|
|
186
269
|
|
|
187
|
-
|
|
270
|
+
## CLI 参考
|
|
188
271
|
|
|
189
|
-
|
|
190
|
-
|------|--------|-------------|
|
|
191
|
-
| `semantic_similarity` | `reference`, `threshold`, `weight` | LLM judges similarity to reference text (threshold default: 3) |
|
|
192
|
-
| `custom` | `fn`, `weight` | Load external JS function (see below) |
|
|
272
|
+
### `omk bench run`
|
|
193
273
|
|
|
194
|
-
|
|
274
|
+
```bash
|
|
275
|
+
omk bench run [选项]
|
|
276
|
+
|
|
277
|
+
选项:
|
|
278
|
+
--samples <路径> 样本文件(默认:eval-samples.json,自动检测 .yaml/.yml)
|
|
279
|
+
--skill-dir <路径> artifact 目录(参数名沿用历史写法,默认:skills)
|
|
280
|
+
--variants <a,b> 变体名称,不指定时自动从 artifact 目录发现
|
|
281
|
+
只有一个 artifact 时自动加 baseline 对照
|
|
282
|
+
特殊值:baseline(空 artifact)、git:name(git 历史版本)、
|
|
283
|
+
git:ref:name(指定 commit)、含 / 的路径(直接读取文件)
|
|
284
|
+
--model <名称> 被测模型(默认:sonnet)
|
|
285
|
+
--judge-model <名称> 评委模型(默认:haiku)
|
|
286
|
+
--output-dir <路径> 输出目录(默认:~/.oh-my-knowledge/reports/)
|
|
287
|
+
--no-judge 跳过 LLM 评分
|
|
288
|
+
--no-cache 禁用结果缓存(默认开启,相同输入自动复用)
|
|
289
|
+
--dry-run 仅预览
|
|
290
|
+
--blind 盲测模式
|
|
291
|
+
--concurrency <n> 并行任务数(默认:1)
|
|
292
|
+
--timeout <秒> 单个任务的执行器超时时间(默认:120)
|
|
293
|
+
--repeat <n> 重复 N 次做方差分析(默认:1)
|
|
294
|
+
--executor <名称> 执行器(默认:claude),支持自定义命令
|
|
295
|
+
--skip-preflight 跳过评测前的模型连通性检查
|
|
296
|
+
--mcp-config <路径> MCP 配置文件,用于通过 MCP Server 获取私有文档 URL 内容
|
|
297
|
+
(默认:当前目录的 .mcp.json)
|
|
298
|
+
--no-serve 评测完成后不自动启动报告服务
|
|
299
|
+
--verbose 打印每个样本的详细执行结果(耗时、tokens、输出预览)
|
|
300
|
+
--each 批量评测:每个 artifact 独立和 baseline 对比
|
|
301
|
+
需要每个 artifact 配对 {name}.eval-samples.json
|
|
302
|
+
```
|
|
195
303
|
|
|
196
|
-
|
|
304
|
+
### `omk bench run --each`(批量评测)
|
|
305
|
+
|
|
306
|
+
当 skills/ 下放了多个**独立的** artifact 时,使用 `--each` 逐个评测,每个 artifact 独立和 baseline 对比,生成一份合并报告。
|
|
197
307
|
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
308
|
+
```
|
|
309
|
+
skills/
|
|
310
|
+
├── asset.md ← artifact 文件
|
|
311
|
+
├── asset.eval-samples.json ← 配对的测试集
|
|
312
|
+
├── home.md
|
|
313
|
+
├── home.eval-samples.json
|
|
314
|
+
└── product/ ← 目录格式也支持
|
|
315
|
+
├── SKILL.md
|
|
316
|
+
└── eval-samples.json
|
|
204
317
|
```
|
|
205
318
|
|
|
206
|
-
|
|
319
|
+
配对规则:
|
|
207
320
|
|
|
208
|
-
|
|
321
|
+
- `{name}.md` → 查找同目录下的 `{name}.eval-samples.json`
|
|
322
|
+
- `{name}/SKILL.md` → 查找 `{name}/eval-samples.json`
|
|
323
|
+
- 没有配对 eval-samples 的 artifact 会被跳过并打印警告
|
|
209
324
|
|
|
210
|
-
|
|
325
|
+
```bash
|
|
326
|
+
omk bench run --each
|
|
327
|
+
omk bench run --each --dry-run
|
|
328
|
+
```
|
|
211
329
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
"nodeVersion": "v22.0.0",
|
|
226
|
-
"skillHashes": { "v1": "a1b2c3d4e5f6", "v2": "f6e5d4c3b2a1" }
|
|
227
|
-
},
|
|
228
|
-
"summary": {
|
|
229
|
-
"v1": {
|
|
230
|
-
"totalSamples": 3,
|
|
231
|
-
"successCount": 3,
|
|
232
|
-
"errorCount": 0,
|
|
233
|
-
"avgCompositeScore": 3.67,
|
|
234
|
-
"avgAssertionScore": 3.0,
|
|
235
|
-
"avgLlmScore": 4.33,
|
|
236
|
-
"avgDurationMs": 2500,
|
|
237
|
-
"avgTotalTokens": 1850,
|
|
238
|
-
"totalCostUSD": 0.0112
|
|
239
|
-
},
|
|
240
|
-
"v2": {
|
|
241
|
-
"totalSamples": 3,
|
|
242
|
-
"successCount": 3,
|
|
243
|
-
"errorCount": 0,
|
|
244
|
-
"avgCompositeScore": 4.5,
|
|
245
|
-
"avgAssertionScore": 5.0,
|
|
246
|
-
"avgLlmScore": 4.0,
|
|
247
|
-
"avgDurationMs": 2800,
|
|
248
|
-
"avgTotalTokens": 2100,
|
|
249
|
-
"totalCostUSD": 0.0122
|
|
250
|
-
}
|
|
251
|
-
},
|
|
252
|
-
"results": [
|
|
253
|
-
{
|
|
254
|
-
"sample_id": "s001",
|
|
255
|
-
"variants": {
|
|
256
|
-
"v1": {
|
|
257
|
-
"ok": true,
|
|
258
|
-
"compositeScore": 3.5,
|
|
259
|
-
"assertions": {
|
|
260
|
-
"passed": 1,
|
|
261
|
-
"total": 2,
|
|
262
|
-
"score": 3.0,
|
|
263
|
-
"details": [
|
|
264
|
-
{ "type": "contains", "value": "SQL injection", "weight": 1, "passed": true },
|
|
265
|
-
{ "type": "contains", "value": "parameterized", "weight": 1, "passed": false }
|
|
266
|
-
]
|
|
267
|
-
},
|
|
268
|
-
"llmScore": 4,
|
|
269
|
-
"llmReason": "Identified the vulnerability but did not provide a complete fix",
|
|
270
|
-
"durationMs": 2300,
|
|
271
|
-
"inputTokens": 850,
|
|
272
|
-
"outputTokens": 1200,
|
|
273
|
-
"totalTokens": 2050,
|
|
274
|
-
"costUSD": 0.0038,
|
|
275
|
-
"outputPreview": "This code has a SQL injection vulnerability..."
|
|
276
|
-
},
|
|
277
|
-
"v2": {
|
|
278
|
-
"ok": true,
|
|
279
|
-
"compositeScore": 4.5,
|
|
280
|
-
"assertions": {
|
|
281
|
-
"passed": 2,
|
|
282
|
-
"total": 2,
|
|
283
|
-
"score": 5.0,
|
|
284
|
-
"details": [
|
|
285
|
-
{ "type": "contains", "value": "SQL injection", "weight": 1, "passed": true },
|
|
286
|
-
{ "type": "contains", "value": "parameterized", "weight": 1, "passed": true }
|
|
287
|
-
]
|
|
288
|
-
},
|
|
289
|
-
"llmScore": 4,
|
|
290
|
-
"llmReason": "Thorough analysis with actionable fix code",
|
|
291
|
-
"durationMs": 2600,
|
|
292
|
-
"inputTokens": 900,
|
|
293
|
-
"outputTokens": 1400,
|
|
294
|
-
"totalTokens": 2300,
|
|
295
|
-
"costUSD": 0.0042,
|
|
296
|
-
"outputPreview": "## Security Issue: SQL Injection\n\nThe code is vulnerable..."
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
],
|
|
301
|
-
"analysis": {
|
|
302
|
-
"insights": [
|
|
303
|
-
{
|
|
304
|
-
"type": "uniform_scores",
|
|
305
|
-
"severity": "info",
|
|
306
|
-
"message": "1/3 samples show score difference < 0.5 between variants"
|
|
307
|
-
}
|
|
308
|
-
],
|
|
309
|
-
"suggestions": []
|
|
310
|
-
}
|
|
311
|
-
}
|
|
330
|
+
### `omk bench gen-samples`(生成测评用例)
|
|
331
|
+
|
|
332
|
+
读取 artifact 内容,通过 LLM 自动生成 eval-samples。生成后请审查编辑再跑评测。
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
# 为指定 artifact 生成测试集(输出到 eval-samples.json)
|
|
336
|
+
omk bench gen-samples skills/my-skill.md
|
|
337
|
+
|
|
338
|
+
# 为 skills/ 下所有缺少测试集的 artifact 批量生成
|
|
339
|
+
omk bench gen-samples --each
|
|
340
|
+
|
|
341
|
+
# 指定生成数量
|
|
342
|
+
omk bench gen-samples skills/my-skill.md --count 10
|
|
312
343
|
```
|
|
313
344
|
|
|
314
|
-
|
|
345
|
+
选项:
|
|
315
346
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
347
|
+
```
|
|
348
|
+
--each 为所有缺少 eval-samples 的 artifact 批量生成
|
|
349
|
+
--count <n> 每个 artifact 生成的样本数(默认:5)
|
|
350
|
+
--model <名称> 生成用的模型(默认:sonnet)
|
|
351
|
+
--skill-dir <路径> artifact 目录(参数名沿用历史写法,默认:skills),配合 --each 使用
|
|
352
|
+
```
|
|
320
353
|
|
|
321
|
-
|
|
354
|
+
### `omk bench evolve`(自我循环改进)
|
|
322
355
|
|
|
323
|
-
|
|
356
|
+
让 AI 自动迭代 artifact:评测 → 分析弱点 → LLM 改进 → 再评测 → 分数涨了留、没涨扔 → 重复。
|
|
324
357
|
|
|
325
358
|
```bash
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
--
|
|
337
|
-
--
|
|
338
|
-
--
|
|
339
|
-
--
|
|
340
|
-
--executor <name> Executor (default: claude)
|
|
359
|
+
# 基本用法:迭代 5 轮
|
|
360
|
+
omk bench evolve skills/my-skill.md
|
|
361
|
+
|
|
362
|
+
# 指定轮数和目标分数
|
|
363
|
+
omk bench evolve skills/my-skill.md --rounds 10 --target 4.5
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
选项:
|
|
367
|
+
|
|
368
|
+
```
|
|
369
|
+
--rounds <n> 最大迭代轮数(默认:5)
|
|
370
|
+
--target <分数> 目标分数,达到即停
|
|
371
|
+
--samples <路径> 样本文件(默认:eval-samples.json)
|
|
372
|
+
--improve-model <名称> 改进用模型(默认:sonnet)
|
|
341
373
|
```
|
|
342
374
|
|
|
375
|
+
每轮产出保存在 `skills/evolve/` 目录(`my-skill.r0.md`、`my-skill.r1.md`...),可以 diff 查看 AI 改了什么。最佳版本自动写回原始文件。
|
|
376
|
+
|
|
343
377
|
### `omk bench ci`
|
|
344
378
|
|
|
345
|
-
|
|
379
|
+
在自动化流水线中运行评测。评分达标则退出码为 0(通过),否则为 1(失败),可直接用于卡点判断。
|
|
346
380
|
|
|
347
381
|
```bash
|
|
348
|
-
omk bench ci [
|
|
382
|
+
omk bench ci [选项]
|
|
383
|
+
--threshold <数值> 达标的最低综合分数(默认:3.5)
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### `omk bench report`
|
|
387
|
+
|
|
388
|
+
启动报告服务,浏览历史报告、提交反馈、删除报告。
|
|
349
389
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
--
|
|
390
|
+
```bash
|
|
391
|
+
omk bench report [选项]
|
|
392
|
+
--port <端口号> 服务端口(默认:7799)
|
|
353
393
|
```
|
|
354
394
|
|
|
355
|
-
|
|
395
|
+
### `omk bench init`
|
|
356
396
|
|
|
357
|
-
|
|
397
|
+
```bash
|
|
398
|
+
omk bench init [目录] # 生成评测项目脚手架
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
## 执行器
|
|
402
|
+
|
|
403
|
+
### 内置执行器
|
|
404
|
+
|
|
405
|
+
| 执行器 | 适用场景 | 说明 |
|
|
406
|
+
|--------|----------|------|
|
|
407
|
+
| `claude` | 默认 | 通过 `claude -p` 调用 Claude CLI |
|
|
408
|
+
| `claude-sdk` | 结构化输出 | 通过 Claude Agent SDK 调用,无 stdout 解析,避免 buffer 截断 |
|
|
409
|
+
| `openai` | 跨厂商对比 | 通过 `openai api` CLI 调用 |
|
|
410
|
+
| `gemini` | 跨厂商对比 | 通过 `gemini` CLI 调用 |
|
|
411
|
+
| `anthropic-api` | 无需 CLI | 直接调用 Anthropic HTTP API(需 `ANTHROPIC_API_KEY`) |
|
|
412
|
+
| `openai-api` | 无需 CLI | 直接调用 OpenAI HTTP API(需 `OPENAI_API_KEY`) |
|
|
413
|
+
|
|
414
|
+
API 直调执行器支持通过环境变量自定义 Base URL:`ANTHROPIC_BASE_URL`、`OPENAI_BASE_URL`。
|
|
415
|
+
|
|
416
|
+
### 自定义执行器
|
|
417
|
+
|
|
418
|
+
任何 shell 命令都可以作为执行器,通过 stdin/stdout JSON 协议通信:
|
|
358
419
|
|
|
359
420
|
```bash
|
|
360
|
-
omk bench
|
|
421
|
+
omk bench run --executor "python my_provider.py"
|
|
422
|
+
omk bench run --executor "./my-executor.sh"
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
**协议约定:**
|
|
426
|
+
|
|
427
|
+
- **输入**(stdin):JSON `{"model":"...","system":"...","prompt":"..."}`
|
|
428
|
+
- **输出**(stdout):JSON `{"output":"模型回复","inputTokens":0,"outputTokens":0,"costUSD":0}`
|
|
429
|
+
- stdout 中只需返回有值的字段,其余默认为 0;也可以直接输出纯文本(不解析 token/成本)
|
|
430
|
+
- 非零退出码视为执行失败
|
|
431
|
+
|
|
432
|
+
### Artifact 目录结构
|
|
433
|
+
|
|
434
|
+
默认执行器(claude/openai/gemini)支持两种 artifact 布局,同一次评测中可混用:
|
|
361
435
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
436
|
+
```
|
|
437
|
+
skills/
|
|
438
|
+
├── v1.md # 方式一:直接放 .md 文件
|
|
439
|
+
└── my-skill/ # 方式二:完整 artifact 目录
|
|
440
|
+
├── SKILL.md # 工具自动读取此文件作为 system prompt
|
|
441
|
+
├── config.json # 其他文件不参与评测,仅保留完整性
|
|
442
|
+
└── scripts/
|
|
365
443
|
```
|
|
366
444
|
|
|
367
|
-
|
|
445
|
+
**Variant 解析规则:**
|
|
446
|
+
|
|
447
|
+
`variant` 是实验分组表达式。解析之后,OMK 会得到一个 `artifact` 与可选的 `runtime context`(当前主要是 `cwd`)。
|
|
448
|
+
|
|
449
|
+
| 格式 | 含义 |
|
|
450
|
+
|------|------|
|
|
451
|
+
| `name` | 从 artifact 目录查找 `name.md` 或 `name/SKILL.md`,解析为一个 artifact |
|
|
452
|
+
| `baseline` | 空 artifact,不使用 system prompt;可直接理解为“什么都没有” |
|
|
453
|
+
| `project-env@/path/to/project` | 空 artifact,但在指定项目目录运行,用于单独观察项目级 runtime context |
|
|
454
|
+
| `git:name` | 从 git HEAD 读取一个 artifact 的上次提交版本 |
|
|
455
|
+
| `git:ref:name` | 从 git 指定 commit 读取一个 artifact |
|
|
456
|
+
| `./path/to/file.md` | 含 `/` 的路径,直接读取文件作为 artifact |
|
|
457
|
+
| `variant@/path/to/project` | 给任意变体附加运行目录,支持 `name@cwd`、`git:name@cwd`、`/file.md@cwd` |
|
|
458
|
+
|
|
459
|
+
不指定 `--variants` 时,自动扫描 artifact 目录下的所有 `.md` 文件和含 `SKILL.md` 的子目录。只有一个 artifact 时自动加 `baseline` 作为对照。
|
|
368
460
|
|
|
369
461
|
```bash
|
|
370
|
-
|
|
462
|
+
# 自动发现 skills/ 下所有 artifact
|
|
463
|
+
omk bench run
|
|
464
|
+
|
|
465
|
+
# 显式指定两个变体
|
|
466
|
+
omk bench run --variants v1,v2
|
|
467
|
+
|
|
468
|
+
# 对比空 artifact 和显式 artifact 的效果差异
|
|
469
|
+
omk bench run --variants baseline,my-skill
|
|
470
|
+
|
|
471
|
+
# 推荐用自描述标签单独观察项目级 runtime context 的影响
|
|
472
|
+
omk bench run --variants project-env@/path/to/target-project
|
|
473
|
+
|
|
474
|
+
# 对比“项目级 runtime context”与“显式 artifact 注入”
|
|
475
|
+
omk bench run --variants project-env@/path/to/target-project,/path/to/target-project/.claude/skills/prd/SKILL.md@/path/to/target-project
|
|
476
|
+
|
|
477
|
+
# 对比修改前后(旧版本从 git 历史读取)
|
|
478
|
+
omk bench run --variants git:my-skill,my-skill
|
|
479
|
+
|
|
480
|
+
# 直接指定文件路径
|
|
481
|
+
omk bench run --variants ./old-skill.md,./new-skill.md
|
|
371
482
|
```
|
|
372
483
|
|
|
373
|
-
|
|
484
|
+
**前置要求:**
|
|
374
485
|
|
|
375
|
-
|
|
486
|
+
- **claude**:安装 [Claude Code](https://claude.ai/code) 并认证
|
|
487
|
+
- **claude-sdk**:安装 [Claude Code](https://claude.ai/code) 并认证(使用 Agent SDK,无需 CLI stdout 解析)
|
|
488
|
+
- **anthropic-api**:设置 `ANTHROPIC_API_KEY` 环境变量
|
|
489
|
+
- **openai**:`pip install openai` 并设置 `OPENAI_API_KEY`
|
|
490
|
+
- **openai-api**:设置 `OPENAI_API_KEY` 环境变量
|
|
491
|
+
- **gemini**:`npm i -g @google/gemini-cli` 并认证
|
|
376
492
|
|
|
377
|
-
|
|
493
|
+
### Agent 评测与项目级 Runtime Context
|
|
378
494
|
|
|
379
|
-
|
|
495
|
+
当执行器使用 `claude-sdk` 时,OMK 现在已经支持第一版 agent-aware evaluation。
|
|
380
496
|
|
|
381
|
-
|
|
497
|
+
这里建议把几个概念分开理解:
|
|
382
498
|
|
|
383
|
-
|
|
499
|
+
- `artifact`:被评测对象,例如 baseline、skill、prompt、agent
|
|
500
|
+
- `variant`:CLI 里的实验分组表达式
|
|
501
|
+
- `runtime context`:运行时上下文,当前主要是 `cwd`;在项目型 agent 场景下,它就包含项目目录、`CLAUDE.md`、本地 skills 等会影响行为的环境因素
|
|
384
502
|
|
|
385
|
-
|
|
386
|
-
- Per-variant mean, standard deviation, 95% confidence interval
|
|
387
|
-
- Pairwise Welch's t-test between variants (significance at p < 0.05)
|
|
503
|
+
在 OMK 里,`agent` 不是所有对象的总称,`skill` 也不是所有对象的总称。更稳妥的说法是:你在比较不同 artifact 在不同 runtime context 下的表现。
|
|
388
504
|
|
|
389
|
-
|
|
505
|
+
- 自动抽取 turns / toolCalls trace
|
|
506
|
+
- 支持基于工具调用行为的断言
|
|
507
|
+
- 支持在指定 `cwd` 下运行,让 Claude Code 自动加载项目内的 `CLAUDE.md`、skills 和本地 runtime context
|
|
390
508
|
|
|
391
|
-
|
|
392
|
-
- **Low-discrimination assertions**: assertions with identical results across all variants
|
|
393
|
-
- **Uniform scores**: samples where variants score within 0.5 of each other
|
|
394
|
-
- **All-pass / all-fail**: assertions that may be too loose or too strict
|
|
395
|
-
- **High-cost samples**: samples with disproportionately high cost
|
|
509
|
+
#### 推荐执行器
|
|
396
510
|
|
|
397
|
-
|
|
511
|
+
```bash
|
|
512
|
+
omk bench run --executor claude-sdk
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
#### 支持的 agent 相关断言
|
|
516
|
+
|
|
517
|
+
| 断言 | 含义 |
|
|
518
|
+
|------|------|
|
|
519
|
+
| `tools_called` | 必须调用指定工具 |
|
|
520
|
+
| `tools_not_called` | 禁止调用指定工具 |
|
|
521
|
+
| `tools_count_min` / `tools_count_max` | 工具调用次数上下界 |
|
|
522
|
+
| `tool_output_contains` | 指定工具输出必须包含关键内容 |
|
|
523
|
+
| `turns_min` / `turns_max` | 交互轮次上下界 |
|
|
524
|
+
|
|
525
|
+
#### 三种常见对照组
|
|
526
|
+
|
|
527
|
+
**1. 裸模型 baseline**
|
|
528
|
+
|
|
529
|
+
不注入 system prompt,也不进入带知识的项目目录。
|
|
530
|
+
|
|
531
|
+
```bash
|
|
532
|
+
omk bench run \
|
|
533
|
+
--executor claude-sdk \
|
|
534
|
+
--variants baseline
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
**2. 空 artifact + 项目级 runtime context**
|
|
538
|
+
|
|
539
|
+
不注入 system prompt,但在项目目录运行。它不是严格意义上的“裸 baseline”,而是“空 artifact + 项目级 runtime context”。
|
|
540
|
+
|
|
541
|
+
```bash
|
|
542
|
+
omk bench run \
|
|
543
|
+
--executor claude-sdk \
|
|
544
|
+
--variants project-env@/path/to/target-project
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
**3. 显式 artifact 注入**
|
|
398
548
|
|
|
399
|
-
|
|
549
|
+
直接把某个外部 `SKILL.md` 作为 artifact 注入,同时保留项目目录上下文。适合对比“项目级 runtime context”与“显式单 artifact 注入”之间的差异。
|
|
400
550
|
|
|
401
|
-
|
|
551
|
+
```bash
|
|
552
|
+
omk bench run \
|
|
553
|
+
--executor claude-sdk \
|
|
554
|
+
--variants /path/to/target-project/.claude/skills/prd/SKILL.md@/path/to/target-project
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
#### 推荐的第一轮对照设计
|
|
558
|
+
|
|
559
|
+
对于 PRD / 复杂业务知识场景,建议先从下面两组开始:
|
|
560
|
+
|
|
561
|
+
```bash
|
|
562
|
+
omk bench run \
|
|
563
|
+
--executor claude-sdk \
|
|
564
|
+
--samples skills/evaluate-review/eval-samples.yaml \
|
|
565
|
+
--variants baseline,/path/to/target-project/.claude/skills/prd/SKILL.md@/path/to/target-project
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
如果你想证明“项目目录中的知识沉淀本身”是否有效,再加第三组:
|
|
402
569
|
|
|
403
|
-
|
|
570
|
+
```bash
|
|
571
|
+
omk bench run \
|
|
572
|
+
--executor claude-sdk \
|
|
573
|
+
--samples skills/evaluate-review/eval-samples.yaml \
|
|
574
|
+
--variants baseline,project-env@/path/to/target-project,/path/to/target-project/.claude/skills/prd/SKILL.md@/path/to/target-project
|
|
575
|
+
```
|
|
404
576
|
|
|
405
|
-
|
|
577
|
+
#### 设计建议
|
|
406
578
|
|
|
407
|
-
|
|
579
|
+
- **先用 `--dry-run`**:确认样本、variant 和 `cwd` 被正确解析
|
|
580
|
+
- **项目级对照必须区分 `cwd`**:相同 prompt 在不同项目目录下会走不同 runtime context
|
|
581
|
+
- **优先先跑 PRD 场景**:相比 Coding,更容易验证知识完整性、影响面识别和业务正确性
|
|
408
582
|
|
|
409
|
-
|
|
583
|
+
### 常见模型配置示例
|
|
410
584
|
|
|
411
|
-
|
|
412
|
-
|----------|----------|---------------|------|
|
|
413
|
-
| `claude` | `claude -p` | `sonnet` | Claude Max plan or API key |
|
|
414
|
-
| `openai` | `openai api chat.completions.create` | `gpt-4o` | `OPENAI_API_KEY` env var |
|
|
415
|
-
| `gemini` | `gemini` (stdin pipe) | Default Gemini model | Google account or `GOOGLE_API_KEY` |
|
|
585
|
+
**没有 Claude?** 大多数国产模型(GLM、通义千问、Moonshot、DeepSeek 等)都兼容 OpenAI API 格式,可以直接使用 `openai-api` 执行器:
|
|
416
586
|
|
|
417
587
|
```bash
|
|
418
|
-
#
|
|
419
|
-
|
|
588
|
+
# GLM(智谱)
|
|
589
|
+
export OPENAI_API_KEY="你的智谱 API Key"
|
|
590
|
+
export OPENAI_BASE_URL="https://open.bigmodel.cn/api/paas/v4"
|
|
591
|
+
omk bench run --executor openai-api --model glm-4-plus \
|
|
592
|
+
--judge-model glm-4-plus --no-cache
|
|
593
|
+
|
|
594
|
+
# 通义千问
|
|
595
|
+
export OPENAI_API_KEY="你的通义 API Key"
|
|
596
|
+
export OPENAI_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1"
|
|
597
|
+
omk bench run --executor openai-api --model qwen-plus \
|
|
598
|
+
--judge-model qwen-plus
|
|
599
|
+
|
|
600
|
+
# DeepSeek
|
|
601
|
+
export OPENAI_API_KEY="你的 DeepSeek API Key"
|
|
602
|
+
export OPENAI_BASE_URL="https://api.deepseek.com"
|
|
603
|
+
omk bench run --executor openai-api --model deepseek-chat \
|
|
604
|
+
--judge-model deepseek-chat
|
|
605
|
+
|
|
606
|
+
# Moonshot(Kimi)
|
|
607
|
+
export OPENAI_API_KEY="你的 Moonshot API Key"
|
|
608
|
+
export OPENAI_BASE_URL="https://api.moonshot.cn/v1"
|
|
609
|
+
omk bench run --executor openai-api --model moonshot-v1-8k \
|
|
610
|
+
--judge-model moonshot-v1-8k
|
|
611
|
+
```
|
|
420
612
|
|
|
421
|
-
|
|
422
|
-
omk bench run --executor gemini --model gemini-2.5-pro --variants v1,v2
|
|
613
|
+
**Ollama 本地模型:**
|
|
423
614
|
|
|
424
|
-
|
|
425
|
-
omk bench run --executor
|
|
426
|
-
|
|
615
|
+
```bash
|
|
616
|
+
omk bench run --executor "python examples/custom-executor/ollama-executor.py" \
|
|
617
|
+
--model llama3 --no-judge
|
|
427
618
|
```
|
|
428
619
|
|
|
429
|
-
|
|
430
|
-
- **claude**: Install [Claude Code](https://claude.ai/code) and authenticate
|
|
431
|
-
- **openai**: `pip install openai` and set `OPENAI_API_KEY`
|
|
432
|
-
- **gemini**: `npm i -g @google/gemini-cli` and authenticate with Google
|
|
620
|
+
**关于评委模型:**
|
|
433
621
|
|
|
434
|
-
|
|
622
|
+
- `--judge-model` 指定 LLM 评委使用的模型,默认 `haiku`
|
|
623
|
+
- `--judge-executor` 指定评委使用的执行器(默认与 `--executor` 相同)
|
|
624
|
+
- 如果你没有 Claude,用 `--judge-executor` 和 `--judge-model` 指向你可用的模型
|
|
625
|
+
- 加 `--no-judge` 可跳过 LLM 评委,仅使用断言评分
|
|
435
626
|
|
|
436
|
-
|
|
437
|
-
|----------|-------------|
|
|
438
|
-
| `CCV_PROXY_URL` | Route requests through cc-viewer proxy for real-time visualization |
|
|
439
|
-
| `OMK_BENCH_PORT` | Report server port (default: 7799) |
|
|
627
|
+
## 环境变量
|
|
440
628
|
|
|
441
|
-
|
|
629
|
+
| 变量 | 说明 |
|
|
630
|
+
|------|------|
|
|
631
|
+
| `CCV_PROXY_URL` | 将请求代理到 cc-viewer,实时可视化评测流量 |
|
|
632
|
+
| `OMK_BENCH_PORT` | 报告服务端口(默认:7799) |
|
|
633
|
+
|
|
634
|
+
## 系统要求
|
|
442
635
|
|
|
443
636
|
- Node.js >= 20
|
|
444
|
-
- `claude` CLI
|
|
637
|
+
- `claude` CLI(用于默认执行器和 LLM 评委,安装方式见 [Claude Code](https://claude.ai/code))
|
|
638
|
+
- 使用其他执行器(openai/gemini)且加 `--no-judge` 时可不装
|
|
639
|
+
|
|
640
|
+
## 安全说明
|
|
641
|
+
|
|
642
|
+
本工具设计用于**本地可信环境**(开发机、CI 流水线)。以下功能会执行本地代码,请确保输入来源可信:
|
|
643
|
+
|
|
644
|
+
| 功能 | 风险说明 | 适用范围 |
|
|
645
|
+
|------|----------|----------|
|
|
646
|
+
| **自定义断言** (`custom`) | 动态加载并执行用户指定的 `.mjs` 文件 | 仅使用自己编写或审查过的断言文件 |
|
|
647
|
+
| **eval-samples.json** | 断言配置中可引用外部文件路径 | 不要使用不可信来源的样本文件 |
|
|
445
648
|
|
|
446
|
-
|
|
649
|
+
**建议:**
|
|
447
650
|
|
|
448
|
-
|
|
651
|
+
- 不要在公网服务中暴露 `omk bench report` 服务(无认证)
|
|
652
|
+
- 不要用不可信的第三方 eval-samples 文件
|
|
653
|
+
- 自定义断言有 30 秒执行超时,但无沙箱隔离
|