内容提要
本文介绍如何通过优化提示缓存来降低LLM API的token成本。提示缓存可复用已计算的KV缓存,避免重复预填充,从而减少费用和延迟。优化要点包括:保持系统提示(工具和技能定义)不变、会话中不修改工具或模型、利用会话压缩控制历史长度,并注意缓存失效和压缩成本。
延伸解读
缓存失效的代价
提示缓存的关键在于前缀的稳定性。一旦系统提示、工具定义或技能描述中的任何字符发生变化,从该位置起的所有缓存都会失效,导致后续请求需要重新进行预填充,增加成本和延迟。因此,在会话开始前确定工具和技能,并在会话中保持模型和配置不变,是优化缓存命中率的核心原则。
会话压缩的权衡
会话压缩虽然能控制上下文长度,但并非没有代价。压缩会生成摘要,使原本的缓存失效,并在下一轮需要重新预填充。如果压缩过于频繁,可能反而增加计算量和费用。此外,压缩是有损的,可能丢失关键信息(如错误代码),影响模型性能。建议在压缩时提供明确指令,引导模型保留重要内容。
工具数量与性能
工具定义在系统提示中占据大量token,且工具数量过多会影响模型性能。文章提到,VS Code默认包含50多个工具,而Pi仅4个,后者在本地运行时预填充计算更轻。因此,在会话开始时精简工具列表,不仅有助于缓存优化,还能提升模型在代理工作流中的表现。
Q&A
什么是提示缓存?它如何降低LLM API的token成本?
提示缓存是LLM API的一种机制,它缓存了请求前缀(如系统提示、工具定义、会话历史等)的KV缓存。当后续请求的前缀与缓存内容匹配时,可以直接复用KV缓存,跳过预填充阶段,从而减少计算量和延迟,降低token成本。
在LLM推理中,预填充和生成(解码)阶段有什么区别?为什么输入token比输出token便宜?
预填充阶段计算KV缓存,是计算密集且高度并行的;生成阶段是内存密集且串行的,因为每个token都需要处理整个模型权重和不断增长的KV缓存。因此,输出token的生成更耗时,API定价也更高(通常是输入的3-10倍)。
在代理工作流中,如何优化提示缓存以降低成本?
优化提示缓存的关键是保持会话前缀的稳定性:在会话开始前确定工具和技能,会话中不要修改工具、技能或模型配置,避免缓存失效。同时,利用会话压缩控制历史长度,但要注意压缩成本。
为什么在会话中修改工具定义会导致缓存失效?
因为提示缓存是基于前缀的,如果修改了工具定义(位于前缀中),那么从该位置开始的所有后续内容都需要重新计算KV缓存,导致缓存未命中,增加成本和延迟。
会话历史长度对LLM推理性能有什么影响?如何应对?
会话历史越长,KV缓存越大,预填充时间呈二次方增长(O(N²)),生成速度线性下降(O(L))。应对方法包括:在不需要历史时开启新会话,或使用会话压缩(手动或自动)将旧对话总结为摘要,但压缩本身有成本和信息损失。
什么是会话压缩?它有什么优缺点?
会话压缩是将旧对话总结为摘要,以减少上下文长度。优点是可以降低KV缓存大小,提高生成速度;缺点是压缩有计算成本(可能抵消缓存优势),且是损失性的,可能丢失关键信息(如错误代码),影响LLM性能。
为什么在会话中切换模型或调整思考努力会导致缓存失效?
因为模型配置(如模型版本、思考努力)是提示前缀的一部分,改变它们会改变前缀内容,导致缓存失效,需要重新计算KV缓存。
如何选择工具和技能以优化提示缓存?
在会话开始前选择必要的工具,避免暴露过多工具(超过30-50个可能降低模型性能)。技能应放在仓库本地(如.agent/skills)以限制数量,并避免在会话中修改工具或技能。