Week2 day1 实现提示缓存(Prompt Caching)

 

 

环境前提:
  1. 安装依赖:pip install litellm python-dotenv
  2. .env 写入 GOOGLE_API_KEY=你的key
  3. 准备 hamlet.txt(哈姆雷特全文文本,你可以自行下载放到同目录)
python
 
运行
 
 
from dotenv import load_dotenv
import os
from litellm import completion

# 加载环境变量
load_dotenv(override=True)
os.environ["GOOGLE_API_KEY"] = os.getenv("GOOGLE_API_KEY")

# 读取长文本哈姆雷特
with open("hamlet.txt", "r", encoding="utf-8") as f:
    hamlet = f.read()

# 定位一小段文本用于验证
loc = hamlet.find("Speak, man")
print("文本片段预览:")
print(hamlet[loc:loc+100])
print("-" * 60)

# ========== 第一次提问:不带长篇上下文 ==========
question = [
    {
        "role": "user",
        "content": "In Hamlet, when Laertes asks 'Where is my father?' what is the reply?"
    }
]
response = completion(
    model="gemini/gemini-3.1-flash-lite",
    messages=question
)
print("【第1轮|无长上下文】")
print("回答:", response.choices[0].message.content)
print(f"输入token: {response.usage.prompt_tokens}")
print(f"输出token: {response.usage.completion_tokens}")
print(f"总token: {response.usage.total_tokens}")
cost = response._hidden_params.get("response_cost", 0)
print(f"费用: {cost*100:.4f} 美分\n")

# ========== 第二次提问:追加完整哈姆雷特文本(首次加载大上下文,构建缓存) ==========
question[0]["content"] += "\n\nFor context, here is the entire text of Hamlet:\n\n" + hamlet
response = completion(
    model="gemini/gemini-3.1-flash-lite",
    messages=question
)
print("【第2轮|首次载入全文,缓存预热】")
print("回答:", response.choices[0].message.content)
print(f"输入token: {response.usage.prompt_tokens}")
print(f"输出token: {response.usage.completion_tokens}")
cached_tokens = response.usage.prompt_tokens_details.cached_tokens
print(f"缓存命中token: {cached_tokens}")
cost = response._hidden_params.get("response_cost", 0)
print(f"费用: {cost*100:.4f} 美分\n")

# ========== 第三次提问:完全相同prompt,触发缓存复用 ==========
response = completion(
    model="gemini/gemini-3.1-flash-lite",
    messages=question
)
print("【第3轮|完全相同prompt,复用缓存】")
print("回答:", response.choices[0].message.content)
print(f"输入token: {response.usage.prompt_tokens}")
print(f"输出token: {response.usage.completion_tokens}")
cached_tokens = response.usage.prompt_tokens_details.cached_tokens
print(f"缓存命中token: {cached_tokens}")
cost = response._hidden_params.get("response_cost", 0)
print(f"费用: {cost*100:.4f} 美分")

 

 

运行现象说明

  1. 第 1 轮:只有简短问题,没有超长原文,无缓存;
  2. 第 2 轮:带上几万字哈姆雷特全文 → 缓存预热;
  3. 第 3 轮:一模一样的消息数组 → cached_tokens > 0,大量文本走缓存,价格更低。

拓展:OpenAI 提示缓存使用要点(代码示范片段)

OpenAI 要求:静态内容放在prompt 前缀,只有前缀完全一致才能触发缓存
python
 
运行
 
 
from openai import OpenAI
client = OpenAI()

# 静态长文本放在最前面(固定前缀,用于缓存)
static_context = """【大量固定知识库、指令、参考文档……】"""
dynamic_query = "用户实时问题,放在最后"

messages = [
    {"role": "user", "content": static_context + "\n" + dynamic_query}
]

resp = client.chat.completions.create(
    model="gpt-4o",
    messages=messages
)

 

 

拓展:Claude 提示缓存(需要显式标记缓存区块)

Claude 和 Gemini/OpenAI 不一样,必须手动标记哪一段开启缓存,不能自动隐式缓存:
python
 
运行
 
 
from anthropic import Anthropic
client = Anthropic()

message = client.messages.create(
    model="claude-3-5-sonnet-20240620",
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text": "大量固定参考文本...",
                    "cache_control": {"type": "ephemeral"} # 显式开启缓存
                },
                {"type": "text", "text": "你的问题"}
            ]
        }
    ]
)
 

 

重要实操提醒

  1. 缓存不是永久的,各家都有生存时间限制;
  2. 只要前缀文本改动一个字符,缓存失效;
  3. 适用场景:RAG、长知识库、固定系统提示 + 动态用户问题;
  4. 示例使用 Gemini + LiteLLM,是最简演示方案。
posted @ 2026-08-12 16:08  漫漫长路</>  阅读(3)  评论(0)    收藏  举报