📢 转载信息
原文链接:https://machinelearningmastery.com/build-an-inference-cache-to-save-costs-in-high-traffic-llm-apps/
原文作者:Kanwal Mehreen
在本文中,您将学习如何为大语言模型(LLM)应用程序添加精确匹配和语义推理缓存,从而在大规模应用中降低延迟和API成本。
我们将涵盖的主题包括:
- 在高流量应用中,重复查询为何会浪费时间和金钱。
- 如何构建一个最小化的精确匹配缓存并衡量其影响。
- 如何使用嵌入(embeddings)和余弦相似度来实现语义缓存。
好了,让我们开始吧。

构建推理缓存以降低高流量LLM应用的成本
图片来源:Editor
引言
大语言模型(LLMs)广泛应用于聊天机器人、客户支持、代码助手等应用程序中。这些应用程序通常每天处理数百万次查询。在高流量应用中,用户提出相同或相似问题的现象非常普遍。现在请思考一下:当模型不是免费的并且会增加响应延迟时,每次调用LLM是否明智?从逻辑上讲,不是。
以客户服务机器人为例。每天可能有数千用户提出问题,其中许多问题是重复的:
- “你们的退款政策是什么?”
- “如何重置我的密码?”
- “交货时间是多久?”
如果每个查询都发送给LLM,您将不必要地耗尽API预算。每次重复请求的成本都一样,尽管模型之前已经生成过该答案。这就是推理缓存发挥作用的地方。您可以将其视为一个存储最常见问题并重复使用结果的内存。在本文中,我将通过代码为您提供一个高层次的概述。我们将从单个LLM调用开始,模拟高流量应用的样子,构建一个简单的缓存,然后研究一个您希望在生产环境中使用的更高级版本。让我们开始吧。
设置
安装依赖项。我在此演示中使用了 Google Colab。我们将使用 OpenAI Python 客户端:
1
|
!pip install openai
|
设置您的OpenAI API 密钥:
1
2
3
4
5
|
import os
from openai import OpenAI
os.environ["OPENAI_API_KEY"] = "sk-your_api_key_here"
client = OpenAI()
|
步骤 1:简单的LLM调用
此函数向模型发送提示词并打印所需时间:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import time
def ask_llm(prompt):
start = time.time()
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}]
)
end = time.time()
print(f"Time: {end - start:.2f}s")
return response.choices[0].message.content
print(ask_llm("What is your refund policy?"))
|
输出:
1
2
|
Time: 2.81s
As an AI language model, I don't have a refund policy since I don't...
|
对于一次调用来说,这运行良好。但是,如果同一个问题被一遍又一遍地问起怎么办?
步骤 2:模拟重复提问
我们创建一小部分用户查询列表。有些是重复的,有些是新的:
1
2
3
4
5
6
7
|
queries = [
"What is your refund policy?",
"How do I reset my password?",
"What is your refund policy?", # repeated
"What’s the delivery time?",
"How do I reset my password?", # repeated
]
|
让我们看看如果对每个查询都调用LLM会发生什么:
1
2
3
4
5
6
7
8
9
|
start = time.time()
for q in queries:
print(f"Q: {q}")
ans = ask_llm(q)
print("A:", ans)
print("-" * 50)
end = time.time()
print(f"Total Time (no cache): {end - start:.2f}s")
|
输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
Q: What is your refund policy?
Time: 2.02s
A: I don't handle transactions or have a refund policy...
--------------------------------------------------
Q: How do I reset my password?
Time: 10.22s
A: To reset your password, you typically need to follow...
--------------------------------------------------
Q: What is your refund policy?
Time: 4.66s
A: I don't handle transactions or refunds directly...
--------------------------------------------------
Q: What’s the delivery time?
Time: 5.40s
A: The delivery time can vary significantly based on several factors...
--------------------------------------------------
Q: How do I reset my password?
Time: 6.34s
A: To reset your password, the process typically varies...
--------------------------------------------------
Total Time (no cache): 28.64s
|
每一次,LLM都会再次被调用。即使有两个查询是完全相同的,我们仍然需要为此付费。对于数千用户来说,这些成本可能会飙升。
步骤 3:添加推理缓存(精确匹配)
我们可以用一个基于字典的缓存作为初步的解决方案来解决这个问题:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
cache = {}
def ask_llm_cached(prompt):
if prompt in cache:
print("(from cache, ~0.00s)")
return cache[prompt]
ans = ask_llm(prompt)
cache[prompt] = ans
return ans
start = time.time()
for q in queries:
print(f"Q: {q}")
print("A:", ask_llm_cached(q))
print("-" * 50)
end = time.time()
print(f"Total Time (exact cache): {end - start:.2f}s")
|
输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
Q: What is your refund policy?
Time: 2.35s
A: I don’t have a refund policy since...
--------------------------------------------------
Q: How do I reset my password?
Time: 6.42s
A: Resetting your password typically depends on...
--------------------------------------------------
Q: What is your refund policy?
(from cache, ~0.00s)
A: I don’t have a refund policy since...
--------------------------------------------------
Q: What’s the delivery time?
Time: 3.22s
A: Delivery times can vary depending on several factors...
--------------------------------------------------
Q: How do I reset my password?
(from cache, ~0.00s)
A: Resetting your password typically depends...
--------------------------------------------------
Total Time (exact cache): 12.00s
|
现在:
- 第一次提问“What is your refund policy?”时,它会调用LLM。
- 第二次提问时,它会立即从缓存中检索结果。
这极大地节省了成本并减少了延迟。
步骤 4:精确匹配的问题所在
精确匹配仅在查询文本完全相同时才有效。让我们看一个例子:
1
2
3
4
5
|
q1 = "What is your refund policy?"
q2 = "Can you explain the refund policy?"
print(ask_llm_cached(q1))
print(ask_llm_cached(q2)) # Not cached, even though it means the same!
|
输出:
1
2
3
4
5
|
(from cache, ~0.00s)
First: I don’t have a refund policy since...
Time: 7.93s
Second: Refund policies can vary widely depending on the company...
|
两个查询都在询问退款事宜,但由于文本略有不同,我们的缓存未命中。这意味着我们仍然需要为LLM付费。在现实世界中,这是一个大问题,因为用户会以不同的方式措辞问题。
步骤 5:使用嵌入进行语义缓存
为了解决这个问题,我们可以使用语义缓存。我们不是检查文本是否相同,而是检查查询在含义上是否相似。我们可以为此使用嵌入(embeddings):
评论区