Prompt 缓存的四种策略:从精确匹配到语义检索

张开发
2026/4/8 22:16:25 15 分钟阅读

分享文章

Prompt 缓存的四种策略:从精确匹配到语义检索
自然语言理解、摘要生成、代码编写、逻辑推理OpenAI 等厂商的模型把这些事情做得相当好。但是只有一个问题那就是 “贵.尤其是在应用上了规模之后API 调用费用的增长速度会让人心跳加速。Prompt 缓存是应对这个问题最直接也最容易被忽视的手段。本文会从原理讲到实践覆盖四种不同层级的缓存策略配有代码示例和架构图。LLM 的成本为什么涨得这么快LLM API 的定价模型就三个维度输入 Token 数也就是 Prompt 长度、输出 Token 数响应长度、调用次数。比如FAQ 机器人、聊天式新人引导助手、内部开发者工具、AI 仪表板——这些应用有一个共同特征大量重复或高度相似的 Prompt 被反复发送而期望得到的回答几乎一样。如果不做缓存的话每次调用都要按量计费那费用肯定就爆炸了。Prompt 缓存是什么一句话概括当相同或等价的 Prompt 再次出现时直接复用之前的 LLM 响应而不是重新调用 API。先查缓存命中就直接返回没命中再去调 LLM拿到结果后存入缓存。就这一个改动成本就能降低 30%–90%具体数字取决于工作负载的重复程度。策略 1精确匹配缓存这是最基础的方案。逻辑非常简单完全相同的 Prompt 字符串出现时直接返回缓存结果。适用场景包括静态 FAQ、政策说明文档、解释 X这一类 Prompt以及聊天机器人中反复出现的 system prompt。下面是 Node.js 的实现import crypto from crypto; const cache new Map(); function hashPrompt(prompt) { return crypto.createHash(sha256).update(prompt).digest(hex); } async function getLLMResponse(prompt) { const key hashPrompt(prompt); // Step 1: Cache lookup if (cache.has(key)) { return cache.get(key); } // Step 2: Call LLM API const response await callLLM(prompt); // Step 3: Store in cache cache.set(key, response); return response; }为什么要对 Prompt 做哈希因为 Prompt 本身可能很长哈希之后得到固定长度的 key查找速度快SHA-256 的碰撞概率也低到可以忽略。内存缓存的优点是极快单实例或小规模系统用起来非常合适。但是这样做也进程重启缓存就没了多实例之间也无法共享。策略 2规范化缓存精确匹配有一个很容易遇到的问题Prompt 里多一个空格、少一个换行、大小写不同就被当成不同的 key 了。实际上这些差异对语义毫无影响。解决办法是在缓存前先做规范化处理。举个例子规范化之前Explain REST APIs Explain REST APIs Explain REST APIs规范化之后全部变成explain rest apis代码实现function normalizePrompt(prompt) { return prompt .toLowerCase() .replace(/\s/g, ) .trim(); } function getCacheKey(prompt) { return hashPrompt(normalizePrompt(prompt)); }不必要的 cache miss 减少了命中率明显上升同时整个过程依然是确定性的、安全的。策略 3语义缓存What is REST? 和 Explain REST architecture 说的其实是同一件事但无论精确匹配还是规范化匹配都会把它们当作两个完全不同的请求。所以思路是引入向量嵌入。把 Prompt 编码成向量通过余弦相似度之类的指标判断两个 Prompt 是否足够接近。如果相似度超过阈值直接返回缓存结果。语义缓存流程工具选型方面Embedding 可以用 OpenAI 的接口向量存储可以选 Pinecone、Weaviate 这类专门的向量数据库小规模场景下在内存里做相似度搜索也够用。伪代码如下const SIMILARITY_THRESHOLD 0.90; async function getSemanticResponse(prompt) { const embedding await getEmbedding(prompt); const match await vectorDB.findClosest(embedding); if (match match.score SIMILARITY_THRESHOLD) { return match.response; } const response await callLLM(prompt); await vectorDB.store({ embedding, response }); return response; }语义缓存的风险语义缓存的核心风险在于阈值设定。设得太低会把不相关的 Prompt 混为一谈返回错误结果设得太高又和精确匹配没什么区别。0.90 是一个比较常见的起步值具体数字需要根据业务场景调优。策略 4分层缓存架构生产环境一般不会只用单一缓存策略而是按层级组合。典型的三层架构长这样L1 Cache (In-memory, per instance) | L2 Cache (Redis / Shared Cache) | L3 Semantic Cache (Vector DB) | LLM Provider每一层的定位不同。L1 是进程内存缓存速度最快但作用域最小L2 一般用 Redis多个实例可以共享同一份缓存L3 是语义缓存层处理那些文本不同但意思相近的 Prompt。只有三层都没命中的情况下请求才会打到 LLM Provider。缓存过期与失效Prompt 缓存不能设了就忘。以下几种情况必须主动失效模型版本升级了Prompt 模板改了或者缓存的内容涉及时效性信息。最简单的做法是设 TTLcache.set(key, response, { ttl: 60*60*24// 24 hours });成本影响缓存带来的收益是双重的——成本下降延迟也降低了。对于重复率高的工作负载这两个指标的改善都非常可观。总结在 LLM 系统的各种优化手段中Prompt 缓存的投入产出比可能是最高的。入手门槛低可以渐进式迭代而且到了一定规模之后几乎是刚需。可以先从精确缓存做起这是成本最低、风险最小的方案。规范化处理应该尽早加上代码量很小但效果明显。语义缓存只在业务确实需要时才引入因为它带来了额外的复杂度和向量计算开销。TTL 和版本控制是必须配套的机制。最后缓存命中率要持续监控因为这是判断缓存策略是否有效的核心指标。

更多文章