Skip to main content
實踐教程

顯式緩衝最佳實務

本文介紹顯式緩衝的使用方法和最佳實務。顯式緩衝通過在請求中添加快取標籤,確保相同輸入內容確定性命中緩衝,從而顯著降低成本和延遲。

什麼時候使用顯式緩衝

  • 需要穩定命中緩衝的情境:當業務對快取命中有明確要求,需要確保指定內容被穩定複用時,建議使用顯式緩衝。顯式緩衝可做到 100% 確定性命中,不受後端資源調度影響。
  • 高頻複用相同 Prompt 的情境:當相同或高度一致的 Prompt 會被反覆提交時,顯式緩衝可以顯著降低調用成本。首次寫入緩衝僅產生標準價格 25% 的額外開銷,後續命中可節省 90% 成本;只要發生至少一次命中,總體成本即低於不使用緩衝的方案。
  • 工業級 Agent 的長上下文管理情境:在 Agent 應用中,常見的壓縮、recap、system reminder 等機制會導致上下文持續變化。顯式緩衝可對關鍵上下文片段進行標記和固定複用,確保這些內容在複雜上下文演化過程中仍能穩定命中緩衝。

常用 Agent 和 Coding 工具

以下 Agent 和 Coding 工具可通過 Anthropic 協議接入百鍊,原生支援顯式緩衝。只需按對應文檔完成配置,工具在運行過程中會自動使用顯式緩衝最佳化上下文管理。 以下樣本以新加坡端點為例,其他地區請替換為對應的地區端點。
  • Claude Code
  • Open Code
  • OpenClaw
  • Hermes
Claude Code 自 v2.x 起預設在請求中攜帶 cache_control 標記(system、env、最近 user message 三處),接入百鍊 Anthropic 相容端點後無需額外配置。接入配置建立 ~/.claude/settings.json(Windows:C:\Users\<使用者名稱>\.claude\settings.json),寫入對應套餐的配置。或通過環境變數接入:
export ANTHROPIC_BASE_URL="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/apps/anthropic"
export ANTHROPIC_AUTH_TOKEN="${DASHSCOPE_API_KEY}"
export ANTHROPIC_MODEL="qwen3.7-max"
claude
確保接入端點為 Anthropic 協議:
  • Token Plan (Team):https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic
  • Coding Plan:https://coding-intl.dashscope.aliyuncs.com/apps/anthropic
  • 隨用隨付:https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/apps/anthropic,調用時請將WorkspaceId替換為真實的Workspace ID
詳見 Claude Code可選:提升跨會話命中率Claude Code 預設會在 system prompt 中包含目前的目錄、日期、git 狀態等動態資訊,可能導致跨會話命中率下降。啟動時增加以下參數可將動態部分移至 user message:
claude --exclude-dynamic-system-prompt-sections
可選:關閉顯式緩衝如需關閉(一般無須關閉):
export DISABLE_PROMPT_CACHING=1
支援按模型粒度關閉:DISABLE_PROMPT_CACHING_HAIKUDISABLE_PROMPT_CACHING_SONNETDISABLE_PROMPT_CACHING_OPUS

API 接入

核心要點

  • 在需要緩衝的訊息上添加 "cache_control": {"type": "ephemeral"},從 messages 數組開頭到該標記位置之間的所有內容將被建立為緩衝塊。
  • 緩衝內容最少需要 1024 Token
  • 單次請求最多支援 4 個快取標籤。
  • 緩衝有效期間為 5 分鐘,每次命中自動續期。
  • Tools 定義是 System Prompt 的一部分參與緩衝計算,如果 Tools 改變則無法命中緩衝。

快速開始

以下樣本展示了顯式緩衝的基本使用方式:第一次請求建立緩衝,第二次請求命中緩衝。
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 調用時請將WorkspaceId替換為真實的Workspace ID。
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

# 需要緩衝的長文本(需超過 1024 Token)
long_text_content = "<Your Long Text Here>" * 400

def get_completion(user_input):
    messages = [
        {
            "role": "system",
            "content": [
                {
                    "type": "text",
                    "text": long_text_content,
                    # 添加快取標籤:從 messages 開頭到此位置的內容將被緩衝
                    "cache_control": {"type": "ephemeral"},
                }
            ],
        },
        {"role": "user", "content": user_input},
    ]
    completion = client.chat.completions.create(
        model="qwen3.7-max",
        messages=messages,
        extra_body={"enable_thinking": False},
    )
    return completion

