tsm-hub:把 LLM、Tools、MCP、Skills 收进一个统一网关

作者:

🇬🇧 English

开篇:为什么需要 tsm-hub

在大模型应用开发中,我遇到了一个普遍的痛点:各家 Provider 的接口格式不统一、限流策略各异,调用方需要为每个模型写一套适配代码。更麻烦的是,当某个模型出现故障或服务不可用时,调用方需要手动切换配置,运维成本很高。

以我自己的项目为例:多个 AI 应用(开发环境、内容生成、自动化服务等)都需要调用 LLM,每个项目都要维护一套 Provider 配置,接入了多家付费模型商但无法统一调度。某个 Provider 出现故障或限流,另一家还能正常服务,但调用方不知道,只能干等着。更麻烦的是,不同任务适合不同的模型,但调用方很难根据任务类型自动选择最合适的模型。

除了模型路由,还有一个更核心的问题:AI 能力的组织方式。每个项目都在重复实现工具调用循环、技能包管理、MCP 服务接入,但这些能力本质上是可以共享的。调用方携带自己的能力声明,网关根据实际使用情况进行统计,管理员可以选择是否将其纳入共享能力池——这才是 tsm-hub 最有辨识度的地方。

为了解决这些问题,我构建了 tsm-hubGitHub 仓库)——一个集 LLM 网关、能力池平台、快路径引擎、运行时环境、可观测性于一体的统一 LLM 接入与能力平台。它的核心思路是:对外只暴露自己签发的 sk-tr-… Key,调用方像用 OpenAI 一样调用,平台在后端自动完成智能路由、能力注入、快路径加速、运行时隔离和全链路观测。

三个核心卖点

  1. Model Gateway:多 Provider / 多模型 / 统一协议,智能路由与自动 failover
  2. Capability Pool:Tools / MCPs / Skills 的发现、统计与纳入,一次接入全网共享
  3. Fastpath:确定性请求绕过 LLM,直接本地计算回答

其他能力(Runtime、Sandbox、Memory、Observability、Streaming)作为能力补充,在后续章节详细介绍。

核心能力矩阵

tsm-hub 已经形成了完整的功能矩阵,覆盖从接入到运行的全链路:

能力域 核心功能
统一入口 OpenAI 兼容 API,调用方只需换 Key、换 base_url、换 model 别名
智能路由 可配置的多维度智能调度策略(smart),支持 cost_first / stability_first / task_aware / balanced 四种模式,各维度权重可单独调整;也支持显式路由表,自定义 failover / weighted 等策略;支持通过 config.json、环境变量或 .env 文件配置
多协议适配 已支持 13 种上游协议(OpenAI 兼容、Anthropic、Azure OpenAI、Google Gemini、AWS Bedrock、AWS SageMaker、Cohere、Mistral、Hugging Face、Replicate、Together AI、Fireworks AI、Groq),统一的 Provider 适配器接口
能力池 内置 Tools(通用工具)、MCPs(Model Context Protocol 服务)、Skills(技能包)三层能力体系,支持发现、统计与择优录用
快路径引擎 Fastpath 可选加速(算术、统计、单位换算等确定性查询直接回答)、Codegen 代码生成 fastpath
运行时环境 Sandbox(Docker 隔离的代码执行环境)、Memory(SQLite 持久化的对话记忆与用户偏好存储)
可观测性 用量统计、Provider 健康监控、按天趋势、成本归因
隐私合规 TLS 传输加密、CORS 白名单、启动安全自检、审计日志

关键设计决策与架构收益

在实现 tsm-hub 的过程中,有几个关键的设计决策不仅解决了当下的问题,更重要的是建立了可扩展的架构思维,为后续开发带来了长期收益。

决策一:自制 Token Key 统一鉴权

设计思维:对外只签发 sk-tr- 开头的自制 Key,服务端只存哈希(明文只在创建时返回一次)。每个 Key 可以独立配置允许使用的模型列表、配额限制(总 Token、总成本、每日 Token、RPM)、技能注入模式(不注入 / 技能清单 / 全部技能 / 指定技能)、Agent 开关(是否经过网关内置 Agent 工具循环)。

