Prompt Caching VS KV Cache
最近看见一个新词(本人非算法序列)—— KV cache,研究agent开发自然而然的会考虑怎么缩减prompt的消耗,包括设计prompt caching策略;但是KV cache显然也是缓存策略,它作用在什么位置?有什么作用?二者之间关系是什么?
1、prompt caching
以客服agent为例,在设计时必然会有一个system prompt 模块。如果不设计cache,每次对话时都会把system prompt完整的放入上下文,每次都要消耗大量token来处理这段相同的内容,这显然是一种无意义的消耗。
Prompt caching就是用复用单次处理结果来代替重复处理相同内容的过程,把重复不变的Prompt前缀(System指令、知识库、工具定义、Few-shot样例)的KV张量持久保存在GPU/主机内存,不同API请求、多轮对话间直接复用。
调度流程:
1、请求哈希路由
服务端对prompt开头的前缀文本做哈希匹配,路由到持有该缓存的节点,提高缓存命中率——该步骤要求必须前缀必须严格匹配严丝合缝,任何空格、换行、字符改动都会导致匹配失败。
【针对这一点,在设计prompt时有一个很重要的设计标准:静态内容在前,动态内容在后(如日期、用户名等)】
2、缓存查找
对比当前请求前缀与缓存中的代码块:
Cache miss:对全部token完整执行prefill,计算整套KV张量,存入cache并设置TTL;
Cache hit:直接KV cache中加载,跳过静态前缀的计算,token用量只计算增量。
实现范式:
1、自动触发
设置触发阈值:前缀token达到阈值时自动触发服务端识别前缀开头,后台维护cache(如OpenAI GPT-4o/GPT5 系列触发阈值为1024 token)。
无需改动代码,但是控制的颗粒度比较大。
2、显示断点缓存
手动指定哪一段需要缓存,需要修改prompt结构、新增标记。
可以更清楚地控制需要缓存的部分,但是改动时的修改量较大。
2、KV cache
在上面提到调度时,提到miss或hit时针对KV cache的不同操作,但是并不清楚这到底是什么,怎么运作的,所以下面来详细介绍一下。
一句话总结:KV Cache 专门解决大模型自回归生成时重复计算注意力的性能浪费。
大模型推理步骤
设输入提示词长度 = N tokens,模型输出长度 = T tokens
Prefill(填充阶段):一次性把你输入的提示词全部并行算完,得到每一个token对应的key、value;
单次Prefill:O(N2),并行计算,复杂度只和输入长度平方相关。
Decode(生成阶段):模型逐个吐出回答,一次只生成一个新的token。在没有KV cache的前提下,每生成一个token,都要将全部的历史token重新跑一遍才能地道道下一个新的token。
总上下文长度随生成递增:
KV 设计
在prefill阶段,将所有算好的K、V存在显存,后续每一步生成都直接复用,不用重复计算历史上下文;KV Cache 不优化 Prefill 本身。
在decode阶段,基于新生成的token和缓存中的K、V做注意力,不需要计算全部历史。
二者关系:
可以看出,KV cache专注单次对话内部token的复用,通过缓存历史计算得到的token减少下一轮注意力计算的消耗,主要优化decode部分;在第一次输入长文本时,prefill依然会有大量消耗;
prompt在不同对话中通过利用复用前缀实现优化,如果在某次对话的开始输入一段长文本且该文本已经在其他对话中出现过,该次对话可以直接挑中重复前缀的计算部分,在prefill部分只有增量消耗。
适用于:固定system prompt(客服系统)、基于同一个长文本的回答等场景;
缺点:需要额外占用显存、上下文极大时要优化上下文的保存方式,只能用于文本生成,不适用于非自回归任务。
