🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付

談談上下文工程(Context Engineering)

大模型發展這兩年,應用型 AI 的焦點一直在 “提示工程”(prompt engineering),但隨著更強大的大語言模型(LLM)走向多輪、長時間的自主行動,一個更關鍵的概念開始走到台前:上下文工程(context engineering)。
與其把精力放在如何雕琢每一句提示,不如把問題聚焦到:怎樣構造和維持 “最可能讓模型產生期望行為” 的上下文?
本文是參考 Claude 官網博客的總結,文章原文:www.anthropic.com/engineering…

1. 什麼是上下文工程

上下文,是在一次 LLM 推斷過程中被納入採樣的全部 token 集合,上下文工程的核心任務,是在模型固有約束下,優化這些 token 的效用,以更穩定地獲得預期結果。
要駕馭 LLM,往往需要 “在上下文中思考”:把模型任意時刻能讀取到的一切狀態視為整體,並評估這些狀態可能產生的行為。

2. 上下文工程 vs 提示工程

  • 提示工程:編寫和組織模型指令以獲得最佳輸出,通常聚焦系統提示如何寫得清晰、有效。
  • 上下文工程:在推斷時動態策劃和維護 “最優信息集”,不僅包含提示,還包含工具、外部數據、消息歷史、模型上下文協議(MCP)、環境狀態等。

圖片

隨著我們構建的代理(agent)變得更有能力、能在更長時間維持自治並反復調用工具,我們的工作不再是一次性寫好一個提示,而是在每一輪決定 “往模型裡放什麼,不應該放什麼”。
代理循環運行會不斷產生新數據,這些信息必須被周期性篩選、提煉。
“上下文工程” 的藝術就在於:在有限的上下文窗口中,選取最有價值的子集。

3. 為什麼 “上下文工程“ 對強代理至關重要?

模型上下文越長,性能不一定越好,大量基準研究揭示了 “上下文腐化” (context rot):當上下文 token 增加,模型從中準確檢索信息的能力會下降,這不是某個模型的特例,而是普遍現象,只是不同模型的退化曲線更緩或更陡。

  • 有限注意力長度:像人類的工作記憶一樣,LLM 的注意力資源是有限的,每納入一個 token,都會消耗注意力預算的一部分,從而降低對其他信息的分配能力。
  • 架構約束:Transformer 允許任意 token 關注到任意其他 token,導致 指數級別增長,當上下文變長,模型捕捉這些關係的能力被攤薄,此外,訓練數據中短序列更常見,模型對 “極長序列的全局依賴” 往往經驗不足。
  • 位置編碼插值:諸如位置編碼插值的技術能讓模型 “適配” 更長序列,但會帶來一定的位置信息理解退化,因此,長上下文下的模型表現更像 “漸進變差”,而非懸崖式崩潰:依舊強,但在信息檢索、長程推理方面精度略降。

這些問題需要用更好的處理方法:把上下文視為稀缺資源,並以工程化方式加以管理,是構建強大代理的基礎。

4. 什麼是有效上下文?

目標是用盡可能少的高信號 token 最大化產出概率,落實到實踐層面,各類上下文組件都要貫徹 “信息密度高、指導性強、冗餘小” 的原則,主要這幾方面:

系統提示(system prompt)

  • 語言要清晰、直接,給出 “恰到好處” 的指令高度,避免兩端的常見失敗模式:
    • 過度硬編碼的複雜邏輯(脆弱、維護成本高)
    • 過於籠統、假定共享語境的 “空話”,缺乏可操作信號
  • 可以把提示組織成分區(如背景信息、核心指令、工具使用準則、輸出格式描述),並用清晰的標籤或標題分隔,格式細節的重要性在降低,但結構清晰仍能有助於模型。
  • 追求 “最小完整信息集”:不必刻意短,但要確保必要信息齊備、無冗餘,建議從一個 “最小可用” 提示起步,用最強模型測試,圍繞失敗模式迭代加入明確的指令和示例。