这样调用方不需要知道上游 Provider 的真实 Key,网关统一管理,也方便后续回收和权限控制。

架构收益

  • 权限细粒度控制:每个 Key 可以独立配置模型范围、配额、技能注入模式,满足不同调用方的需求
  • 密钥安全:服务端只存哈希,即使数据库泄露也无法获取明文 Key;明文只在创建时返回一次,降低泄露风险
  • 统一回收:某个调用方不再需要时,只需禁用对应的 Key,不需要修改上游 Provider 的配置
  • 可追溯:每个请求都关联到具体的 Key,用量统计、成本归因、审计日志都可以按 Key 维度聚合

决策二:可配置的多维度智能调度 + 显式路由表

设计思维:接入多家模型商后,不同场景对路由策略的需求是不同的:有的场景成本敏感,有的场景可靠性优先,有的场景需要平衡质量和速度。因此智能路由不应该是写死的单一策略,而应该是可配置的多维度评分系统,让用户根据自己的业务需求选择合适的策略模式和权重。

默认采用 smart 智能调度策略,对于没有显式路由表的模型,网关自动扫描所有支持该模型的 Provider,综合评估多个维度后智能选择最优上游,无需为每个模型手动配置路由。

四种策略模式settings.smart.strategy_mode 可配置):

模式 成本权重 稳定性权重 延迟权重 适用场景
cost_first 100 40 30 成本敏感场景,免费/低价优先
stability_first 30 100 50 生产服务,可靠性优先,成功率高的 Provider 优先
task_aware 50 80 70 混合负载,平衡质量与速度
balanced 60 70 70 通用场景,各维度均衡

各维度权重也可以通过 settings.smart.cost_weight / stability_weight / latency_weight 单独覆盖(0 表示用策略默认值)。支持通过 config.json、环境变量(TSM_HUB_SMART_*)或 .env 文件配置。

