拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

LLM、Tools、MCP、Skills 统一网关 tsm-hub 实战:架构设计与踩坑指南

LLM、Tools、MCP、Skills 统一网关 tsm-hub 实战:架构设计与踩坑指南

1. 为什么要把 LLM、Tools、MCP、Skills 塞进同一个网关

第一次看到 tsm-hub 这个项目名的时候,我脑子里冒出来的第一个念头是:又是一个"大一统"的抽象层。做后端和 AI 应用的人对"统一网关"这四个字应该都不陌生,API Gateway、服务网格、BFF 层,本质上都是在解决同一个问题——当系统里的组件越来越多、协议越来越杂、调用方越来越懒的时候,你需要一个中间人把脏活累活全接过去。

但 tsm-hub 要收拢的东西有点特殊:LLM、Tools、MCP、Skills。这四个词放在一起,其实代表了当前 AI 应用开发里四条完全不同的技术脉络。

LLM 是模型本身,是那个"会说话的大脑"。Tools 是模型能调用的外部函数,比如查天气、算数学、读数据库。MCP 是 Model Context Protocol,一套让模型和外部工具、数据源之间用标准方式对话的协议。Skills 则是更高层的封装,是把一组工具、提示词、执行逻辑打包成一个可复用的能力单元,比如"帮我做数学建模"或者"帮我写漫剧脚本"。

问题在于,这四样东西在传统架构里是各管各的。模型走一套 API,工具走另一套注册中心,MCP 服务端单独部署,Skills 又散落在各个项目的 prompt 目录里。你每接一个新模型,就要重写一遍工具调用逻辑;每加一个 MCP server,就要改一遍路由配置;每换一个 Skills 库,就要重新对齐参数格式。

tsm-hub 的核心价值就在这里:它把模型、工具、协议、技能四层抽象收敛到一个统一的入口。调用方只需要面对一个网关地址,至于背后是哪个模型、走的是原生 function call 还是 MCP 协议、加载的是哪套 Skills,全部由网关内部消化。

我实测下来的感受是,这种设计对两类人特别友好。一类是快速做原型的独立开发者,不想在基础设施上花时间,只想把模型和工具拼起来跑通业务。另一类是团队里的平台工程师,需要给多个业务线提供统一的 AI 能力出口,但又不想让每个业务线都去理解 MCP 和 Skills 的细节。

注意:统一网关不是银弹。它解决的是"接入复杂度"问题,不解决"模型能力"问题。如果你的场景只需要调一个模型做文本生成,硬上网关反而是过度设计。

2. tsm-hub 的四层抽象到底各自管什么

要理解 tsm-hub 的设计,得先把 LLM、Tools、MCP、Skills 这四层各自的职责边界划清楚。很多人第一次接触这些概念时容易混淆,尤其是 MCP 和 Tools,看起来都是"让模型调用外部能力",但它们的抽象层级完全不同。

2.1 LLM 层:模型接入与路由

LLM 层负责的是模型本身的接入。tsm-hub 在这一层做的事情包括:统一不同厂商的 API 格式、管理模型列表、处理鉴权、做请求路由和降级。

举个实际场景。你手上有三个模型来源:一个本地部署的开源模型、一个云端商用模型、一个专门做代码补全的小模型。如果没有网关,你的业务代码里会散落着三套不同的 SDK 调用逻辑,每套的请求体格式、返回结构、错误码都不一样。tsm-hub 的做法是在这一层做适配器模式,把不同来源的模型统一成一套内部接口。

路由策略是这一层的重点。我见过比较实用的几种策略:

策略类型适用场景实现要点
按任务类型路由代码任务走代码模型,对话走通用模型在请求里带 task_type 字段
按成本路由简单任务走便宜模型,复杂任务走贵模型需要预估 token 量或复杂度
按可用性降级主模型超时自动切备用模型设置超时阈值和重试次数
按上下文长度路由长文本走长窗口模型请求前统计 token 数

这一层最容易踩的坑是错误码不统一。不同厂商对"限流"的返回码不一样,有的是 429,有的是自定义错误码。网关必须把这些统一映射,否则上层业务没法做统一的异常处理。

2.2 Tools 层:函数注册与调用

Tools 层管的是模型可以调用的外部函数。这一层的核心是注册机制和参数校验。

一个工具在 tsm-hub 里的生命周期大概是这样的:先注册工具定义(名称、描述、参数 schema),然后模型在对话中决定调用哪个工具并生成参数,网关校验参数后执行实际函数,最后把结果回传给模型。

参数校验这一步特别关键。模型生成的参数经常不靠谱,比如该传数字的传了字符串,该传枚举值的传了个不存在的选项。如果不在网关层拦住,错误会一路传到业务函数里,排查起来非常痛苦。tsm-hub 在这一层用 JSON Schema 做校验,不通过的直接返回错误给模型让它重新生成。

