AI-LECTURER 速報課|2026-09-24|約 25 分鐘

GPT-6 提示詞快取升級:讓跑好幾小時的 AI 代理人更快、更省,還能查出「為什麼沒命中」

取材:Better prompt caching for GPT-6(OpenAI News)
📍 真實場景
阿哲,台中一家 12 人軟體外包公司的後端工程師,正在用 GPT-6 打造「自動重構舊程式碼」的 AI 代理人。

他的代理人一跑就是兩三個小時:每往前一步就要呼叫一次 API,而且每次都得重新帶上同一份很長的作業規則、二十幾個工具的說明書,還有前面所有的對話紀錄。

😖 卡住的地方:月底帳單比預估高出一截,他卻看不出錢花在哪。更糟的是,上週他為了「這一輪用不到搜尋工具」,隨手把工具清單刪掉幾個,隔天成本反而更高——他完全不知道,問題出在自己「好心」改了工具清單。
💡 這堂課會給他一套完整的判斷方法:看懂快取到底「認」什麼、用儀表板抓出命中率掉在哪一天、用診斷工具查出是哪個改動害的,再學會幾招「改東西又不弄壞快取」的做法。

🧭 這到底是什麼(白話版)

當你用 GPT-6 打造 AI 代理人能自己規劃步驟、呼叫工具、連續工作很久的 AI 程式,不是問一句答一句的聊天機器人,它每往前做一步,就要透過 API應用程式介面,程式用來呼叫別人服務的標準入口,這裡指你的程式跟 OpenAI 溝通的管道 送出一次請求。OpenAI 在說明裡點出一個關鍵現象:這些請求是一環扣一環的,每一次都常常重複帶著同樣的指示、工具定義用文字寫給 AI 的「工具說明書」,告訴它有哪些工具可用、每個工具的參數要怎麼填,還有前面幾輪的內容。

既然每次的開頭都差不多,何必每次從頭算一遍?這就是 提示詞快取把多次請求共有的開頭內容「算過的結果」記起來,下次遇到一樣的開頭就直接重用,不必重算 的概念。OpenAI 表示,快取能重用計算、縮短回應時間,而且對被快取的輸入 tokenAI 處理文字的最小計量單位,大約是一個字或半個字,計費就是按 token 數量算 提供最高 90% 的折扣。

GPT-6 家族推出了改良版快取:預設就有更高的 命中率送出的請求裡,有多少比例成功找到之前記過的內容而重用;找不到就叫沒命中,英文是 cache miss。符合資格的「共用前綴」(前綴一段內容從第一個字開始算起的開頭部分,必須從頭就一模一樣才算共用),只要在 30 分鐘的視窗內再次被用到,就能拿到快取折扣。請抓住那個關鍵字:是「前綴」。從官方要你「保持工具定義與順序穩定、把新指示加在後面」的建議可以推得,快取認的是「從開頭起完全一樣的那一段」,一旦前面某處變了,後面就對不上了。

除了提高命中率,這次還給開發者幾樣新工具:能看命中率走勢的 Prompt Caching Dashboard(儀表板)、能回答「為什麼沒命中」的診斷工具、能自己決定「哪一段要被快取」的明確快取斷點(explicit cache breakpoints),以及讓你在不弄壞快取的前提下調整 推理力道reasoning effort,讓模型決定「想多深」的設定:越高,代表模型願意花越多力氣思考 的做法。這堂課要教你的,就是把它們組合成一套「省錢又省時間」的工程習慣。

🎯 為什麼值得你花時間