# 第一次請求:建立緩衝
first = get_completion("請總結文檔的核心要點")
print(f"建立緩衝 Token:{first.usage.prompt_tokens_details.cache_creation_input_tokens}")
print(f"命中緩衝 Token:{first.usage.prompt_tokens_details.cached_tokens}")

# 第二次請求:相同 system 內容,不同問題,命中緩衝
second = get_completion("文檔中提到了哪些注意事項?")
print(f"建立緩衝 Token:{second.usage.prompt_tokens_details.cache_creation_input_tokens}")
print(f"命中緩衝 Token:{second.usage.prompt_tokens_details.cached_tokens}")
運行上述代碼,預期輸出類似如下:
建立緩衝 Token:2005
命中緩衝 Token:0
建立緩衝 Token:0
命中緩衝 Token:2005
第一次請求時系統建立緩衝塊,第二次請求因 System Prompt 內容完全一致,成功命中緩衝。命中緩衝的 Token 僅按標準輸入價格的 10% 計費。

確認緩衝狀態

請求完成後,可以通過響應中的 usage 欄位確認緩衝狀態:
  • cache_creation_input_tokens:本次請求新建立緩衝的 Token 數。該值大於 0 說明建立了新緩衝。
  • cached_tokens(OpenAI 相容)或 cache_read_input_tokens(Anthropic 相容):本次請求命中緩衝的 Token 數。該值大於 0 說明成功命中緩衝。

不同情境下的最佳實務

多輪對話情境

情境特點:
  • 使用者與模型進行多輪互動,每輪請求攜帶完整對話歷史
  • 典型應用:客服對話、知識問答、代碼輔助等
最佳實務:在每次請求的最後一條訊息上添加 cache_control 標記。每輪對話都會命中上一輪建立的緩衝(對話歷史部分),同時為下一輪建立包含當前完整對話的新緩衝。 樣本:
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 調用時請將WorkspaceId替換為真實的Workspace ID。
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

# System Prompt(產品手冊,需超過 1024 Token)
product_manual = """你是智能家居產品"百鍊智家"的客服助手。以下是完整產品手冊:

## 產品概述
百鍊智家 是一款全屋智能中控裝置,支援語音控制、情境聯動、能耗管理等功能...

## 安裝指南
1. 選擇中心位置安裝,確保 WiFi 訊號覆蓋...
2. 串連電來源配接器(5V/2A)...

## 常見問題
Q: 裝置無法串連 WiFi?A: 請確認路由器支援 2.4GHz...
""" * 80  # 重複以確保超過 1024 Token

messages = [{"role": "system", "content": product_manual}]

def chat(user_input):
    # 關鍵:在最後一條使用者訊息上添加 cache_control
    messages.append({
        "role": "user",
        "content": [
            {
                "type": "text",
                "text": user_input,
                "cache_control": {"type": "ephemeral"},
            }
        ],
    })
    completion = client.chat.completions.create(
        model="qwen3.7-max",
        messages=messages,
        extra_body={"enable_thinking": False},
    )
    assistant_msg = completion.choices[0].message.content
    messages.append({"role": "assistant", "content": assistant_msg})

    usage = completion.usage
    created = usage.prompt_tokens_details.cache_creation_input_tokens
    cached = usage.prompt_tokens_details.cached_tokens
    print(f"  [緩衝] 建立: {created} Token, 命中: {cached} Token")
    return assistant_msg

# 類比多輪客服對話
print("使用者: 百鍊智家 支援哪些語音助手?")
print(f"客服: {chat('百鍊智家 支援哪些語音助手?')[:60]}...\n")

print("使用者: WiFi 連不上怎麼辦?")
print(f"客服: {chat('WiFi 連不上怎麼辦?')[:60]}...\n")

print("使用者: 可以同時控制多少個裝置?")
print(f"客服: {chat('可以同時控制多少個裝置?')[:60]}...")
運行結果樣本:
使用者: 百鍊智家支援哪些語音助手?
  [緩衝] 建立: 8658 Token, 命中: 0 Token
客服: 百鍊智家支援天貓精靈、小愛同學、Siri等主流語音助手...

使用者: WiFi 連不上怎麼辦?
  [緩衝] 建立: 149 Token, 命中: 8658 Token
客服: WiFi 串連問題請按以下步驟排查:1. 確認路由器支援 2.4GHz...

使用者: 可以同時控制多少個裝置?
  [緩衝] 建立: 162 Token, 命中: 8807 Token