工具(tools)

  • 工具是代理與環境互動、拉取新上下文的通道,工具必須令信息返回 “token 高效”,並鼓勵代理採取高效策略。
  • 設計工具時遵循“ 單一職責、魯棒、用途清晰”,輸入參數要描述明確、無歧義,並契合模型的自然優勢。
  • 警惕工具集過於龐雜或功能重疊,導致選擇困難,如果人類工程師都拿不準該用哪個工具,代理也難以做對。 保持工具集的 “最小可行集” 不僅提升可靠性,還方便在長時交互中做維護與上下文修剪。

示例(few-shot)

  • 少樣本示例仍是強烈推薦的最佳實踐,但不要把所有邊界條件都擠進提示,試圖羅列每一條規則。
  • 更好的做法是精心挑選 “多樣而典型” 的示例,直觀描摹期望行為,對 LLM 來說,示例往往勝過冗長說明。

總體原則:在系統提示、工具、示例、消息歷史等各組件上保持 “信息緊湊而有用”。

4.1 低效的樣例

樣例1:低效的系統提示

體驗AI代碼助手
代碼解讀
複製代碼
你是一個非常聰明的全能 AI,儘可能全面地回答所有問題。 無論問題是什麼,都要先給出10步解決方案和詳細解釋。 如果問題涉及價格,則必須先搜索“pricing”關鍵字;如果是技術問題則必須按下列條件分支:
- 如果包含“error”,先假設用戶使用的是Linux,再給出Linux專屬排錯步驟;
- 如果包含“timeout”,請把所有相關文檔全文粘貼進來,以免遺漏;
- 如果問題很複雜,請寫一篇至少1000字的長文來解釋背景、歷史和可能的未來演進。 

請務必列出所有可能的邊界情況(不少於20條),並逐條覆蓋。 儘量引用你記得的一切信息,避免遺漏。 
# 輸出
不限制格式,儘量詳細,越長越好。 

樣例2:低效的工具提示

體驗AI代碼助手
代碼解讀
複製代碼
- search: 任意搜索(字符串或正則或自然語言),返回所有匹配文檔的全文內容與元數據(可能很大)。 
- semantic_search: 與search類似,但“更智能”,返回更長的上下文片段。 
- list_docs: 列出所有文檔並返回每個文檔的首5頁內容,防止錯過重要信息。 
- fetch_document: 輸入doc_id,返回完整文檔(不做截斷)。 
- open_url: 打開任意URL並把網頁完整HTML塞回上下文。 
(說明模糊,職責重疊,返回內容過大且無長度限制)

樣例3:低效的少樣本

示例1(定價問題):
- 輸入:我們的專業版多少錢?
- 輸出:逐條列出30條可能的價格方案、所有歷史版本定價、每個地區的稅率、以及可能的促銷活動;同時粘貼相關文檔全文以備參考。 

示例2(技術問題):
- 輸入:API 請求出現 timeout 怎麼辦?
- 輸出:先貼出所有網絡相關文檔全文,再給出一個長達2000字的網絡排錯手冊,覆蓋DNS、TLS、路由、BGP等所有可能性,最後再總結。 

4.2 高效的樣例

樣例1:高效的系統提示

## 角色
你是“企業知識庫問答與行動項生成”代理,目標是在有限上下文內準確回答,並附上文檔引用;必要時提出精煉的後續行動。 

## 目標
- 高信號:以儘可能少的token交付準確答案與清晰引用。 
- 穩健:不確定時按需檢索;避免加載全文。 
- 可執行:當信息不足,提出具體的下一步。 

## 指令
1) 先用工具檢索,再回答;避免憑空臆測。 
2) 優先返回摘要與引用,不要粘貼大段原文。 
3) 若檢索結果不足或衝突,說明不確定點並提出下一步(如縮小查詢、定位章節)。 
4) 遵守輸出格式,控制總長度(答案≤200字,引用≤3條)。 

## 工具指南
- 先 search_docs(query) 獲取候選與片段摘要;
- 用 get_doc(doc_id, section_hint, max_chars=1000) 讀取必要部分;
- 用 write_note(key, summary) 記錄關鍵結論與未決項,供後續輪次引用。 

## 輸出格式
以Markdown返回:
- 答案(簡潔結論)
- 引用(最多3條,格式:文檔名 · 章節/段落 · 摘要)
- 下一步(當信息不足時)

樣例2:高效的工具