帳單:重複的開頭,最高省 90%代理人每一輪都重複帶同一大包內容,這正是快取最能發揮的地方。OpenAI 表示,被快取的輸入 token 最高可享 90% 折扣。工作越長、輪數越多、重複的開頭越大,省下的就越多,所以對「一跑好幾小時」的代理人特別划算。
速度:重用計算,回應更快快取不只是打折,它還讓 OpenAI 重用先前的計算,因此縮短回應時間。代理人完成一個任務要來回很多次,每次快一點,累積起來就是使用者體感上的「它比較不卡」。
可控:從「默默發生」變成「看得到、查得出、管得到」這次新增了儀表板(看命中率趨勢,以及已快取/未快取 token 的比例)、診斷工具(指出沒命中的原因與受影響 token 數)、明確斷點(自己選要快取哪一段)。快取不再是你只能祈禱的幕後優化,而是能量測、能除錯、能調整的工程指標。

⚙️ 它是怎麼運作的

1
送出請求:前面一大段,每輪幾乎一樣代理人每一輪送出的請求,大致由「指示+工具說明書+前面的對話+這一輪的新內容」組成。前面那一大段每輪幾乎不變,只有最後面的新內容不同。
2
比對開頭:有沒有共用前綴?系統會看你這次請求的開頭,跟近期請求有沒有共用的前綴。官方的折扣條件是:符合資格的共用前綴,在 30 分鐘的視窗內被再次使用。
3
命中:重用計算、享折扣共用的那一段直接重用先前的計算:回應更快,而且這段被快取的輸入 token 最高可以享 90% 折扣。沒共用的部分(例如新的問題)照常計算、照常計費。
4
沒命中:用診斷工具查原因遇到意料之外的沒命中,就拿診斷工具比對這次請求和最近一次回應,它會指出是模型、工具、設定或輸入哪一項變了,並估計受影響的 token 數。例如官方範例回報 reason 是 tools_changed,受影響 5629 個 token。
5
長期監控:看儀表板Prompt Caching Dashboard 會畫出命中率隨時間的變化,並提供輸入組成圖,讓你比較已快取與未快取的 token。你就能發現「哪天命中率突然掉了」,再回頭想是不是那天改了什麼。
6
調整:改行為,但別動前面想控制快取範圍,可用明確快取斷點挑選要重用的前綴。想改行為,遵守「前面不動、變化放後面」:用 allowed_tools請求裡的設定,指定這一輪只有哪些工具可以被呼叫,其他工具的定義仍留在原處 限縮工具,或把 tool_choice請求裡決定模型要不要用工具的設定;設成 none 就是這一輪不用工具 設成 none;新指示用 developer 訊息由開發者(也就是你)加入對話的指示訊息,放得越後面,越能當作最新的指示 追加在最後;調推理力道則用 configuration_update附加在對話尾端的設定更新,讓你調整推理力道這類設定,卻不必動請求層級的設定
改東西的兩種做法:哪些可能弄壞快取,哪些是官方建議的保命做法
你想做的事可能弄壞快取的做法官方建議、能保住快取的做法
這一輪用不到某些工具把那幾個工具的定義從清單裡刪掉定義原封不動;用 allowed_tools 只開放相關工具,或設 tool_choice 為 none 表示這輪不用工具
想新增或推翻一條指示回頭去改前面的舊指示用新的 developer 訊息追加在最後面,蓋過舊指示
想調高或調低推理力道直接改請求層級的推理力道設定在後面附加 configuration_update,請求層級的設定保持不變
想整理工具清單調換順序,或修改參數格式(schema)保持工具定義、參數格式、順序都穩定

🔍 程式碼漫遊(點有 ● 的行看白話講解)

這是 cache_lab.py 的核心:diagnose 函式。它模擬「拿新請求跟上一個請求比開頭」,找出第一個對不上的地方,再用跟官方診斷相似的 JSON 格式回報。注意:這是教學用的簡化模擬器,比對邏輯只為了幫你理解概念,並不是 OpenAI 的真實實作。

