PromptCache 第I部分:停止为相同的 LLM 答案付两次费
Source: Dev.to

LLM 系统中的隐形成本泄漏
如果你在生产环境中运行 LLM,几乎可以肯定你正在为以下情况付费:
- “如何重置我的密码?”
- “我忘记密码了,怎么办?”
- “重置账户密码的步骤?”
- “帮我修改密码”
不同的字符串,却有相同的意图、相同的答案,却产生不同的计费请求。
传统缓存无济于事,因为完全匹配会失败:
"How do I reset my password?" != "Steps to reset account password?"
意义并未改变——这正是 语义缓存 发挥作用的地方。
理论:为什么可行
LLM 会把文本转换为向量(嵌入)。意义相近的两个句子会产生在高维空间中彼此靠近的向量。
示例(简化):
"Reset my password"
↓
[0.12, -0.87, 0.44, ...]
"How do I change my password?"
↓
[0.11, -0.89, 0.41, ...]
因为向量非常接近,我们可以问:
“我之前是否见过 语义相似 的内容?”
如果相似度足够高,就复用缓存的答案——这就是语义缓存。
实际工作原理
当请求到来时:
User Prompt
↓
Embedding
↓
Vector search in Redis
↓
High similarity?
↓
Yes → Return cached response
No → Call LLM and store result
相当于在 LLM 前面加了一层语义记忆(memoization)层。
实际效果
在一个查询高度重复的客服工作负载中:
- 大约 60 % 的缓存命中率
- 大约 50 % 的 token 使用量下降
- 大约 40 % 的 API 支出降低
结果会因工作负载密度和重复模式而异,但在结构化环境中,影响是立竿见影的。
示例实现
使用 Redis 向量搜索的简化示例:
from promptcache import SemanticCache
from promptcache.backends.redis_vector import RedisVectorBackend
from promptcache.embedders.openai import OpenAIEmbedder
from promptcache.types import CacheMeta
embedder = OpenAIEmbedder(model="text-embedding-3-small")
backend = RedisVectorBackend(
url="redis://localhost:6379/0",
dim=embedder.dim,
)
cache = SemanticCache(
backend=backend,
embedder=embedder,
namespace="support-bot",
threshold=0.92,
)
meta = CacheMeta(
model="gpt-4.1-mini",
system_prompt="You are a helpful support assistant.",
)
result = cache.get_or_set(
prompt="How can I change my password?",
llm_call=my_llm_call,
extract_text=lambda r: r.output_text,
meta=meta,
)
print(result.cache_hit)
就这么简单——不需要任何编排框架。
GitHub:
PyPI:
安装
pip install promptcache-ai
适用场景
语义缓存在以下情况下表现最佳:
- 提示语重复度高
- 温度(temperature)低
- 答案相对稳定
- 请求量大
不太适用于:
- 高度个性化的提示
- 创意写作
- 上下文快速变化
在这些情况下,新颖性占主导,缓存的收益会递减。
更大的洞见
大多数 LLM 系统本质上是无状态的;即使没有任何实质性变化,它们仍会重新计算答案。语义缓存引入了选择性的记忆,仅在经济上合理时复用智能。
与其不停地微调提示,有时更聪明的做法是优化基础设施。如果你在生产环境中构建 LLM 系统,语义缓存是可以带来最高杠杆效应的优化之一。
智能是昂贵的。
记忆是廉价的。
明智地同时使用两者。