- search_docs(query: string) -> [{doc_id, title, score, snippet}]
  說明:語義檢索,返回最多5條候選,含簡短片段snippet;不返回全文。 

- get_doc(doc_id: string, section_hint?: string, max_chars?: number=1000) -> {title, section, excerpt}
  說明:按提示抓取指定章節或鄰近段落,長度受max_chars限制,返回精煉摘錄excerpt。 

- write_note(key: string, summary: string) -> {ok: boolean}
  說明:將關鍵結論與未決項持久化,便於後續調用;不回填長文本到上下文。 
(職責單一,參數明確;返回內容受限以節省token)

樣例3:高效的少樣本

示例1:定價問答(有答案)
- 輸入:專業版的月費是多少?
- 工具:search_docs("專業版 定價"); get_doc(top.doc_id, "價格/訂閱", 800)
- 輸出:
  答案:專業版月費為¥199(按月訂閱)。 
  引用:專業版定價 · 訂閱與計費 · “專業版:¥199/月”
  下一步:如需年度方案,請檢索“年度定價”。 

示例2:技術故障(需要更多信息)
- 輸入:API 請求出現 timeout,如何排查?
- 工具:search_docs("API timeout 排查"); get_doc(top.doc_id, "網絡與重試", 800)
- 輸出:
  答案:建議先檢查網絡連接與重試策略(超時閾值、重試間隔)。 
  引用:服務可用性指南 · 超時與重試 · “建議超時≥3s,指數退避重試”
  下一步:請檢索“區域網絡狀態”或提供具體報錯信息。 

示例3:無答案場景(信息不足)
- 輸入:有沒有針對巴西市場的專屬折扣?
- 工具:search_docs("巴西 市場 折扣")
- 輸出:
  答案:當前未檢索到巴西市場專屬折扣的正式說明。 
  引用:營銷政策總覽 · 區域優惠 · “未包含巴西的專屬折扣條目”
  下一步:請查詢“區域促銷公告”或聯繫市場團隊獲取最新政策。 

5. 運行時上下文檢索與 “代理式搜索”

我們將 “代理” 簡化定義為:LLM 在循環中自主使用工具,隨著模型提升,代理自治能力增強,能更好地獨立探索與糾錯。

  • 傳統做法:在推斷前用嵌入檢索,把相關資料預先塞入上下文。
  • 新的方案:“即時”(just-in-time)上下文策略,代理維護輕量引用(如文件路徑、存儲查詢、網頁鏈接),在需要時用工具動態加載數據,而非一口氣把所有數據預處理入上下文。

這一策略像人類的認知:我們不背整庫的內容,而是借助文件系統、收件箱、書籤等外部索引按需調用。
它還有額外好處:引用的元數據(命名、層級、時間戳、大小)本身就是指導信號,幫助代理更合理地評估用途與相關性。
通過探索,代理逐步揭示重要上下文,並只維持必要的 “工作記憶”,其餘用 “筆記” 持久化,這能避免在冗餘信息裡迷失。

當然以上的方案不一定適合你當前的工程,基於實際場景也可以權衡混合策略:

  • 即時探索通常比預先檢索慢,而且需要更精心的工程指導(工具可用性、導航啟發式),否則代理可能濫用工具、走彎路、錯過關鍵信息。
  • 在許多場景裡,混合策略更優:部分數據預取以提速,其餘由代理按需探索,比如把關鍵說明文檔直接放入上下文,同時提供 glob、grep、head、tail 等原語,讓代理就地檢索文件、分析數據,繞過陳舊索引和複雜語法樹的負擔。
  • 相對靜態的領域(法律、金融)往往更適合混合策略,隨著模型能力躍升,設計會逐步放手,讓智能模型更自由地做 “智能行為”,在此過渡期,對團隊的建議始終是:用 “最簡單且有效” 的方案。

5.1 低效的樣例

# 場景
目標:找出過去1小時 API 超時率上升的根因,並給出可執行行動項。 

