Skip to main content
Glama
gungunj
by gungunj
README.md
# Router-MCP 高精度路由识别 MVP

这是一个围绕“准确率优先、宁可拒答也不误触发”构建的最小可运行 Router-MCP 路由识别服务。它不是通用聊天机器人,而是一个针对结构化路由层,负责把用户口语化输入安全、可解释地路由到 MCP / Skill / Tool / Planner。

## 当前实现

- `agent-router-mcp`:统一入口、路由编排、输出结构化决策。
- `semantic-router`:配置驱动的候选召回与多字段打分,默认优先调用本地 embedding 服务并自动回退规则召回。
- `NeMo-Guardrails 风格守护层`:对执行前决策做二次守护,控制 clarify / refuse 质量,拦截高风险误执行。
- 多意图拆分:一句话可拆成多个子任务分别决策。
- planning intent:识别“方案设计 / 任务拆解 / 步骤规划 / 工作流编排”并路由到 `plan`。
- 作用域控制:支持 `tenant / customer / role / enabled` 过滤。
- 可解释 trace:每个子意图保留标准化、召回、过滤、打分、决策审计信息。
- `local_embedding_service`:独立目录部署的本地 embedding 服务,主路由服务通过 HTTP 调用。
- API / CLI / MCP Server / OpenClaw 薄包装 / 评测脚本 / 单测:可直接本地演示。

## 目录结构

```text
config/
  capabilities.yaml          # 能力注册表示例
  router_settings.yaml       # 阈值、别名、反问模板、打分配置
docs/eval/datasets/
  qdport_real_query_30_eval.yaml         # 30 条基础命中集
  qdport_generalized_query_240_eval.yaml # 240 条泛化评测集
  qdport_multiturn_query_240_eval.yaml   # 240 条多轮对话评测集
src/router_mcp/
  agent_router_mcp/          # 路由编排服务
  semantic_router/           # 候选召回与语义打分
  guardrails/                # 执行前守护与反问/拒答规范
  pipeline/                  # normalize / slot / rerank / decision
  registry/                  # registry schema 与加载校验
  eval/                      # 批量评测脚本
  api.py                     # FastAPI demo API
  cli.py                     # CLI demo
tests/
  test_router_pipeline.py
  test_api.py
```

## 快速开始

```bash
python3 -m pip install -e '.[dev]'
pytest
python3 -m pip install -r local_embedding_service/requirements.txt
python3 -m local_embedding_service.app
python3 scripts/extract_qdport_eval_datasets.py
python3 scripts/generate_multiturn_eval_dataset.py
python3 -m router_mcp.eval.run_eval --summary-only
python3 -m router_mcp.eval.run_eval --dataset docs/eval/datasets/qdport_real_query_30_eval.yaml --dataset docs/eval/datasets/qdport_generalized_query_240_eval.yaml --summary-only
python3 -m router_mcp.eval.run_multiturn_eval --dataset docs/eval/datasets/qdport_multiturn_query_240_eval.yaml
python3 -m router_mcp.cli "帮我查下今天异常流程,再把昨天没跑完的补跑一下" --tenant qingdao_port --customer default --role supervisor --execute
python3 -m router_mcp.cli "先别执行,先规划一下这个需求怎么落地" --tenant qingdao_port --customer default --role supervisor --plan
python3 -m router_mcp.app
python3 -m router_mcp.mcp_server
```

日常开发建议直接使用固定验证脚本:

```bash
scripts/verify_quick.sh
scripts/verify_boundary.sh
scripts/verify_full.sh
```

说明:

- `scripts/extract_qdport_eval_datasets.py` 现在默认优先读取仓库内的缓存 bundle:
  [qdport_generalized_query_240.json](/Users/zhuhaihua/Desktop/router-mcp/docs/eval/datasets/qdport_generalized_query_240.json)
- 如需重新从外部 Excel 全量抽取,仍可显式传 `--source /path/to/qdport_query_generalization_v2.xlsx`

如果动了 API / MCP / OpenClaw 入口,可加:

```bash
scripts/verify_quick.sh --with-api
```

