-
Notifications
You must be signed in to change notification settings - Fork 14
Home
基于章节树(Chapter Tree)的个人/团队知识库 RAG 检索系统 + Agent Harness
端到端流水线:Markdown 知识库 → 章节树解析 → 向量 + BM25 混合检索 → Rerank → LLM 回答
适用版本:v0.3.0 | 最近更新:2026-06-13
- 1. 项目概览
- 2. RAG —— 检索增强生成引擎
- 3. Wiki —— Markdown 知识库
- 4. Harness —— Agent 执行回路
- 5. Skills —— RAG 自主进化能力
- 6. 四维度协作流(端到端示例)
- 7. 常见问题 FAQ
- 8. 路线图
he-wiki-rag 不是一个单纯的 RAG Demo,而是一个端到端的"知识 → 检索 → Agent 回答"工程样板。它把整个系统拆成四个相互独立、又可独立升级的维度:
| 维度 | 角色 | 技术栈 | 入口路径 |
|---|---|---|---|
| RAG | 检索后端:把 Wiki 知识库变成可被语义查询的 API | Python 3.11+ / FastAPI / ChromaDB / BGE-M3 | he-rag-engine/ |
| Wiki | 内容来源:以 Markdown + 章节树组织的可检索知识库 | Markdown / YAML frontmatter | wiki/ |
| Harness | 智能体执行回路:流式对话、工具调用、状态持久化、Trace | Node.js 18+ / SQLite | he-harness/ |
| Skills | RAG 自主进化能力:通过 he-rag-eval 等技能包,让 Agent 持续评测→诊断→优化→回归 RAG 系统 | Markdown / YAML frontmatter / Checkpoint 清单 | he-skills/ |
四者通过 HTTP + tool calling 解耦:
┌──────────────────┐ ┌──────────────────────┐
│ he-harness │ HTTP │ he-rag-engine │
│ (Node.js CLI) │ ──────▶ │ (FastAPI + Chroma) │
│ Harness + Skills│ │ RAG │
└──────────────────┘ └──────────┬───────────┘
│
▼
┌──────────────────┐
│ wiki/ │
│ Markdown 知识库 │
│ + chapter_trees │
└──────────────────┘
flowchart LR
subgraph Wiki[Wiki 维度]
MD["Markdown 文档<br/>+ frontmatter"]
CT["chapter_trees.json<br/>章节树索引"]
end
subgraph RAG[RAG 维度]
EMB["BGE-M3 Embedding"]
BM["BM25 (jieba)"]
QE["自动查询扩展"]
RR["Qwen3-Reranker"]
end
subgraph Harness[Harness 维度]
LOOP["Agent Loop"]
STATE["State Store<br/>(SQLite)"]
TRACE["Tracer + Replay"]
TOOLS["内置 Tools<br/>(tool calling)"]
end
subgraph Skills[Skills 维度 - RAG 自主进化]
SK1["he-rag-eval<br/>SKILL.md<br/>8 阶段工作流"]
SK2["评测→诊断→优化→回滚闭环"]
end
MD --> CT --> EMB
MD --> BM
EMB --> QE
LOOP --> TOOLS
TOOLS --> RAG
RAG --> LOOP
LOOP --> STATE
LOOP --> TRACE
SK1 -.->|驱动| SK2
SK2 -.->|评测 + 优化| RAG
SK2 -.->|被 Agent 平台加载| LOOP
概念区分:Harness 维度里的 Tools(如
knowledge_search)是 OpenAI 风格 tool calling,运行时由 AgentLoop 调度;Skills 维度里的 SKILL.md 是工作流文档,被外部 Agent 平台加载后引导 LLM 一步步完成评测-优化-回滚闭环。前者是单次函数调用,后者是 RAG 系统的"自我进化引擎"。
he-wiki-rag/
├── he-rag-engine/ # Python FastAPI 检索后端(向量 + BM25 + Rerank)
│ ├── app/ # FastAPI 入口、配置、模型、索引器、检索引擎
│ ├── scripts/ # 摘要增强脚本
│ ├── evaluate.py # 内置评测脚本
│ └── pyproject.toml
├── he-harness/ # Node.js Agent Harness(CLI 交互 + 工具调用)
│ ├── src/ # Agent Loop、State、Tracer、Tools
│ ├── cli/ # 交互式 CLI
│ ├── examples/ # 使用示例
│ └── package.json
├── he-skills/ # 外置技能包(驱动 RAG 自主进化)
│ └── he-rag-eval/ # RAG 评测 + 优化 + 回滚(v1.2.0)
│ ├── SKILL.md # 8 阶段工作流 + 检查清单
│ └── README.md # 公式、目标值、原理详解
├── wiki/ # 示例知识库(Markdown + 章节树索引)
│ ├── 03-knowledge-and-rag/ # ~76 篇 RAG 主题 Markdown
│ └── indices/chapter_trees.json
├── assets/ # 演示截图
├── start.sh # 一键启动脚本
└── README.md
# 1. 克隆 & 进入
git clone <repo-url> && cd he-wiki-rag
# 2. 配置环境变量
cp he-rag-engine/.env.example he-rag-engine/.env # 填 RAG_SILICONFLOW_API_KEY
cp he-harness/.env.example he-harness/.env # 可选:填 LLM Key,或保留 Mock
# 3. 一键启动
./start.sh启动后即可在 CLI 中提问:
你: RAG 的切块策略有哪些?
🔎 正在检索知识库...
✅ 知识库助手:……(引用了 3 个章节,附带面包屑路径)
详细步骤、配置项、二次开发模式见 根 README。
路径:
he-rag-engine/,技术栈 Python 3.11 + FastAPI + ChromaDB + BGE-M3 + jieba + Qwen3-Reranker。
RAG 维度解决的核心问题:把 Markdown 知识库变成可被语义查询的 API,并保证结果可溯源(带面包屑、源文件、原文片段)。
flowchart TB
subgraph API["FastAPI Server"]
direction LR
EP1["/search"]
EP2["/chapter/:id"]
EP3["/health"]
EP4["/stats"]
EP5["/admin/rebuild-index"]
end
API --> SE
subgraph SE["Search Engine"]
direction TB
QE["Query Expand<br/>Embedding 自动扩展 + Fallback 词典"]
QE --> VS & BS
VS["Vector Search<br/>ChromaDB + BGE-M3"]
BS["BM25 Search<br/>rank_bm25 + jieba"]
VS --> RRF["RRF Fusion<br/>加权倒数排名融合<br/>k=60, Vector:2.0 / BM25:1.0"]
BS --> RRF
RRF --> RR["Rerank<br/>Qwen3-Reranker-8B<br/>SiliconFlow API"]
RR --> PCI["Parent-Child Injection<br/>父子节点注入 (保守策略)<br/>MIN_SCORE=0.8, DISCOUNT=0.5"]
PCI --> RES["Results"]
end
RES --> OUTPUT["Search Results"]
subgraph DS["Data Layer"]
direction LR
IDX["Indexer<br/>ChromaDB + BM25 索引"]
TS["Tree Store<br/>内存章节树"]
SUM["Summary Enhancer<br/>LLM 摘要增强 (Qwen2.5-7B)"]
end
IDX -.->|"索引构建"| SE
TS -.->|"章节树查询"| SE
SUM -.->|"增强摘要"| IDX
系统的核心创新是基于 Markdown 标题层级构建的章节树,而非传统的固定 token 切块。
每篇文档被解析为:
| 概念 | 含义 | 关键字段 |
|---|---|---|
| Document | 一个 .md 文件 |
docId, filePath, frontmatter
|
| Chapter / Node | 按 H1~H6 切出的章节段 |
node_id, title, breadcrumb, summary, parent_id, children_ids, line, anchor
|
与"傻切块"相比,章节树保留了:
-
层级关系:父子兄弟节点可用于上下文扩展(
expand=children/parent/siblings) -
面包屑路径:检索结果直接告诉用户"这条来自
RAG > 关键设计点 > 切块策略" -
精确溯源:
line+anchor直接定位回源文件段落
| 通道 | 模型 / 算法 | 输入 | 输出 |
|---|---|---|---|
| 向量检索 | ChromaDB + BGE-M3(1024 维) | 原始查询 | 语义 Top-N 候选 |
| BM25 检索 | rank_bm25(BM25Okapi) + jieba 分词 | 查询扩展后的查询 | 关键词 Top-N 候选 |
两路用 ThreadPoolExecutor 并行执行降低延迟。
RRF_score(d) = Σ weight_i / (k + rank_i(d))
-
k = 60(平滑常数) - 向量权重
2.0(语义优先),BM25 权重1.0(关键词补充) - 候选集大小:
top_k × candidate_multiplier(rerank 时为 4 倍,否则 3 倍)
使用 Qwen3-Reranker-8B(SiliconFlow API)对候选精排:
-
主方案:SiliconFlow
/v1/rerankAPI,单次批量请求,输出连续相关性分数 -
备选方案:本地 Ollama 部署
Qwen3-Reranker-4B,逐文档 yes/no 判定 - Reranker 输入 = 标题 + 面包屑 + 关键词 + 摘要 + 原文前 8 行(≤ 300 字)
- 最大候选数 35 篇,输出
top_n=30
为什么用 Rerank API 而非本地模型? Reranker 8B 参数量大,本地部署要大量 GPU 显存;API 方案低延迟、可批量;保留 Ollama 作为离线备选。
问题:BM25 是纯词频匹配,"切块" 永远匹配不到 "chunking"。
方案:用 Embedding 相似度自动发现同义词,零维护词典。
flowchart TD
Q["查询: 切块策略"] --> T["jieba 分词"]
T --> Terms["术语: 切块, 策略"]
Terms --> Emb["BGE-M3 Embedding"]
Emb --> Sim["余弦相似度匹配"]
Sim --> Match["匹配结果<br/>chunking (0.89)<br/>分块 (0.85)<br/>切分 (0.82)"]
Match --> Exp["扩展后查询"]
Exp --> Final["切块策略 chunking 分块 切分"]
关键特性:
-
零维护:换知识库后
rebuild-index即可,自动从新知识库提取术语 - 多语言:BGE-M3 天然支持中英双语,自动发现"切块 ↔ chunking"
- 优雅降级:扩展器未加载时回退到精简的 Fallback 手工词典
-
阈值可调:
RAG_EXPAND_SIMILARITY_THRESHOLD(默认 0.75) - 性能:词汇表 Embedding 仅索引构建时执行一次;查询时相似度计算 = numpy 矩阵乘法(< 1ms)
Rerank 后,对高分结果的子节点进行保守注入,扩展检索上下文:
| 参数 | 值 | 说明 |
|---|---|---|
MIN_PARENT_SCORE |
0.8 |
父节点 rerank 分数阈值 |
MAX_CHILDREN_PER_PARENT |
2 |
每个父节点最多注入子节点数 |
CHILD_SCORE_DISCOUNT |
0.5 |
子节点分数 = 父节点分数 × 0.5 |
设计原则:不污染顶部结果,只为高度相关的父节点补充子章节信息。
用 LLM 为每个章节生成 50-100 字的中文摘要,提升 Embedding 质量:
- 模型:Qwen2.5-7B-Instruct(SiliconFlow API)
- 输入:章节路径 + 标题 + 正文片段(≤ 500 字)
-
输出:中文摘要,存于
data/enhanced_summaries.json - 支持增量:已生成摘要的章节自动跳过
Embedding 文档格式:
路径: RAG > 关键设计点 > 切块策略
标题: 切块策略
摘要: 讨论了知识库文档的切块方法,包括按 token 数切分和重叠窗口策略...
内容: <原文内容,最多 2048 字符>
| Method | Path | 说明 |
|---|---|---|
POST |
/search |
知识库搜索主接口 |
GET |
/chapter/{node_id} |
获取章节详情(含原文 + 子章节) |
GET |
/chapter/{node_id}/children |
子章节列表 |
GET |
/chapter/{node_id}/siblings |
兄弟章节列表 |
GET |
/health |
健康检查 |
GET |
/stats |
索引 + 章节树统计 |
POST |
/admin/rebuild-index |
触发全量索引重建(热更新,不中断服务) |
POST /search 请求体:
{
"query": "什么是 RAG 的切块策略?",
"top_k": 10,
"search_mode": "hybrid", // hybrid | vector | keyword
"rerank": true,
"expand": "none", // none | children | siblings | parent
"filters": {
"category": ["rag"],
"priority": ["high"],
"doc_type": ["concept"],
"keywords": ["切块"]
}
}响应示例:
{
"results": [
{
"node_id": "doc-001__ch-003",
"score": 0.92,
"rank_source": { "vector": 1, "bm25": 3, "rerank": 1 },
"title": "切块策略",
"breadcrumb": ["RAG", "关键设计点", "切块策略"],
"content": "## 切块策略\n...",
"summary": "讨论了知识库文档的切块方法...",
"metadata": {
"file_path": "wiki/rag/chunking-strategy.md",
"line": 42,
"anchor": "切块策略",
"level": 2,
"keywords": ["切块", "chunking"],
"doc_type": "concept",
"priority": "high",
"category": "rag"
},
"expanded": null
}
],
"total": 10,
"took_ms": 826.3,
"index_stats": { "total_chunks": 1234, "total_documents": 56, "last_sync": "..." }
}- 加载
chapter_trees.json到TreeStore - 预加载文件内容缓存
- 加载增强摘要
- 加载查询扩展词汇表
- 尝试加载已有索引;空索引 → 自动
build()
| 维度 | 说明 |
|---|---|
| 触发时机 | 知识库内容变更、章节树重新生成、摘要增量更新后 |
| 是否中断 | ❌ 不中断(用旧索引继续服务) |
| 耗时 | 1000 文档 ~ 30-60s;5000 文档 ~ 3-5min(瓶颈 = Embedding API) |
| 与重启区别 | Rebuild = 热更新;重启 = 冷启动(适合配置变更 / 部署) |
Rebuild 流程:
- 重新加载
chapter_trees.json - 加载增强摘要
- 重建 ChromaDB 向量索引
- 重建 BM25 关键词索引
- 重建查询扩展词汇表
cd he-rag-engine
python evaluate.py # 默认评测(hybrid 模式)
python evaluate.py --modes hybrid vector keyword
python evaluate.py --rerank # 开启 rerank 评测
python evaluate.py --hierarchical # 父子节点算部分命中
python evaluate.py --output results.json -v评测指标:
- Recall@K(K=5,10,20):相关文档的召回率
- Precision@K:返回结果的精确率
- MRR:首个相关文档的排名倒数
- NDCG@K:归一化折损累积增益
- Hit Rate@K:至少命中一个相关文档的查询比例
- 层级匹配:子节点(权重 0.5)和父节点(权重 0.3)算部分命中
支持按难度(easy/medium/hard)和分类(category)细分分析。
| 变量 | 默认 | 说明 |
|---|---|---|
RAG_SILICONFLOW_API_KEY |
必填 | SiliconFlow API Key |
RAG_EMBEDDING_PROVIDER |
siliconflow |
siliconflow / ollama
|
RAG_RERANK_PROVIDER |
siliconflow |
siliconflow / ollama
|
RAG_RERANK_MODEL |
Qwen/Qwen3-Reranker-8B |
Rerank 模型名 |
RAG_KB_ROOT |
./wiki |
知识库根目录 |
RAG_EXPAND_SIMILARITY_THRESHOLD |
0.75 |
自动查询扩展相似度阈值 |
RAG_EXPAND_MAX_TERMS |
6 |
最多扩展术语数 |
完整配置见 he-rag-engine/.env.example。
路径:
wiki/,被 RAG 引擎索引的内容来源。
wiki/
├── README.md # 仓库元信息(项目说明,不参与检索)
├── 03-knowledge-and-rag/ # 示例知识库正文(~76 篇 Markdown)
│ ├── README.md # ⚠️ 领域根节点(带 frontmatter,参与检索,请勿随意改)
│ ├── rag-system-design.md
│ ├── chunking-strategies.md
│ ├── retrieval-*.md
│ └── ...(约 70+ 主题页 + ~30 routing 治理页)
└── indices/
└── chapter_trees.json # 章节树索引(由 he-rag-engine 构建阶段生成)
⚠️ 重要:wiki/03-knowledge-and-rag/README.md的 frontmatter 是type: domain-root,它本身会被检索系统当作一篇文档。修改它会污染检索结果。
每篇 Markdown 顶部加 YAML frontmatter:
---
title: 文章标题
type: concept # concept / pattern / architecture / faq
priority: P0 # P0 / P1 / P2
category: rag # 用于检索过滤
keywords: 切块, chunking
---字段含义:
| 字段 | 类型 | 用途 |
|---|---|---|
title |
string | 文档标题(显示 + 检索) |
type |
enum | 文档类型(concept/pattern/architecture/faq/domain-root) |
priority |
enum | 重要程度(P0/P1/P2) |
category |
string | 主题分类(rag/agent/harness 等),用于检索过滤 |
keywords |
list | 关键词列表(用于检索过滤 + Embedding 增强) |
chapter_trees.json 是 RAG 引擎的核心输入,由知识库构建流程生成,存放于 wiki/indices/。
关键结构:
{
"generatedAt": "2026-06-05T17:01:02",
"version": "1.0.0",
"statistics": {
"totalDocuments": 772,
"totalChapters": 8337,
"maxDepth": 4
},
"documents": [
{
"docId": "e63bc74b-...",
"filePath": "wiki/00-home/agent-orchestration.md",
"frontmatter": { "title": "Agent 编排", "type": "concept", ... },
"chapters": [
{
"id": "30d9aeff-...",
"node_id": "30d9aeff-...",
"title": "编排架构",
"level": 1,
"ordinal": 1,
"parentId": "e63bc74b-...",
"line": 11,
"anchor": "编排架构",
"summary": "编排架构",
"breadcrumb": ["编排架构"]
}
]
}
]
}| 字段 | 说明 |
|---|---|
filePath |
Markdown 文件相对 kb_root 的路径 |
chapters[].level |
Markdown 标题层级(1=H1, 2=H2, ...) |
chapters[].parentId |
父节点 ID(指向 doc_id 或上级 chapter.id) |
chapters[].breadcrumb |
面包屑路径(数组),提供定位语境 |
chapters[].line |
标题在源文件中的行号(1-based) |
chapters[].anchor |
URL 锚点标识符 |
-
用标题层级组织内容:
######划分章节,章节树解析依赖标题层级 - 单篇 200~500 行:过长会被自动切块并破坏结构语义
-
稳定结构:
概念 / 模式 / 架构 / 示例 / 延伸阅读是建议的章节顺序 - 一个文档一个核心主题:降低正文混杂度
-
来源材料放
raw/:正式知识页只保留必要的来源引用
# 1. 替换内容
rm -rf wiki/03-knowledge-and-rag
mkdir -p wiki/your-topic
# ... 放入你的 .md 文件
# 2. 重新生成章节树索引
python scripts/build_chapter_trees.py --kb-root ./wiki
# 3. 触发索引热更新(不需要重启服务)
curl -X POST http://localhost:8000/admin/rebuild-indexflowchart TD
A["修改/新增/删除<br/>Markdown 文件"] --> B["重新生成 chapter_trees.json"]
B --> C["增量生成摘要<br/>python scripts/enhance_summaries.py"]
C --> D["POST /admin/rebuild-index"]
D --> E["索引热更新完成<br/>(服务不中断)"]
日常开发循环:
# 1. 编写/修改 Markdown
# 2. 重新生成章节树
python scripts/build_chapter_trees.py --kb-root ./wiki
# 3. 增量生成摘要(已生成则自动跳过)
python scripts/enhance_summaries.py
# 4. 热更新索引
curl -X POST http://localhost:8000/admin/rebuild-index路径:
he-harness/,技术栈 Node.js 18+ / ES Modules / SQLite(better-sqlite3)。
Harness 维度解决的核心问题:让 LLM 在"可控、有边界、有可观测、可回放"的执行回路里工作,而不是一次性问答。
项目根植于以下五条工程原则:
-
Agent 应被理解为执行回路,而非单次问答 ——
AgentLoop -
没有 Trace 的 Harness,很难调试;没有 Replay 的 Harness,很难进化 ——
Tracer -
Harness 管的不是功能多少,而是运行边界 ——
ToolGuardrail -
状态是一等资产 ——
StateStore(SQLite 持久化) -
压缩解决的是扩展,重置解决的是漂移 ——
ContextCompressor
| 层级 | 名称 | 实现文件 | 职责 |
|---|---|---|---|
| 1 | Task Input Layer | cli/index.js |
接收用户任务、CLI 交互 |
| 2 | Agent Loop | src/agent-loop.js |
主执行回路(LLM ↔ Tools) |
| 3 | Tool & Permission Layer | src/tool-guardrail.js |
工具白名单、循环检测、渐进干预 |
| 4 | State Layer | src/state-store.js |
会话/消息持久化、压缩续传链 |
| 5 | Observation Layer | src/tracer.js |
Trace 记录、Replay、Bad Case 下沉 |
| 6 | Governance Layer | (可扩展) | 跨 Harness 的策略、限流、配额 |
flowchart TB
U["用户"] --> L1["1. Task Input<br/>CLI 交互"]
L1 --> L2["2. Agent Loop<br/>主执行回路"]
L2 --> L3["3. Tool and Permission<br/>工具白名单 + 防护栏"]
L2 --> L4["4. State<br/>SQLite 持久化"]
L2 --> L5["5. Observation<br/>Trace + Replay"]
L2 --> L6["6. Governance<br/>策略 / 限流"]
L3 --> Tools["Skills<br/>(tools)"]
import { AgentLoop, createHarness } from './src/index.js';
const harness = createHarness({
llmClient, // LLM 客户端
tools, // 工具定义数组
validToolNames: new Set(['knowledge_search', 'chapter_detail']),
maxTurns: 30,
dbPath: './harness.db',
tracesDir: './traces',
});
const result = await harness.agentLoop.run(initialMessages, taskId);主循环(每轮):
- 上下文压缩(如启用)→
ContextCompressor.compress(messages) - 调用 LLM →
llmClient.chatComplete({ messages, tools }) - 提取推理内容(多提供商:
reasoning_content/reasoning/thinking/<think>标签) - 无工具调用 → 任务自然结束,保存状态 + Trace
- 有工具调用 → 逐个执行
_executeToolCall(含 4 层防御) - 保存中间状态到 StateStore
- 达到
maxTurns→ 强制结束
import { StateStore } from './src/index.js';
const store = new StateStore({ dbPath: './harness.db' });
store.createSession(sessionId);
store.saveState(sessionId, messages);
const { session, messages } = store.loadSession(sessionId);特性:
- 基于
better-sqlite3,WAL 模式并发优化 - 完整消息历史(含
tool_calls、tool_call_id、reasoning、token_count、finish_reason) - 支持会话恢复、压缩续传链
- 声明式 Schema(
SCHEMA_DEFINITION),可平滑迁移 - 索引:
started_at、parent_session_id、title
import { ToolGuardrailController, ToolGuardrailConfig } from './src/index.js';
const guardrail = new ToolGuardrailController(new ToolGuardrailConfig({
warningsEnabled: true,
hardStopEnabled: true,
idempotentTools: new Set(['knowledge_search', 'chapter_detail', 'read_file']),
}));职责:
- 幂等工具 vs 修改工具分类:防止修改类工具被滥用
- 循环检测:相同失败 / 同工具失败 / 无进展
- 渐进式干预:警告 → 阻止
import { ContextCompressor, CompressorConfig } from './src/index.js';
const compressor = new ContextCompressor(new CompressorConfig({
protectFirstN: 4, // 保护前 N 条消息
targetTotalMessages: 24, // 目标总消息数
}), llmClient); // 可选:传 LLM 做真实摘要策略:
-
头部保护:
protectFirstN永远不压缩(保 system prompt + 关键设定) - 尾部保护:保留最近 N 条(最相关上下文)
- 中间区域压缩:用 LLM 摘要旧工具结果
- 预压缩:旧工具结果先被摘要再参与压缩
import { Tracer, TracerConfig } from './src/index.js';
const tracer = new Tracer(new TracerConfig({
tracesDir: './traces',
saveTraces: true,
verbose: true,
}));
await tracer.recordStart(taskId, messages);
await tracer.recordLLMCall(taskId, turn, assistantMsg);
await tracer.recordToolCall(taskId, turn, toolCall, result);
await tracer.recordEnd(taskId, success, finalMessages);特性:
- 完整记录执行资产(LLM 调用、工具调用、推理、错误)
- JSONL 格式导出
- 支持 Replay
-
Bad Case 自动下沉:
failed/目录留作离线分析 - 调试 → 复现 → 修复 → 上线的标准工作流
import { createLLMClient } from './src/index.js';
// OpenAI 官方
const client = createLLMClient('openai', {
apiKey: 'sk-...', model: 'gpt-4o', baseURL: 'https://api.openai.com/v1',
});
// OpenAI 兼容(DeepSeek / vLLM / Azure / Ollama 都可以)
const client = createLLMClient('openai-compatible', {
apiKey: '...', model: '...', baseURL: 'https://your-api/v1',
});
// Mock(无 Key 也能跑)
const client = createLLMClient('mock');支持多提供商的工具调用规范化(normalizeToolCall)和推理内容提取(reasoning_content / <think> / OpenRouter reasoning_details 等)。
AgentLoop._executeToolCall 内置 4 层防御:
| 层级 | 防御 | 失败行为 |
|---|---|---|
| 1 |
工具名验证(白名单 validToolNames) |
返回 { error: "Unknown tool..." }
|
| 2 |
工具防护栏检查(ToolGuardrail.beforeCall) |
返回 { error: "<guardrail msg>" }
|
| 3 |
JSON 参数解析(JSON.parse 容错) |
返回 { error: "Invalid JSON..." }
|
| 4 | 工具执行异常捕获(try-catch) | 返回 { error: "Tool execution failed..." }
|
关键设计:所有失败都"以工具结果的形式"返回给 LLM,让模型有机会理解错误并自我修正,而不是直接抛异常中断回路。
cd he-harness
npm install
npm run rag-chat # 启动 RAG 问答 CLI
# 或
node cli/index.js内置命令:
-
/help—— 查看帮助 -
/tools—— 查看当前可用工具 -
/exit或/quit—— 退出
示例对话:
你: RAG 的切块策略有哪些?
🔎 正在检索知识库...
✅ 知识库助手:……(引用了 3 个章节,附带面包屑路径)
| 变量 | 默认 | 说明 |
|---|---|---|
LLM_PROVIDER |
mock |
openai / openai-compatible / mock / ollama
|
OPENAI_API_KEY |
- | OpenAI API Key |
OPENAI_MODEL |
gpt-4o |
OpenAI 模型 |
OPENAI_BASE_URL |
https://api.openai.com/v1 |
OpenAI API 地址 |
OPENAI_COMPATIBLE_* |
- | 兼容 API 配置(Key/Model/BaseURL) |
MAX_TURNS |
20 |
最大对话轮数 |
SYSTEM_PROMPT |
You are a helpful AI assistant... | 系统提示词 |
RAG_API_BASE_URL |
http://localhost:8000 |
RAG 引擎地址(被 knowledge_search 工具使用) |
路径:
he-harness/src/tools.js
Harness 维度的「Tools」是 OpenAI 风格的 tool calling 工具集合,由 AgentLoop 运行时直接调度,让 LLM 拥有"动手能力"。注意:这里的 tools 与第 5 章的「外置技能包」是完全不同的概念——前者是运行时调用的函数,后者是离线加载的工作流文档。
getAllTools(includeRAG=true) 返回 6 个工具:
| 工具名 | 类型 | 用途 | RAG 工具? |
|---|---|---|---|
read_file |
幂等 | 读文件(限 2000 字符) | 否 |
write_file |
修改 | 写文件(自动建目录) | 否 |
calculator |
幂等 | 四则运算 | 否 |
search |
幂等 | 模拟搜索(演示用) | 否 |
knowledge_search |
幂等 | 调用 RAG /search 检索知识库 |
✅ |
chapter_detail |
幂等 | 调用 RAG /chapter/{id} 取章节全文 |
✅ |
{
"name": "knowledge_search",
"description": "Search the knowledge base for relevant information. Use this when you need to find documents, guidelines, or answers from the internal knowledge base.",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string", "description": "The search query in natural language" },
"top_k": { "type": "integer", "default": 5, "description": "Number of results (max 20)" },
"search_mode": { "type": "string", "enum": ["hybrid", "vector", "keyword"], "default": "hybrid" },
"rerank": { "type": "boolean", "default": false, "description": "Enable rerank (slower, ~3-8s)" }
},
"required": ["query"]
}
}行为:
- 调用
POST {RAG_API_BASE_URL}/search - 把结果格式化为 LLM 易消费的结构(rank / score / summary / content / node_id)
-
无结果时返回
found: false+ 友好提示,让 Agent 主动告知用户"超出知识库范围"
{
"name": "chapter_detail",
"description": "Get full content of a specific chapter by node_id. Use this after knowledge_search to read the complete document.",
"inputSchema": {
"type": "object",
"properties": {
"node_id": { "type": "string", "description": "The node_id (from knowledge_search results)" },
"include_children": { "type": "boolean", "default": true, "description": "Include child chapters" }
},
"required": ["node_id"]
}
}典型协作模式:
sequenceDiagram
participant U as User
participant A as Agent (LLM)
participant K as knowledge_search
participant C as chapter_detail
participant R as RAG Engine
U->>A: "RAG 切块策略有哪些?"
A->>K: knowledge_search(query="RAG 切块策略", top_k=5)
K->>R: POST /search
R-->>K: 5 条候选(含 node_id)
K-->>A: 5 条带摘要的结果
A->>C: chapter_detail(node_id="doc-001__ch-003")
C->>R: GET /chapter/{id}
R-->>C: 完整章节内容
C-->>A: 原文 + 子章节
A-->>U: 整合答案 + 引用
每个工具是 ES Module Class,包含 3 部分:
export class MyTool {
static name = 'my_tool'; // 工具标识(Agent 调用时使用)
static schema = { // OpenAI 风格 tool schema
name: 'my_tool',
description: '一句话说清用途和调用时机', // ⚠️ 决定 LLM 是否会选它
inputSchema: {
type: 'object',
properties: { /* ... */ },
required: ['...'],
}
};
async execute(args) { // 实际执行逻辑
// 返回 JSON.stringify(...) 的字符串
return JSON.stringify({ success: true, result: '...' });
}
}关键设计原则:
-
description写完整且具体(LLM 不会调用描述模糊的工具) -
execute必须始终返回 JSON 字符串(成功或错误) - 错误也要结构化:
{ error: "..." }而不是抛异常 - 长结果要截断(如
read_file限 2000 字符、knowledge_search限 1500)
步骤 1:实现工具类
// 在 src/tools.js 中添加
export class MyTool {
static name = 'my_tool';
static schema = {
name: 'my_tool',
description: 'Description of when to use this tool',
inputSchema: {
type: 'object',
properties: {
param1: { type: 'string', description: '...' },
param2: { type: 'integer', default: 10 }
},
required: ['param1']
}
};
async execute(args) {
// 实现工具逻辑
return JSON.stringify({ success: true, result: '...' });
}
}步骤 2:注册到 getAllTools
export function getAllTools(includeRAG = true) {
const tools = [
// ... 现有工具
{ name: MyTool.name, schema: MyTool.schema, execute: (args) => new MyTool().execute(args) }
];
// ...
}步骤 3:在 CLI 中使用
// cli/index.js 中指定 validToolNames
const validToolNames = new Set(['knowledge_search', 'chapter_detail', 'my_tool']);步骤 4:防护栏注册(如涉及修改操作)
const guardrail = new ToolGuardrailController(new ToolGuardrailConfig({
idempotentTools: new Set(['knowledge_search', 'my_tool']), // 幂等工具
// 修改工具不加入 idempotentTools,自动按修改类处理
}));最重要的安全边界:在 AgentLoop 初始化时声明 validToolNames: Set<string>,LLM 即便输出了不在白名单中的工具名,也会被第一层防御拦截(详见 §4.4)。
// ✅ 推荐:最小权限原则
const validToolNames = new Set(['knowledge_search', 'chapter_detail']);
// ❌ 不推荐:把全部工具都给 LLM(容易误调)
const validToolNames = new Set([...所有工具名]);路径:
he-skills/he-rag-eval/核心载体:he-rag-eval 技能(v1.2.0) 当前支持:Trae IDE / Cursor / Claude Code 等支持 skill 加载的 Agent 平台 he-harness 原生支持:列入 §8 路线图
Skills 维度回答的核心问题:RAG 系统如何"自我进化"? —— 通过 he-rag-eval 这类技能包,把 RAG 的评测→诊断→优化→回滚串成闭环,让 Agent 持续把 RAG 系统改得更好。
传统 RAG 工程常见的痛点:
| 痛点 | 后果 |
|---|---|
| 改完 RAG 不知道改得对不对 | 没指标就只能凭感觉 |
| 指标低找不到原因 | 没分析就只能乱猜 |
| 优化完不敢上线 | 怕回退就只能保守 |
| 上线后无法持续改进 | 没闭环就只能救火 |
he-rag-eval 提供完整的"评测→分析→优化→验证→回归"闭环:
┌──────────────────────────────────────────────────────────────┐
│ ① 评测 量化现状 ← 6 指标 + 30+ 查询数据集 │
│ ② 诊断 定位短板 ← 9 维度评分卡 + 失败模式归因 │
│ ③ 优化 定向改进 ← 4 层策略目录(快速赢→调优→高级→实验)│
│ ④ 验证 安全演进 ← Accept 标准 + 自动 Rollback │
│ ⑤ 回归 持续跟踪 ← 优化日志 + 评分轨迹 │
│ ↓ 循环 │
│ 让 RAG 系统持续自我进化 │
└──────────────────────────────────────────────────────────────┘
| 项 | 说明 |
|---|---|
| 路径 | he-skills/he-rag-eval/ |
| 版本 | v1.2.0 |
| 主文件 |
SKILL.md(8 阶段工作流 + 检查清单) |
| 副文件 |
README.md(公式、目标值、原理详解) |
| 适用对象 | he-rag-engine 引擎、ChromaDB + BGE-M3 + Qwen3-Reranker 体系,或同类 RAG 架构 |
触发条件(写在 SKILL.md 的 description 字段,Agent 自动据此决定是否加载):
- "评估我的 RAG 系统" / "看看检索质量" / "测试召回率"
- "为知识库构建评估数据集"
- "对比不同搜索模式的效果"(向量 vs 关键词 vs 混合)
- "诊断为什么某些查询的返回结果很差"
- 提到 Recall、Precision、MRR、NDCG 或检索基准
- "快速评估" / "quick eval" / "快速看看效果"
| 阶段 | 名称 | 关键产物 |
|---|---|---|
| 1 | 理解知识库 | 知识库结构总结、章节树映射、覆盖盲点 |
| 2 | 构建评测数据集 | ≥ 30 条自然语言查询 + 标注的相关 node_id |
| 3 | 编写评测脚本 | 实现 6 个核心指标的 Python 脚本 |
| 4 | 执行评估与分析 | 指标对比表、最差 5 条查询、难度/分类分组 |
| 4b | 问题排查 | API 不可达、空结果、超时等系统化诊断清单 |
| 5 | 优化与重新评估 | 针对性优化 + 重新评测验证 |
| 6 | 生成文档 | 完整评测报告(6 章节:指标/结果/分类/失败/优化/建议) |
| 7 | 系统评分(0-100) | 9 维度加权评分卡 + 等级 + 前 3 短板 + P0 预计得分 |
| 8 | 迭代优化与回滚 | Accept/Rollback 机制 + 4 层优化策略目录 |
每个阶段末尾都附检查清单(Checkpoint),让 LLM 自检质量门禁,避免"跳步"。
| 指标 | 公式 | 衡量什么 |
|---|---|---|
| Recall@K | hits / total_relevant |
相关文档中有多少被找到了(最重要) |
| Precision@K | hits / K |
返回的文档中有多少是相关的 |
| Hit Rate@K | 1 if hits > 0 else 0 |
是否至少找到了一个相关文档 |
| MRR | 1 / rank_of_first_hit |
第一个相关文档出现在多早的位置 |
| NDCG@K | DCG / IDCG |
位置加权的相关性(二值:1=相关,0=不相关) |
| Hierarchical Recall | 同 Recall,但子/父节点算部分命中 | 考虑章节树结构的层次化召回 |
在 K=5、10、20 上分别计算所有指标。
| 指标 | 较差 | 可接受 | 良好 | 优秀 |
|---|---|---|---|---|
| Recall@5 | < 0.2 | 0.2-0.4 | 0.4-0.7 | > 0.7 |
| MRR | < 0.3 | 0.3-0.5 | 0.5-0.7 | > 0.7 |
| Hit Rate@5 | < 0.5 | 0.5-0.7 | 0.7-0.9 | > 0.9 |
| NDCG@5 | < 0.2 | 0.2-0.4 | 0.4-0.6 | > 0.6 |
评测和优化完成后,输出一张 0-100 分的评分卡,把 RAG 系统的"健康度"量化成一目了然的分值。
| # | 维度 | 权重 | 数据来源 |
|---|---|---|---|
| 1 | 检索召回(Hybrid Recall@5) | 25% | 评测结果 |
| 2 | 排序质量(MRR) | 15% | 评测结果 |
| 3 | 覆盖与命中率(Hit Rate@5) | 10% | 评测结果 |
| 4 | Embedding 质量(Vector/Hybrid 比值) | 10% | 评测 + 配置 |
| 5 | Reranker 效果 | 10% | 评测 + 代码审查 |
| 6 | 切块策略 | 10% | 代码审查 |
| 7 | 架构成熟度 | 10% | 代码审查 |
| 8 | 工程质量 | 5% | 代码审查 |
| 9 | 评测覆盖度 | 5% | 数据集审查 |
| 合计 | 100% |
等级划分:
| 分数区间 | 等级 | 含义 |
|---|---|---|
| 90-100 | A | 生产就绪,业内领先的检索能力 |
| 80-89 | B | 系统扎实,仅需小幅改进 |
| 70-79 | C+ | 可接受,但存在一些明显短板 |
| 60-69 | C | 可用但表现欠佳,存在多个问题 |
| 50-59 | D | 问题严重,需要大刀阔斧的整改 |
| 0-49 | F | 关键失败,不能用于生产 |
评分卡输出示例:
============================================================
RAG 系统评分:65.7 / 100 (C+)
============================================================
维度 权重 分数 加权得分
─────────────────────────────────────────────────
检索召回率 25% 58 14.5
排序质量 15% 74 11.1
覆盖度与命中率 10% 73 7.3
Embedding 质量 10% 73 7.3
重排序器效果 10% 30 3.0
Chunk 策略 10% 80 8.0
架构成熟度 10% 85 8.5
工程质量 5% 40 2.0
评估覆盖度 5% 80 4.0
─────────────────────────────────────────────────
总计 100% 65.7
前 3 大短板:
1. 重排序器(30/100)—— 二值重排序器无法对结果排序
→ 切换为 bge-reranker-v2-m3 cross-encoder(预计 +8 分)
2. 检索召回率(58/100)—— 5 条查询 Recall@5=0
→ 查询改写 + 知识库扩充(预计 +6 分)
3. 工程质量(40/100)—— API 密钥硬编码,没有测试
→ 将密钥迁移到 .env,补充单元测试(预计 +2 分)
完成 P0 修复后预计得分:75/100 (B)
============================================================
这是 he-rag-eval 的核心价值——让 RAG 系统安全、可持续地自我改进。
| 层级 | 名称 | 风险 | 典型策略 | 预期收益 |
|---|---|---|---|---|
| Tier 1 | 快速赢 | 低 | 修复 embedding 模型名、调 reranker top_n、补充同义词、修标注 | +0.01~0.30 |
| Tier 2 | 调优 | 中 | 调 RRF 权重、父子节点注入、调注入参数 | +0.02~0.08 |
| Tier 3 | 高级 | 高 | 换 reranker provider、文档增强、文件缓存、查询路由 | +0.02~0.15 |
| Tier 4 | 实验性 | 高 | LLM 查询扩展、多阶段检索、LTR、Embedding 升级 | +0.05~0.20 |
核心原则:从 Tier 1 起步,一次只改一处,先验证再前进。
基线评估
→ 识别薄弱查询(Recall@5 < 0.5)
→ 选择单条优化策略
→ 应用优化
→ 重新评估
├─ 满足接受标准 → 接受,更新基线,继续下一轮
└─ 出现回退 → 立即回滚,记录失败原因,尝试下一条
接受标准(同时满足所有条件才接受):
| 指标 | 要求 |
|---|---|
| Recall@5 | Δ ≥ +0.01(至少 1% 提升) |
| MRR | Δ ≥ -0.02(允许的回退不超过 2%) |
| Hit Rate@5 | Δ ≥ 0(不回退) |
| 延迟 | Δ ≤ +100ms(变慢不超过 100ms) |
| 回退查询 | ≤ 2 条,且没有一条退化 > 0.2 分 |
只要任何一条不满足,立即回滚。
所有实验必须记录到 optimization_log.md,失败的实验也值得记录(避免重蹈覆辙):
### 实验 N:增大 BM25 权重
- 日期:YYYY-MM-DD
- 策略:Tier 2.1 —— 调整 RRF 中 BM25 权重
- 变更:`bm25_weight` 0.5 → 1.0
- 基线:Recall@5=0.572,MRR=0.840,Latency=782ms
- 结果:Recall@5=0.601(+0.029),MRR=0.809(-0.031),Latency=1012ms(+230ms)
- 决策:接受(Recall 提升,MRR 回退在容忍范围内)
- 备注:由于更多候选项进入重排序,延迟增加评分轨迹示例(随时间跟踪 RAG 系统的进化曲线):
第 1 轮(基线): 62/100 C
第 2 轮(修复重排序器):70/100 C+
第 3 轮(查询改写): 76/100 B
第 4 轮(chunk 增强): 81/100 B
评测数据集是 RAG 自主进化的基石——"garbage in, garbage out"。
- 总数:≥ 30 条查询
- 分类覆盖:每个分类 ≥ 2 条
-
难度分布:
- easy(30%):直接概念查询——"什么是 X?"
- medium(50%):需要理解——"如何设计 X?"
- hard(20%):跨文档综合——"如何端到端部署 X 系统?"
- ✅ 只标注具有实质性知识内容的节点(永远不要标注纯索引/目录/README 节点)
- ✅ 优先选择 L2/L3 子章节(语义上更聚焦)
- ✅ 每条查询 1-4 个相关节点(超过 4 个会稀释召回率计算)
- ✅ node_id 必须与
chapter_trees.json完全一致(不要伪造 ID)
当用户说"快速评估" / "quick eval" 时,按知识库规模自动选参数:
| 知识库规模 | 推荐查询数 | 推荐 K 值 | 覆盖范围 |
|---|---|---|---|
| < 50 篇 | 20 | 5, 10 | 全部分类 |
| 50–200 篇 | 30 | 5, 10, 20 | 全部分类 |
| 200–500 篇 | 50 | 5, 10, 20 | 全部 + 分层子采样 |
| > 500 篇 | 100 | 10, 20, 50 | 按分类分层采样 |
只执行 Phase 1→2→3→4,输出:指标对比表 + 最差 5 条 + 前 3 改进建议。
| 维度 | §2.9 evaluate.py
|
§5 he-rag-eval |
|---|---|---|
| 形式 | Python 脚本(人工运行) | Agent 技能(自动驱动) |
| 工作流 | 单步(运行 → 出报告) | 8 阶段(评测→分析→优化→回归) |
| 优化能力 | ❌ 无 | ✅ 4 层策略目录 |
| 评分系统 | ❌ 无 | ✅ 9 维度加权评分卡 |
| 安全演进 | ❌ 无 | ✅ Accept/Rollback 闭环 |
| 持续跟踪 | ❌ 无 | ✅ 优化日志 + 评分轨迹 |
| 使用门槛 | 需懂 Python + 命令行 | 自然语言触发 |
| 定位 | 验证工具 | 自主进化引擎 |
简言之:§2.9 帮你"测量",§5 帮你"改进"。
- ✅ Trae IDE / Cursor / Claude Code 等支持 skill 加载的 Agent 平台开箱即用
- ❌ he-harness 当前不支持自动加载
he-skills/(列入 §8 路线图)
未来 he-harness 集成规划:
-
自动发现 —— 启动时扫描
he-skills/*/SKILL.md,解析 frontmatter -
按需加载 —— LLM 在 SYSTEM_PROMPT 中引用
name触发,Harness 注入 SKILL.md 全文到上下文 -
版本感知 —— 支持
he-skills/<name>@<version>显式锁定版本 -
白名单 + 防护栏 —— 复用
validToolNames机制管理可加载技能
本节是"如何编写一个类似 he-rag-eval 的技能包"的元信息,普通用户可跳过。
每个外置技能包的主文件必须是 SKILL.md:
---
name: "he-rag-eval" # 技能名(小写连字符,全局唯一)
description: "触发条件:...'评估我的 RAG 系统'...'测试召回率'... 多个具体场景"
---结构模板:
# 技能标题
## 使用场景
## 快速开始模式 # 可选
## 阶段 1:xxx
## 阶段 2:xxx
### 阶段 N 检查清单 # 每个阶段末尾的 Checkpoint
## 参考:关键公式
## 参考:典型目标值
## 版本历史关键设计原则:
-
description必须完整具体——决定 LLM 何时自动加载 - 多阶段 + 检查清单——避免"一长篇说明"
- 复杂概念配速查表——症状 → 原因 → 修复
-
SKILL.md ≤ 800 行——超长内容拆到
README.md
| 技能 | 用途 | 状态 |
|---|---|---|
he-rag-eval |
RAG 自主进化(评测+优化+回滚) | ✅ v1.2.0 |
he-wiki-build |
知识库构建(Markdown → 章节树 → 索引) | 规划中 |
he-agent-health |
Agent 体检(harness workflow / eval 健全性) | 规划中 |
下面是一个用户问 "RAG 的切块策略有哪些?" 时,四个维度协同的完整流程:
sequenceDiagram
autonumber
participant U as User
participant CLI as Harness CLI
participant AgentLoop as AgentLoop
participant Skill as knowledge_search
participant API as RAG API
participant Wiki as Wiki KB
participant State as StateStore
participant Trace as Tracer
U->>CLI: 输入问题
CLI->>AgentLoop: run messages and taskId
AgentLoop->>Trace: recordStart taskId messages
AgentLoop->>AgentLoop: ContextCompressor.compress
AgentLoop->>AgentLoop: llmClient.chatComplete
Note over AgentLoop: LLM 决定调用 knowledge_search
AgentLoop->>Skill: execute query and top_k=5
Skill->>API: POST /search
API->>Wiki: 加载 chapter_trees.json
API->>API: QueryExpand + VectorSearch + BM25Search
API->>API: RRF Fusion + Rerank + Parent-Child Injection
API-->>Skill: 返回 5 条候选
Skill-->>AgentLoop: 格式化结果
AgentLoop->>Trace: recordToolCall turn toolCall result
AgentLoop->>State: saveState taskId messages
AgentLoop->>AgentLoop: LLM 整合答案 必要时再调用 chapter_detail
AgentLoop->>Trace: recordEnd success messages
AgentLoop-->>CLI: 返回 AgentResult
CLI-->>U: 渲染回答 + 引用
关键产物:
- 📄
harness.db:完整会话状态(可恢复) - 📄
traces/{taskId}.jsonl:每一步执行资产(可 Replay) - 📄
wiki/indices/chapter_trees.json:知识库结构(可重建) - 📄
he-rag-engine/data/:向量 + BM25 + 词汇表(可热更新)
A:首次启动会调用 Embedding API 构建向量索引。如果你的知识库较大(> 1000 文档),可能需要几分钟。后续启动从磁盘加载已有索引,秒级。
A:可以。he-harness 通过 OpenAI 兼容协议对接 LLM,只需修改 .env 中的 OPENAI_BASE_URL 和 OPENAI_API_KEY 即可指向任何 OpenAI 兼容服务(Azure OpenAI、vLLM、Ollama、DeepSeek 等)。
A:不是。RAG_EMBEDDING_PROVIDER=ollama + RAG_RERANK_PROVIDER=ollama 可以完全本地化部署(需要 16GB+ 显存跑 Qwen3-Reranker-4B)。
A:是仓库自带的一份示例知识库(约 76 篇 RAG / 知识工程相关的 Markdown),用于让你 clone 下来就能直接跑通。你也可以清空 wiki/03-knowledge-and-rag/ 然后放入自己的内容。
# 1. 替换内容
rm -rf wiki/03-knowledge-and-rag && mkdir -p wiki/your-topic
# 2. 重新生成章节树
python scripts/build_chapter_trees.py --kb-root ./wiki
# 3. 增量生成摘要
python scripts/enhance_summaries.py
# 4. 触发索引热更新
curl -X POST http://localhost:8000/admin/rebuild-indexA:检查日志,确认 chapter_trees.json 存在;然后调用 POST /admin/rebuild-index。
A:索引可能为空。先调用 POST /admin/rebuild-index;如仍 0 结果,检查 data/vocab.json 和 data/chroma/ 是否生成。
A:编辑 src/tool-guardrail.js 的 ToolGuardrailConfig:
new ToolGuardrailConfig({
warningsEnabled: true,
hardStopEnabled: true,
idempotentTools: new Set([...]),
maxConsecutiveFailures: 3,
// ...
})A:参考 §4.7.4 自定义工具开发 的 4 步流程。
A:详见 §5.0 价值定位。核心是让 RAG 系统"自我进化"——通过 8 阶段工作流(理解知识库 → 构建评测集 → 编写评测脚本 → 执行评估 → 问题排查 → 优化 → 评分 → Accept/Rollback),把"改完不知道改得对不对"变成"每改一处都有指标跟踪 + 失败自动回滚"。
A:he-harness 内置工具(tools)(详见 §4.7)是 OpenAI 风格 tool calling,运行时由 AgentLoop 调度,单次调用;外置技能包(SKILL.md)(详见 §5)是工作流文档,被 Trae IDE / Cursor / Claude Code 等外部 Agent 平台加载后引导 LLM 执行多阶段闭环任务(如 RAG 自主进化)。前者是"调函数",后者是"跑流程"。
A:详见 §5.7.1。简言之:evaluate.py 是单步评测脚本(人工运行,出报告),he-rag-eval 是多阶段自主进化引擎(自然语言触发,含 4 层优化目录 + Accept/Rollback + 评分轨迹)。§2.9 帮你"测量",§5 帮你"改进"。
A:暂未支持,已列入 §8 路线图。当前 he-rag-eval 技能包需要由支持 skill 加载的 Agent 平台(Trae IDE / Cursor / Claude Code)使用,详见 §5.7.2。
- he-harness 支持加载外置 skill 包(来自
he-skills/*/SKILL.md,自动发现 + 按需注入上下文 + 版本锁定 + 白名单防护,详见 §5.7.2) - Wiki 前端编辑器(所见即所得)
- 多个Wiki知识库组合
- Wiki知识库增加图片处理能力
- Eval 集自动从 Bad Case 沉淀
文档版本:v0.3.0 | 最近更新:2026-06-13 任何问题请提交 GitHub Issue 反馈。