smart 策略的调度算法综合考虑多个维度

  • 成本维度:免费模型加分 + 单价档位加分(可配置 free_bonus / price_tiers
  • 稳定性维度:历史成功率 (requests - errors) / requests × 100,连续失败惩罚;新 provider 给 70 分鼓励探索
  • 延迟维度:EWMA 延迟,100ms 以内 100 分,1000ms 以上 0 分;无数据给 60 分
  • 健康过滤:自动过滤 429 限流、5xx 错误、高延迟等不健康的 Provider,故障节点自动摘除
  • 能力匹配:带 tools 的请求优先选择支持 tool_calls 的模型,长文本请求优先选择支持长上下文的模型
  • 通用惩罚:半开候选扣分,429 限流期间大幅降权(-1000)

调度算法对多个维度进行加权综合评分,网关按得分从高到低排序,优先选择得分最高的健康 Provider。如果第一个失败,自动 failover 到下一个,实现多家模型商之间的无缝切换。

同时,用户也可以自由配置显式路由表,为特定模型或路由别名(如 chatfastcodereason)定义一组上游 target,选择 failover(严格优先级故障转移)、weighted(加权负载均衡)或 smart(在 target 范围内应用智能调度)等策略。

请求进来时,网关按以下步骤决策:① 匹配显式路由表(如有)→ ② 应用对应策略 → ③ 健康检查过滤 → ④ 能力匹配过滤 → ⑤ 按配置的策略模式和权重综合评分排序 → ⑥ 选择最终 Provider → ⑦ 失败自动 failover。

架构收益

  • 灵活可配置:四种策略模式 + 各维度权重可单独调整,适配不同业务场景;支持 config.json / 环境变量 / .env 三种配置方式
  • 稳定性优先可选:选择 stability_first 模式时,优先选择近期成功率高的 Provider,故障节点自动摘除,服务质量有保障
  • 任务-模型匹配:通过显式路由表为不同任务类型(普通对话、代码生成、深度推理等)配置不同的模型池,各尽其用
  • 多活容灾:接入多家模型商,某家出现故障或限流时自动切换到其他家,调用方完全无感知
  • 零配置上手:新模型不需要手动配置路由,smart 策略自动扫描所有 Provider 并智能选择
  • 质量保证:健康状态和能力匹配是硬过滤条件,不健康或不匹配的 Provider 直接排除

决策三:能力池三层架构 + 发现统计机制

设计思维:将通用能力抽象为三层:

  • Tools:轻量级通用工具(get_time、calc、fetch_url、read_file、remember、recall、execute_code 等),网关内置执行,无需外部依赖
  • MCPs:Model Context Protocol 服务,通过 stdio 或 HTTP 连接外部工具服务(如文件系统 fs、代码编辑 serena、记忆 memory、思考 think 等),工具名支持 server__toolserver:toolserver/tool 三种格式
  • Skills:技能包,通过 git submodule 加载(如 demo-lab 服务器巡检、weekly-investment 投资周报等),支持技能清单注入和 skill-run 调用

三层能力都支持"发现—统计—择优录用"机制:网关记录调用方在请求中声明的外部能力,按命名约定自动分类(普通工具名→Tools、skill: 前缀→Skills、MCP 风格→MCPs),统计调用次数和使用方数量,在管理后台展示候选列表。管理员可以根据实际需求择优录用,录用时选择实现方式(仅记录标记 / HTTP 调用 / MCP 工具 / 内置实现)。

这个机制的核心价值在于发现和统计——让管理员看到调用方实际在使用什么能力,避免重复造轮子;晋升需要人工审核和配置,不是完全自动化的。对于遵循命名约定的能力识别准确率较高,第三方框架可能需要额外适配。

架构收益

  • 一次接入,全网共享:Tools/MCPs/Skills 只需在网关配置一次,所有通过网关的项目都可以使用
  • 能力可见性:自动发现和统计调用方声明的外部能力,让管理员看到实际使用情况,避免重复造轮子
  • 渐进式积累:通过"发现—统计—择优录用"机制,能力池可以持续积累调用方的最佳实践
  • 灵活的录用方式:录用时可以选择仅记录、HTTP 调用、MCP 工具、内置实现等多种方式,适配不同能力的实际情况
  • 解耦调用方与能力实现:调用方只需要声明工具名,不需要知道能力的具体实现方式(内置/MCP/HTTP),网关自动代理

决策四:Fastpath 快路径(可选加速)

设计思维:对于明确的算术、统计、单位换算、日期计算、进制转换、字数统计等确定性查询,网关可以直接在本地计算回答,不调用上游 LLM,从而节省额度并降低延迟。Fastpath 是可配置的加速选项,用户可以根据业务场景选择开启或关闭。

为了降低误匹配风险(比如文章写作请求中的章节编号被当成算术题),设计了三层防护机制:任务型关键词黑名单、全局长度限制、查询型关键词白名单。三层防护的设计原则是"宁漏勿错"——对于不确定的请求,保守地转发给 LLM 处理,宁可多消耗一点额度,也不返回错误的计算结果。

架构收益

  • 低延迟:命中时无需调用上游 LLM,本地直接计算,响应从秒级降至毫秒级
  • 节省调用:确定性查询直接本地执行,不消耗 LLM 调用额度
  • 安全可控:三层防护 + "宁漏勿错"原则,不确定的请求直接回退到 LLM
  • 可选开启:用户可以根据业务场景选择开启或关闭,对于开放式对话或内容生成场景建议谨慎使用

决策五:统一抽象层——多协议流式响应的解耦设计

面对 13 种上游协议各不相同的流式响应格式,采用统一抽象层的设计思维:把"上游格式解析"和"下游格式输出"彻底解耦。每个 Provider 适配器只需实现 StreamChunk 接口,把上游原始 chunk 转换为统一内部表示,再由统一 SSE 编码器负责输出。新增协议只需实现一个适配器文件(通常几百行),输出格式调整只需修改统一编码器,13 种协议自动生效。

决策六:容错识别——MCP 工具名多格式的优雅降级

MCP 生态中工具命名格式不统一(server__toolserver:toolserver/tool 等),采用容错识别设计:按优先级尝试多种分隔符,提取 server 名后校验过滤误匹配,识别成功的按 server 聚合,识别失败的优雅降级到普通 Tools。这样能力发现机制可以自动适配新出现的 MCP 框架命名格式,不需要为每个框架写专门的识别逻辑。

决策七:不可变数据——配置热加载的无锁并发安全

管理后台运行时修改配置需要立即生效,同时有大量请求正在使用旧配置。采用不可变数据 + 原子替换设计:配置对象加载后不可变,修改时创建全新配置对象,通过 atomic.Value 原子替换全局指针。读操作完全无锁,写操作只有原子开销,每个请求生命周期内使用同一份配置,不会出现半新半旧的不一致状态。

典型场景与调用示例

场景一:多项目统一接入,额度集中管理

多个 AI 应用(开发环境、内容生成、自动化服务等)不再各自维护 Provider 配置,而是统一通过 tsm-hub 调用 LLM。网关集中管理多家付费模型商的额度,为不同任务自动选择最合适的模型,优先选择近期成功率高的 Provider,某家模型商出现故障或限流时自动切换到其他家,调用方完全无感知。运维人员只需在管理后台维护 Provider 和 Key,不需要逐个项目修改配置。

场景二:能力复用平台,一次接入全网共享

Tools、MCPs、Skills 三层能力池一次接入,所有通过网关的项目都可以共享使用。例如:文件系统 MCP 服务只需在网关配置一次,所有项目都能通过 fs__read_file 等工具调用;服务器巡检技能包只需加载一次,所有项目都能通过 skill-run 调用。网关还会自动发现和统计调用方声明的外部能力,在管理后台展示候选列表,管理员可以根据实际需求择优录用,避免重复造轮子。

场景三:故障自动转移,服务高可用

当某个上游 Provider 出现故障(429 限流、500 错误、网络超时)时,网关自动 failover 到路由表中的下一个健康 Provider,调用方不需要做任何处理。健康检查机制定期探测各模型的可用性,出现问题自动标记为降级状态,路由时自动跳过。对于关键业务,还可以配置跨 Provider 的多活路由,确保即使某家服务商完全不可用,服务也能正常运行。

调用示例一:内置 Tools 自动执行(客户端不传 tools)

客户端发送普通对话请求,不传 tools 字段,网关自动启用内置 Agent,附加工具池并在服务端执行工具调用循环:

// 客户端请求
{
  "model": "chat",
  "messages": [{"role": "user", "content": "帮我算一下 123 * 456 等于多少,然后获取当前时间"}]
}

// 网关内部处理流程
// 1. 自动附加工具池(get_time、calc、fetch_url、read_file、remember 等)
// 2. 调用上游 LLM,模型决定调用 calc 工具
// 3. 网关在本地执行 calc(123 * 456) = 56088
// 4. 把工具结果返回给 LLM,模型决定调用 get_time 工具
// 5. 网关在本地执行 get_time() = "当前时间"
// 6. 把工具结果返回给 LLM,模型生成最终回答

整个过程中,算术计算和时间获取都由网关本地执行,不消耗额外的 LLM 调用,延迟从几秒降到几十毫秒。

调用示例二:MCP 工具调用(通过网关代理)

客户端通过网关调用已接入的 MCP 服务,工具名采用 server__tool 格式:

// 客户端请求
{
  "model": "chat",
  "messages": [{"role": "user", "content": "读取项目根目录下的 README.md 文件"}],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "fs__read_file",
        "description": "Read a file from the filesystem",
        "parameters": {"type": "object", "properties": {"path": {"type": "string"}}}
      }
    }
  ]
}