Dashboard 前端工程位于 `frontend/`,开发与构建命令:

```bash
cd frontend
npm install
npm run dev
npm run build
```

- `npm run dev`:本地起前端开发服务器,自动代理后端 API
- `npm run build`:生成 `frontend/build/`,供 FastAPI 在 `/` 提供生产页面
- 如果直接运行 `python3 -m router_mcp.app` 且还没构建前端,根路径会返回提示先执行 `cd frontend && npm install && npm run build`

服务启动后可用接口:

- `GET /capabilities`
- `POST /capabilities/validate`
- `POST /route`
- `POST /route/explain`
- `POST /route/plan`
- `POST /route/batch`

## API 示例

### `POST /route`

```json
{
  "text": "帮我查下今天异常流程,再把昨天没跑完的补跑一下",
  "context": {
    "tenant_id": "qingdao_port",
    "customer_scope": "default",
    "role": "supervisor",
    "allow_execute": true
  },
  "dry_run": true
}
```

返回重点字段:

- `overall_decision`
- `decisions[].decision`
- `decisions[].trace_id`
- `decisions[].reason`
- `decisions[].evidence`
- `decisions[].goal_type`
- `decisions[].risk_level`
- `decisions[].selected_capability`
- `decisions[].decision_reason`
- `decisions[].matched_capabilities`
- `decisions[].confidence_breakdown`
- `decisions[].missing_slots`
- `decisions[].clarify_question`
- `decisions[].refuse_reason`
- `decisions[].execution_target`
- `decisions[].audit_trace`

## 核心决策原则

- 高置信单命中才执行。
- 多候选接近时优先 `clarify`。
- 缺关键槽位时必须 `clarify`。
- 方案设计 / 任务拆解 / 步骤规划 / 多阶段编排时进入 `plan`。
- 未命中或低置信度时 `refuse`。
- 高风险执行缺少确认或证据不足时强制拦截。
- `customer / tenant / role` 不匹配时直接过滤,不允许越权命中。

## 默认评测集覆盖

- 明确命中样例
- 模糊表达样例
- 多意图样例
- 未命中样例
- 高相似能力混淆样例
- 权限不足样例
- 缺槽位样例

评测输出至少包含:

- `correct_decisions`
- `correct_capabilities`
- `top1_accuracy`
- `topk_recall`
- `clarify_count`
- `refuse_count`
- `execute_count`
- `false_execute_count`
- `wrong_route_rate`
- `direct_execution_rate`
- `clarification_precision`
- `refusal_precision`
- `planning_detection_precision`
- `planning_detection_recall`

其中 `false_execute_count` 是当前 MVP 最关键指标。

当前默认 `run_eval` 会顺序跑两套整理后的评测集:

- [qdport_real_query_30_eval.yaml](/Users/wangxue08/Desktop/routrt-mcp/docs/eval/datasets/qdport_real_query_30_eval.yaml):30 条基础命中集,用于检查最基础的流程名直达命中
- [qdport_generalized_query_240_eval.yaml](/Users/wangxue08/Desktop/routrt-mcp/docs/eval/datasets/qdport_generalized_query_240_eval.yaml):240 条泛化评测集,用于检查 execute / clarify 边界与泛化稳定性

另外新增了一套并行维护的多轮评测集:

- [qdport_multiturn_query_240_eval.yaml](/Users/zhuhaihua/Desktop/router-mcp/docs/eval/datasets/qdport_multiturn_query_240_eval.yaml):由 30 条基础命中集派生出的 240 条多轮对话样本,覆盖 `clarify_fill_slots / proposal_confirm_cancel_revise / context_break_or_new_request`

这套数据不进入默认 `run_eval`,而是通过独立 runner 回放共享 `session_key + thread_id` 的 turns:

```bash
python3 -m router_mcp.eval.run_multiturn_eval \
  --dataset docs/eval/datasets/qdport_multiturn_query_240_eval.yaml
```

如果需要覆盖默认口径,仍可显式传入 `--dataset ...`。

## 最新调优结果

本轮调优重点放在 5 件事:

- 补强中文口语槽位抽取:`最近三天 / 本班 / 上一班 / 按货种汇总 / excel / 发给值班负责人 / 录到目标系统`
- 支持 `查 -> 整理 -> 发出` 的结构化步骤识别,并给同 family 多步骤链增加 rerank 组合分
- 修正 family 级别 guardrail:`query/generate` family 可以按 family 安全放行,`execute` family 仍必须按 resolved member 槽位复核;`hard_confusion` 强制 clarify
- 补齐 `plan / refuse`:显式 planning intent 检测、planner capability、MCP/OpenClaw 薄包装和 planning 指标
- `decision.py` 的 guardrail 阻断收尾分支抽成具名 `finalize_rule`,并补齐 `rule_name` trace 回归测试
- 对运行时能力集做轻量归一化:合并同名 seed family、去掉单成员 family 的同名 leaf,并对剩余不可安全合并的重名 seed leaf 做运行时改名,避免出现 “A 或 A / generate 还是 generate”

在默认 240 条泛化评测集 [qdport_generalized_query_240_eval.yaml](/Users/wangxue08/Desktop/routrt-mcp/docs/eval/datasets/qdport_generalized_query_240_eval.yaml) 上,当前 summary-only 指标为:

- `decision_accuracy`: `0.8125`
- `execute_count`: `81`
- `clarify_count`: `159`
- `direct_execution_rate`: `0.3375`
- `false_execute_count`: `0`
- `wrong_route_count`: `0`
- `named_target_accuracy`: `0.9667`
- `trace_coverage`: `1.0`
- `reason_coverage`: `1.0`

这轮结果对应的关键策略是:

- 恢复 `missing_required_slots -> clarify`
- 关闭 `hard_confusion` 高分直通 execute 的豁免

关于 LLM 的当前口径也需要明确:

- 当前主链路仍是 `heuristic + 结构化规则`
- 只有当 `heuristic` 槽位候选置信度 `< 0.72` 时,才触发 runtime LLM fallback 做受约束补充抽取
- LLM 不是默认主判决器,不会直接接管 `execute / clarify / refuse`
- 当前多轮补槽的主路径也仍由结构化 pending context 驱动;LLM 只适合作为受约束的 follow-up 分类或槽位补充,不应用来掩盖 registry 重复或 family 歧义问题

当前默认评测结果会以两套整理后的数据集分别输出:

- `qdport_real_query_30_eval.yaml`
- `qdport_generalized_query_240_eval.yaml`

## MCP / OpenClaw

- MCP Server: `src/router_mcp/mcp_server.py`
- MCP tools: `route_query`、`clarify_query`、`validate_route`、`list_capabilities`、`explain_route`、`plan_task`
- OpenClaw 薄包装: `src/router_mcp/openclaw_skill/bridge.py`
- OpenClaw 调用入口: `route_for_openclaw(...)`
- 所有内部命中 `execute` 的请求,现已优先返回待确认的 `execution_proposal`
- OpenClaw 如需承接多轮确认,请透传稳定的 `session_key + thread_id`
- 用户可通过自然语言回复“确认执行 / 取消 / 改成……”驱动 proposal 状态流转
- `clarify` 现在也支持 session-aware 续接:同一 `session_key + thread_id` 下,补充槽位会优先续接上一轮 `pending_clarify`

## 2026-04-11 增量结果

本轮新增两类能力:

- session-aware clarify / proposal-first 多轮链路
- flow 12 `凭证及回单` 能力簇重构
- session-aware phase2 轻分层:`CapabilityCatalog / SessionContextManager / FollowupResolver / RouteOrchestrator`
- `RouterCore`:承接单轮 fan-out 与识别-召回-打分-决策主链路

当前已验证:

- `clarify` 第二轮补槽位不会默认按新请求全量重路由
- OpenClaw / dashboard demo 已透传 `thread_id`
- `把凭证及回单处理一下` 会稳定回到 `SEED_FAMILY_1201`,并追问 `单据凭证号 / 单据流水号`
- `补发 / 结果归档 / 发送日志` 会回到各自子族 `1204 / 1203 / 1207`

