上下文工程
💡 學習指南:提示詞工程解決的是「怎麼把話說清楚」,上下文工程解決的是「讓模型在合適的時刻看到合適的資訊」。本章節會圍繞一個問題展開:在有限的上下文視窗裡,如何既讓模型懂你,又不把錢燒光?
在開始之前,建議你先補兩塊「基礎磚」:
- Token 是什麼:可以先閱讀 大語言模型入門 的「分詞 & Token」部分。
- Prompt 是什麼:如果你還不熟悉 System / User / Assistant 的基本結構,可以先看 提示詞工程。
0. 引言:為什麼聊著聊著,它就忘事,還越來越貴?
💡 Everything is normal:The current token count (1200) is still within the window. The model can recall all conversation details.
很多人在實際使用大模型時都會遇到類似的情況:
- 聊到一半,模型突然「忘記」之前說過的關鍵條件;
- 長對話裡,前後回答自相矛盾,很難保持同一套設定;
- 對話輪次一多,帳單像打車計價一樣不斷往上走。
直覺上,我們會以為是:「這個模型記性不好」。 但大多數時候,問題並不在於模型「不會記」,而在於我們沒有設計好它能看到的上下文。
- Context is hard to keep consistent:As conversations grow, earlier and later meaning can drift apart.
- Key facts are easy to lose:Information given early can be hard to reference accurately later.
- Call cost keeps rising:Every round has to process a large amount of history again.
- The model only sees the current call:It can only rely on the context provided in this round.
- Information is not structured:Important facts and minor details are mixed together, making stable memory hard.
- History is recomputed repeatedly:Large fixed prefixes are processed again and again across turns.
- Answer quality becomes unstable:Longer conversations make consistency and traceability harder.
- Cost is hard to estimate:Context size fluctuates heavily from turn to turn.
- Production systems become hard to maintain:Without a clear context strategy, systems are hard to operate and extend.
面對這些挑戰,單純依靠「寫好提示詞」已經捉襟見肘。我們需要一套更系統的工程方法,來在有限的視窗和預算內,讓模型始終獲得最關鍵的資訊。這正是上下文工程試圖解決的問題。
1. 什麼是「上下文工程」?(定義 + 場景)
先給一個簡短的工作定義,再看幾個典型場景。
上下文工程,是一門為 LLM 構建和管理「資訊環境」的工程方法,決定模型「看到什麼、忽略什麼、什麼時候看到」,從而在有限的上下文視窗內穩定完成任務。
你可以簡單地把它理解成三件事:整理資訊、控制視窗、管理成本。 常見會用到它的場景包括:
- 對話型 Agent 和客服機器人
- 程式碼 / 文件助手
- 多輪工具調用和長流程編排
接下來,我們就從一個真實團隊的「血淚教訓」出發,看看他們是怎麼一點點從「只會寫 Prompt」進化到「會做上下文工程」的。
2. 從「血淚教訓」說起:Manus 團隊踩過的坑
本章案例來自 Manus(一款通用 AI Agent)。 與普通對話不同,Manus 需要自主規劃並調用工具完成長任務(涉及幾十甚至上百輪互動)。
這帶來了核心矛盾:
- 如果不記:關鍵資訊丟失,任務中斷。
- 全記:成本和延遲爆炸,甚至超出視窗限制。
Manus 團隊經歷過多次架構重構,才明白一個道理:上下文不能只靠「寫」,而要靠「設計」。
2.1 四次重構教會我們什麼?
Manus 的聯合創辦人季逸超分享過他們的「踩坑史」:
| 階段 | 遇到的問題 | 當時的想法 | 結果 |
|---|---|---|---|
| 第一次 | AI 聊著聊著就忘事 | 「多寫點提示詞就好了」 | 越寫越長,越寫越貴 |
| 第二次 | 重要資訊總被擠掉 | 「把重要的多複製幾遍」 | 文本更長,成本更高 |
| 第三次 | 帳單高得嚇人 | 「能不能複用之前的計算?」 | 找到降低重複計算成本的方式 |
| 第四次 | 長文件處理不了 | 「能不能需要時再查?」 | 建立「圖書館+按需檢索」的方案 |
核心領悟:不是記得越多越好,而是記得越巧越好。
2.2 AI 的「記性」到底像什麼?
傳統電腦記憶體 = 硬碟:
- 容量大:可以長期保存大量資料;
- 價格低:存放一年成本較低;
- 讀寫速度相對較慢,尋找資訊需要一定時間。
AI 的上下文 = 小黑板:
- 讀寫快:模型可以在一次調用中直接看到全部上下文;
- 容量有限:寫滿後不得不擦除舊內容;
- 每寫入一個 token 都會帶來額外計算與費用。
Manus 的經驗:小黑板要用得省,用得巧,別用來存百科全書。
3. 第一步:認識成本 - 你的每一分錢花在哪?
3.1 為什麼要先看成本?
讓我們看看一次典型的 AI 對話,你的錢是怎麼花的:
💰 成本構成(一次對話):
├─ 70% 重複看舊內容(「剛才聊了什麼?」)
├─ 20% 處理新內容(「現在說什麼?」)
└─ 10% 生成回覆(「怎麼回答?」)驚人發現:70% 的錢花在讓 AI 重新看你之前說過的話!
3.2 什麼是 KV Cache?(前綴複用)
在討論價格之前,我們得先搞懂一個核心技術概念:KV Cache(鍵值快取)。 別被這個技術名詞嚇到,它其實就是 AI 的「短期記憶速查表」。
- 沒有 KV Cache 時:AI 每次都要像第一次看到這篇文章一樣,從第一個字開始重新閱讀、理解、計算。
- 有了 KV Cache 時:AI 會把看過的部分(Pre-fill)計算結果存下來。下次如果開頭的內容沒變,它就直接調取記憶,不用重新算了。
這就好比:
你去考場考試。 情況 A:每次都要把整本教材從頭讀一遍,再開始答題。(慢、累、貴) 情況 B:教材內容你已經背得滾瓜爛熟了(Cache),坐下直接答題。(快、輕鬆、便宜)
在雲端廠商的計費表裡,「背過的書」(Cache Hit)通常比「新看的書」(Cache Miss)便宜 90% 以上。
3.3 「背課文」vs「現查現用」的價格差
以 Claude 為例:
- 現查現用(沒快取):$3.00 / 百萬字
- 背過再用(有快取):$0.30 / 百萬字
- 相差 10 倍!
Manus 的實踐:透過讓 AI「背課文」,他們把成本從 $0.15 降到 $0.02,省了 87%!
💡Note: The context window is like a small board for the model. The board has limited space, so old content must be erased before new content can fit. Once it overflows, the earliest content disappears from the model view.
3.4 避坑指南:別讓時間戳毀了你的「快取」
很多開發者習慣把「當前時間」寫在 System Prompt 的第一句,覺得這樣很嚴謹。 但這其實是上下文工程中最大的反模式之一。
想像一下:你背了一整本歷史書(System Prompt),結果書的第一行寫的是「現在的秒數」。 如果這行字每秒都在變,那你上一秒背的所有內容,下一秒就全廢了——你得從頭再背一遍。
這就是前綴複用(KV Cache)的死穴:只要開頭變了,後面全都要重算。
錯誤示範:把動態資訊放前面
System: 現在是 2024-01-01 12:00:01。你是助手...
(一分鐘後)
System: 現在是 2024-01-01 12:01:01。你是助手...後果:雖然只變了幾個字,但因為在開頭,導致後續 99% 的固定內容無法複用快取,每次請求都像第一次一樣慢且貴。
正確姿勢:動靜分離
System: 你是助手... (這裡放幾千字的固定規則、知識庫)
User: (在這裡透過工具調用或使用者訊息傳入當前時間)好處:前面的幾千字規則永遠不變,AI 只需要「背」一次。後續請求直接調用記憶,速度極快。
👇 動手點點看: 點擊下方的開關,開啟「背課文加速」,然後多次點擊「發送新請求」。 觀察一下:當第一塊內容變成「已背過」時,開口速度(TTFT)會發生什麼變化?
⏱️Without cache:Every request recomputes attention from the beginning, like rereading a textbook from page one every time.
4. 第二步:滑動視窗 - 當「記性」變成「成本」
隨著對話越來越長,最先遇到的問題就是:視窗滿了怎麼辦?
4.1 為什麼「先進先出」會出問題?
最簡單的記憶管理是滑動視窗(Sliding Window):新的進來,舊的出去。 這聽起來很公平,但在實際任務中卻是個災難。
場景重現:
對話記錄:
[1] 使用者:我是張三,負責支付系統
[2] 使用者:專案用 Go 語言開發
[3] 使用者:資料庫是 PostgreSQL
...
[20] 使用者:幫我寫個介面結果:當聊到第 20 句時,第 1 句「我是張三」已經被擠出了視窗。AI 徹底忘了你是誰,也不知道你在負責什麼系統。
問題本質:這種策略把重要資訊(身份、技術棧)和廢話(「好的」、「收到」)同等對待,一起被踢了出去。
4.2 「中間失憶症」- 為什麼 AI 總看不到關鍵資訊?
除了「忘得快」,AI 還有一個怪癖:它也會「看漏」。 研究發現:AI 對開頭和結尾最敏感,中間最容易被忽略。這就是著名的 Lost in the Middle(中間迷失)現象。
U 型記憶曲線:
位置:開頭 → 中間 → 結尾
記憶: 高 → 低 → 高👇 動手點點看:
- 先試試「滑動視窗」:在下面的聊天框裡多發幾條訊息,看看舊的對話是怎麼被無情「擠出去」的。
- 再看看「中間迷失」:觀察一下,當關鍵資訊藏在整段話的中間位置時,檢索成功率是不是最低的?
💡Note: A sliding window is the simplest memory strategy: new content enters and old content leaves. It never overfills the context, but once content slides out, the model forgets it completely.
🔍Observation:When a key fact is hidden in the middle of a long context, the model is most likely to miss it.
The reliable approach is to place important instructions at the very front in the System Prompt or at the end in the latest user query.
解決方案:把關鍵資訊放在開頭(系統提示)或結尾(使用者問題)。
5. 第三步:選擇性保留 - 如何「釘」住關鍵資訊?
既然「先進先出」不靠譜,那我們該怎麼辦? Manus 的答案是:建立「資訊等級制度」。
5.1 為什麼要給資訊分等級?
不再平等對待每條資訊,而是根據重要程度決定它們的去留:
| 等級 | 資訊類型 | 待遇 | 成本影響 |
|---|---|---|---|
| VIP | 系統設定、使用者身份 | 永遠保留 | +15% 成本 |
| 重要 | 當前任務目標 | 任務期內保留 | +10% 成本 |
| 一般 | 普通對話歷史 | 最近 5 輪保留 | 基準成本 |
| 可棄 | 可檢索的知識 | 用時再查 | -60% 成本 |
核心思想:用 25% 的成本增加,換取 90% 的關鍵資訊保留。
5.2 「釘釘子」策略
你可以把上下文視窗想像成一面黑板:
- VIP 資訊:用釘子死死釘在黑板最上面(System Prompt)。
- 重要資訊:用磁鐵吸在黑板中間(Context Injection)。
- 普通對話:寫在黑板下半部分,滿了就擦掉舊的(Sliding Window)。
👇 動手點點看: 試著在下面的演示裡,把某條重要的對話「釘」住。 觀察一下:當你繼續聊天時,被釘住的資訊是不是一直都在,而沒釘住的就被擠走了?
💡Note: Selective retention means pinning important information to the board while ordinary messages slide away. System prompts are usually pinned permanently, and key user facts such as names, accounts, or preferences can be pinned through memory modules or RAG.
6. 第四步:RAG - 當「記性」需要「圖書館」
有時候,我們要處理的資訊太多了(比如幾百頁的技術文件),黑板根本寫不下。這時候就需要外掛大腦——RAG(檢索增強生成)。
6.1 為什麼「小黑板」不夠用?
Manus 面對百萬字級的技術文件時,對比了兩種做法:
- 全量寫入:所有內容一次性塞進上下文。
- 後果:黑板瞬間被佔滿,處理極慢,而且根據「中間迷失」理論,AI 根本記不住中間的內容。
- 成本:約 $50/次,等待 15 秒。
- 按需檢索(RAG):先去圖書館(資料庫)查,只把相關的幾段話抄到黑板上。
- 後果:黑板很清爽,AI 聚焦於關鍵資訊。
- 成本:約 $0.5/次,等待 2 秒。
省了 99% 的錢,87% 的時間!
6.2 「查資料」的最佳實踐
Manus 的經驗總結:
- 每本書撕成多大片? 500-1000 字效果最好。
- 一次查幾本書? 3-5 本,多了反而干擾。
- 多相關的書才查? 相似度 > 0.7,避免「硬湊」不相關的內容。
👇 動手點點看: 在搜尋框裡輸入問題(比如「如何重置密碼」),看看系統是如何從一大堆文件裡只找出最相關的那幾條的。
7. 第五步:壓縮 - 如何讓「小黑板」寫得更密?
如果資訊都很重要,實在刪不掉,又不想查資料怎麼辦? 那就只能把字寫小點——這就是上下文壓縮。
7.1 什麼時候需要「縮寫」?
- 檢索回來的資料太厚(>2000 字)。
- 對話歷史太囉嗦(佔了 >80% 黑板空間)。
- 需要快速回答,不想讓 AI 讀長篇大論。
7.2 「縮寫」的三種境界
| 壓縮方式 | 壓縮率 | 保留什麼 | 適用場景 | 省錢效果 |
|---|---|---|---|---|
| 總結式 | 70% | 主要意思 | 快速了解 | 省 30% |
| 要點式 | 50% | 關鍵要點 | 結構化輸出 | 省 50% |
| 表格式 | 30% | 核心資料 | 程式處理 | 省 70% |
👇 動手點點看: 選擇不同的壓縮策略,看看長篇大論是如何變短、變精煉的。
8. 系統整合:打造 AI 的「記憶宮殿」
前面我們像搭積木一樣,學習了各種獨立的策略:
- KV Cache:幫我們省錢(第 3 章)
- 滑動視窗:幫我們騰位置(第 4 章)
- 分級保留:幫我們留重點(第 5 章)
- RAG:幫我們開外掛(第 6 章)
現在,是時候把這些積木搭成一座完整的城堡了——我們稱之為 Manus 的「記憶宮殿」。
8.1 像蓋房子一樣組裝上下文
不要把上下文看作一堆亂糟糟的文字,而要把它看作一座分層的建築。每一層都有它獨特的功能和「居住規則」。
👇 動手點點看: 點擊「開始建造」,看看我們是如何一層層把這座宮殿蓋起來的。
8.2 為什麼這樣設計最強?
這座宮殿的設計哲學,其實就為了解決三個矛盾:
地基(System Prompt)—— 解決「貴」的問題
- 矛盾:系統設定(你是誰、規則是什麼)最長,每次都要發。
- 解法:把它放在最底層,利用 KV Cache 技術,只要不改動,AI 就能「背誦全文」。後續幾百輪對話,這部分的計算成本幾乎為 0。
支柱(Task Context)—— 解決「忘」的問題
- 矛盾:對話一長,AI 容易忘了最初的任務目標(比如「寫一個貪吃蛇遊戲」)。
- 解法:利用分級保留策略,把任務目標「釘」在第二層。不管聊了多少輪,這層永遠不刪,確保 AI 不忘初心。
頂層(Chat & RAG)—— 解決「亂」的問題
- 矛盾:又有新對話,又有查到的資料,混在一起容易暈。
- 解法:
- 客廳(對話):用滑動視窗管理,只留最近 5-10 句熱乎的。
- 圖書館(RAG):資料用完即走,不佔地方。
8.3 實戰效果
Manus 團隊把這套架構搬上線後,效果立竿見影:
- 省錢了:因為地基被「背」下來了,每輪對話的成本暴跌 84%。
- 變快了:AI 不用每次都從頭讀幾千字,平均回應時間從 8 秒縮短到 2 秒。
- 更準了:關鍵資訊被「釘」死,再也不會聊著聊著就忘了自己是幹嘛的。
9. 實戰模板:直接抄作業
為了讓你更直觀地理解這套機制是如何運作的,我們為你準備了全鏈路模擬。
請選擇一個場景,點擊「下一步」,看看從使用者發問到 AI 回答的幾秒鐘內,記憶宮殿是如何動態調取、組裝和清理上下文的。
📝 拿來即用的實戰設計
如果你要設計一個類似 Manus 的系統,不要只盯著 Prompt 怎麼寫,更要關注系統架構如何調度上下文。
以下是兩個經典場景的系統設計藍圖,包含了提示詞設計和程式碼邏輯(虛擬碼)。
場景 1:全端工程師 Agent(長程記憶型)
核心挑戰:任務週期長,容易忘了最初的需求和專案背景。 解決策略:System 層(身份)+ Task 層(釘死目標)+ Chat 層(滑動視窗)。
1. 系統提示詞 (Layer 1 & 2)
# Layer 1: 身份設定 (System Prompt) - 永遠不變,利用 KV Cache
你是一名資深的全端工程師,精通 Python 和 Vue3。
程式碼風格:
- 變數命名嚴格遵守 PEP8
- 關鍵邏輯必須包含註解
- 優先使用專案已有的工具函式
# Layer 2: 任務鎖定 (Task Context) - 任務期間不許刪
當前任務:重構支付模組 (payment_module)
核心約束:
1. 必須相容舊版 API 介面 v1.0
2. 資料庫遷移腳本必須是冪等的
3. 截止時間:本週五2. 上下文組裝邏輯 (Pseudo-Code)
def build_engineer_context(user_input, chat_history, task_info):
context = []
# 1. 地基層:身份設定 (利用 KV Cache 快取)
# 這部分內容幾百輪對話都不變,計算成本幾乎為 0
context.append(SYSTEM_PROMPT)
# 2. 支柱層:任務鎖定 (Pinned)
# 無論對話多長,這部分永遠插入在 System 之後
context.append(f"當前任務:{task_info}")
# 3. 檢索層:程式碼片段 (RAG)
# 根據使用者的問題,去程式碼庫裡找相關的程式碼
relevant_code = search_codebase(user_input)
if relevant_code:
context.append(f"參考程式碼:\n{relevant_code}")
# 4. 互動層:對話歷史 (Sliding Window)
# 只取最近 10 輪,避免撐爆上下文
recent_chat = chat_history[-10:]
context.extend(recent_chat)
# 5. 最新輸入
context.append(user_input)
return context場景 2:智慧客服 Agent(精準問答型)
核心挑戰:成本敏感,且絕對不能胡說八道。 解決策略:System 層(強約束)+ RAG 層(動態注入)。
1. 系統提示詞 (Layer 1)
# Layer 1: 身份設定 (System Prompt)
你是一名專業的電商客服專員。
回覆原則:
1. 語氣溫柔、專業、簡潔
2. **絕對禁止**編造事實,只根據[參考資料]回答
3. 如果資料裡沒有答案,請直接回答「非常抱歉,這個問題我需要轉接人工客服」2. 上下文組裝邏輯 (Pseudo-Code)
def build_support_context(user_input):
context = []
# 1. 地基層:身份設定
context.append(SYSTEM_PROMPT)
# 2. 圖書館層:動態檢索 (RAG)
# 只有客服場景,RAG 才是主角,放在中間位置
docs = vector_db.search(user_input, top_k=3)
context.append("【參考資料開始】")
for doc in docs:
context.append(doc.content)
context.append("【參考資料結束】")
# 3. 互動層:極短的歷史
# 客服通常不需要太久遠的記憶,保留最近 3 輪即可
context.extend(get_recent_chat(limit=3))
context.append(user_input)
return context10. 名詞對照表
| 英文術語 | 中文對照 | 解釋 |
|---|---|---|
| Context Window | 上下文視窗 | 模型一次性能夠處理的文本最大長度(包括輸入和輸出)。超出限制的內容會被截斷或遺忘。 |
| Token | 詞元 | LLM 處理文本的最小單位。通常 1 個 Token 約等於 0.75 個英文單詞或 0.5 個漢字。計費和視窗限制都以此為單位。 |
| KV Cache | KV 快取 | 一種推理加速技術,透過快取已經計算過的注意力鍵值對,避免對重複前綴進行重複計算,顯著降低延遲和成本。 |
| RAG | 檢索增強生成 | 在回答問題前,先從外部知識庫檢索相關資訊,作為上下文提供給模型,以減少幻覺並擴展知識邊界。 |
| Sliding Window | 滑動視窗 | 最基礎的上下文管理策略。保持視窗內 Token 數量恆定,當新內容進入時,自動移除最早的舊內容。 |
| Lost in Middle | 中間迷失 | 大模型的一種局限性。研究表明,模型對長上下文開頭和結尾的資訊記憶最深,而容易忽略中間部分的資訊。 |
| System Prompt | 系統提示 | 位於對話最開始的指令,用於設定模型的身份、行為規範、回覆風格和核心任務。 |
| Few-shot | 少樣本學習 | 在提示詞中提供幾個「問題-答案」的範例,幫助模型快速理解任務模式和輸出格式。 |
| Chain of Thought | 思維鏈 | 引導模型在給出最終答案前,先輸出推理步驟。這種方法能顯著提升模型解決複雜邏輯和數學問題的能力。 |
| Hallucination | 幻覺 | 模型自信地生成看似合理但實際上錯誤或不存在的資訊的現象。 |
| Embedding | 向量化 | 將文本轉換為高維數值向量的技術。語義相似的文本在向量空間中的距離更近,是語義搜尋的基礎。 |
| Vector DB | 向量資料庫 | 專門用於儲存和檢索向量資料的資料庫。支援透過相似度搜尋快速找到與查詢最匹配的文件片段。 |
| Temperature | 溫度 | 控制模型輸出隨機性的超參數。數值越高(如 0.8)輸出越多樣、有創意;數值越低(如 0.2)輸出越確定、嚴謹。 |
| TTFT | 首字延遲 | Time to First Token,即從使用者發送請求到模型輸出第一個 Token 所花費的時間,是衡量互動體驗的關鍵指標。 |
總結:上下文工程的本質
Manus 的四次重構告訴我們:
從實踐來看:不是記得越多越好,而是記得越有結構、越有選擇性越好。
從成本視角看:
- 大部分浪費來自對固定前綴的重複計算,需要透過前綴穩定和快取機制解決;
- 重要資訊被誤刪,往往源於「一視同仁」的滑動視窗,需要透過資訊分級與釘住策略解決;
- 面對超長文件和知識庫時,僅依賴增大上下文視窗並不現實,必須結合檢索與壓縮機制。
目標是:在給定的模型與上下文上限下,讓每一個 token 的投入都具備明確的用途。