// 网关内部处理流程
// 1. 识别工具名 fs__read_file,提取 server=fs, tool=read_file
// 2. 查找已配置的 fs MCP 服务(stdio 传输,已常驻连接)
// 3. 通过 MCP 协议调用 fs 服务的 read_file 工具,参数 path="README.md"
// 4. MCP 服务执行文件读取,返回文件内容
// 5. 网关把工具结果返回给上游 LLM
// 6. LLM 基于文件内容生成最终回答

客户端不需要知道 MCP 服务的具体连接方式(stdio/HTTP),只需要按 server__tool 格式声明工具名,网关自动代理调用。

技术实现与源码导航

完整源码已开源在 GitHub,欢迎 Star 和提交 Issue。

在具体实现上,选择了 Go + Angular 的技术栈:

后端(Go)

  • 标准库 net/http 实现 HTTP 服务,无外部 Web 框架依赖
  • sqlite 存储 Provider 健康状态、记忆、审计日志
  • JSON 配置文件(data/config.json)存储 Provider、路由、Key 等配置
  • 插件式架构:Provider 适配器、Fastpath 匹配器、Agent 工具都可以独立扩展
  • 编译为单个二进制,部署简单

前端(Angular)

  • 管理后台覆盖 Provider 管理、路由配置、Key 签发、模型目录、额度查询、用量统计、可观测性、Tools/MCPs/Skills 管理、Sandbox/Memory 管理等全部功能
  • 组件按 ts/html/css/ 分目录组织,模板与逻辑分离
  • 响应式设计,支持桌面端使用

