Engineering

Sidecar 集群与 RLM:先收集证据,再作答

一个会循环调用搜索工具、直到真正拿到代码的检索模型,以及一个告诉服务器哪些硬件处于唤醒状态的集群代理。两个部件,一个答案。

Alper Üzmezler· Sep 17, 2026 · 11 分钟阅读

检索增强系统里有一种失败模式,没人会放进演示里。你提出一个问题,系统把它嵌入向量、取出得分最高的十个片段、塞进提示词,然后模型基于恰好得分最高的那十个片段写出一段流畅的回答。

如果答案需要第十一个片段,你根本不会知道。无论如何,你都会得到同样自信的一段文字。

解决办法不是更好的嵌入模型,而是让某个东西再看一次——这正是 RLM 所做的事。

两个组件,界限分明

Sidecar 是一个集群代理。它运行在算力所在之处,汇报自己拥有什么,并提供推理服务。Fantom MCP Server 注册为 sidecar 所汇报的 master 之一。

RLM 是一个检索语言模型——一个专职模型,它的任务不是撰写文字,而是收集。它反复调用代码搜索工具,直到拿到回答所需的确切代码,然后交回它收集到的证据以及一份简短草稿。再由独立的综合步骤把这些内容转化为带引用的最终答案。

这种拆分很重要。收集模型针对工具调用做优化,可以又小又快。综合模型则针对写作做优化。让一个模型同时干这两件事,得到的要么是调研糟糕的答案,要么是文笔糟糕的答案。

集群如何汇报

发起连接的是 sidecar,而不是服务器——当算力位于那些时开时关的工作站上时,这才是正确的方向。

Fantom MCP 充当 master 注册表 + 快照 原子写入,崩溃安全 Sidecar · GPU 主机 code-embedding · embedding 本地模型,真实 VRAM Sidecar · RLM 主机 rlm · vLLM,兼容 OpenAI 上下文窗口从 /v1/models 读取 虚拟容器 <PCName>-OR-<Role> 提供服务能力 · 无 GPU,无 VRAM register · heartbeat · result registered · command · config

通信协议刻意做得很小。sidecar 打开一个 WebSocket,发送 register,带上自己的地址、主机名和容器列表。之后它发送 heartbeat 帧,携带容器信息、活跃请求数和一个状态数据块。master 回复 registered,并可以推回 commandconfig 帧。如果 WebSocket 不可用,同样的交换也能通过用于心跳、轮询和结果的 HTTP 端点完成。

Fantom MCP 目前并不通过这个通道下发工作指令——它实际的推理调用走 HTTP。它确实做的是从每一次心跳中挖掘能力数据,这样路由层始终知道此刻哪些角色真正在提供服务。

有一个细节值得点名,因为这是用惨痛代价换来的:那份注册表在每一次心跳时都会被重写,读-改-写,写入一个同时保存搜索设置的配置文件。早期版本在读取被截断时会返回一个空对象,于是一次损坏的读取就可能只持久化 sidecar 列表,抹掉其他所有内容——连备份也一起。现在读取会从同级备份中恢复,写入是原子的。集群代码触碰配置的频率远超任何人的预期。

收集循环

下面是问题到来时真正发生的事。

规划 我需要什么? semanticCodeSearch 工具调用 getCallers 工具调用 searchFantomCode 工具调用 并行执行 合并证据 去重 · 预算 带引用的答案 综合模型 还不够——再来一轮 循环本身就是产品

模型先制定计划,发出工具调用,结果以受限并发的方式收集回来。证据块会被拆分、合并,并按上下文窗口做预算——这个窗口是从服务端点动态读取的,而不是写死的,因为同一个循环会跑在限制各不相同的不同模型上。

如果拿回来的东西不够,它就再来一轮。这就是它与一次性检索的全部区别:系统被允许意识到自己掌握的还不够。

最近的一次优化很好地说明了真正的成本在哪里。与其在每一次扩展步骤中重新做嵌入,不如把查询只嵌入一次,然后并行地向相邻片段扩展搜索范围,并在该扩展轮次中跳过重排序器。“再看一次”中昂贵的部分从来不是“看”——而是对同一个问题的冗余重复编码。

失败是一等路径

这条链路上的每一个端点都属于某台可能正在休眠、正在重启或正忙碌的机器。因此 RLM 路径上的规则直截了当:任何端点错误都返回 null,调用方随即回退。它永远不抛异常。

听上去没什么抱负。但在实践中,正是这一点让该功能在真实集群上可用——在那里,“RLM 主机离线”应该让答案降级,而不是在控制工程师的编辑器里冒出一段堆栈跟踪。默认的回退模式是仅本地,而收集步骤是对检索的增强,而非检索的依赖项。

没有硬件的服务能力

最后一块把这一切与云连接起来。sidecar 可以把某个角色路由到 OpenRouter 而不是本地模型,Fantom MCP 把每一组这样的配对视作一个虚拟容器——一个独立的逻辑提供方,按 <PCName>-OR-<Role> 模式命名,代表真实的服务能力,背后却没有 GPU、没有 VRAM。

这就是嵌入如何同时扇出到本地 GPU 与云端的方式,也是在机器都忙于其他工作的集群上,重排序如何还能有一个后端的原因。

这种安排有两个特性值得明说:

  • 发现走的是 HTTP,而不是心跳。 心跳携带的是一份精简快照,其中不包含虚拟容器数据。若有系统试图从心跳里挖掘这些数据,它会永远悄无声息地一无所获,却看起来像是在正常工作。
  • API 密钥从不接触 Fantom MCP。 密钥由 sidecar 持有。Fantom 只会指明一个提供方和一个模型。发现路径中没有任何环节会读取、存储、记录或传输密钥。

至于这些提供方随后如何被选择、门控和预算,是下一篇文章的主题。


Fantom MCP Server 以源码可见方式发布于 github.com/Project-SandStar/FantomMcpServer