客服: 百鍊智家最多可同時控制 256 個智慧型裝置...
從第二輪開始,每輪對話都命中了上一輪建立的緩衝(即之前完整的對話歷史),同時建立包含當前輪新內容的緩衝。對話輪數越多,節約越顯著。

複雜工業級 Agent 情境

情境特點:
  • 超長多輪對話,包含:長 System Prompt + skills/tools 說明 + project 上下文 + 使用者對話 / 工具調用
  • 不同部分的變化頻率不同
  • 典型應用:AI 編程助手(如 Claude Code、OpenClaw)、RAG 問答系統等
最佳實務:使用多個快取標籤(最多 4 個),分別標記不同穩定性層級的內容。每個標記需放在不同的 message 上才能作為獨立截斷點:
  • System Prompt 加一個(幾乎不變)
  • skills/tools 說明加一個(可能出現組合變化)
  • project 上下文加一個(可能切換/壓縮)
  • 使用者對話 / 工具調用加一個(每輪增長)
樣本:以下樣本中,系統人設幾乎不變(快取標籤 1),知識庫隨商品切換而變化(快取標籤 2),對話歷史每輪增長(快取標籤 3)。注意:知識庫放在 user message 中,以確保它有獨立的緩衝截斷點——多條 system message 會被內部合并,無法作為獨立截斷點:
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 調用時請將WorkspaceId替換為真實的Workspace ID。
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

# 第一層:系統人設(幾乎不變)
system_persona = """你是"百鍊電子"的進階客服 AI 助手。你需要:
1. 基於知識庫內容準確回答使用者問題
2. 對於知識庫中沒有的資訊,如實告知"我需要為您轉接人工客服"
3. 始終保持專業、友善的語氣
4. 如使用者表示不滿,先致歉再解決問題

以下是你的完整服務規範和話術指南:
""" + "服務規範詳細說明..." * 200  # 確保超過 1024 Token

# 第二層:知識庫檢索結果(半穩定,隨使用者諮詢的商品變化)
knowledge_base_product_a = """### 當前諮詢商品:百鍊 Pro Max 無線耳機
- SKU: BL-PM-2024
- 價格: 599 元
- 顏色: 極夜黑 / 星雲白 / 冰晶藍
- 續航: 主動降噪開啟 8 小時,關閉 12 小時
- 防水等級: IPX5
- 保修: 1 年質保,支援 7 天無理由退換
- 當前庫存: 極夜黑(充足)/ 星雲白(少量)/ 冰晶藍(缺貨)
""" * 50  # 確保超過 1024 Token

def ask_about_product_a(user_question, history=None):
    if history is None:
        history = []
    messages = [
        {
            "role": "system",
            "content": [
                {
                    "type": "text",
                    "text": system_persona,
                    "cache_control": {"type": "ephemeral"},  # 快取標籤 1:系統人設
                }
            ],
        },
        {
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text": f"以下是當前商品的知識庫資訊:\n{knowledge_base_product_a}",
                    "cache_control": {"type": "ephemeral"},  # 快取標籤 2:知識庫
                }
            ],
        },
        {"role": "assistant", "content": "好的,我已瞭解該商品的詳細資料,請問有什麼可以幫您?"},
    ]
    # 添加對話歷史
    messages.extend(history)
    # 添加當前問題(帶快取標籤 3)
    messages.append({
        "role": "user",
        "content": [
            {
                "type": "text",
                "text": user_question,
                "cache_control": {"type": "ephemeral"},  # 快取標籤 3:對話歷史
            }
        ],
    })

    completion = client.chat.completions.create(
        model="qwen3.7-max",
        messages=messages,
        extra_body={"enable_thinking": False},
    )
    usage = completion.usage
    print(f"  建立緩衝: {usage.prompt_tokens_details.cache_creation_input_tokens}, "
          f"命中緩衝: {usage.prompt_tokens_details.cached_tokens}")
    return completion.choices[0].message.content

# 第一次:使用者詢問商品 A
print("Q1: 這款耳機有冰晶藍色嗎?")
a1 = ask_about_product_a("這款耳機有冰晶藍色嗎?")
print(f"A1: {a1}\n")

# 第二次:繼續追問商品 A(系統人設 + 知識庫均命中)
history = [
    {"role": "user", "content": "這款耳機有冰晶藍色嗎?"},
    {"role": "assistant", "content": a1},
]
print("Q2: 那什麼時候能補貨?")
a2 = ask_about_product_a("那什麼時候能補貨?", history)
print(f"A2: {a2}")
運行結果樣本:
Q1: 這款耳機有冰晶藍色嗎?
  建立緩衝: 7394, 命中緩衝: 0