源码导航

文件/目录 说明
cmd/server/main.go 服务入口,加载配置、初始化各模块、启动 HTTP 服务
internal/proxy/proxy.go 代理核心,请求鉴权、路由选择、failover、用量记录
internal/proxy/adapter/ 上游协议适配器层,13 种协议,统一接口 + 流式转换
internal/router/router.go 路由选择算法,支持 smart / failover / weighted 三种策略
internal/store/ 配置存储与热加载,SQLite 记忆与健康状态持久化
internal/proxy/fastpath.go Fastpath 快路径匹配器(算术、统计、单位换算等)
internal/proxy/agent.go 网关内置 Agent,工具调用循环与多轮推理
internal/proxy/codegen.go Codegen 代码生成 fastpath
internal/api/ Admin API(Key 管理、能力管理、模型目录、路由配置等)
internal/skills/ Skills 技能包加载与注入(git submodule 管理)
internal/mcp/ MCP 服务连接与工具代理(stdio/HTTP 传输、工具调用转发)
internal/sandbox/ Docker 沙箱管理(容器生命周期、资源限制、安全隔离)
web/src/app/ Angular 前端,管理后台全部页面(按 ts/html/css 分目录组织)

部署与运维

Docker 容器化部署

tsm-hub 提供完整的 Docker 容器化部署方案,采用多阶段构建,镜像仅包含 Go 二进制和运行时依赖,体积小、启动快。

快速启动

make docker-up    # 自动构建前端 + 镜像,后台启动容器

启动后访问 http://localhost:9070 即可进入管理台。

Makefile 运维命令

命令 说明
make docker-build 构建 Docker 镜像(自动先构建前端)
make docker-up 构建并启动容器(后台运行,挂载 ./data)
make docker-down 停止并删除容器(保留 ./data 数据)
make docker-stop 停止容器(不删除,可恢复)
make docker-start 启动已停止的容器
make docker-restart 重启容器
make docker-logs 跟踪容器日志
make docker-status 查看容器状态 + 健康检查

数据持久化

容器通过卷挂载 ./data:/data 持久化所有数据,包括配置文件、用量日志、会话记忆、审计日志等。容器删除和重建不会丢失数据,只需保持 ./data 目录完整。

配置方式

支持四种配置方式,优先级从高到低:

  1. 命令行 flag:如 -addr :9070-admin-token xxx
  2. 系统环境变量:如 TSM_HUB_ADDR=:9070
  3. .env 文件:项目根目录的 .env 文件(docker compose 自动加载)
  4. config.json:挂载的 ./data/config.json 配置文件

智能路由策略可通过环境变量配置:

TSM_HUB_SMART_STRATEGY=stability_first  # cost_first / stability_first / task_aware / balanced
TSM_HUB_SMART_COST_WEIGHT=40
TSM_HUB_SMART_STABILITY_WEIGHT=100
TSM_HUB_SMART_LATENCY_WEIGHT=60

健康检查与高可用

  • 健康检查端点GET /healthz,返回所有 provider 健康状态、请求数、运行时间
  • docker compose healthcheck:每 30s 自动检查,异常时自动标记
  • 配置热加载config.json 变更后自动热重载(fsnotify),无需重启容器
  • 故障自动转移:某 provider 故障或限流时,自动 failover 到其他健康 provider