def diagnose(prev, curr, minutes_gap):
💬 定義函式:拿「上一個請求 prev」和「這一個請求 curr」互相比對,再帶入兩次請求相隔幾分鐘。
"""比對「上一個請求」與「這一個請求」,輸出仿官方診斷的 JSON 結構。
💬 這兩行是說明文字:一個請求就是一串「區塊」,每個區塊由(種類, 內容)組成。
請求 = [(種類, 內容), ...];種類沿用新聞稿提到的 model / settings / tools / input。"""
💬 種類沿用新聞稿提到的四類變動:模型(model)、設定(settings)、工具(tools)、輸入(input)。
if minutes_gap > WINDOW_MINUTES:
💬 先檢查時間:隔超過 30 分鐘,就算開頭一模一樣,也不再符合折扣資格。
return {"type": "cache_miss", "reason": "window_expired"}
💬 直接回報 window_expired。這個原因名稱是模擬器自己取的,官方文件的名稱請以官方為準。
reusable = 0
💬 reusable 記錄「到目前為止可以重用的 token 數」,從 0 開始累加。
for i, (old, new) in enumerate(zip(prev, curr)):
💬 從頭開始,一個區塊一個區塊地比新舊請求——這就是「前綴」比對:只認開頭,一路比到出現差異為止。
if old != new: # 第一個對不上的區塊:從這裡起,後面全部跟著失效
💬 第一個不一樣的區塊出現了!從這裡開始,後面就算一模一樣也全部算沒命中——這是整堂課最重要的一行。
missed = sum(tokens(text) for _, text in curr[i:])
💬 把「這個區塊(含)之後」所有區塊的 token 加總,就是受影響的 token 數。
return {"type": "cache_miss", "reason": new[0] + "_changed",
💬 回報 cache_miss;reason 用「被改動區塊的種類」加上 _changed,例如 tools_changed(新聞稿範例只出現這一種,其他名稱是仿照命名)。
"comparison_reusable_tokens": reusable,
💬 前面已經對上的 token 數:這些還是可以重用的部分。
"cache_missed_tokens": missed}
💬 沒命中的 token 數:這就是官方診斷所說「受影響的 token」的模擬版。
reusable += tokens(new[1])
💬 這個區塊新舊一模一樣,把它的 token 數計入可重用,然後繼續比下一個。
fresh = sum(tokens(text) for _, text in curr[len(prev):])
💬 整段都走完、沒有任何差異:代表上一個請求整個都是這次請求的開頭,只有結尾多出來的部分要重算。
return {"type": "cache_hit", "comparison_reusable_tokens": reusable,
💬 回報 cache_hit 以及可重用的 token 數。
"new_tokens": fresh}
💬 new_tokens 是這次必須全新計算的部分(例如新加的問題)。

🛠️ 動手做:動手做:用一支 Python「快取模擬器」,親眼看「改哪裡最傷」

這是一個真實小專案:下載(或複製)檔案,照步驟在你電腦上跑起來。

📄 cache_lab.py ⬇ 下載
# cache_lab.py — 提示詞快取「前綴比對」模擬器
# 純 Python 標準庫,不連網、不需要 API 金鑰;只用來體會「改了前面,後面全部對不上」。
import json

WINDOW_MINUTES = 30  # 新聞稿:符合資格的共用前綴,30 分鐘視窗內再用才有折扣
MAX_DISCOUNT = 0.9   # 新聞稿寫「最高 90%」;實際折扣請以官方定價頁為準


