prefix caching
深入阅读 · 第 12 章 KV cache——跨请求复用一个 prompt 的 KV,而不仅仅是在一次生成内部。
你在本章认识的 KV cache 是在一次生成内部复用的:单条回复里的每个 token,复用它前面那些 token 的 key 和 value。prefix caching 把同一个想法往上抬一层——在恰好以相同 token 开头的不同请求之间复用那份 KV。
机制是精确的。两个共享前导 prefix 的请求,共享这些 token 的 key 和 value,于是这段 prefix 只计算一次,之后每个请求都在它上面跳过 prefill——一次 cache hit,把它的 TTFT 一路降到第一个新 token。但复用在第一个不同的 token 处终止。模型是自回归的,所以一个不同的 token 会改变其后所有 token 的 hidden state——也就改变了 KV——哪怕再往下看上去完全一样的文本也是如此。过了第一处 miss,cache 就一文不值:
示意 token——讲概念,并非本模型的真实分词。
两个请求共享前缀 prefix Weather in。这段 KV cache 只计算 一次,于是第二个请求在这些 token 上 跳过 prefill——这是一次 cache hit,降低了它的 TTFT。prefix 在 第一个差异 处结束(SF 对 NYC);模型是自回归的,所以 miss 之后的每个 token 的 KV 也不同,需要 重新计算。
当一段较长的 prefix 在多个请求间共享时收益巨大:长 system prompt(agent、 chatbot、工具调用)、RAG / 检索到的文档,以及共享的代码上下文。多轮对话每一轮都会复用到目前 为止的整段对话。
对本 demo 要诚实:作为 batch size 1 的单一用户,你没有任何对象可以共享 prefix——每个请求都要把整段 prompt 冷启动 重新 prefill 一遍。生产环境的 API 会在数百万请求间复用同一段固定的 system prompt,这正是按 token 计费的 API 把 cache-hit 的 token 算得更便宜、在样板内容上几乎瞬时、只在新 token 上「思考」的原因。
这条「第一处差异」的规则也是一条设计经验:把新内容尽量放在靠后的位置。一段固定的长 system prompt 后面跟着用户的问题,每次都能复用整段 system prompt;同样的内容若把每请求各异的 id 贴在最前面,则什么都复用不了。最大的收益正是那些高复用形状——agent 和 chatbot 的长 system prompt、带共享检索文档的 RAG、共享的代码上下文,以及多轮对话(它每一轮都会重发到目前为止的整段对话)。
对本 demo 还要补一句诚实的脚注:作为 batch 1 的单一用户,你没有任何对象可以共享 prefix——每个请求都要把整段 prompt 冷启动重新 prefill 一遍。生产环境的 API 会在数百万请求间复用同一段固定的 system prompt,这正是按 token 计费的 API 把 cache-hit 的 token 算得更便宜、在样板内容上几乎瞬时、只在真正新的 token 上「思考」的原因。