我自己的经验是,工具描述写得好不好,直接决定模型调用准确率。描述里要明确说清楚:这个工具做什么、什么时候用、参数是什么含义、返回什么格式。我见过太多人把工具描述写成一句话,然后抱怨模型老是调错工具。

2.3 MCP 层:协议适配与连接管理

MCP 是这一层里最容易被误解的。很多人第一次听到 MCP,会以为它是某种硬件协议或者网络传输协议。其实 MCP 是 Model Context Protocol,是一套应用层协议,规定的是模型和外部上下文提供者之间怎么交换信息。

tsm-hub 在 MCP 层做的事情,本质上是协议转换。因为 MCP 有自己的消息格式和交互流程,而网关内部用的是统一的工具调用接口,所以需要一个适配层把 MCP 的请求翻译成内部格式,再把内部结果翻译回 MCP 格式。

这一层的连接管理是个技术难点。MCP server 可能是本地进程,也可能是远程服务,连接方式可能是 stdio,也可能是 HTTP 或 WebSocket。网关需要维护这些连接的生命周期,处理断线重连、超时、并发调用等问题。

提示:如果你在配置 MCP 连接时遇到握手失败,先检查两件事——协议版本是否匹配,以及 server 端是否真的在监听。我踩过好几次坑,最后发现是 server 启动脚本里的端口写错了。

2.4 Skills 层:能力封装与复用

Skills 层是最高层的抽象。一个 Skill 可以理解为一个"技能包",里面包含了一组工具、一段系统提示词、一套执行流程,甚至一些示例对话。

为什么需要 Skills 这一层?因为 Tools 和 MCP 解决的是"模型能做什么",而 Skills 解决的是"模型应该怎么做"。同样是调用搜索工具,做学术调研和做新闻摘要的调用方式、结果处理、输出格式完全不同。Skills 就是把这些领域知识固化下来,让模型不用每次从零开始理解任务。

tsm-hub 在 Skills 层的设计思路是声明式加载。你只需要在配置里声明要加载哪些 Skills,网关会自动把 Skill 里的工具注册到 Tools 层,把提示词注入到对话上下文,把执行流程编排好。

这一层最实用的特性是Skills 组合。比如你可以把"数学建模"Skill 和"数据可视化"Skill 组合起来,模型就能同时具备建模和画图的能力。组合的时候要注意工具命名冲突,两个 Skill 里如果有同名工具,需要做命名空间隔离。

3. 从零搭一个 tsm-hub 实例的完整路径

光讲概念没意思,我把自己搭 tsm-hub 的完整过程拆一遍。这套流程我在不同环境里跑过三次,每次都会遇到一些新问题,下面把关键步骤和踩坑点都列出来。

3.1 环境准备与依赖确认

第一步是确认运行环境。tsm-hub 本身是个服务,需要 Node.js 或 Python 运行时(取决于你选的实现版本),还需要能访问模型 API 的网络环境。

我建议在动手之前先列一个清单:

  • 运行时版本:Node.js 18+ 或 Python 3.10+
  • 包管理器:npm/pnpm 或 pip/uv
  • 模型 API 凭证:至少一个可用的模型来源
  • 存储:如果需要持久化配置和日志,准备一个 SQLite 或 PostgreSQL
  • 网络:确认能访问模型 API 和 MCP server 地址

这里有个容易忽略的点:时区和字符编码。我有一次在容器里跑,日志时间全是 UTC,排查问题时对不上业务时间。还有一次 Skills 里的中文提示词出现乱码,最后发现是环境变量里的 LANG 没设置。

3.2 配置文件的结构与关键字段

tsm-hub 的配置一般分几块:模型配置、工具配置、MCP 配置、Skills 配置、服务配置。我用一个简化版的结构说明:

server: port: 8080 log_level: info models: - name: default-chat provider: openai-compatible base_url: https://api.example.com/v1 api_key: ${MODEL_API_KEY} model: gpt-4o-mini timeout: 30s tools: - name: get_weather description: 查询指定城市的当前天气 parameters: type: object properties: city: type: string description: 城市名称 required: [city] handler: ./handlers/weather.js mcp: servers: - name: filesystem transport: stdio command: npx args: ["-y", "@modelcontextprotocol/server-filesystem", "/data"] skills: - name: math-modeling path: ./skills/math-modeling enabled: true

几个关键字段的说明:

provider字段决定用哪个适配器。如果是标准 OpenAI 兼容接口,用openai-compatible就行。如果是特殊厂商,可能需要自定义适配器。

timeout一定要设。我见过太多因为没设超时导致请求挂死的情况。建议根据模型响应速度设,一般 30 到 60 秒。