安全设计

  • 容器以非 root 用户运行,遵循最小权限原则
  • Admin Token 建议通过环境变量注入,不写入配置文件
  • 生产环境建议启用 TLS 或前置反向代理(Nginx / Caddy)
  • 所有管理操作自动记录审计日志,可追溯

tsm-hub 和普通的 LLM 代理(如 one-api、new-api)有什么区别?

tsm-hub 不仅做路由和鉴权,还内置了能力池(Tools/MCPs/Skills)、Fastpath 快路径、Codegen、Sandbox 沙箱、Memory 记忆等网关侧能力。调用方不需要自己实现工具调用循环、不需要自己管理技能包、不需要自己处理算术等确定性问题,网关全部搞定。同时支持 13 种上游协议适配器,不局限于 OpenAI 兼容协议。

多模型池是如何统一管理和路由的?

每个 Provider 配置自己的 API Key 和模型列表,网关定期探测各模型的健康状态和成功率。采用可配置的多维度智能调度策略(smart),支持 cost_first / stability_first / task_aware / balanced 四种模式,各维度权重可单独调整。对于没有显式路由表的模型,网关自动扫描所有支持该模型的 Provider,按配置的策略模式综合评分后智能选择最优上游。用户也可以自由配置显式路由表,为特定模型或路由别名定义一组 target 和优先级,选择 failover 或 weighted 等自定义策略。同时支持带 tools 的请求自动过滤不支持 tool_calls 的模型。配置方式支持 config.json、环境变量(TSM_HUB_SMART_*)或 .env 文件。

调用方如何使用网关的 Tools/MCPs/Skills 能力?外部能力如何发现和录用?

有两种使用方式:一是调用方不传 tools,网关自动启用内置 Agent,附加工具池并在服务端执行工具调用循环;二是调用方通过 skill-run 等工具显式调用技能。对于有自己 Agent 流水线的客户端,可以在 Key 配置中关闭网关 Agent,直接透传到上游模型。

网关会自动发现和统计调用方声明的外部能力,按命名约定分类(普通工具名→Tools、skill: 前缀→Skills、MCP 风格→MCPs),展示调用次数和使用方数量,管理员可以根据实际需求择优录用。录用时选择实现方式(仅记录标记 / HTTP 调用 / MCP 工具 / 内置实现),其中 MCP 工具可能需要手动配置连接参数。这个机制的核心价值在于能力的发现和统计,晋升需要人工审核和配置。

Fastpath 快路径会不会误匹配正常的对话请求?

Fastpath 快路径是可选的加速功能,适用于明确的算术、统计、单位换算等确定性查询。为了降低误匹配风险,设计了三层防护机制:任务型关键词黑名单、全局长度限制、查询型关键词白名单。三层防护的设计原则是”宁漏勿错”——对于不确定的请求,保守地转发给 LLM 处理。Fastpath 命中时延迟从几秒降到几毫秒,且不消耗 LLM 额度;用户可以根据业务场景选择开启或关闭。

新增一个上游 Provider 或能力需要做多少工作?tsm-hub 适合生产环境吗?

新增 Provider 方面,如果是 OpenAI 兼容协议,只需要在配置文件中添加 Provider 条目(name、base_url、api_key、models),无需改代码。如果是非 OpenAI 兼容协议(如 Gemini、Bedrock),需要实现一个 Provider 适配器,通常几百行代码即可。新增能力方面,外部 Tools/MCPs/Skills 可以通过发现机制自动录入,管理员择优录用即可。

生产环境方面,tsm-hub 目前已用于实际项目,并持续迭代,核心功能经过实际验证:自制 Key 鉴权与配额管理、多 Provider 智能路由与自动 failover、全链路用量统计与成本核算、TLS 传输加密与 CORS 安全控制、完整的审计日志与操作追溯。编译为单个二进制文件,部署和运维简单,适合中小团队快速搭建统一的 LLM 接入与能力平台。架构设计上预留了扩展空间,可根据业务增长逐步演进到多实例部署。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

商店 Web Chat Nsbp 关于 隐私政策

@ 2026 ESN
沪ICP备2024079226号-1   沪公网安备31010502007082号