bookworm-smart-assistant/docs/routing-pipeline.md
Bookworm Admin b7a8e29d21 release: v6.7.0 - OTA E2E test release
- VERSION file as authoritative version source
- export.mjs reads VERSION with package.json fallback
- bw-ota.ps1 DryRun mode for safe testing
- auto-setup.ps1 bumped to v3.2.0 (Phase 8 OTA)
2026-04-27 17:59:44 +08:00

208 lines
8.6 KiB
Markdown
Raw Permalink 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.

# Bookworm 路由与消歧管线技术参考
> 版本v6.6.0 · 最后更新2026-04-25
> 对应代码hooks/prompt-dispatcher.js, hooks/route-interceptor-bundle.js, scripts/route-engine.js, scripts/route-analyzer.js, scripts/intent-classifier.js, scripts/disambiguation-tree.js, scripts/adaptive-disambiguator.js, scripts/bwr-builder.js, scripts/route-state.js
## 一、整体管线
```mermaid
flowchart TD
U[用户输入 prompt] --> PD[prompt-dispatcher.js<br/>UserPromptSubmit 入口]
PD --> SG[security-startup-guard<br/>同步 fail-open]
SG --> SUB[spawn route-interceptor-bundle<br/>子进程 2s 硬超时]
SUB --> RB[route-interceptor-bundle.js]
RB --> BN[showActivationBanner<br/>首条消息横幅]
RB --> ES{逃生舱<br/>/force /checks /reset}
ES -->|命中| OUT0[直接输出]
ES -->|未命中| IF[隐式反馈检测<br/>3min 窗口 · 30 字头]
IF --> SC{显式调用<br/>/skill-name}
SC -->|命中| OUT0
SC -->|未命中| IC[intent-classifier<br/>三级分流]
IC --> LVL{complexity?}
LVL -->|simple| INH{尝试继承<br/>5min 窗口}
LVL -->|medium 短 CJK<br/>&lt;6 字| INH
LVL -->|image query| INH
LVL -->|medium/complex| RE[runRouteEngine]
INH -->|继承成功| WRS
INH -->|继承失败 & CJK 3-14| RE
INH -->|纯 simple| OUT0
RE --> BM25[1.BM25 baseline]
BM25 --> CTX[2.Context tracker]
CTX --> PRJ[3.Project detector]
PRJ --> WF[4.Workflow 30d bigram]
WF --> DC[5.Domain classifier L1<br/>conf ≥ 0.3 缩候选]
DC --> SEM[6.Semantic TF-IDF]
SEM --> FUS[7.融合权重<br/>bm25 0.40 sem 0.30 ctx 0.15 proj 0.10 wf 0.05]
FUS --> DL2[8.Domain L2 精排<br/>域外 ×0.2 / ×0.5]
DL2 --> EMB[9.Embedding tie-breaker<br/>top-2 gap &lt; 10%]
EMB --> DIS[applyDisambiguation<br/>88 条硬规则投票]
DIS --> ADA[adaptive-disambiguator<br/>Bayesian 0.3 + 硬规则 0.7]
ADA --> CS[冷启动 boost]
CS --> RR[rerank top-k]
RR --> NORM[normalize + confidence cap<br/>短查询 ≤3 token 封顶 0.8]
NORM --> SM[session-memory boost]
SM --> AB[ab-test 探索]
AB --> WRS[writeRouteState<br/>route-state-current.json]
WRS --> BWR[buildBWRDirective]
BWR --> OUT[additionalContext 注入]
OUT --> HK2[route-compliance-gate<br/>PreToolUse:Skill]
HK2 --> HK3[subagent-route-injector<br/>SubagentStart]
HK3 --> HK4[route-auditor<br/>Stop 会话结束闭环]
```
## 二、核心数据契约
### 2.1 route-state-current.json (DEBUG_DIR)
```jsonc
{
"traceId": "8d4fb84f",
"ts": "2026-04-25T01:30:00Z",
"promptHash": "abc123def456",
"promptRaw": "<脱敏首 200 字>",
"intent": { "intents": ["data"], "modifiers": [], "entities": [], "complexity": "medium" },
"routing": {
"primary": "vue-expert",
"candidates": [{ "name": "vue-expert", "confidence": 1.0 }, ...],
"confidence": 1.0,
"chain": [],
"experiment": null,
"domain": null
},
"recommendation": { "action": "route", "skill": "vue-expert" },
"mustInvoke": true,
"version": "v6.2",
"sessionId": "..."
}
```
消费者route-compliance-gate / subagent-route-injector / route-auditor。
### 2.2 BWR 指令结构(写入 additionalContext
末行决策表(`scripts/bwr-builder.js:22-57`
| 条件 | 输出末行 |
|---|---|
| `simple && !inherited` | `[BWR:skip] 简单查询,直接回复` |
| `complexity == complex` | `[MUST_INVOKE_SKILL: {primary}]` 强制 |
| 意图 ∈ EXEMPT (translate/explain/greeting/meta/remember/continue/select/confirm) | `执行: 使用 /{primary}` 豁免 |
| `medium && conf>=0.5 && primary ≠ developer-expert/none` | `[MUST_INVOKE_SKILL: {primary}]` 中度强制 |
| 其他 | `执行: 使用 /{primary}` |
## 三、意图分类三级分流 (`intent-classifier.js`)
14 条意图规则 + 3 条修饰符。复杂度决策树:
```
modifiers.complex → complex
modifiers._force_medium (V-01) → medium
modifiers.simple → simple
intents.length == 2 & 非相邻对 → complex
intents.length >= 3 (排除 general) → complex
全在 {explain,general,continue,select,confirm} & 无实体 → simple
其他 → medium
```
**V-01 修复**`confirm/continue/select` 前缀后接 >8 字符或转折词 → 移除前缀标签重分类。
## 四、消歧两层机制
### 4.1 硬规则层 `scripts/disambiguation-rules.json` (v1.5.0, 88 条)
规则结构:
```jsonc
{
"id": "R84",
"note": "...",
"trigger": "正则",
"boost": "target-skill",
"penalty": ["skill1", "skill2"],
"weight": 0.55,
"mutual_exclusion": { "with": "R05", "on_keyword": "...", "resolution": "..." },
"agent": "self-auditor" // 可选,标注 agent 型路由
}
```
`applyDisambiguation` 三阶段 (`route-analyzer.js:745-828`)
1. **Phase 1**:收集所有命中规则的 boost/penalty 投票,`effectiveWeight = weight × (0.5 + specificity × 0.5)`
2. **Phase 1.5**mutual_exclusion 消解
3. **Phase 2**:分数应用 — `boost: score = base × (1+boost)``penalty: score = base × (1 - penalty × 0.3)`(仅未 boost 时)
4. **Phase 3**:强制排名 — boost 技能必须位于其 penalty 对手之前
### 4.2 自适应层 `scripts/adaptive-disambiguator.js` (Bayesian Dirichlet)
- 对每对 (skillA, skillB) 维护 α 向量
- 硬规则 boost 给 α=10 强先验,其他 α=1
- 收敛:`totalSamples ≥ 30 && posterior ≥ 0.80`
- 融合:`bayesian × 0.3 + hardRule × 0.7`
- C3_DIRICHLET_HARDENINGsoftmax-lite 归一化防 ±1 饱和
## 五、关键韧性设计
| 机制 | 位置 | 作用 |
|---|---|---|
| 2000ms 硬超时 | route-interceptor-bundle L159 | 超时静默退出不阻断 prompt |
| 磁盘断路器 | route-compliance-gate L41-92 | `<100MB` 跳过门控 |
| 原子写入 | route-state.js / fusion-weights | `tmp + rename` 防半写入 |
| fail-open vs fail-close | 路由层 open / 门控层 close | 安全组件异常拒绝,路由异常放行 |
| 5min 继承窗口 | route-interceptor-bundle L301 | 衰减 ×0.7 + 置信度阈值 0.5 |
| 短查询封顶 | route-engine L280-292 | ≤3 token 置信度 ≤ 0.8,防 BM25 过拟合 |
| TraceId 贯穿 | crypto.randomUUID().slice(0,8) | 全管线日志关联 |
## 六、已知缺陷
### D1`applyDisambiguation` boost 目标 score=0 时降级为纯 penalty
**现象**R81/R84/R85/R86 的 boost 目标 `self-auditor` 是 agent若其 keywords 不覆盖查询词(如"路由/消歧/管线"BM25 原始分为 0`route-analyzer.js:765` 的 `results.find(r => r.name === rule.boost && r.score > 0)` 返回 undefined整条规则降级为仅 penalty。
**影响**2026-04-25 端到端测试中,"booworm路由和消歧模块技术梳理" 最终路由到 `industry-research-cn` 而非 `self-auditor`penalty 仅让 vue-expert 降了 4%,不足以让 self-auditor 上位。
**三种修复路径**
- (a) **补 keywords**(治本,工作量小):在 `agents/self-auditor.md` frontmatter 补 "路由/消歧/管线/钩子/注入器/遥测" 等元词,重跑 `generate-skill-index.js`
- (b) **改 applyDisambiguation**(治标,影响面大):当 firedRules 含强规则 (weight ≥ 0.5) 且 boost 目标 score=0 时,强制注入分数 = top × 1.05 上位。
- (c) **增强 penalty 强度**:把 penalty 衰减因子从 `0.3` 提到 `0.6-0.8`,允许纯 penalty 也有决胜力。
### D2路由日志中 `candidates:[]` 的盲点
`route-blind-spots.jsonl` 140 条全是 `confidence=0 & candidates=[]`,即 simple/continue 类查询继承失败落到兜底。这不是路由算法缺陷,但掩盖了真正的误判案例。**真正误判应从 `route-YYYY-MM-DD.jsonl` 扫描 `topResult != developer-expert & confidence >= 0.9 & 语义不匹配`**。
## 七、调优/审计常用命令
```bash
# 查看消歧规则冲突
node scripts/disambiguation-tree.js
# 意图分类调试
node scripts/intent-classifier.js "我的查询"
# 端到端路由分析
node scripts/route-analyzer.js --json "我的查询"
# 融合权重状态
cat debug/fusion-weights.json
# 今日路由统计
cat debug/route-stats-daily-$(date +%F).jsonl | jq -s 'group_by(.skill) | map({skill: .[0].skill, n: length, avgConf: (map(.confidence) | add / length)}) | sort_by(-.n)'
# 自适应消歧学习状态
node scripts/adaptive-disambiguator.js --state
```
## 八、变更记录
| 日期 | 版本 | 变更 |
|---|---|---|
| 2026-04-25 | v1.5.0 | R84-R88 Bookworm 元词路由修复,发现 D1 缺陷 |
| 2026-04-24 | v1.4.0 | R74-R83 补 preferred_mcp 激活路由绑定 + R81-R83 Bookworm 基础元词 |
| 2026-04-19 | — | P0v2 stop-dispatcher 3 批并行 + P1 pre-agent-gate |
| 2026-04-16 | — | W1 权重衰减 + C1 原子重置 + C3 Dirichlet softmax 硬化 |
| 2026-04-14 | — | read-stdin 双 JSON.parse 修复 + stats 漂移同步 |