def tokens(text):
    # 教學用粗估(約 4 個字元算 1 個 token);真實用量請看 API 回傳的數字
    return max(1, len(text) // 4)


def diagnose(prev, curr, minutes_gap):
    """比對「上一個請求」與「這一個請求」,輸出仿官方診斷的 JSON 結構。
    請求 = [(種類, 內容), ...];種類沿用新聞稿提到的 model / settings / tools / input。"""
    if minutes_gap > WINDOW_MINUTES:
        return {"type": "cache_miss", "reason": "window_expired"}
    reusable = 0
    for i, (old, new) in enumerate(zip(prev, curr)):
        if old != new:  # 第一個對不上的區塊:從這裡起,後面全部跟著失效
            missed = sum(tokens(text) for _, text in curr[i:])
            return {"type": "cache_miss", "reason": new[0] + "_changed",
                    "comparison_reusable_tokens": reusable,
                    "cache_missed_tokens": missed}
        reusable += tokens(new[1])
    fresh = sum(tokens(text) for _, text in curr[len(prev):])
    return {"type": "cache_hit", "comparison_reusable_tokens": reusable,
            "new_tokens": fresh}


def relative_cost(curr, result):
    """相對成本:沒命中的 token 算 1,命中快取的 token 依折扣打折。"""
    total = sum(tokens(text) for _, text in curr)
    reusable = result.get("comparison_reusable_tokens", 0)
    return round(total - reusable * MAX_DISCOUNT)


def swap(request, index, block):
    # 複製一份再改,避免動到原本的請求
    copy = list(request)
    copy[index] = block
    return copy


TOOLS = "search_code: 搜尋程式碼\nread_file: 讀取檔案\nrun_tests: 執行測試\n" * 40
RULES = "你是重構代理人:小步修改、每步都跑測試、不可刪除公開函式。\n" * 30
# 模擬器假設的排列順序是 model → settings → tools → input(真實系統以官方文件為準),
# 只是為了讓你體會「越前面的東西一變,損失越大」。
turn1 = [("model", "gpt-6"), ("settings", "reasoning_effort=medium"),
         ("tools", TOOLS), ("input", RULES), ("input", "請重構 utils.py")]
tail = [("input", "已完成 utils.py"), ("input", "接著重構 db.py")]

SCENARIOS = [
    ("A 正常做法:只在最後追加新問題", turn1 + tail, 5),
    ("B 這輪用不到 run_tests,所以把它從工具清單刪掉",
     swap(turn1, 2, ("tools", TOOLS.replace("run_tests: 執行測試\n", "", 1))) + tail, 5),
    ("C 回頭去改前面的舊指示",
     swap(turn1, 3, ("input", RULES + "請改用繁體中文回覆。\n")) + tail, 5),
    ("D 在最後追加一則 developer 訊息來蓋過舊指示",
     turn1 + tail + [("input", "[developer] 從現在起請改用繁體中文回覆。")], 5),
    ("E 直接把推理力道從 medium 改成 high(模擬:設定屬於被比對的前面內容)",
     swap(turn1, 1, ("settings", "reasoning_effort=high")) + tail, 5),
    ("F 改用 configuration_update 附加在最後來調高推理力道",
     turn1 + tail + [("configuration_update", "reasoning_effort=high")], 5),
    ("G 一切照 A,但距離上次請求已過 45 分鐘",
     turn1 + tail, 45),
]

if __name__ == "__main__":
    for name, request, gap in SCENARIOS:
        result = diagnose(turn1, request, gap)
        print("=" * 50)
        print(name)
        print(json.dumps({"prompt_cache_diagnostics": result}, ensure_ascii=False, indent=2))
        no_cache = sum(tokens(text) for _, text in request)
        print("相對成本:{}(完全沒快取會是 {})".format(relative_cost(request, result), no_cache))
  1. 把下載的 cache_lab.py 放進一個好找的資料夾,例如 C:\lab(在檔案總管新增資料夾即可)。
  2. 按 Win 鍵,輸入 PowerShell 開啟視窗,切到該資料夾:cd C:\lab
  3. 確認電腦有 Python:py -3 --version(看到 Python 3.x 即可;若提示找不到,請先到 python.org 安裝,安裝時勾選 Add python.exe to PATH)。
  4. 讓中文正常顯示,先輸入:chcp 65001 接著輸入:[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
  5. 執行模擬器:py -3 cache_lab.py
  6. 對答案:情境 A、D、F 應顯示 cache_hit(可重用 744 個 token);B 顯示 tools_changed(可重用只剩 6);C 顯示 input_changed(可重用 516);E 顯示 settings_changed(可重用 1);G 顯示 window_expired。數字是模擬器的粗估,你的結果應該與此一致。
  7. 觀察重點:B、C、E 都只是「改了一點點」,為什麼損失差這麼多?對照每個情境最後一行的「相對成本」:A 只有 79,B 卻高達 740。答案:改動的位置越靠前,後面被連累失效的內容越多。
  8. 動手 1:把 cache_lab.py 裡 TOOLS 那一行的「* 40」改成「* 4」,存檔後重跑。情境 B 的 cache_missed_tokens 會從 739 掉到約 280——工具說明書越大,隨手刪一個工具越痛。(改完記得把 * 40 改回來再做下一步。)
  9. 動手 2:把情境 G 的 45 改成 20 再重跑,它會變回 cache_hit——這就是 30 分鐘視窗的效果。
  10. 挑戰:在 SCENARIOS 加一個情境 H:把 turn1 最後一則 input「請重構 utils.py」改成「請重構 util.py」(少一個 s),先猜猜 reason 與 comparison_reusable_tokens 大概是多少,再執行驗證。(提示:前面四個區塊都對得上,所以可重用的 token 會非常多,你可以在執行結果看到 741。)

🧠 工程思維透鏡(資深工程師看到的是什麼)

🔭 為什麼官方叫你「這一輪用不到的工具也別刪,改用 allowed_tools 或 tool_choice: none」?
資深工程師會先問:快取到底認什麼?答案是「開頭一模一樣的一段」。官方說保持工具定義穩定,是為了讓「更早的上下文」繼續可重用,這暗示工具定義位在前面、影響範圍大。刪一個工具看似省了幾行字,卻可能讓從那裡起的整段內容全部重算——用小小的省換大大的賠(在模擬器的情境 B,相對成本從 79 飆到 740)。allowed_tools 與 tool_choice 的設計理由,是把「這一輪能不能用」變成一個外掛的控制開關,而不是去改動內容本身:內容保持穩定,控制權放在旁邊。這是一條通用原則:不常變的放前面、固定住;常變的放後面,或做成開關。
🔭 新指示為什麼要「追加在最後」蓋過舊指示,而不是回頭修改原本那一條?
這是「只增不改(append-only)」的設計,就像記帳本寫錯了不塗改,而是在後面補一筆更正。好處是前面的內容一個字都沒動,快取可以繼續用。代價也要看清楚:對話會越來越長、舊指示還躺在那裡佔空間,而且模型得自己判斷「後面的新指示優先」,指示一多,可能互相打架。資深工程師的取捨是:短期用追加保住快取;等補丁累積得太多太亂,就值得主動重整一份乾淨的開頭,心甘情願付一次沒命中的代價。同樣的邏輯也出現在 configuration_update:調整推理力道這種「設定變動」,被設計成追加在尾端的事件,而不是去改請求層級的設定。
🔭 官方為什麼不只給折扣,還要另外做儀表板和診斷工具?
折扣是「結果」,命中率才是「能力」。快取是一種看不見的優化:沒人量測,它就會悄悄退化——某天有人調了工具順序,命中率掉了,帳單慢慢變貴,卻沒人發現。所以官方給了兩種分工的工具:儀表板看「趨勢」(命中率隨時間怎麼變、已快取與未快取 token 的比例),像看整片森林;診斷工具看「單點」(這一次為什麼沒命中、哪一項變了、估計影響多少 token),像檢查一棵樹。「估計影響 token 數」特別重要,它讓你排出優先順序:先修影響最大的改動,而不是憑感覺亂試。這就是 可觀測性能從外面看見系統內部狀況的程度,做法是持續量測指標並留下線索,出問題時才查得出原因 的思維——沒有量測,就沒有優化。
🔭 如果代理人流程裡會停下來等人(例如等使用者核准),超過 30 分鐘視窗該怎麼辦?
官方說明的規則是:符合資格的共用前綴,要在 30 分鐘的視窗內被再次用到才有折扣。對「連續跑好幾小時」的代理人,每一輪間隔通常很短,問題不大;但如果流程要等人,間隔就可能超過 30 分鐘,這段前綴就不再符合資格。資深工程師不會一味想辦法「撐住不過期」,而是先算帳:這段前綴有多大?多久會等一次?重算一次多貴?再決定要接受重算,還是調整流程的節奏。官方沒有替你做這個決定,這個取捨要自己算。

📝 隨堂考(點選答案,立即回饋)

Q1. GPT-6 的提示詞快取,最主要是讓哪一類內容可以被重複使用、享有折扣?
✅ 官方說明:代理人的一連串請求常常帶著同樣的指示、工具定義和先前脈絡,OpenAI 把這些共用的內容快取起來重用,被快取的輸入 token 最高可享 90% 折扣。每次都不同的新問題,本來就不是共用的部分。
Q2. 阿哲的代理人這一輪不需要搜尋工具,最符合官方建議的做法是?
✅ 官方建議保持工具定義、參數格式與順序穩定,讓更早的上下文可以繼續重用;要限制工具,用 allowed_tools 只開放相關工具,或在完全不需要工具時把 tool_choice 設為 none,而不是移除定義。刪除、換順序、換模型都會讓前面的內容對不上。
Q3. 診斷工具回傳 reason 是 tools_changed,最正確的解讀是?
✅ 診斷工具的用途,就是把你的請求和最近一次回應比對,指出是模型、工具、設定或輸入哪一項變動,導致沒能重用;並估計受影響的 token 數(官方範例是 5629)。它不代表工具故障或額度問題。
Q4. 在很長的對話中途,你想加入一條新規定,又想盡量保住快取,最好的做法是?
✅ 官方建議用新的 developer 訊息把新指示追加在上下文的尾端,覆蓋較舊的指示。這樣前面的內容完全沒動,共用前綴仍然對得上。改最前面或重新排序,都會讓後面整段失效。
Q5. 代理人等使用者核准,隔了 45 分鐘才送出下一輪,開頭與上一輪一模一樣。依官方說明,最合理的預期是?
✅ 官方寫的是「符合資格的共用前綴,在 30 分鐘視窗內再次使用」才給折扣。超過視窗就不再符合這個條件,所以要預期可能得重新計算;細節請看官方的快取指南。

🃏 翻牌記憶卡(先想答案,再點開對答)

提示詞快取在做什麼?點我翻面
把多次請求共有的開頭內容(指示、工具定義、先前脈絡)算過的結果記起來重用:回應更快,被快取的輸入 token 最高可享 90% 折扣。
共用前綴要在多長的視窗內再次使用,才有快取折扣?點我翻面
30 分鐘。官方寫的是「符合資格的共用前綴,在 30 分鐘視窗內再次使用」。
快取沒命中時,第一個該用什麼工具查?怎麼查?點我翻面
診斷工具:比對這次請求與最近一次回應,找出是模型、工具、設定或輸入哪一項變了,並附估計受影響的 token 數(例如 reason: tools_changed)。
這一輪用不到某些工具,正確做法是什麼?點我翻面
不要刪定義。保持工具定義、參數格式、順序穩定;用 allowed_tools 只開放相關工具,或在完全不需要時把 tool_choice 設為 none。
對話中途要改指示或調推理力道,怎麼做才不破壞快取?點我翻面
指示:用新的 developer 訊息追加在尾端蓋過舊的。推理力道:附加 configuration_update,請求層級的推理力道設定保持不變。
儀表板與診斷工具,各自負責什麼?點我翻面
儀表板看趨勢:命中率隨時間的變化、已快取與未快取 token 的比例。診斷工具查單點:這一次為什麼沒命中、哪項改動、影響多少 token。

✅ 離開前自測(全勾=這課真的學會了)

0%