AI News HubLIVE
站内改写3 分钟阅读

每一个AI助手功能都是一个缓存失效面

本文作者李亚飞,OpenClacky(一个用Ruby编写的开源AI助手)的创始人,分享了在构建具备技能、记忆、子助手、浏览器自动化、动态模型切换和长时间运行的会话等功能的AI助手时,遇到的缓存问题。经过三代架构演进,他们总结出七个工程决策,使缓存命中率达到90%以上。文章详细介绍了前两代架构(RAG和多智能体协调)的失败原因,以及第三代架构中的三个关键决策:双缓存标记、冻结系统提示和单一元工具。

来源Hacker News AI作者: gemHunter

作者李亚飞是OpenClacky(一个用Ruby编写的开源AI助手)的创始人。他们希望构建一个具备技能、记忆、子助手、浏览器自动化、动态模型切换和长时间运行会话等功能的AI助手,却发现每个功能都以不同方式使提示缓存变得更糟。真正的架构问题不是如何调用LLM、添加另一个工具或协调更多智能体,而是在产品不断变化的同时保持缓存前缀稳定。每个AI助手功能都是一个缓存失效面:技能加载新的系统上下文,对等智能体工作流分叉前缀,浏览器自动化添加易变的工具输出,压缩重写历史,模型切换可能碎片化缓存命名空间。如果正在构建一个强大的助手,而缓存命中率远低于预期,这很可能就是原因。

经过两年和三代架构(前两代失败)的演进,他们得出了七个工程决策,能够在不牺牲功能的情况下,在实际任务中达到90%以上的缓存命中率。全文详细介绍了哪些地方出了问题、尝试过的方法以及真正有效的方案。

第一代:RAG一切(2024年初至2025年初)。他们构建了一个教科书式的RAG系统,将用户的代码库、文档和对话历史嵌入向量存储中。每次查询都经过混合检索、重排序和查询重写。听起来合理,但实际上成本不断攀升,数据始终过时。代码库更新需要重新嵌入,实时同步不可靠,向量存储落后于实际代码。他们在为越来越错误的索引支付越来越高的费用。90%的召回率不够,因为错误在多步骤中快速累积。据估计,97%的召回率可能是助手产生净收益的最低要求。此外,向量数据库增加了另一个可能崩溃或引入延迟的组件。对于在本地仓库上工作的编码助手,他们彻底放弃了RAG,不再使用嵌入、向量存储或检索流水线,而是让助手直接读取文件或使用grep搜索。

第二代:多智能体协调(2025年中)。他们采用SWEBench排行榜上的方案:规划者、编码者、审查者和测试者智能体通过消息总线协调,每个角色有特定的提示词。SWEBench得分不错,但产品很糟糕。每个智能体交接都是缓存缺失,子智能体有自己的系统提示和缓存命名空间。上下文传递需要序列化状态,每次交接都清空接收智能体的缓存前缀。一个智能体4分钟完成的任务,四个智能体需要14分钟,成本提高6倍,调试是噩梦。他们得出结论:单一边界模型已经是通用型,划分智能体工作不是分工,而是倍增开销。角色的多智能体协调被放弃,改为一个主智能体、一个对话、一个缓存命名空间,子智能体仅作为通过单一稳定工具调用的独立技能执行上下文。

第三代:七个决策。第三代从一个问题开始:如果我们围绕单个智能体的缓存命中率优化一切会怎样?不是作为成本技巧,而是作为架构原则。高缓存命中意味着模型看到一致的上下文、响应更快、成本更低。以下是前三个决策:

决策1:历史增长破坏前缀匹配 → 双缓存标记。提示缓存通过前缀匹配工作,但历史单调增长、工具调用重试和中途模型切换都会打破单标记缓存。他们使用双标记:每轮标记两个连续消息,形成滚动双缓冲。这样,即使在工具调用重试时,第二个标记通常也能幸存。标记选择逻辑硬性跳过系统注入的消息(如session context块),因为它们不会在下一轮以相同形式存在。

决策2:动态会话状态破坏系统提示 → 冻结系统提示。系统提示在会话开始时构建一次,然后字节冻结。任何动态信息(当前日期、工作目录、模型ID、新技能、用户偏好)都不能放在系统提示中,而是作为带有系统注入标记的用户消息注入历史。这样,即使这些信息变化,也不会使所有后续缓存失效。注入时机至关重要:必须在系统提示构建之后进行,否则会导致跳过系统提示构建。

决策3:技能和子助手膨胀历史 → 单一元工具。invoke_skill是16个工具中工作最多的一个,它从可搜索的技能工作区读取技能文件并填充工具定义。关键设计是:技能描述不是预先填充在工具定义中,而是在调用时从SKILL.md读取。这保持了缓存前缀的稳定,因为工具定义不会因新技能安装而变化。技能名称在会话开始时渲染到系统提示中,然后冻结,因此新技能只在下一次会话中自动发现,但用户明确请求时仍可通过invoke_skill执行。

文章到此中断,但作者承诺提供实现每个决策的代码链接。