上个月我盯着云厂商的推理账单愣了半天,某个客服机器人的成本环比翻了快两倍,可调用量也就涨了一成。我第一反应是并发压上去了,回头把指标翻了个底朝天,才发现根本不是那么回事——是那套系统的 system prompt 太长了,长到每次都让模型把同样的开头重新"读"一遍。
你可能也干过这事:为了让客服回答得稳一点,把公司介绍、产品文档、话术规范全塞进系统提示里,一条 prompt 动辄好几千 token。结果呢,模型每次生成回复之前,都得把这堆内容从头到尾计算一遍。这中间有个概念我一开始完全没意识到,就是 KV Cache——它决定了这笔钱到底花得冤不冤。
先说 KV Cache 是什么。Transformer 推理的时候,每个 token 都要算一堆键值对,也就是 K 和 V,用来让模型在生成时"回头看"之前说过的话。这些 K 和 V 会被缓存下来,就叫 KV Cache。它的好处很直观:模型每生成一个新 token,只需要计算新 token 的部分,前面算过的东西直接复用,不用重算。可问题也出在这——它是按 token 数量存的,prompt 越长,缓存占的内存越大,首次生成前那一下"预填充"也越费劲。
我第一次理解到它的成本,是在给内部那个报表助手做压测的时候。那是个纯 RAG 的应用,每次提问前都先检索文档,把几百个片段拼成一大段上下文塞进 prompt。压测到第 200 个并发,GPU 直接 OOM 崩了。运维同事看了一眼监控图,丢给我一句:"你这 prompt 是给模型当饭喂呢。"我这才去翻原理,发现自己犯了个典型错误——把所有历史对话、检索结果一股脑全塞进去,以为上下文长就是好,结果内存全被 KV Cache 吃掉了。
这个坑我在之前聊上下文长度那篇也碰过,但那是从准确性的角度说漏信息。这次更扎心,是从钱和资源的角度。同一个前缀反复出现,每次推理都重新计算一遍那部分 KV,纯属重复劳动。你想想,客服场景里几乎所有请求都共用同一套 system prompt 和开场白,这部分内容占了可能三分之一以上的计算量,理论上完全可以只算一次、反复复用。
所以就有了上下文缓存这回事,行业里叫 prompt caching 或者 context caching。思路特别朴素:把请求里稳定的前缀缓存下来,命中就直接用缓存的 KV,不用重新算。很多推理服务都内置了这个能力,按前缀哈希命中的思路来做。我在生产上开了之后,系统提示那部分的算力成本直接砍掉了一多半,效果立竿见影。
不过你别以为开个开关就完事了,这里面的门道多得是,我踩了一轮才摸清楚。
有个坑是命中率没你想的那么高。缓存是按前缀精确匹配的,你只要把开头哪怕一个 token 改了,比如动态插了个日期、用户名,整条前缀就匹配不上了,缓存直接失效。我一开始把用户 ID 写进了 system prompt 里,结果每个用户都是不同前缀,等于白缓存,成本一点没省。后来我学乖了,把动态内容全部挪到请求的尾部,让固定的那部分系统提示永远做前缀,命中率一下就上去了。
另一个坑更隐蔽,是缓存和采样参数的打架。有些实现里,缓存的 KV 和采样参数是有绑定关系的,比如 temperature、top_p 这类参数一变,缓存可能也要跟着重建。我之前为了做 AB 测试,给同一套 prompt 用了两套不同的 temperature,结果缓存被拆成了两份,内存翻倍。你要是做实验,最好把参数做成稳定的那一档,别在线上频繁改动。
还有一点容易被忽略,就是缓存的存续时间。KV Cache 占的是显存,不是免费的,它按你配置的 TTL 存活。配置太短,命中率上不去;配置太长,闲置的前缀一直占着显存不释放,挤压了真正要算的请求。我见过有人把 TTL 调到一天,结果半夜没流量的时候,一大堆用不上的缓存把 GPU 占得死死的。后来我按业务时段调了个折中的值,才算是把命中和显存这两头都照顾到。
说回最要紧的一层判断——不是所有场景都适合上缓存。你如果是个单轮问答,每次 prompt 都不太一样,那缓存帮不上什么忙,老老实实控制 prompt 长度才是正路。但凡是那种"同样的开场白反复用"的密集场景,像客服、报表助手、多轮对话,缓存就是白捡的成本。我后来给部门定了条规矩:先量一下系统提示占请求总 token 的比例,超过三成就值得做缓存,低于这个线就先想想是不是该精简提示。
顺便打岔说一句,我上周看有个同事把产品介绍写得跟小作文似的,塞进 system prompt 当"知识库"用。我跟他说你这不是缓存能救的,你该去检索。就为这事我后来又单独开了一篇讲召回的文章,感觉很多人把"塞上下文"和"搭知识库"当成一回事,其实是两码事。
成本这玩意儿,其实比你想的更有得省。你看 GPT 那类接口早就把输入缓存单独标了低价,冲着这个,长 prompt 场景就更值得把稳定部分剥离出来缓存了。你要是手头有那种慢吞吞、又贵又耗显存的线上模型,不妨先查一眼你的 KV 命中率,没准能省出一台机器的钱。
你现在线上那套推理,prompt 里有多少是每个请求都在重复的?有没有算过那部分的钱?聊聊你的缓存命中率呗,我挺好奇大家实际踩出来的数字。