为什么我们要从 Cloudflare Durable Objects 迁移
Wire 是用于 AI 代理的上下文容器:处理知识(条目、嵌入、知识和来源图)的隔离存储,通过 MCP 进行查询。从第一天起,每个容器都是 Cloudflare Durable Object。这种情况正在改变。我们从头开始重建了容器运行时,并在相同数据(相同容器、相同问题、相同评估者)上与旧的运行时进行了基准测试,首批工作区已经迁移到我们自己构建的数据平面。这是基准测试背后的故事。这不是一篇 “我们离开 Cloudflare” 的文章。我爱 Cloudflare,而 Wire 会尽可能留在 Cloudflare 上:API、前端、控制平面以及所有处理仍然运行在 Workers 上。Durable Objects 对于成千上万的小型、多数处于闲置状态的有状态单元非常合适,而我还没有见过任何东西能更快地构建。我们离开的原因是四个结构性限制,而不是可靠性。1. 向量索引位于对象之外。检索是容器最重要的功能,而嵌入存储在 Vectorize 这个独立服务中。这是对热点路径的网络跳转,以及一个可以漂移的状态的第二个副本。DO SQLite 无法加载扩展,因此索引永远无法进入内部。2. 我们希望计算靠近数据。检索是一个多阶段的管道:混合候选生成、融合、查询扩展和广泛重排名。在 Durable Objects 上,只有一小部分可以在数据所在位置运行;其余部分被导出到对象周围的服务。代理在工具循环中调用容器,每次跳转的变异都落在关键路径上。位置提示在创建时存在,但对象之后永远不会移动,因此从伦敦创建的容器将永远为弗吉尼亚的代理舰队服务。并且您无法为一个租户购买专用容量。我们希望位置跟随调用者,并将隔离作为产品层级:付费工作区拥有自己的进程和机器。4. 您无法自托管 Durable Object。受监管的团队不断要求在他们控制的基础设施上运行容器。只能在 Cloudflare 上存在的运行时不行。我们构建的东西。每个组织在 Fly Machines 上获得一个主机进程(Bun)来处理其所有容器。一个容器是一个 SQLite 文件,通过 sqlite-vec 嵌入向量索引,因此候选检索在进程内部运行;模型调用、查询嵌入和重排名仍然外发到推理。快照被发送到对象存储,因此容器在任何地方都能逐字重建。每个区域的路由器将容器放置在调用者附近,控制平面通过签名请求与数据平面通信,绝不会接触容器内容。温暖的工具调用大约保持0.3秒稳定,而之前波动到2秒以上的平均约为0.4秒。一个闲置的容器从头到尾唤醒需要1.4秒,而之前为3.7秒。为了准确说明最后一个数字:它从未是“Durable Object 冷启动”,隔离在毫秒内唤醒。3.7秒是我们自己的堆栈重组。表面上没有改变。相同的容器 URL,相同的五个 MCP 工具,相同的 REST API,相同的响应形状。代理继续调用相同的地址;对迁移容器的请求只是由新的运行时回答。重新购买耐用性。Durable Objects 无条件提供耐用性和单写者一致性,离开意味着要重新购买它们。Cloudflare 在确认每个 DO 存储写入之前进行复制。我们第一次的尝试仅是“在下一个检查点处耐用”,负载下杀死机器的浸泡测试准确显示了这意味着什么:一小部分确认的写入,消失了。真正的修复是持续的 WAL 传输。一个写入在其 WAL 帧进入对象存储之前不会确认;组提交将其保持在大约100毫秒,而死机器不能带走确认的写入。如果您不需要上述四件事,请继续使用该平台。对数字的诚实解读。检索增益(recall@5 从 78.1% 到 89.1%)并非全是架构;我们还迁移到了一种更新的嵌入模型。架构所做的是让昂贵的部分便宜:进程内检索使您能够过度获取和广泛重排名,而每个容器索引足够小以进行精确的最近邻搜索。完整的前后对比表和方法在基准写作中。现状新运行时处于测试阶段:我们的预览环境加上选择性生产工作区,现在,随着我们的耐用性触发器保持绿灯,全面生产迁移随之进行。完成切换后,我们计划开源容器运行时。我们应该发布我们实际运行的代码。
本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