A1: 百鍊 Pro Max 無線耳機確實有冰晶藍配色,不過...目前該顏色暫時缺貨...

Q2: 那什麼時候能補貨?
  建立緩衝: 0, 命中緩衝: 7394
A2: 關於冰晶藍的具體補貨時間...我需要為您轉接人工客服...
第二輪中,從請求起始到快取標籤 2(系統人設 + 知識庫 = 7,394 Token)的首碼完全一致,因此全部命中緩衝。僅標記 2 之後的新增內容(對話歷史 + 新問題)需要正常處理。 多標記緩衝的命中邏輯:
  • 使用者繼續追問同一商品:系統人設 + 知識庫均未變化,命中快取標籤 2 處的緩衝(最長首碼匹配),節約最大。
  • 對話輪次增加:前面的內容(系統人設 + 知識庫 + 歷史對話)命中上一輪的緩衝,僅新增部分需建立新緩衝。
建議將內容按穩定性從高到低排列:將變化最少的內容放在最前面(如系統人設),變化最頻繁的內容放在最後面(如目前的交談),以最大化快取命中率。

任務完成型情境(批量處理)

情境特點:
  • 單輪對話,不需要上下文記憶
  • 不變的長 System Prompt(任務說明)+ 變化的使用者輸入(待處理資料)
  • 典型應用:文本分類、意圖識別、資料提取、內容審核等
最佳實務:僅在 System Prompt 上添加 cache_control 標記。後續每次請求只要 System Prompt 不變,即可命中緩衝。 樣本:
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 調用時請將WorkspaceId替換為真實的Workspace ID。
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

# 長 System Prompt:包含詳細的分類規則說明(需超過 1024 Token)
classification_prompt = """你是一個電商評論分類助手。請將使用者評論分類為以下類別之一:
- 正面評價
- 負面評價
- 中性評價
- 諮詢問題
- 投訴建議

只輸出類別名稱,不要其他內容。

以下是詳細的分類規則和樣本:
""" + """規則說明:
1. 正面評價:包含積極情感詞彙(如"好"、"棒"、"滿意"、"推薦"等),或表達對供應項目的肯定。
2. 負面評價:包含消極情感詞彙(如"差"、"失望"、"退貨"等),或表達對供應項目的不滿。
3. 中性評價:情感傾向不明顯,僅陳述事實。
4. 諮詢問題:以疑問句形式出現,詢問產品資訊。
5. 投訴建議:表達改進意見或提出投訴。
""" * 100

# 待分類的評論列表(類比批量處理情境)
reviews = [
    "這個產品太棒了,品質超好,強烈推薦!",
    "發貨太慢了,等了一個星期才到,封裝還破損了",
    "請問這個商品有紅色的嗎?尺碼偏大還是偏小?",
    "建議增加更多尺碼選擇,M碼對我來說太大了",
    "東西還行吧,中規中矩,沒什麼驚喜",
]

print("=== 批量文本分類(顯式緩衝)===")
for i, review in enumerate(reviews):
    completion = client.chat.completions.create(
        model="qwen3.7-max",
        messages=[
            {
                "role": "system",
                "content": [
                    {
                        "type": "text",
                        "text": classification_prompt,
                        "cache_control": {"type": "ephemeral"},  # 緩衝分類規則
                    }
                ],
            },
            {"role": "user", "content": review},
        ],
    )
    result = completion.choices[0].message.content
    cached = completion.usage.prompt_tokens_details.cached_tokens
    created = completion.usage.prompt_tokens_details.cache_creation_input_tokens
    print(f"評論{i+1}: \"{review[:20]}...\"{result}")
    print(f"  建立緩衝: {created}, 命中緩衝: {cached}")
運行結果樣本:
評論1: "這個產品太棒了,品質超好,強烈推..." → 正面評價
  建立緩衝: 5353, 命中緩衝: 0
評論2: "發貨太慢了,等了一個星期才到,封裝..." → 負面評價
  建立緩衝: 0, 命中緩衝: 5353
評論3: "請問這個商品有紅色的嗎?尺碼偏大還..." → 諮詢問題
  建立緩衝: 0, 命中緩衝: 5353
評論4: "建議增加更多尺碼選擇,M碼對我來說..." → 投訴建議
  建立緩衝: 0, 命中緩衝: 5353
