提示词缓存如何让LLM推理成本直降36%?原理与工程落地

发布时间:2026/9/6 6:54:21
提示词缓存如何让LLM推理成本直降36%?原理与工程落地 大模型推理成本降 36%靠的是“提示词缓存”这事值得每个 LLM 应用开发者重新想一遍。如果你在做一个基于大模型的应用比如聊天机器人、智能客服、知识库问答系统或者给 LLM 套一层的 Agent 工作流大概率会有一个体感模型能力很强但每调一次接口都在烧钱。尤其是当系统提示词越来越长、业务流程越来越复杂时你会发现自己明明只问了模型一句“今天天气怎么样”但实际发给 API 的请求里可能有几千个 token 都是重复的、固定的、每次都要重新计算的“系统指令”。这些重复计算就是纯浪费。一个扎心的现实是很多团队在做 LLM 应用时第一版 Demo 跑起来很快一上线账单涨得也很快。优化模型输出质量还只是问题的一半另一半是“推理成本到底怎么降”。而在目前所有降本思路里prompt caching提示词缓存是我认为最“划算”的一招因为它不需要你去换模型、不需要你做复杂的模型蒸馏也不需要改业务逻辑只需要你理解它的原理然后在工程实现上做一点调整就能看到成本明显下降。这篇文章不是去复述某一家厂商的文档而是把 prompt caching 当成 LLM 应用工程里一项必备的降本手段来拆它到底缓存了什么、为什么能省这么多钱、在哪些场景下收益最大、落地时会遇到哪些坑以及如何用代码和配置真正把成本降下来。读完这篇你应该能对你的 LLM 推理成本结构有一个更清晰的判断。1. 这篇文章真正要解决的问题先说一个很容易被忽视的事实LLM 推理的成本大头往往不是“生成”的那部分而是“输入”的那部分。很多人觉得模型生成一个很长的回答肯定很贵于是把优化精力都放在控制输出长度上。但如果你打开账单仔细看会发现当一个请求里塞进了 3000 字的历史聊天记录、2000 字的系统提示词、再加上一堆 few-shot 示例时输入侧的 token 开销早就超过输出侧了。而且这种“输入很长”的请求往往是高频的、重复的甚至每次的内容都高度相似。这就是 prompt caching 要解决的问题。它把你的请求中“不变的、重复出现的”那一段 prompt 在服务端缓存下来当你下一次发请求时只要前缀相同就不需要重新计算那一部分的 KV cache直接复用上一次的中间状态只计算新增加的内容。这个机制的直观效果是请求延迟降低单位时间吞吐提升而推理成本因为它减少了重复的 prefill 计算而直接下降。以文章标题提到的 36% 为例这个数字并不是凭空出现的。它来自实际业务场景里当一个应用中存在大量高重复度的前缀提示词时采用 prompt caching 后能看到的推理成本降幅。当然不同模型、不同业务、不同调用频率最终省下的比例会不一样。但有一个基本判断是可以给的任何需要反复携带长 system prompt、长上下文、多轮历史记录的 LLM 应用中prompt caching 都是一个收益大、风险小、落地快的优化手段。这篇文章适合的读者很明确正在做 LLM 应用发现 API 账单越来越高的开发者自己在本地部署或私有化部署推理服务想提升吞吐、降低显存压力的工程师设计 RAG 或 Agent 架构时希望降低重复计算、提升响应速度的技术负责人刚接触大模型应用开发想知道“成本到底花在哪”的新手。2. 大多人把“缓存”想简单了缓存的是 KV不是文本要理解 prompt caching最怕的就是把它想成普通意义上的“缓存”——也就是把旧的响应结果存起来下次请求相同问题直接返回旧答案。这是两个完全不同层级的东西。如果你做过传统 Web 开发可能很熟悉这种缓存把 key 为“北京时间现在几点”的接口响应存到 Redis下次有人再问同样的内容直接返回“2025 年 6 月 8 日 14:30”。但在 LLM 应用里这种方法的问题很明显用户不可能每次都问一模一样的问题而且 LLM 需要的是“理解”和“生成”不是一个固定的答案表。真正能让推理成本大幅下降的是缓存模型在“理解 prompt”阶段产生的中间状态也就是 KV cache。2.1 先理解 KV cache 是什么Transformer 模型在生成回答时并不是一次性把整段话都想好而是一个 token 一个 token 地生成。每生成一个 token它都要参考之前所有 token 的信息去计算注意力分数。为了不每次从头计算模型会把已经计算过的一些中间结果保存下来。这个中间结果就是一个大 key-value 缓存业内叫 KV cache。KV cache 的引入其实就是拿显存换速度它让模型不用每次生成新 token 时都把之前所有输入重新算一遍而是直接读取缓存。但问题是KV cache 的大小和输入序列的长度是正相关的。输入越长KV cache 占的显存越大计算生成的单次成本也越高。2.2 prompt caching 缓存的是“前缀计算结果”不同请求之间虽然问题不同但可能共享同一个很长的系统提示词比如你是某银行客服助手你需要遵守以下规则 1. 不要透露内部系统逻辑 2. 回答要简洁 3. 不要编造事实 ...这段 system prompt 可能在几分钟内被调用了几百次。从模型视角看它每一次都在重复计算这一段的理解结果。prompt caching 的做法就是在服务端检测到请求的前缀内容与缓存内容一致时直接复用该前缀对应的 KV cache。这样你新的请求中只有新增的那部分内容需要走完整的 prefill 阶段计算重复部分直接跳过。可以这么类比以前读一本书解读每次都必须从第一页开始逐字逐句读。prompt caching 相当于你记住了前 100 页的内容下一次讲解时只需要从第 101 页往后翻到第 200 页即可。2.3 为什么“36%”这样的降幅会出现推理成本主要由两部分构成prefill处理输入和 decode生成输出。其中prefill 是对输入序列进行并行计算的过程看似只是一次“阅读理解”但在长输入、高并发的情况下它的计算量和耗时都相当惊人。假设你的业务里有 60% 的输入都是重复前缀那么启用 prompt caching 后理论上能节省的比例也接近这个数字。再结合不同云厂商对 cache hit 的 token 单独计价通常远比正常输入 token 便宜最终体现在账单上的成本降幅就会非常可观。36% 就是在大量重复系统提示词的场景下一个相对合理的观察结果。但也要说清楚并不是所有输入都是可以被缓存的。只有那些“前缀完全一致”的内容才能命中缓存。如果每次请求的第一句话都不一样那就享受不到这个机制的红利。这引出了后面要讲的一个关键实践把可复用的固定部分放在 prompt 的最前面让后缀的内容负责变化。3. 在“哪一层”做缓存效果完全不同如果你现在想给项目接入 prompt caching第一反应可能是在代码里搞一个缓存中间层把用户请求的 prompt 存起来下次遇到相同的 prompt 再返回上次的结果。这个思路在很多场景下也有用但在 LLM 推理降本这件事上你要先分清自己做的是哪一种缓存。3.1 第一层网关缓存结果级缓存在应用层或网关层对“完全相同的请求”做结果缓存。比如用户连续问两次“什么是 prompt caching”第二次就不去调模型直接返回第一次的结果。优点响应极快成本几乎为零。 缺点LLM 应用里很难出现大量完全相同的请求除非是同一批数据在做批量处理。3.2 第二层推理服务缓存KV 级缓存这就是 prompt caching 的核心。它在推理框架内部复用前缀的 KV cache减少重复的 prefill 计算。这也是开源推理框架中常见的 prefix caching 方案。你不需要精确命中完整请求只需要命中“固定前缀”即可。优点对用户透明不需要改业务逻辑覆盖场景广。 缺点需要额外显存来缓存 KV同时需要配置合理前缀长度否则缓存命中率很低。3.3 第三层模型侧压缩与调度有些方案是通过减少原始输入来实现降本比如动态压缩历史对话、把冗长的 few-shot 示例抽成摘要。这一类严格来说不属于 prompt caching但它和 prompt caching 是可以叠加使用的。实际工程里推荐顺序也很简单先用结果级缓存兜底精确重复再用前缀 KV 缓存覆盖高频重复前缀最后再通过 prompt 压缩减少永久性输入。4. 环境准备不同接入方式前提条件并不一样在开始写代码之前先明确你要在哪种环境下使用 prompt caching。它不是一个独立的工具而是一个和模型服务提供商、推理框架深度绑定的能力。如果你用的是云厂商的托管 API或者开源推理框架环境准备完全不一样。4.1 云厂商托管 API这是最省事的一种方式。目前主流大模型服务平台基本都支持自动或手动启用 prompt caching不需要额外安装 Python 包或推理引擎。你只需要确认两件事你的账号是否开通了该模型对应的缓存能力你使用的 SDK 或 HTTP 请求中是否传入了启用缓存所需的参数。这种场景下环境准备基本就是一次 API 配置。需要注意的是不同厂商的开启方式不同。有的平台是自动开启默认会缓存一定时间内的前缀有的平台需要你在请求参数里显式声明“enable caching”之类的开关还有的平台要求你的请求前缀不能超过某个 token 长度。# 示例伪代码演示在 Python SDK 中开启缓存类参数 from openai import OpenAI client OpenAI( api_key你的API密钥, base_url你的服务地址 ) response client.chat.completions.create( modelyour-model-name, messages[ {role: system, content: 你是一个专业的AI助手请遵守公司规范。}, # 固定前缀 {role: user, content: 今天天气如何} ], # 这里的参数名以服务商官方文档为准有的服务商不需要显式传 extra_headers{X-Enable-Prompt-Cache: true} )值得强调的是以上代码里的extra_headers只是一个示意。不同厂商对这个能力的暴露方式差异很大有的平台甚至不需要你在客户端做任何事。所以读到这篇时请务必拿到你正在用的服务商的官方文档再确认具体参数名和用法不要照搬这个示例去生产环境因为 API 接口可能已经变化。4.2 本地部署开源模型如果你使用的是 vLLM、SGLang、TGI 这类开源推理框架环境准备就要更深入一些。你需要一台 GPU 服务器显存能装下目标模型安装对应推理框架并用它启动模型服务读取框架文档开启自动前缀缓存或 KV 复用功能。以 vLLM 为例它内置了自动前缀缓存能力你在启动服务时可以通过配置参数来控制启用方式和缓存空间。这里不推荐写死某个版本的具体命令因为 vLLM 的配置项更新非常频繁。更稳妥的做法是在启动帮助信息里查找这些关键词prefix、cache、kv、block。python -m vllm.entrypoints.openai.api_server \ --model meta-llama/Llama-3.1-8B-Instruct \ --max-model-len 8192 \ --gpu-memory-utilization 0.9然后你可以通过--help查看当前版本的缓存相关参数。不同版本差别很大有的版本默认开启前缀缓存有的版本需要显式关闭某些和长上下文相关的功能才能获得较高的命中率。4.3 通过网关或代理中转如果你的团队已经搭建了统一的 LLM 网关比如 LiteLLM、OpenRouter 这类代理层通常它们也会透传或管理缓存配置。这时候你的环境准备会是网关服务配置模型路由和认证网关层开启结果缓存可选向网关转发的请求中带上原始服务商的缓存控制参数。这种方式的优势是可以在一个位置统一控制不同模型的服务策略。缺点是网关层如果不支持透传某个平台的缓存参数那么你再怎么在业务侧设置头信息也可能不生效。5. 一个能看得到降本效果的完整示例下面通过一个真实可运行的思路演示 prompt caching 在实际工程中的使用效果。这个示例里我们模拟一个“企业知识库问答机器人”的场景系统提示词很长所有用户请求都共享这一段固定前缀而用户的提问则千变万化。5.1 模拟场景知识库问答机器人在没有 prompt caching 的情况下每次请求的 token 组成大概是这样固定系统提示词1500 tokens检索到的知识库片段1000 tokens历史对话500 tokens用户当前提问50 tokens也就是说每次请求输入约 3050 tokens其中真正变化的只有“用户提问”50 tokens其余 3000 tokens 几乎完全一样。如果一天有 10000 次请求那么光输入侧的 token 消耗就是 3050 万 tokens。其中大约 3000 万 tokens 是重复计算的。接入 prompt caching 后如果缓存命中率较高那么每次请求中固定前缀部分不再按正常输入价格计费而是按缓存命中的优惠价格计费甚至只收很低的额度。5.2 代码示例使用 OpenAI 风格接口调用下面用一段 Python 示例演示“同样的固定系统提示词 不同用户提问”的调用方式。这里的关键不是代码本身而是让你看到何种调用模式能够命中前缀缓存。import openai import time client openai.OpenAI(api_key你的API密钥) system_prompt 你是一家大型企业的内部知识库助手。 你的职责是回答员工关于公司制度的提问。 回答要求 1. 先给出结论再补充细节。 2. 如不确定必须说明“该信息不在知识库中”。 3. 不要编造制度条款。 4. 回答控制在200字以内。 以下是公司的考勤制度 - 上班时间9:30-18:30 - 弹性工作每日可弹性1小时 - 请假需提前一天在OA系统提交 - 加班需部门负责人审批 def ask_question(question: str): start time.time() response client.chat.completions.create( model你的模型名称, messages[ {role: system, content: system_prompt}, {role: user, content: question}, ], temperature0.3, max_tokens256, ) latency time.time() - start usage response.usage return { answer: response.choices[0].message.content, latency: latency, prompt_tokens: usage.prompt_tokens, completion_tokens: usage.completion_tokens, total_tokens: usage.total_tokens, } result1 ask_question(我今天可以晚一点上班吗) print(第一次回答, result1[answer]) print(第一次请求耗时, result1[latency]) print(第一次输入 tokens, result1[prompt_tokens]) result2 ask_question(加班审批的流程是什么) print(第二次回答, result2[answer]) print(第二次请求耗时, result2[latency]) print(第二次输入 tokens, result2[prompt_tokens])这段代码的核心是system_prompt 是完全固定的user 的 question 每次不同。在支持 prompt caching 的服务上第一次请求之后的相同前缀请求会明显降低 latency同时 usage 里可能会出现独立的 cache_hit_tokens 或类似字段。5.3 成本对比估算脚本为了让你更直观地看到 36% 这个数字是怎么来的写一个简易的成本估算脚本。它不依赖具体 API只是把计费逻辑抽象出来。# cost_compare.py # 演示相同前缀在高重复场景下的成本对比 total_requests 10000 system_tokens 1500 knowledge_tokens 1000 history_tokens 500 user_tokens 50 # 假设正常输入 token 单价为 1 个单位输出 token 单价为 2 个单位 price_input 1.0 price_output 2.0 cache_hit_price price_input * 0.1 # 假设缓存命中token按正常输入价格的10%计费 # 每次输出平均 200 tokens output_tokens_per_request 200 # 未启用 prompt caching cost_no_cache total_requests * ( (system_tokens knowledge_tokens history_tokens user_tokens) * price_input output_tokens_per_request * price_output ) # 启用 prompt caching固定前缀可以命中缓存只有 user_tokens 按正常输入计价 cost_with_cache total_requests * ( user_tokens * price_input (system_tokens knowledge_tokens history_tokens) * cache_hit_price output_tokens_per_request * price_output ) # 输出侧不受缓存影响所以这里降本主要来自 prefill saving_ratio (cost_no_cache - cost_with_cache) / cost_no_cache * 100 print(f未启用缓存总成本: {cost_no_cache:.0f}) print(f启用缓存总成本: {cost_with_cache:.0f}) print(f成本降低比例: {saving_ratio:.2f}%)跑一下这段脚本你会发现在“固定前缀占比极高”的场景下成本下降比例很容易超过 30%。这也就是标题里 36% 这个数字出现的原因它来自有大量重复 system prompt、上下文命中率高的业务场景。5.4 如何验证是否真的生效很多刚接入 prompt caching 的开发者最困惑的问题是“我怎么知道它到底缓存了没有”不同平台有不同的暴露方式。常见的有三种响应体里的 usage 字段部分平台会返回prompt_tokens_details.cached_tokens这类字段告诉你本次请求有多少输入 token 命中了缓存。延迟明显下降当缓存命中时prefill 阶段的计算量大幅减少整体延迟通常会下降 30%-60%。如果你连续发送多个前缀相同的请求第二次的延迟一般比第一次快很多。账单中的单价变化在云服务商的账单明细里缓存命中的 token 往往有单独的计费项单价更低。如果你发现延迟完全没有变化usage 里也没有任何缓存相关字段那大概率是请求前缀没有完全匹配。常见情况是你以为自己用了相同的 system prompt但代码里其实在 system prompt 前面动态拼了一个时间戳或者用户 ID。6. 真实业务场景谁最适合 prompt caching不是所有 LLM 应用都适合用 prompt caching但以下是收益最明显的几类场景。6.1 长系统提示词的垂直客服与助手很多企业内部应用会为 AI 助手写一份 1000 到 3000 token 的系统提示词里面包含品牌人设、回答规范、敏感词限制、知识库索引、工具调用说明。这类应用的共性就是系统提示词非常长而且几乎不变用户提问非常短变化多。这正好是 prompt caching 最理想的使用场景。6.2 RAG检索增强生成RAG 的一种常见实现是把检索到的文档片段拼在 prompt 里连同用户问题一起发给模型。这里有一个容易被忽略的细节很多 RAG 应用的检索结果是高度重复的。比如用户连续问三个关于“考勤制度”的问题三次检索到的知识库片段可能都是从同一篇制度文档里来的。如果每次请求都把这些片段重新计算一遍就存在大量浪费。更合理的做法是把“固定不变的系统指令 检索到的知识库内容”放在前缀位置。但注意如果每次检索结果差异很大缓存命中率会降低。所以这里更推荐先做一轮文档去重和排序把高频命中的公共知识片段尽量固定下来。6.3 多轮对话与 Agent 工作流多轮对话里历史消息逐轮累积后面的每一轮请求都带着前面所有对话内容。如果你的业务是客服、角色扮演、教育辅导这类长对话场景prompt caching 的价值在于新的一轮请求只需要从头开始把之前的对话历史作为固定前缀模型只需要处理最新一条用户消息。因为有前缀缓存这个“带上全部历史”的代价会变得低很多。Agent 工作流也是一个典型场景。Agent 在调用多个工具时往往会反复使用同一段 system prompt 来描述工具的能力和使用方式。工具定义越长Agent 的 tool calling 循环越多缓存的好处就越明显。6.4 不适合 prompt caching 的场景也有一些场景做了 prompt caching 可能帮助不大每次请求都是完全独立的随机问题且不含任何固定前缀prompt 非常短比如只有几十个 token请求量非常低一天只有几百次调用省下的成本有限使用不支持前缀缓存的模型或服务或者缓存窗口极短无法在业务请求间隙命中。7. 常见问题与排查思路在实际接入过程中最容易踩的坑往往不是“无法开启”而是“看起来开了实际上没有命中”。问题现象可能原因排查方式解决方案第一次请求和后续请求延迟几乎一样请求前缀没有完全一致打印请求消息对比每次请求前 50 个字符是否一致将固定系统提示词放在 messages 数组最前面避免在前面拼接动态内容usage 中没有缓存相关字段模型或服务商不支持可见的缓存字段查看服务商文档确认缓存参数和返回字段以延迟和账单作为辅助判断不依赖单个字段开启后显存明显升高KV cache 需要额外显存保存监控 GPU 显存使用率限制缓存 token 长度上限或调整缓存回收策略缓存命中率很低动态内容出现在固定前缀之前检查是否在 system prompt 前加入了时间戳、用户ID把动态内容移动到 system prompt 之后生产环境出现隐私担忧共享前缀可能被其他请求命中评估前缀中是否包含敏感信息敏感数据不入前缀或者关闭跨请求缓存一个额外提醒某些平台的缓存是跨用户共享的。如果你的 system prompt 中包含某个特定用户的隐私信息那么另一个用户只要前缀相同理论上也能命中同一段缓存。这在多数情况下不是问题因为缓存的是 KV 计算结果并不会直接把你的私有数据返回给别人。但在合规要求极高的场景下建议先做隐私评估再决定是否开启全局前缀缓存。8. 最佳实践与工程建议最后把 prompt caching 落地到生产环境时我整理了几条值得长期遵守的原则。8.1 前缀固定是第一位的要求这是所有优化里最重要的一条。要让缓存命中率高就必须把“不变的、公共的、大型的”内容放在 prompt 的最前面并保证它绝对固定。不要在前面拼接日期、随机 ID、环境变量、用户名。这些看似“无害”的动态信息每出现一次就会把整个前缀缓存打碎一次。8.2 隔离变化与不变在工程实现上建议把 prompt 模板拆成三层固定层系统提示词、品牌规范、工具定义业务层检索到的知识库内容、当前会话摘要动态层用户当前输入、需要模型立即响应的指令。让固定层尽可能长、动态层尽可能短这样缓存收益最大。这也是很多高吞吐 LLM 应用在 prompt 工程上的通用做法。8.3 利用缓存窗口设计重试策略一些服务商会对缓存设置有效窗口比如 5 分钟、1 小时或者更长。如果你的业务有明显的“短时间高频”特征例如集中处理一批数据、短时间内测试同一套流程可以尽量把最高频的调用集中在一个窗口内完成这样能提高命中率。8.4 不要只看单次延迟要关注整体成本和吞吐很多团队评估 prompt caching 的效果时只盯着“单次请求快了多少”。但对于工程系统更重要指标是“单位时间能处理多少请求”以及“每 1000 次请求的成本”。缓存命中后prefill 计算量减少GPU 算力空闲出来整体吞吐会明显提升这才是生产环境里最有价值的收益。8.5 日志里记录缓存命中信息在接入缓存后强烈建议在日志系统里记录每次请求的缓存命中信息。这可以帮你分析不同业务场景下的命中率也为后续调整 prompt 结构提供数据支撑。{ request_id: abc123, model: your-model, prompt_tokens: 3200, cached_tokens: 3000, cache_hit: true, latency_ms: 620 }有了这些数据你才能逐步把“缓存命中率”变成一个可观测的工程指标而不是黑盒里的玄学。8.6 与其他降本手段叠加prompt caching 不是万能的它最擅长处理“重复前缀”。但对于不重复的部分你还需要搭配其他手段用 prompt 压缩来缩短固定层长度用动态摘要减少多轮对话的历史长度用小模型做分类和路由让大模型只处理复杂请求在离线场景用批量推理减少重复上下文加载。最终你会发现真正稳定的降本是多个手段组合出来的结果而不是某一个单一开关。9. 总结与后续学习方向如果只记住一句话那就是prompt caching 省的不是“回答”的成本而是“重新理解同一段话”的成本。在任何一个存在长固定前缀、高频重复请求的 LLM 应用里它都应该是优先考虑的降本手段。如果你现在正在做 LLM 应用下一步可以做这样几件事打开你的 API 调用日志统计一下输入 token 里有多少是重复的固定前缀选一个支持 prompt caching 的服务或推理框架做一个最小测试对比缓存开启前后的延迟和账单如果已经在用开源推理框架去读一下你当前版本的前缀缓存文档看看哪些配置项可以优化命中率。更深入的方向还可以研究前缀缓存与调度策略的组合、动态上下文压缩、以及 KV cache 的显存管理。毕竟大模型推理的成本优化是一个持续推进的过程prompt caching 只是其中一个性价比比较高的起点。如果你能把这条路走通遇到更复杂的成本问题时也会有更清晰的判断框架。