LLM Prompt Caching Versus Semantic Caching

TL;DR · AI 摘要
LLM Prompt Caching Versus Semantic Caching ByteByteGo Oct 21, 2026 Add AuthKit to your app in one command Sponsored Your...
核心要点
- 主题聚焦:LLM Prompt Caching Versus Semantic Caching
- 来源:ByteByteGo Newsletter,建议结合原文判断细节。
- AI 分析暂不可用,本条为保底评分与摘要。
LLM 提示缓存与语义缓存
ByteByteGo
2026 年 10 月 21 日
通过一条命令将 AuthKit 添加到你的应用中(赞助)
你的应用需要认证功能。通常这意味着安装 SDK、设置回调路由、配置中间件并调整环境配置。或者你也可以运行一条命令:npx workos@latest install。
WorkOS AI 安装器会检测你支持的框架,并将 AuthKit 适配到现有项目中。它会安装 SDK、创建认证路由并设置环境变量,默认启用安装后验证。
查看生成的代码,测试登录流程,然后继续构建你的产品。
尝试使用 AuthKit 安装器
缓存是系统设计中非常重要的一个方面,尤其是对于大规模系统。你可以使用缓存来存储一些计算成本高昂的数据,以便后续重复使用而无需付出相同的代价。例如,一个网站可能会缓存数据库查询的结果,而不是每次有人打开页面时都执行该查询。
大型语言模型同样适用这一原则。与普通系统一样,LLM 应用中的缓存也意味着存储先前请求中计算出的内容,以便后续重复使用。这有助于降低处理成本和响应时间,特别是当请求包含相同指令、文档或问题时。
然而,在 LLM 中我们有两种缓存方式:提示缓存和语义缓存。两者都旨在减少重复工作,但它们在请求的不同阶段起作用,遵循的规则也不同。
在本文中,我们将详细探讨 LLM 缓存的工作原理。你将学到以下内容:
- 为什么 LLM 请求会产生费用
- 什么是提示缓存
- 在提示缓存中如何放置共享内容
- 什么是语义缓存
- 语义缓存的难点
- 仅检查问题并不足够
- 何时使缓存失效
- 提示缓存和语义缓存如何协同工作
免责声明:本文基于来自多个来源的公开信息。文末有参考文献。如果你发现任何不准确之处,请在评论区指出。
为什么 LLM 请求会产生费用
当你向 LLM 发送一些文本时,LLM 会处理该文本并生成响应。在处理过程中,文本会被分割成标记(token)。每个标记是文本的一个小片段。一个标记可以是一个词、词的一部分或标点符号。
这些标记直接影响成本。对于典型的文本生成 API,成本有两个主要组成部分:
- 作为输入提供的标记
- 作为输出生成的标记
输出标记通常成本更高,原因显而易见。然而,输入标记也可能因数量庞大而产生高额费用。输入内容可能包含的不仅仅是用户的最新问题。例如,假设你有一个客户支持应用。除了当前问题外,该应用还可能发送一堆指令,告诉模型应该如何行为。它还可能发送良好回答的示例、相关产品文档、之前的对话消息。换句话说,一个 10 个词的问题可能属于由数千个输入标记组成请求的一部分。
假设你有另一个应用程序,每次用户请求时都会附带一份长长的使用手册。这份手册就像一本百科全书,包含了用户可能需要查询的所有信息。一个用户可能询问安装步骤,另一个用户可能询问故障排除方法,第三个用户可能询问账户设置。虽然他们的提问各不相同,但答案都包含在每次请求中附带的那本长手册里。
还存在另一种重复现象。可能有数百名用户询问如何更改头像,但每个用户可能会用略有不同的措辞表达这个问题。在这种情况下,模型可能会反复生成相似的答案。
你可能已经注意到,我们有两次机会减少这种重复工作并降低成本:
- 如果应用程序能够复用已经处理过的输入信息会怎样?例如产品手册。
- 如果应用程序能够复用之前生成的合适答案会怎样?例如反复出现的相似问题。
提示缓存用于利用第一个机会,语义缓存用于第二个机会。让我们详细探讨这两种机制。
提示缓存:复用模型的输入处理
要使缓存有效,你需要制定一个规则来判断某物是否适合复用。这个规则是构建高效缓存系统最关键的部分。
对于提示缓存,规则是匹配模型输入的开头部分。
典型的文本生成式变压器模型分为两个阶段工作:
- 首先处理输入。这个阶段称为预填充(prefill)。
- 其次生成新令牌。这个阶段称为解码(decoding)。
在处理输入时,模型会将文本转换为数字。这种数字表示帮助模型利用之前读取的信息生成后续输出令牌。其中一些表示被称为键(keys)和值(values),或称KV状态(KV states)。
键帮助注意力机制确定哪些早期信息是有用的,值是这些信息的实际表示。KV缓存存储这些中间结果以便复用。所有这些都属于大语言模型(LLM)常规文本生成流程的一部分。
提示缓存利用了这种复用机制。它将这种机制扩展到所有具有相同开头的兼容输入请求中。假设你有以下两个请求:
请求A:支持说明 + 产品手册 + "如何配置安装?" 请求B:支持说明 + 产品手册 + "如何启用诊断日志?"
可以看到,支持说明和产品手册在两个请求中是共享的,称为共享前缀。实际问题属于每次输入请求中变化的后缀部分。
当模型处理完请求A后,系统可以存储共享前缀的KV状态。当请求B到达时,模型可以复用这些相同的KV状态来处理新问题并生成答案。我们已经复用了常见上下文的中间计算过程,无需重新计算,无需重新处理。
AI编写了代码。谁来支付CI费用?(赞助内容)
更多由AI编写的代码意味着需要更多CI运行时间。在默认运行器上,这些时间既慢又昂贵。
WarpBuild 一举两得:
- 快速程度提升一倍,工程师等待时间更少
- 成本降低一半,随着使用量增加账单反而减少
- 仅为你实际使用的分钟数付费
Teams at Braintrust, Raycast, OpenRouter, Comcast and Jane Street trust WarpBuild with their GitHub Actions.
The switch is one runs-on change. Use code START50 for $50 in free credits.
Cut your CI bill
在提示缓存中放置共享内容的位置
要使提示缓存生效,需要将共享内容放在请求的开头位置,也就是前缀位置。"前缀"这个词在这里非常重要,因为一个标记的内部表示依赖于输入中它前面的信息。
在典型的因果语言模型中,提示中较早出现的标记无法预知请求后续可能出现的问题。这就是为什么即使最终用户的问题完全不同,模型仍能复用开头部分的共享内容。
然而,当你在手册前放置不同的问题时,会改变手册的处理方式。问题会影响手册中文本的表示形式。手册的文本内容本身是相同的,但处理后的版本却完全不同。
这就是为什么我们必须在请求细节之前放置固定且稳定的指令或任何共享参考材料。即使你在输入开头放置看似无关紧要的时间戳或随机请求ID,也可能阻止模型复用大量共享内容。
需要明确的是,即使是指令也需要"完全"一致。即使你有两个可能含义相同的指令,也不能在提示缓存中互换使用。措辞不能有任何变化。文档顺序不能改变。请求设置也不能调整。
提示缓存的成本节约
仅仅缓存共享前缀并不能使成本降为零。大多数LLM提供商通常会以折扣费率收费。同时,输出标记的费用保持不变,因为模型仍然需要生成新的回答。
以Anthropic为例,其标准提示缓存定价采用普通输入速率的十分之一作为缓存读取费率。某些特定模型存在例外情况。其标准5分钟缓存写入费用为普通输入速率的1.25倍,而1小时写入费用为普通输入速率的2倍。这些是受影响标记的总费率,而不是在普通输入成本基础上的额外收费。
举个例子,如果正常处理前缀的成本是1美元,那么这个五分钟定价方案会使初始写入成本变为1.25美元,后续读取成本变为0.10美元。因此,一次写入加一次读取的总成本为1.35美元,而不是原本的2美元。读取次数越多,节省的成本就越大。但如果缓存的前缀从未被复用,就无法获得任何收益。
LLM提供商和模型规则还决定了最低合格长度、过期时间和缓存写入定价。即使我们重复提示,如果缓存记录已过期或不可用,也无法保证缓存命中。
总结来说,提示缓存主要减少输入处理工作,可以缩短生成响应前的等待时间。但无法消除生成长答案所需的工作量。
语义缓存:复用之前的回答
语义缓存通常是围绕LLM的应用程序的一部分。它也可以是应用程序在向LLM请求答案前调用的独立服务。考虑以下两个可能向LLM提出的问题示例:
"暗黑模式的设置在哪里?" "如何将应用切换到暗黑主题?"
如你所见,如果应用程序功能没有发生重大变化,相同的答案可能可以同时满足两个问题。但简单的文本比较会将它们视为两个独立的问题并给出不同的答案。然而,语义比较可以识别出它们本质上是用略有不同的措辞提出的相同问题。
要实现语义缓存,你需要一个嵌入模型。这种模型将文本转换为称为向量的数字列表。这些数字以一种便于比较文本的方式表示文本的特征。
整体流程如下:
- 嵌入模型为传入的问题生成嵌入向量。
- 它在已存储的问题嵌入中搜索合适的候选答案。
- 它检查候选答案是否与当前问题相似且有效。
- 如果接受,它会返回存储的答案。本质上就是缓存命中。
- 如果未命中,它会调用大语言模型生成新答案。可能会存储答案以供将来重用。
如你所见,如果发生缓存命中,我们无需调用大语言模型生成新答案。这种情况下不会产生输入和输出费用。然而,嵌入生成、查找和缓存存储等任务仍然会消耗资源。因此并非完全免费。此外,如果发生缓存未命中,我们还需要支付预处理任务以及大语言模型请求的费用。因此未命中会更加昂贵。
语义缓存的难点
语义缓存最困难的部分是确定两个独立问题的相似程度。
在语义缓存中,我们计算相似度分数并将其与某个阈值进行比较。你可以将这个阈值视为接受问题相似性的截止点。
如果我们设置非常严格的阈值,会导致更多候选答案被拒绝。虽然这可以提高准确性和减少不恰当的重用,但也会拒绝许多合法的问法变体。然而,如果我们采用宽松的阈值,更多候选答案会被接受。这会提高整体缓存命中率。但也会增加返回不适当答案的可能性。没有一种单一的、通用的阈值适用于所有应用场景。你需要根据具体情况决定阈值。
假设用户在订单发货前和发货后分别询问了两次关于取消订单的问题。
如你所见,这两个问题几乎相同。只差一个关键的词改变了含义。两个问题都涉及取消和发货。它们的嵌入向量可能也非常接近。但"是的,可以取消"这个简短答案可能对其中一个问题是正确的,对另一个问题却完全错误。
数字、否定、日期、产品版本和资格条件等数据类型在确定相似性时也可能引发类似问题。例如,"基础版是否包含备份?"无法自动重用关于专业版的问题答案。
此外,我们不能将相似度分数等同于答案正确的概率。例如,即使两个问题之间的相似度分数为0.92,也不意味着缓存答案对两个问题都适用的概率是92%。我们对分数的解释取决于嵌入模型和比较方法。某些系统会显示距离分数,其中较小的值表示更接近的匹配。
因此,我们需要建立一个评估流程,以验证语义缓存实现的效果。该评估流程需要判断特定存储的答案是否能正确满足新请求。为测试目的,开发团队可以收集大量请求,识别候选答案,并标注是否重用特定答案是正确的方式。测试套件应包含覆盖合法同义表达和困难近似匹配的示例。这样,我们才能更有可能找到最佳阈值。
最后,我们需要衡量从缓存中回答的请求数量比例,以及这些答案实际适用的比例。我们不能仅凭高命中率就庆祝。我们还可以增加一个额外的验证器来检查边界情况。然而,这样的验证器也会增加成本和延迟。
为什么不能仅依赖检查问题
你可以多次提出相同的问题。但每次,你可能期望得到不同的答案。例如,“我的订单状态是什么?”这个问题取决于客户和订单的当前状态。同样,“它是否支持离线访问?”这个问题取决于对话上下文中“它”所指的具体对象。此外,如果用户用不同语言请求答案,我们不能自动使用之前用英文生成的缓存答案。
因此,要使语义缓存生效,我们需要的信息不仅仅是问题本身,还需要其他信息来做出正确决策。根据应用场景的不同,可能需要包含客户或组织信息、访问权限、产品版本、语言、相关对话状态以及源数据版本等信息。
我们还需要在应用程序中强制实施这些条件。你不能指望嵌入模型仅因为用户在输入问题中包含客户标识符,就自动识别客户信息。通常,语义缓存实现需要具有元数据过滤功能,以限制搜索范围到合适的范围。
还有一个具体复杂情况的示例。如果用户提问“纽约的天气如何?”和“纽约今天天气如何?”,它们可能看起来是合适的匹配项。但答案取决于用户是想了解当前天气状况还是每日预报。在生成答案时,我们需要考虑位置、日期、预报周期、单位和数据的新鲜度。
何时使缓存失效
有时,缓存中的答案可能看起来与新问题高度匹配。但答案仍可能是错误的,因为支撑答案的源信息可能已发生变化。
假设你有一个允许产品退货的应用程序,规定退货期限为30天。现在公司改变了政策,将退货期限缩短为14天。然而,缓存中的答案可能仍然提及旧的30天期限。在这种情况下,你可能会提出相同的问题,但得到的缓存答案已不再有效。
这就是为什么我们需要制定缓存失效策略。
失效意味着使缓存条目无法被重复使用。我们可以采用多种方法构建理想的失效机制。
第三种可能影响缓存失效的方式是生成答案时使用的整体设置。例如高级指令、输出格式、模型行为指南等。这些设置在决定何时使缓存失效时具有重要意义。如果这些设置发生更改,我们应该使之前的答案失效。
提示缓存与语义缓存的处理方式存在差异。如果应用程序在提示中发送了更新后的策略,那么从策略变更点开始,修改后的前缀无法复用不兼容的旧版本。然而,如果存在未更改的早期部分,这部分内容仍可能被复用。此外,如果应用程序在每次输入中持续提供旧策略,提示缓存无法自动检测实际业务规则是否在其他地方发生了变更。获取当前策略信息并将其传递给模型是应用程序的责任。
提示缓存和语义缓存能否协同工作
可以在同一系统中同时使用提示缓存和语义缓存。它们是互补的关系。例如,应用程序可以首先通过语义缓存查找是否存在有效的现有答案。如果找不到有效答案,才会调用大语言模型并利用可复用的提示前缀。
如果获得语义缓存命中,就不需要发起主生成请求。另一方面,提示缓存可以降低仍需发送给大语言模型的请求成本。我们还可以在任何语义查找之前设置精确答案缓存进行检查。它能够以低成本处理重复的相同请求。
我们不一定需要在流程一开始就进行缓存查找。例如,如果应用程序必须获取当前源版本来验证答案,这个特定检查应该更早进行。
结论
在需要为不同问题生成新鲜答案的场景中,提示缓存是自然的选择。但这些答案必须基于共享上下文生成。这种共享上下文可以是通用产品手册、一组指令、稳定的工具定义,或长时间的对话历史。
语义缓存适用于需要重复使用相同答案的场景,例如产品常见问题解答或稳定的支持说明。然而,当需要生成高度个性化的回答时,或答案依赖于快速变化的事实时,语义缓存的效果会大打折扣。此外,当需要生成新颖创意内容时,语义缓存也难以胜任。
对于操作类请求的处理需要格外谨慎。例如,缓存中显示“订阅已取消”的消息,不能替代实际执行取消订阅操作。
要实际应用这些缓存策略,需要建立相应的评估体系。在提示缓存场景中,需要测量输入令牌的重复使用率,因为重复使用短前缀与重复使用长文本的请求成本差异显著。对于语义缓存,需要评估通过率、内容新鲜度和适用范围等指标。只有满足应用质量要求的回答,才应转化为可复用的缓存条目。
无论是采用哪种缓存方式,最终目标都是在保证回答质量的前提下,降低运营成本并提升响应速度。
参考资料:
- 缓存机制原理
- 提示缓存技术
- 语义缓存优化方法
- 提示缓存诊断工具