内容
# MCP 动态路由
<div align="center">
<img src="assets/banner.jpg" alt="MCP 动态路由 Banner" width="800px" style="border-radius: 8px; margin-bottom: 20px;" />
</div>
<p align="center">
<a href="https://github.com/kavinbm16/Mcp-Dynamic-Router/actions"><img src="https://github.com/kavinbm16/Mcp-Dynamic-Router/actions/workflows/ci.yml/badge.svg" alt="CI 状态"></a>
<a href="https://goreportcard.com/report/github.com/kavinbm16/Mcp-Dynamic-Router"><img src="https://goreportcard.com/badge/github.com/kavinbm16/Mcp-Dynamic-Router" alt="Go 报告卡"></a>
<a href="https://pkg.go.dev/github.com/kavinbm16/mcp-dynamic-router"><img src="https://pkg.go.dev/badge/github.com/kavinbm16/mcp-dynamic-router.svg" alt="Go 参考"></a>
<a href="LICENSE"><img src="https://img.shields.io/github/license/kavinbm16/Mcp-Dynamic-Router.svg" alt="许可证"></a>
</p>
<h3 align="center">为您的语音管道赋予数千种工具。让模型只看到正确的少数工具。</h3>
---
## ❓ 为什么使用 MCP 动态路由?
如果您在 `claude_config.json` 中硬编码了 10 多个下游 MCP 服务器:
* **巨大的上下文窗口开销:** 您迫使 LLM 处理所有 100 多种工具的模式和参数定义,从而增加了延迟和令牌成本。
* **准确性下降:** 注册太多工具会引入语义混淆,导致 LLM 产生幻觉参数或选择错误的工具。
* **静态生命周期:** 添加或删除工具需要重启 LLM 会话。
**MCP 动态路由** 作为一个智能中间层:
1. **集中生命周期:** 同时连接和编排多个 MCP 服务器(SSE/HTTP),动态地实时热加载工具模式。
2. **亚毫秒级延迟(快速通道):** 精确的词汇匹配绕过语义向量嵌入和 LLM 重新排序调用,返回时间不到 1 毫秒。
3. **流式 RAG 预取:** 在用户仍在讲话时评估部分语音转录,以预热连接并安全地预取只读工具。
4. **安全性和自定义范围:** 按请求限制工具暴露,并在查询置信度低时安全地放弃执行。
```mermaid
graph TD
User([用户提示/语音]) -->|1. 音频/文本| Client[客户端代理/应用程序]
subgraph 网关 ["MCP 动态路由网关(routerd)"]
Client -->|2. 路由/流式传输| API[HTTP 端点:/v1/route,/v1/stream]
API -->|3. 选择候选工具| Routing[两阶段路由引擎]
Client -->|4. 执行工具| API
API -->|5. 验证模式| Validator{JSON 模式验证器}
API -->|6. 分发调用| Downstream[SSE / HTTP MCP 客户端]
end
subgraph 服务器 ["下游服务器"]
Downstream -->|7. JSON-RPC| S1[天气服务器]
Downstream -->|7. JSON-RPC| S2[健康服务器]
end
```
---
## ⚡ 主要功能
* **🔌 动态服务器编排** — 同时连接到多个 MCP 服务器(通过 HTTP/SSE),在工具模式更新时处理实时热加载。
* **📈 流式 RAG 引擎** — 在用户仍在讲话时启动路由部分转录,以预热下游连接并安全地预取只读工具。
* **🎯 混合评分和重新排序** — 将 BM25 词汇评分、语义向量嵌入和基于 LLM 的重新排序相结合,以实现精确、低延迟的选择。
* **🛡️ 安全放弃策略** — 当输入不明确或低于置信度阈值时,放弃路由以防止错误突变。
* **🚀 多语言兼容性** — 直接嵌入到您的 Go 代码库中,或作为轻量级本地 HTTP 边车伴侣,与 Python、TypeScript、LiveKit 或 Pipecat 代理一起部署。
```text
"您能检查 Bengaluru 的天气在——"
│
├── 部分转录 → 领域检索 → 工具候选列表
│ └── 暖和安全上下文
│
"...明天早上?" ─┴── 最终转录 → 确认路由 → 绑定 → 执行
```
路由器完全 **提供者中立**;它与任何 STT、LLM、TTS、实时语音 API 或代理框架无缝集成。
> **状态:** 积极开发中。动态注册发现、自动工具审计、混合检索、流式 RAG、模式验证和 HTTP 边车已完全实现并测试。
## 🚀 30 秒快速入门
在本地尝试动态路由器,零配置。我们提供一个模拟服务器命令,托管两个虚拟 MCP 服务(天气和计算器),并为您自动生成 `mcp-mock.toml`。
### 1. 启动模拟 MCP 服务器
打开一个终端并运行:
```bash
go run ./cmd/mock-servers
```
*(这启动了一个模拟天气服务,监听 `:8091`,和一个模拟计算器服务,监听 `:8092`,并写入一个本地 `mcp-mock.toml` 文件。)*
### 2. 启动动态路由器守护进程
打开第二个终端并运行:
```bash
go run ./cmd/routerd -mcp mcp-mock.toml
```
*(这启动了动态网关边车,监听 `:8090`,并连接到两个下游模拟服务器。)*
### 3. 验证路由
打开第三个终端并使用简单的 HTTP 请求测试路由:
```bash
curl -s -X POST http://localhost:8090/v1/route \
-H "Content-Type: application/json" \
-d '{"utterance": "What is the weather in New York?"}'
```
您将收到一个 JSON 响应,显示所选的天气服务,完全绕过计算器服务!
---
### 2A. 集成到 Go 中
```go
package main
import (
"context"
"fmt"
dynamicrouter "github.com/kavinbm16/mcp-dynamic-router"
"github.com/kavinbm16/mcp-dynamic-router/router"
)
func main() {
ctx := context.Background()
app := dynamicrouter.NewBuilder().WithMCPConfigPath("mcp.toml").Build()
defer app.Close()
report, err := app.Start(ctx)
if err != nil { panic(err) }
fmt.Println("connected:", report.Connected)
result, err := app.Route(ctx, router.RouteRequest{
Utterance: "Will I need an umbrella in Bengaluru tomorrow?",
Context: "User timezone: Asia/Kolkata",
Final: true,
})
if err != nil { panic(err) }
fmt.Println(result.Decision, result.Candidates[0].Tool.ID)
}
```
### 2B. 或在任意管道旁边运行边车
```bash
go run ./cmd/routerd -mcp mcp.toml
```
路由最终的语音转录:
```bash
curl -s http://127.0.0.1:8090/v1/route \
-H 'content-type: application/json' \
-d '{
"utterance": "Will I need an umbrella in Bengaluru tomorrow?",
"context": "User timezone: Asia/Kolkata",
"final": true
}'
```
然后执行所选工具(边车代理调用下游 MCP 服务器并自动验证参数):
```bash
curl -s http://127.0.0.1:8090/v1/execute \
-H 'content-type: application/json' \
-d '{
"tool_id": "weather-service.get_forecast",
"arguments": {
"location": "Bengaluru",
"units": "metric"
}
}'
```
这是完整的集成边界:JSON 输入,路由决策和工具执行输出。客户端不需要任何 MCP 特定的连接代码。
## 流式 RAG:在用户停止讲话之前路由
普通的工具路由等待对话结束。流式 RAG 在用户讲话时利用这段原本空闲的语音时间检索可能的领域和工具。
包含的流式 RAG 会话执行四个精确的操作:
1. 忽略太短或 ASR 置信度弱的部分转录。
2. 当更新的假设到达时,取消旧转录的路由。
3. 仅在同一工具连续更新后标记路由稳定。
4. 仅允许预取标记为 `readOnly` 的工具;最终转录触发提交。
它从不将部分转录视为执行副作用的许可。
### 从任何语言通过 HTTP
发送部分 ASR 更新:
```bash
curl -s http://127.0.0.1:8090/v1/stream \
-H 'content-type: application/json' \
-d '{
"session_id": "call-42",
"transcript": "check the weather in Bengaluru",
"confidence": 0.91,
"final": false
}'
```
然后提交最终转录:
```bash
curl -s http://127.0.0.1:8090/v1/stream \
-H 'content-type: application/json' \
-d '{
"session_id": "call-42",
"transcript": "check the weather in Bengaluru tomorrow morning",
"confidence": 0.97,
"final": true
}'
```
每个响应都包含 `triggered`、`stable`、`stability_count`、路由决策、候选工具、置信度、边距和阶段延迟。最终请求自动关闭其服务器端流式 RAG 会话;废弃的会话在两分钟后过期。
### 直接在 Go 中
```go
session := app.NewStreamBuilder().
OnPrediction(func(p streamrag.Prediction) {
log.Printf("partial route stable=%v decision=%s", p.Stable, p.Result.Decision)
}).
OnPrefetch(func(ctx context.Context, tool router.Tool) error {
// 暖和一个缓存或下游连接。永远不要在这里执行突变。
return warm(tool)
}).
OnCommit(func(p streamrag.Prediction) {
// 转录是最终的。继续进行参数绑定和策略。
commit(p.Result)
}).
Build()
defer session.Close()
session.Submit(ctx, streamrag.Event{
Transcript: partialTranscript,
Confidence: asrConfidence,
Final: false,
})
```
`Submit` 是异步的,立即返回。`Update` 为请求/响应传输提供相同的状态机。
## 它在哪里适用
| 管道 | 集成点 |
|---|---|
| 级联 STT → LLM → TTS | 发送每个有用的 STT 部分到 `/v1/stream`;用 `final:true` 发送结束转录。 |
| 原生语音到语音 API | 镜像转录事件到流式 RAG;返回最终选定的模式到实时模型。 |
| 文本代理 | 对每个最终用户消息调用 `/v1/route`。 |
| Go 代理 | 嵌入根 `dynamicrouter.App`。 |
| Python 或 TypeScript 代理 | 作为本地边车运行 `routerd`,使用普通的 HTTP JSON。 |
| 多代理系统 | 运行一个共享的路由器服务或一个注册隔离的实例,每个信任边界一个。 |
管道拥有音频和对话 UX。路由器拥有发现、缩小、排名、不确定性和 MCP 连接。
## 准确性始于工具描述
路由器无法推断出工具未声明的限制。对 856 个 MCP 工具的 2026 年分析报告称,**97.1% 包含至少一个描述缺陷**。参见 [MCP 工具描述质量研究](https://arxiv.org/abs/2602.14878)。
在普通的 MCP `description` 字段中使用此格式:
```text
领域:日历
目的:创建用户日历中的新事件。
调用时机:当用户明确要求安排、
预订或添加日历事件时调用。
参数:
- title (string, required): 简短的事件标题。语音示例:“dentist appointment”。
- start_time (string, required): 用户时区解析的 ISO-8601 时间。
语音示例:”tomorrow at three“。
- timezone (string, optional): IANA 时区,如 "Asia/Kolkata"。
限制:
- 不搜索、更新或删除现有事件。
- 不应在用户仅询问可用性时调用。
- 需要在邀请外部与会者之前确认。
示例:
用户:”Schedule lunch with Mira tomorrow at noon.“
参数:{“title”:”Lunch with Mira”,”start_time”:”2026-06-30T12:00:00+05:30”,”timezone”:”Asia/Kolkata”}
```
这些字段很重要:
| 字段 | 它为路由器提供了什么 |
|---|---|
| `Domain` | 一个小的第一阶段搜索空间。 |
| `Purpose` | 积极的语义身份。 |
| `Invoke when` | 自然的语音模式和意图边界。 |
| `Parameters` | 语音到模式的接地。 |
| `Limitations` | 对混淆邻居的负面证据。 |
| `Example` | 从语音到有效参数的现实桥梁。 |
`Domain` 是路由器约定而非 MCP 要求。设置 `Tool.Domain` 直接、在描述中包含 `Domain:`,或让路由器回落到 MCP 服务器名称。
JSON 模式应重复每个机器强制执行事实:
```json
{
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "从用户的言语中推断出的短事件标题"
},
"timezone": {
"type": "string",
"description": "IANA 时区",
"examples": ["Asia/Kolkata"]
}
},
"required": ["title"],
"additionalProperties": false
}
```
审计描述本地或在 CI 中:
```bash
go run ./cmd/router-audit -tools testdata/tools.json -minimum 90
```
如果描述不合策略,命令以非零退出。
## 路由工作原理
```mermaid
flowchart LR
A["语音转录 + 对话上下文"] --> B["阶段 1:领域路由器"]
R["动态 MCP 注册表"] --> C["工具卡编译器"]
C --> B
B -->|"最多 20 种工具"| D["阶段 2:工具选择器"]
D --> E["置信度 + 边距策略"]
E --> F["已选定"]
E --> G["澄清"]
E --> H["no_tool"]
F --> I["模式验证"]
I --> J["MCP 执行"]
```
### 阶段 1:领域路由器
注册表被分组为显式领域文档。BM25 和可选的嵌入式检索选择相关的领域文档,然后限制活动池中的工具不超过 20 个。大领域在截断前会进行内部排名;工具顺序永远不会决定短列表。
### 阶段 2:工具选择器
选择您的管道所需成本/准确性点:
* **词汇:** 无依赖的 BM25。
* **混合:** BM25 和嵌入相似性融合。
* **重新排序:** 混合检索加上一个小的约束输出 LLM。
#### 评分融合公式
使用混合路由时,词汇和语义分数被归一化并使用您配置的权重融合:
1. **标准化分数:** 对于两个运行,各个分数通过该集合中的最大分数标准化。
$$S_{norm} = \frac{S}{S_{max}}$$
2. **权重融合:** 归一化权重计算如下:
$$W_{lex\_norm} = \frac{W_{lex}}{W_{lex} + W_{sem}}, \quad W_{sem\_norm} = \frac{W_{sem}}{W_{lex} + W_{sem}}$$
$$S_{fused} = W_{lex\_norm} \cdot S_{lex\_norm} + W_{sem\_norm} \cdot S_{sem\_norm}$$
3. **重新插值:** 如果启用了第二阶段重新排序器,最终分数会插值融合得分和重新排序得分 ($S_{rerank} \in [0, 1]$):
$$S_{final} = (1 - W_{reranker}) \cdot S_{fused} + W_{reranker} \cdot S_{rerank}$$
### 放弃
路由器返回:
* `selected` 当置信度和 top-1 边距均通过时;
* `clarify` 当合理的工具太接近时;
* `no_tool` 当没有候选工具足够强时。
错误的动作不是延迟优化。置信度阈值必须在您的保留数据上进行校准。
#### 校准决策策略
该策略使用您的配置中的两个超参数来控制路由行为:
### 1. **MinConfidence**
浮点数 | 0.42 | **提高** 以减少假阳性路由(例如,路由随机聊天到工具)。**降低** 如果有效意图被归类为 `no_tool`。
|---|---|---|---|
### 2. **MinMargin**
浮点数 | 0.06 | **提高** 以强制严格的消歧义(产生 `clarify` 如果工具接近)。**降低** 如果相似的工具可以安全地互换使用。
## 可选的本地智能
在边车中启用 Ollama 嵌入和第二阶段选择器:
```bash
go run ./cmd/routerd \
-mcp mcp.toml \
-ollama http://localhost:11434 \
-embedding-model nomic-embed-text \
-selector-model qwen3:4b
```
或在 Go 中配置:
```go
app := dynamicrouter.NewBuilder().
WithMCPConfigPath("mcp.toml").
WithEmbedder(&embedding.Ollama{
BaseURL: "http://localhost:11434",
Model: "nomic-embed-text",
}).
WithReranker(&selector.Ollama{
BaseURL: "http://localhost:11434",
Model: "qwen3:4b",
}).
Build()
```
两个接口都是可替换的。实现 `router.Embedder` 或 `router.Reranker` 以使用另一个本地模型、托管 API 或专用分类器。
## 动态 MCP 行为
- 服务器从 `mcp.toml` 并发连接。
- 一个失败的服务器不会禁用健康的服务器。
- 连接使用可重用的 Streamable HTTP 会话。
- `notifications/tools/list_changed` 原子地替换该服务器的工具并重建索引。
- 进行中的请求继续针对其不变的快照。
- 工具参数可以使用 `router.ValidateArguments` 在执行之前进行检查。
### 唤起
- `enabled=false`:不宣传诱导处理程序。
- `enabled=true, auto_accept=false`:除非应用程序提供 `mcpclient.WithElicitationHandler`,否则请求被拒绝。
- `auto_accept=true`:自动接受请求。避免对后果严重的工具使用此功能。
- `timeout`:应用程序处理程序的超时时间(秒)。
语音应用程序应将诱导映射到其自己的用户确认状态机。沉默不是同意。
## 衡量
包含的评估器读取工具注册表和标记的 JSONL:
```json
{"utterance":"Will I need an umbrella in Bengaluru?","expected_tool":"weather.get_forecast"}
{"utterance":"Tell me a bedtime story","expected_tool":""}
```
运行词汇基线:
```bash
go run ./cmd/router-eval -tools testdata/tools.json -cases testdata/cases.jsonl
```
运行混合检索:
```bash
go run ./cmd/router-eval \
-tools testdata/tools.json \
-cases testdata/cases.jsonl \
-ollama http://localhost:11434 \
-model nomic-embed-text
```
报告包括 top-1 准确率、top-1 回忆率、错误路由率(`no_tool` 请求)和 P50/P95 路由延迟。
可信的数据集包括混淆的工具对、实际的 ASR 错误、`no_tool` 请求、口语名称和数字、跨回合上下文和多个规模的注册表。在开发数据上进行调优;在保留的测试集上发布结果。
## HTTP API
`routerd` 默认绑定到 `127.0.0.1:8090`。如果需要在本地机器以外公开访问,请有意设置 `-listen`;身份验证和 TLS 应在部署边界处进行。
### 端点
#### `GET /healthz`
如果进程正常运行且健康,则返回 `200 OK`。
**响应**:
```json
{
"status": "ok"
}
```
#### `POST /v1/route`
路由单个语句,无会话状态。
**请求**:
```json
{
"utterance": "明天在班加罗尔需要带伞吗?",
"context": "用户时区: Asia/Kolkata",
"final": true
}
```
**响应**:
```json
{
"decision": "selected",
"confidence": 0.854,
"margin": 0.352,
"candidates": [
{
"tool": {
"id": "weather-service.get_forecast",
"server": "weather-service",
"name": "get_forecast",
"domain": "weather",
"description": "领域: weather\n目的: 获取预报...",
"input_schema": {
"type": "object",
"properties": {
"location": { "type": "string" }
},
"required": ["location"]
}
},
"score": 0.854,
"lexical_score": 0.9,
"semantic_score": 0.8,
"rank": 1
}
],
"reason": "top candidate passed confidence and margin thresholds",
"trace": {
"registry_version": 1,
"domains": ["weather"],
"domain_latency": 1500000,
"select_latency": 2500000,
"total_latency": 4000000,
"used_embeddings": true,
"used_reranker": false
}
}
```
*(注意: `trace` 中的延迟值以纳秒表示。)*
#### `POST /v1/stream`
路由与会话相关的增量用户转录。
**请求**:
```json
{
"session_id": "session-101",
"transcript": "检查班加罗尔的天气",
"confidence": 0.91,
"final": false
}
```
**响应**:
```json
{
"triggered": true,
"final": false,
"stable": true,
"stability_count": 2,
"result": {
"decision": "selected",
"confidence": 0.854,
"margin": 0.352,
"candidates": [
{
"tool": {
"id": "weather-service.get_forecast",
"server": "weather-service",
"name": "get_forecast",
"domain": "weather",
"description": "领域: weather\n目的: 获取预报...",
"input_schema": {
"type": "object",
"properties": {
"location": { "type": "string" }
},
"required": ["location"]
}
},
"score": 0.854,
"lexical_score": 0.9,
"semantic_score": 0.8,
"rank": 1
}
],
"reason": "top candidate passed confidence and margin thresholds",
"trace": {
"registry_version": 1,
"domains": ["weather"],
"domain_latency": 1500000,
"select_latency": 2500000,
"total_latency": 4000000,
"used_embeddings": true,
"used_reranker": false
}
}
}
```
*(注意: 发送请求时,如果 `"final": true`,则会在服务器上自动关闭会话;未使用的会话在 2 分钟后过期。)*
## 生产部署
将动态路由器 (`routerd`) 作为 sidecar 容器部署(例如,在 Kubernetes、ECS 或 Docker Compose 中)。
### 🐳 容器化
构建基于 Alpine 的最小镜像:
```bash
docker build -t mcp-dynamic-router .
```
运行容器,挂载您的 `mcp.toml` 配置文件:
```bash
docker run -d -p 8090:8090 \
-v $(pwd)/mcp.toml:/etc/routerd/mcp.toml:ro \
mcp-dynamic-router \
-listen 0.0.0.0:8090 -mcp /etc/routerd/mcp.toml
```
或通过 [docker-compose.yml](file:///Users/kavin/Projects/MCP-Dynamic-router/docker-compose.yml) 运行:
```yaml
services:
routerd:
build: .
ports:
- "8090:8090"
volumes:
- ./mcp.toml:/etc/routerd/mcp.toml:ro
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://127.0.0.1:8090/healthz || exit 1"]
restart: unless-stopped
```
### ⚙️ 最佳实践
* **热加载**:sidecar 会轮询 `-mcp` 文件。修改它会触发下游连接的零停机时间热加载。
* **健康检查**:查询 `GET /healthz` 进行存活和就绪探测。
* **安全**:绑定到 `127.0.0.1`(默认)用于本地 sidecar。如果外部公开,请使用 API 网关或反向代理进行 TLS/身份验证。
* **远程 LLM / 嵌入**:传递 `-ollama http://ollama:11434` 或实现自定义 Go `Embedder`/`Reranker` 适配器,在生产中运行云模型(OpenAI、Gemini、Cohere)。
---
## 集成蓝图和示例
对于实时语音、流式 STT/ASR 和嵌入式应用程序管道,您可以在 `/examples` 目录下找到完整的、可运行的实现蓝图:
* **Go 应用程序嵌入:** [main.go](examples/go_embed/main.go) — 演示如何直接在 Go 中导入 `dynamicrouter` 库,重新加载配置,并在没有 sidecar 的情况下运行无状态 `Route` 或有状态 `streamrag.Session` 调用。
* **Go 自定义 HTTP 网关:** [main.go](examples/go_http_server/main.go) — 展示如何构建一个自定义的 Go HTTP JSON API 服务器,封装动态路由器库(mini-`routerd`)。
* **Go 自定义嵌入器和重新排序器:** [main.go](examples/go_custom_llm/main.go) — 编写和注入自定义 `router.Embedder` 和 `router.Reranker` 接口实现(例如,接入 HuggingFace 或 OpenAI)的详细蓝图。
* **Pipecat(Python):** [pipecat_router.py](examples/pipecat/pipecat_router.py) — 演示如何将语音转录更新输送到 `routerd` 以处理实时预取和提交的工具执行。
* **LiveKit 代理(Python):** [livekit_agent.py](examples/livekit/livekit_agent.py) — 接入用户语音转录和提交事件,以流式传输部分结果并执行最终工具决策。
* **OpenAI 实时 API(Python):** [openai_realtime_session.py](examples/openai_realtime/openai_realtime_session.py) — 与 OpenAI 实时 WebSockets 会话接口,拦截 `invoke_tool` 意图并通过 sidecar 执行它们。
* **Gemini 多模态实时 API(Python):** [gemini_live.py](examples/gemini/gemini_live.py) — 通过 WebSockets 使用 `google-genai` SDK 与 Gemini 多模态实时 API 接口,将用户意图映射到动态工具执行。
* **Gemini SDK(Go):** [main.go](examples/gemini_go/main.go) — 演示如何使用官方 `google.golang.org/genai` SDK 在 Go 中集成标准 Gemini 函数调用,通过嵌入式注册表路由调用。
## 仓库地图
| 路径 | 责任 |
|---|---|
| `dynamicrouter.go` | 单构造函数 Go 外观。 |
| `router/` | 注册、审计、领域路由、选择、放弃、模式检查。 |
| `streamrag/` | 可取消的部分路由、稳定性、安全预取、最终提交。 |
| `mcpclient/` | `mcp.toml`、官方 MCP SDK、热发现、执行。 |
| `embedding/` | 可选的 Ollama 批量嵌入。 |
| `selector/` | 可选的 Ollama 约束输出重新排序器。 |
| `cmd/routerd/` | 提供者中立的 HTTP sidecar。 |
| `cmd/router-audit/` | 描述质量 CI 门控。 |
| `cmd/router-eval/` | 准确性、拒绝和延迟评估器。 |
## 🎯 核心原则
* **质量描述:** 工具描述被视为可执行代码,而非装饰。
* **广泛检索,狭窄推理:** 在阶段 1 检索中投出广泛的网,然后积极修剪。
* **流安全:** 部分转录仅预取安全的只读工具;它们从不授权修改。
* **安全放弃:** 我们更喜欢返回 `clarify` 或 `no_tool` 而不是执行自信的错误操作。
* **策略分离:** 路由决策和工具执行保持独立的边界。
* **可检查和可基准测试:** 每个路由路径和延迟预算都必须完全可审计。
## 🚀 路线图
* [ ] 公共语音路由基准和混淆集生成器。
* [ ] 保留置信度校准。
* [ ] 模式约束参数绑定和自我修复循环。
* [ ] 多意图依赖 DAG 并行执行。
* [ ] LiveKit、Pipecat、OpenAI Realtime 和 Gemini Live 的生产集成。
* [ ] OpenTelemetry 和 Prometheus 仪表盘。
* [ ] Voxa 集成,感知延迟测量。
## 🤝 贡献和良好第一问题
我们欢迎贡献!无论您是添加中间件遥测、编写新的语音代理包装器(例如,用于 LiveKit 或 Pipecat),还是实现新的自定义嵌入缓存,请参阅我们的 [CONTRIBUTING.md](CONTRIBUTING.md) 指南,了解如何开始。
高优先级机会包括:
* **Prometheus 和 OpenTelemetry 集成**(添加延迟和决策指标)。
* **基于 SQLite 的嵌入缓存**(在重启之间持久化向量)。
* **自定义 LLM 适配器**(Hugging Face、Cohere、OpenAI)。
* **LiveKit / Pipecat 适配器中间件**(Python)。
运行验证命令:
```bash
go test -race ./...
go vet ./...
go run ./cmd/router-audit
go run ./cmd/router-eval
```
在更改任何排名策略时,请包含基准测试影响。
## License
MIT. See [LICENSE](LICENSE).
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器