評論5: "東西還行吧,中規中矩,沒什麼驚喜..." → 中性評價
  建立緩衝: 0, 命中緩衝: 5353
第一條請求建立緩衝後,後續所有請求均命中緩衝。處理 1000 條資料時,999 次請求的輸入 Token 成本降低 90%。

Function Calling 時緩衝工具列表

情境特點:
  • 使用 Function Calling 功能,工具定義列表較長
  • 工具定義在多次請求間保持不變
最佳實務:tools 參數的內容會作為 System Prompt 的一部分參與緩衝。只需確保每次請求的工具定義完全一致(工具順序、欄位順序、欄位結構),並在 messages 的 content 上添加 cache_control 標記即可。
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 調用時請將WorkspaceId替換為真實的Workspace ID。
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

# 類比長文本確保超過 1024 Token 閾值
long_text_content = "<Your Code Here>" * 400

# 工具定義:確保每次請求完全一致
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "查詢指定城市的當前天氣資訊",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "城市名稱"},
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
                },
                "required": ["city"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "search_flights",
            "description": "搜尋兩個城市之間的航班",
            "parameters": {
                "type": "object",
                "properties": {
                    "origin": {"type": "string", "description": "出發城市"},
                    "destination": {"type": "string", "description": "目的城市"},
                    "date": {"type": "string", "description": "出發日期,格式 YYYY-MM-DD"}
                },
                "required": ["origin", "destination", "date"]
            }
        }
    }
]

def ask(user_input):
    messages = [
        {
            "role": "system",
            "content": [
                {
                    "type": "text",
                    "text": long_text_content,
                    # cache_control 只能加在 messages 的 content 上,不能加在 tools 上
                    "cache_control": {"type": "ephemeral"},
                }
            ],
        },
        {"role": "user", "content": user_input},
    ]
    completion = client.chat.completions.create(
        model="qwen3.7-max",
        messages=messages,
        tools=tools,
        extra_body={"enable_thinking": False},
    )
    usage = completion.usage
    print(f"  建立緩衝: {usage.prompt_tokens_details.cache_creation_input_tokens}, "
          f"命中緩衝: {usage.prompt_tokens_details.cached_tokens}")
    tool_calls = completion.choices[0].message.tool_calls
    if tool_calls:
        print(f"  調用工具: {[t.function.name for t in tool_calls]}")
    return completion

# 第一次請求:建立緩衝(包含 tools 定義)
print("Q1: 北京今天天氣怎麼樣?")
ask("北京今天天氣怎麼樣?")

# 第二次請求:命中緩衝
print("\nQ2: 幫我查明天從上海到北京的航班")
ask("幫我查明天從上海到北京的航班")
運行結果樣本:
Q1: 北京今天天氣怎麼樣?
  建立緩衝: 1995, 命中緩衝: 0
  調用工具: ['get_weather']

Q2: 幫我查明天從上海到北京的航班
  建立緩衝: 0, 命中緩衝: 1995
  調用工具: ['search_flights']
提高 Function Calling 快取命中率的關鍵:
  • 工具列表順序一致:tools 數組中各工具的排列順序需保持一致。
  • 欄位順序一致:同一個 tool 的 JSON 欄位順序需保持一致。
  • 欄位結構一致:不要遺漏或新增欄位,即使該欄位為空白或可選。

注意事項

  • content 格式要求:添加 cache_control 時,必須將 content 欄位改為數組形式。字串形式的 content 不支援添加快取標籤。
  • 快取標籤粒度:Qwen3.5 及之後的模型僅支援訊息層級的緩衝截斷點。在同一條 message 的 content 數組內放置多個 cache_control 不會產生多個截斷點——系統僅在該 message 的最後一個 marker 位置儲存緩衝,無法在中間 block 處截斷命中。此外,多條 system message 會被內部合并為一個整體,也無法在中間截斷。如需多個獨立截斷點,應將帶 cache_control 的內容分布在不同角色的 message 上(如 system 放一個,user 放一個)。Qwen3.5 之前的模型支援 content 層級(訊息內部)的緩衝截斷。
  • 與隱式緩衝互斥:同一請求只能使用一種緩衝模式。若請求中包含 cache_control 標記則使用顯式緩衝,否則系統自動使用隱式緩衝。

支援的模型

支援顯式緩衝的模型列表請參見上下文緩衝
Token Plan
模型體驗
  • 音樂產生
用量統計與效能監控
資產中心
服務支援