# 預處理(推斷前)
- 用嵌入檢索關鍵字 "timeout", "latency", "error"
- 將所有匹配文檔(Wiki 頁、運行手冊、SRE 備忘、過去事故報告)的大段內容粘貼入上下文
- 將最近24小時的日誌文件(/logs/api/*.log)全文截斷到前3MB後仍塞入
- 將監控平台的幾張圖表(以Markdown導出)和完整查詢DSL放入

# 傳入模型的初始上下文(≈20k tokens)
- Wiki: 《API超時全指南》(3,000+字)
- 運行手冊:網絡棧排查(2,500+字)
- 事故報告:2023‑09‑17 高延遲事件(摘要+長引用)
- 日誌:api‑gateway.log(最近24h前半段)
- 日誌:auth‑service.log(最近24h前半段)
- 監控:Latency 95th/99th、Error Rate 圖表說明與查詢DSL全文
- 若干無關的邊緣案例(誤檢)
…(大量冗餘、上下文污染)

# 第1輪推斷行為
- 模型在冗餘信息中“撿針”,關注分散,回溯變慢
- 將不相關的舊事故細節混入當前分析
- 給出冗長結論(>1,500字),包含多條假設與過度覆蓋

# 輸出問題
- 結論不聚焦,包含過期配置與不適用策略
- 後續行動不具體:建議“全面檢查網絡與依賴”,成本高
- Token 浪費,且後續輪次難以保持上下文清晰

5.2 高效的樣例

# 場景
目標不變:定位過去1小時超時率上升的根因,輸出精煉行動項與引用。 

# 初始上下文(≈300 tokens)
- 任務說明:排查過去1小時的 API timeout spike
- 輕量引用(不加載內容): 
  - 日誌根路徑:/logs/api/
  - 監控面板URL(id=latency_p95, error_rate)
  - Wiki 索引:SRE/Runbooks/Timeout.md, Incidents/
- 工具可用:list_files, grep, head/tail, read_partial, query_metrics, open_wiki, write_note

# 第1輪(探索起點:用元數據縮小範圍)
- list_files("/logs/api/", last_modified>=now-90m)
  - 返回(文件名·大小·修改時間):
    - api-gateway.log(420MB, 09:15)
    - auth-service.log(180MB, 09:12)
    - payments-service.log(95MB, 09:17)
- 決策信號:
  - 修改時間接近事件窗口,大小提示數據量與複雜度
  - 優先檢查 gateway(流量匯聚點)

- grep("/logs/api/api-gateway.log", "timeout", window=last_60m)
  - 返回匹配統計與最近片段的偏移量

- tail("/logs/api/api-gateway.log", n=200, from=offset)
  - 觀察模式:timeout集中在某條上游路由

- query_metrics(panel="error_rate", range=last_60m, filter="service=gateway route=/v1/orders")
  - 結果:09:05‑09:20 錯誤率升高,與日誌吻合

- write_note("hypothesis", "超時集中在 /v1/orders 路由,時間對齊監控峰值;可能與下游 auth-service 連接池耗尽相關")

# 第2輪(漸進披露:加載必要片段)
- grep("/logs/api/auth-service.log", "connection pool|timeout", window=last_60m)
- head("/logs/api/auth-service.log", n=100, from=matched_offset-500)
  - 結果:09:05 開始出現 "pool exhausted" 警告

- open_wiki("SRE/Runbooks/Timeout.md#connection-pool")
  - 只取節選(max_chars=600):推薦將 pool.size 從 200 提升至 400,並啟用指數退避

- query_metrics(panel="latency_p95", range=last_60m, filter="service=auth")
  - 結果:p95 在 09:05 附近突升,與連接池告警時間一致

- 更新工作記憶(上下文僅保留三條核心摘錄)
  - 摘錄1:gateway 路由 /v1/orders timeout 片段(~200行尾部)
  - 摘錄2:auth‑service pool exhausted 告警片段(~80行)
  - 摘錄3:Wiki Runbook 連接池節選(~400字)
- 其他細節寫入持久筆記(write_note),不留在上下文

# 第3輪(收斂與行動)
- 結論(≤200字):超時由 auth‑service 連接池耗盡引發,集中影響 /v1/orders;與監控峰值時間吻合
- 引用(≤3條):日誌片段偏移、監控查詢ID、Wiki小節錨點
- 行動項:
  - 臨時:提升 auth 連接池至 400 並啟用指數退避;觀察 15 分鐘
  - 根因復盤:評估本週訂單高峰的流量建模與容量規劃
  - 跟進:記錄變更與影響範圍到 Incidents/2025‑10‑18.md

# 上下文管理
- 工作記憶:僅保留當前決策所需的3個摘錄
- 持久化:詳細日誌偏移、圖表鏈接、附加線索寫入筆記(不佔用上下文)
- Token 用量:每輪≈1‑2k tokens,隨檢索漸進增加但保持可控

6. 長時任務的上下文工程

當任務跨越數十分鐘到數小時,超過上下文窗口容量時,代理需要專門技術維持連貫性、目標導向與狀態記憶,使用更大窗口的模型並不能解決問題:再大的窗口也會遭遇上下文污染與相關性衰減。
我們實踐出三類應對手段:壓縮、結構化筆記、多代理架構。

壓縮(Compaction)

  • 當對話接近窗口上限,先高保真總結,再以該總結重建新上下文,保留關鍵決策、未解決問題、實現細節,丟弃重複的工具輸出或不再有用的信息。
  • 工程要點是 “取捨的藝術”:過度壓縮會丟掉後來才顯得關鍵的細節,建議用複雜的代理軌跡調教壓縮提示,先最大化召回率(儘可能捕獲所有相關信息),再迭代提升精確度(去掉冗餘)。
  • 低風險的輕量壓縮舉措是 “清理歷史工具調用結果”:一旦工具結果在很早的歷史中出現,通常無需再次原樣保留。

結構化筆記(Agentic Memory)

  • 讓代理定期把重要信息寫入上下文外的持久筆記(如 NOTES.md、待辦清單),並在需要時拉回上下文。
  • 這是一種低開銷的持久記憶機制,適合複雜項目的進度跟蹤、依賴管理、關鍵策略保留,跨越數十次工具調用仍保持連貫。
  • 實踐表明,即便在非編碼領域,結構化記憶也能顯著提升代理能力:它能維護地圖、目標計數、策略效果,跨越多次上下文重建仍能連續推進長期計劃。

多代理架構(Sub-agent)

  • 將大任務拆分為專長明確的子代理,每個子代理獨立探索、保持乾淨的上下文,主代理負責高層規劃與結果統籌。
  • 子代理可用大量 token 深挖細節,但只返回凝練的摘要(如 1,000–2,000 tokens),這樣就實現了清晰的關注點分離:細節搜索的上下文隔離在子代理中,主代理只處理綜合與決策。
  • 在複雜研究與分析任務中,這一模式往往比單代理更穩健。

如何選擇策略(按任務特徵)

  • 壓縮:適合需要大量來回互動、對話連續性的任務。
  • 結構化筆記:適合里程碑明確、迭代推進的開發類任務。
  • 多代理:適合並行探索收益顯著的複雜研究與分析。

7. 總結上下文功能原則

  • 明確目標與評估標準:期望的行為具體是什麼?怎麼度量成功?
  • 從最小上下文開始:用最強模型測底線表現,圍繞失敗模式增補信息。
  • 精煉系統提示:把“剛剛好”的指令高度寫清楚,結構分區,去掉硬編碼的脆弱邏輯。
  • 篩選工具:保留最小可行集,明確參數與用途,避免重疊與選擇歧義。
  • 精挑示例:多樣而典型,優先展示期望的推理與輸出形態。
  • 設計檢索策略:根據任務選擇預檢索、即時檢索或混合;提供輕量引用與基礎命令。
  • 管理上下文污染:上線壓縮與歷史清理,優先清理冗餘工具輸出。
  • 建立記憶機制:持久筆記/文件式內存,記錄目標、進度、關鍵決策與依賴。
  • 考慮多代理:對複雜任務引入子代理,要求返回高質量摘要。
  • 持續迭代:基於真實代理軌跡調參提示與策略,以召回和精確度為雙目標。

如果以上內容你覺得太多,最有效的一條建議就是:上下文儘量足夠小,一次只做少量的任務。


原文出處:https://juejin.cn/post/7562188129948565539


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝26   💬9   ❤️7
656
🥈
我愛JS
📝4   💬13   ❤️7
284
🥉
御魂
💬1  
4
#4
2
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付