transport字段在 MCP 配置里很关键。stdio 适合本地进程,http 和 websocket 适合远程服务。选错了连不上。

3.3 启动与首次连通性验证

配置写完后,启动服务。启动日志里会打印加载了哪些模型、注册了哪些工具、连接了哪些 MCP server、启用了哪些 Skills。这一步一定要仔细看日志,很多配置错误在启动阶段就会暴露。

验证连通性我一般分三步:

  1. 先调一个最简单的对话接口,确认模型层通了
  2. 再调一个带工具调用的请求,确认 Tools 层通了
  3. 最后调一个需要 MCP 或 Skills 的复杂请求,确认全链路通了

第三步最容易出问题。我遇到过一次,模型层和工具层都正常,但一走到 MCP 就超时。排查了半天发现是 MCP server 的启动命令里路径写的是相对路径,而网关的工作目录和我想的不一样。

注意:首次验证时把日志级别调到 debug,能看到完整的请求和响应链路。确认没问题后再调回 info,否则日志量会很大。

3.4 接入第一个真实业务场景

跑通 demo 之后,下一步是接真实业务。我建议从一个具体的、边界清晰的任务开始,不要一上来就做通用助手。

比如"根据用户输入的城市名查询天气并生成出行建议"就是一个好场景。它涉及模型调用、工具调用、结果格式化,但逻辑不复杂,出问题容易定位。

接入过程中要重点关注错误处理。模型调用可能超时,工具执行可能抛异常,MCP 连接可能断开。这些错误在网关层怎么处理、怎么返回给调用方,需要提前设计好。我的做法是定义一套统一的错误码,上层业务根据错误码决定是重试、降级还是提示用户。

4. 那些文档里不会写的踩坑记录

这一节是我最想写的部分。官方文档和 README 通常只讲"怎么用",不讲"哪里会炸"。下面这些坑都是我实际踩过的,希望能帮你省点时间。

4.1 MCP 连接握手失败的排查链路

MCP 连接失败是最常见的问题,而且报错信息往往很模糊。我的排查链路是这样的:

先看网关日志里 MCP 相关的输出,确认是连接阶段失败还是握手阶段失败。连接阶段失败通常是地址或命令不对,握手阶段失败通常是协议版本或初始化参数不匹配。

如果是 stdio 传输,检查启动命令能不能在命令行里手动跑通。我有一次配的 MCP server 需要特定环境变量,网关启动时没带上,导致 server 启动就崩了。

如果是 HTTP 或 WebSocket 传输,先用 curl 或 websocket 客户端工具直接连一下,确认服务端是活的。这一步能排除掉一半的问题。

最后检查协议版本。MCP 协议在演进,不同版本的 server 和 client 可能不兼容。网关配置里如果有版本协商选项,确认两边对得上。

4.2 工具参数校验的边界情况

JSON Schema 校验看起来简单,实际用起来边界情况很多。

模型有时候会传null给一个非必填但类型是 string 的参数。严格校验会拒绝,但模型的本意可能是"不传这个参数"。这种情况我一般在校验前先做一层清洗,把null转成 undefined。

还有枚举值的问题。模型可能传一个语义相近但不在枚举列表里的值。比如枚举是["北京", "上海", "广州"],模型传了"北京市"。严格校验会失败,但用户意图是明确的。我的做法是在校验失败时,先尝试做一次模糊匹配,匹配不上再返回错误让模型重试。

数字类型也有坑。模型可能把数字传成字符串"25",或者传成浮点数25.0而 schema 要求 integer。这些都需要在校验层做兼容处理。

4.3 Skills 加载顺序与覆盖规则

Skills 加载顺序会影响最终行为,这一点很多人没注意到。

如果两个 Skill 都定义了同名工具,后加载的会覆盖先加载的。如果两个 Skill 都注入了系统提示词,提示词会拼接在一起,但拼接顺序会影响模型的理解。

我的建议是:显式声明加载顺序,不要依赖默认顺序。在配置里按优先级从低到高排列,高优先级的 Skill 放后面。同时给每个 Skill 的工具加命名空间前缀,避免冲突。

还有一个坑是 Skills 的依赖关系。有的 Skill 依赖另一个 Skill 提供的工具,如果加载顺序不对,依赖的工具还没注册,Skill 初始化就会失败。这种情况需要在配置里声明依赖,让网关按依赖顺序加载。

4.4 高并发下的连接池与限流

单机跑 demo 没问题,一上并发就原形毕露。

MCP 连接是长连接,如果每个请求都新建连接,很快就会把 server 端打满。网关需要维护连接池,复用连接。连接池的大小要根据 server 端的承载能力设置,太小会排队,太大会把 server 压垮。

模型 API 一般都有速率限制。网关需要做限流,超过限制的请求要么排队要么降级。我一般用令牌桶算法,桶的大小根据 API 的配额设置。