这轮 focused tests 已通过:

- `PYTHONPATH=src python3 -m pytest tests/test_session_state_flow.py tests/test_confirmation_flow.py tests/test_openclaw_bridge.py tests/test_dashboard_api.py tests/test_dashboard_demo_page.py tests/test_router_pipeline.py -q`
  - `84 passed`

phase2 轻分层后的兼容性回归也已通过:

- `PYTHONPATH=src python3 -m pytest tests/test_confirmation_flow.py tests/test_session_state_flow.py tests/test_routing_orchestrator.py tests/test_openclaw_bridge.py tests/test_dashboard_api.py tests/test_router_pipeline.py -q`
  - `86 passed`

继续提取 `RouterCore` 后已通过:

- `PYTHONPATH=src python3 -m pytest tests/test_confirmation_flow.py tests/test_session_state_flow.py tests/test_routing_orchestrator.py tests/test_routing_core.py tests/test_openclaw_bridge.py tests/test_dashboard_api.py tests/test_router_pipeline.py -q`
  - `88 passed`

这轮 240 条泛化评测集 summary 为:

- `decision_accuracy`: `0.7958`
- `false_execute_count`: `4`
- `wrong_route_rate`: `0.0`
- `direct_execution_rate`: `0.3542`

也就是说,flow 12 专项已经明显改善,但全局边界集仍未回到 `false_execute_count = 0`。详细记录见 [2026-04-11-session-aware-router-report.md](/Users/zhuhaihua/Desktop/router-mcp/docs/eval/2026-04-11-session-aware-router-report.md)。

## 协作工作流

仓库内已经补充了面向 `CC + Codex` 的固定协作骨架:

- 方案目录:[docs/plans](/Users/wangxue08/Desktop/routrt-mcp/docs/plans)
- 复核目录:[docs/reviews](/Users/wangxue08/Desktop/routrt-mcp/docs/reviews)
- 协作文档:[WORKFLOW.md](/Users/wangxue08/Desktop/routrt-mcp/WORKFLOW.md)

推荐分工:

- `CC`:调研、方案、反例、challenge review
- `Codex`:主链路实现、测试、验证、文档回写

这样可以把“方案设计”和“主链路落地”拆开,同时仍然用统一验证脚本守住红线。

## Eval Dashboard

评测 Dashboard 现已切换为独立前端工程,而不是仓库根目录静态页:

- 前端工程:`frontend/`
- 后端数据接口:`/api/dashboard/*`
- 生产产物目录:`frontend/build/`
- 样例数据目录:`data/eval_results/`

推荐启动方式:

```bash
# 终端 1:启动后端
python3 -m router_mcp.app

# 终端 2:启动前端开发服务器
cd frontend
npm install
npm run dev
```

如果只想用单进程方式查看页面,先执行:

```bash
cd frontend
npm install
npm run build
python3 -m router_mcp.app
```

当前实时演示页特性:

- 输入一句 query,先查看待确认执行计划,再通过自然语言确认或取消
- 可切换 `tenant / customer_scope / role / allow_execute`
- 可从评测结果中随机切换示例 query
- 基于 `@ant-design/x` 的 `Bubble.List + Sender` 展示对话流
- 展示 Top-3 候选能力和 5 步中文链路解释
- 原始 Trace 默认折叠,不抢主视觉

当前能力管理页特性:

- 复用真实能力数据构建三栏管理台
- 左侧按业务域 / 能力族导航
- 中间查看能力对象列表,支持卡片 / 表格切换
- 右侧查看与编辑能力详情
- 支持前端闭环的新建能力、保存草稿、发布变更

## 待办

- 用通用槽位抽取层逐步替换当前 `rules + keywords` 方案:基于 `capability.required_slots + slot schema + examples` 做受约束抽取,而不是继续穷举关键词。
- 引入模型化 reranker,优先考虑中文友好的 cross-encoder / reranker,用于同 family 成员重排、查询/导出/执行细分和 hard negative 区分。
- 让 LLM 只负责“复杂 query 分解 + schema 约束下的槽位抽取/解释”,`execute / clarify / reject` 仍然走结构化决策层,避免黑盒直执行业务。
- 建立持续评测闭环,沉淀真实 query、clarify 补充信息、最终正确 capability、误执行样例,逐步把规则 MVP 过渡到 `embedding recall + model rerank + constrained extraction + structured decision`。

## 关于 semantic-router / NeMo-Guardrails

为了让仓库开箱可跑、测试稳定,这个 MVP 采用了两个“薄适配层”:

- `semantic_router.engine.LocalSemanticRouter`:默认优先调用独立本地 embedding 服务做语义召回,并和确定性多字段匹配融合;当 embedding 服务不可用时自动回退到纯规则召回。
- `guardrails.policy.GuardrailPolicy`:默认用显式规则落地 NeMo-Guardrails 风格守护,可在后续接入真实 guardrails runtime。

这样可以先把“安全、可解释、可评测”的基础设施层跑起来,再逐步替换底层模型。

## 本地 Embedding 服务

独立服务位于 `local_embedding_service/`,默认监听 `http://127.0.0.1:8001`,默认模型为 `BAAI/bge-small-zh-v1.5`。

启动命令:

```bash
python3 -m pip install -r local_embedding_service/requirements.txt
python3 -m local_embedding_service.app
```

可选环境变量:

- `EMBEDDING_MODEL_NAME`:自定义本地模型名称
- `EMBEDDING_DEVICE`:强制设备,例如 `cpu`、`mps`、`cuda`
- `EMBEDDING_HOST`:监听地址
- `EMBEDDING_PORT`:监听端口

主服务的 embedding 调用配置在 `config/router_settings.yaml` 的 `embedding` 段中:

- `enabled`:是否启用 embedding 召回
- `service_url`:独立 embedding 服务地址
- `timeout_seconds`:请求超时
- `similarity_weight` / `lexical_weight`:embedding 分和规则分的融合权重

## 500 条原始种子接入

仓库会自动读取 [config/qingdaogang_500cap.json](/Users/zhuhaihua/Desktop/qingdaogang/config/qingdaogang_500cap.json) 并映射到统一 registry schema:

- `capability_name -> name`
- `aliases -> aliases`
- `capability_description -> description`
- `generalized_user_query -> examples`
- `required_slots -> required_slots`
- `action_type -> 统一 action_type`
- `clarify_when / reject_when -> guardrail hints`

这样当前服务默认会同时加载手工高精度样例能力和 500 条原始种子能力。

## 开发约定与最新报告

- 开发方式、下一步任务与工程约束见 [Agents.md](/Users/zhuhaihua/Desktop/qingdaogang/Agents.md)
- 本轮路由优化与启动性能沉淀见 [2026-04-04-routing-optimization-report.md](/Users/zhuhaihua/Desktop/qingdaogang/docs/eval/2026-04-04-routing-optimization-report.md)
- guardrail finalize 规则对象化增量报告见 [2026-04-04-guardrail-finalize-rule-report.md](/Users/wangxue08/Desktop/routrt-mcp/docs/eval/2026-04-04-guardrail-finalize-rule-report.md)

TDQS

C2.1/5.0

Scored across 7 tools

Disambiguation4/5

Most tools have distinct purposes: clarify_query, explain_route, route_query, and validate_route target different stages of query processing, while list_capabilities and validate_capabilities focus on server capabilities. However, plan_task is somewhat vague and could overlap with route_query or clarify_query in function.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern using snake_case, such as clarify_query, explain_route, and list_capabilities. There are no deviations in naming conventions, making the set predictable and readable.

Tool Count5/5

With 7 tools, the count is well-scoped for a router server, covering query clarification, routing, validation, and capability management without being overwhelming. Each tool appears to serve a specific role in the routing workflow.

Completeness4/5

The tool set covers key aspects of routing: query clarification, route explanation, planning, routing, and validation, along with capability listing and validation. A minor gap might be the lack of tools for dynamic route updates or error handling, but core operations are present.

Maintenance

ActivityInactive
ResponsivenessNo issues