还有一个容易忽略的点是超时传递。如果调用方设了 10 秒超时,网关内部调模型设了 30 秒,那调用方早就超时了网关还在等模型。正确的做法是网关的超时时间要小于调用方的超时时间,留出处理余量。

5. 把 tsm-hub 用出花来的几个进阶思路

基础功能跑通之后,可以玩一些进阶的。这些思路有的是我自己实践过的,有的是看到社区里别人分享的,都挺有意思。

5.1 用 Skills 做领域知识的固化

Skills 最大的价值不是封装工具,而是固化领域知识。

举个例子,做医疗问答场景。通用模型对医学术语的理解可能不够准确,但如果你把一套医学知识库的检索工具、一套医学术语的标准化处理流程、一套回答格式规范打包成一个 Skill,模型的表现会好很多。

再比如做法律文书生成。不同文书的格式要求、引用规范、措辞习惯都不一样。把这些做成 Skills,模型就不用每次从零学习。

我自己的做法是,每做一个新场景,先花时间把领域知识整理成 Skill。前期投入大,但后面复用的时候非常省事。

5.2 多模型协同的路由策略

tsm-hub 支持多模型,这给了做协同路由的空间。

一种思路是大小模型配合。简单任务走小模型,复杂任务走大模型。判断任务复杂度可以用规则,也可以用一个小模型做分类。

另一种思路是多模型投票。同一个问题发给多个模型,取多数一致的结果。适合对准确性要求高的场景,但成本会翻倍。

还有一种是模型接力。第一个模型做初步处理,第二个模型做精修。比如先让模型生成大纲,再让另一个模型根据大纲写正文。

这些策略在 tsm-hub 里都可以通过路由配置实现,不需要改业务代码。

5.3 可观测性建设:日志、指标、追踪

网关是流量的必经之路,天然适合做可观测性。

日志方面,我建议记录每个请求的完整链路:调了哪个模型、用了哪些工具、走了哪些 MCP、加载了哪些 Skills、各阶段耗时多少。这些信息在排查问题时非常有用。

指标方面,关注几个核心数据:请求量、成功率、平均延迟、各模型的调用分布、各工具的调用频率。这些指标能帮你发现瓶颈和异常。

追踪方面,如果团队有分布式追踪系统,把网关的调用链路接进去。一个请求从进入到返回,中间经过了哪些环节,一目了然。

提示:日志里不要记录完整的请求和响应内容,尤其是涉及用户隐私的场景。记录摘要和元数据就够了。

5.4 安全边界:鉴权、审计、内容过滤

网关作为统一入口,也是做安全控制的好地方。

鉴权方面,可以在网关层做 API Key 校验、JWT 验证、权限控制。不同调用方给不同的权限,能访问哪些模型、哪些工具、哪些 Skills,都在网关层控制。

审计方面,记录谁在什么时候调了什么,用于事后追溯。合规要求高的场景,审计日志是必须的。

内容过滤方面,可以在请求进入模型之前和响应返回调用方之前做过滤。输入过滤防止恶意提示词注入,输出过滤防止敏感内容泄露。

这些安全能力如果散落在各个业务里,维护成本很高。收敛到网关层,统一管理,省事很多。

6. 关于统一网关这件事我的真实看法

写到这里,我想说点掏心窝的话。

统一网关这个思路,在工程上是对的。它确实能降低接入复杂度,提高复用率,让业务方专注于业务逻辑。tsm-hub 把 LLM、Tools、MCP、Skills 四层收拢到一个入口,设计上是清晰的。

但网关不是没有代价的。它引入了一个额外的抽象层,意味着多一跳网络开销,多一个故障点,多一层需要维护的配置。如果团队规模小、场景简单,硬上网关可能是负优化。

我的判断标准是:当你发现同样的接入逻辑在三个以上的地方重复出现时,就该考虑抽网关层了。如果只有一个业务在用,直接在业务里调模型和工具反而更简单。

另外,网关的抽象要适度。我见过一些网关设计得过于通用,配置项多到没人能看懂,最后大家还是绕过网关直接调底层。好的网关应该是"默认配置就能用,高级配置才需要看文档"。

tsm-hub 目前给我的感觉是抽象层级把握得还不错,四层各司其职,没有过度设计。但具体到每个团队,还是要根据自己的场景做取舍。工具是死的,人是活的,适合自己的才是最好的。

最后分享一个小技巧:搭网关的时候,先别急着接所有模型和工具。先用一个模型、一个工具、一个 Skill 把全链路跑通,确认架构没问题,再逐步扩展。我见过太多人一上来就配一大堆,结果出了问题根本不知道是哪一层的事。从最小可用开始,逐步迭代,这个原则在网关搭建上同样适用。

返回列表