詳解AI Agent Context 壓縮策略選型
Context 壓縮有哪些主流策略?
它們各自的成本與保真度怎么算?
面對具體場景,到底該怎么選?
上一篇 AI Agent Context 工程我們鋪開了 4 層 context 的全貌(輸入 / 運(yùn)行時 / 壓縮 / 長期記憶),里面只給了一張策略對比表就翻篇了。本篇專門把「壓縮層」拆開講——6 種主流策略的可運(yùn)行代碼、各自的代價,以及一張決策樹。

一、壓縮策略選錯,問題代價是任務(wù)崩盤
先說一個反直覺的事實:壓縮策略選錯,不是 token 多花一點的問題,是任務(wù)完成率掉 30% 的問題。
NirDiamant 在項目里跑了一組對照實驗(基于 LoCoMo benchmark),同一段 50 輪長對話,硬截斷會把"用戶在第 12 輪提到的忌口信息"直接砍掉,下游 Agent 推薦餐廳時直接踩雷;摘要壓縮在 5 輪一次時任務(wù)完成率最高(92%),但 1 輪一摘要時反而掉到 71%——因為每次摘要都丟掉一些次要細(xì)節(jié),最后細(xì)節(jié)全沒了。
壓縮率高的策略不一定保真度高——這是新手最容易踩的坑。壓縮的本質(zhì)是"用信息熵?fù)Q token 預(yù)算",不同策略在不同熵分布上表現(xiàn)天差地別。
二、6 大核心概念 + 引用塊定義(含酒店類比)
Context 壓縮策略:在 LLM 調(diào)用前對 prompt 做有損/無損瘦身的技術(shù)族,由 6 大主流方法組成。
- 硬截斷 (Truncation):直接砍掉超出 N token 的最早內(nèi)容,最便宜也最暴力
- 滑動窗口 (Sliding Window):保留最近 K 輪 + K-1 輪重疊,平衡遺忘與開銷
- 摘要壓縮 (Summarization):LLM 把歷史生成摘要替換原文,保真度最高但要 LLM 調(diào)用
- 關(guān)鍵提取 (Extraction):用規(guī)則/小模型抽實體/數(shù)字/決策,只留骨架
- 神經(jīng)壓縮 (LLMLingua):用小分類模型逐 token 判重要性再裁剪,微軟 2023 提出的
- 外部化 (Offloading):大塊內(nèi)容寫盤/向量庫,只在 prompt 里留引用/檢索片段
類比時間。我把這 6 種策略映射成"酒店前臺給客人辦入住":
- 硬截斷 = 行李員只看最上面 5 件行李,剩下的直接塞倉庫
- 滑動窗口 = 只看你最近 3 次出差帶了什么,第 4 次就忘掉
- 摘要壓縮 = VIP 客戶經(jīng)理幫你寫一段"客戶畫像",下次憑畫像接待
- 關(guān)鍵提取 = 入住登記表只填"姓名/身份證/房型",其他信息都不要
- 神經(jīng)壓縮 = 前臺配了個 AI 助理,看一眼行李就知道哪些是"重要物品"
- 外部化 = 行李太多?前臺告訴你"行李柜 031 號,憑取件碼隨時取"
選型的關(guān)鍵不是"哪個最好",是"哪個最匹配你的行李特征"——你出差帶的是書(長文本)還是雜物(多模態(tài)),前臺給你的方案完全不同。
三、代碼實現(xiàn):6 種策略逐個上手
下面 6 段代碼都可以獨立運(yùn)行,邏輯都從 Agent_Memory_Techniques 和 mem0ai/mem0 提煉出來,可直接 copy 到你的項目里。
3.1 硬截斷(最便宜)
# 硬截斷:保留 System + 最近 N 條消息
from langchain_core.messages import SystemMessage, BaseMessage
def hard_truncate(messages: list[BaseMessage], max_messages: int = 20) -> list[BaseMessage]:
"""保留 SystemMessage 不動 + 最近 max_messages 條"""
system = [m for m in messages if isinstance(m, SystemMessage)]
others = [m for m in messages if not isinstance(m, SystemMessage)]
return system + others[-max_messages:]適用:閑聊機(jī)器人、簡單客服問答。禁用:用戶偏好、關(guān)鍵決策類對話。
3.2 滑動窗口(任務(wù)流友好)
# 滑動窗口:保留最近 K 輪(user+assistant 算一輪)
def sliding_window(messages: list[BaseMessage], window_size: int = 10) -> list[BaseMessage]:
"""以"輪"為單位保留,user+assistant 算 1 輪"""
system = [m for m in messages if isinstance(m, SystemMessage)]
others = [m for m in messages if not isinstance(m, SystemMessage)]
# 按 2 條消息一輪倒推
kept = others[-(window_size * 2):] if len(others) > window_size * 2 else others
return system + kept適用:固定長度的多步任務(wù)(數(shù)據(jù)分析、報表生成)。禁用:長程依賴任務(wù)(用戶 12 輪前提到的信息要用到第 30 輪)。
3.3 摘要壓縮(保真度最高)
# 摘要壓縮:Anchored Iterative Summarization(Anthropic 推薦結(jié)構(gòu))
from langchain_openai import ChatOpenAI
from langchain_core.messages import SystemMessage, RemoveMessage
SUMMARY_PROMPT = """請將以下對話壓縮成結(jié)構(gòu)化摘要,每個 section 一行,不要超過 250 字:
- INTENT: 用戶核心目標(biāo)
- DECISIONS: 已做出的關(guān)鍵決定
- FACTS: 重要的實體/數(shù)字/事實
- OPEN: 未解決的問題
對話:
{messages}
"""
def summarize_compress(messages: list[BaseMessage], threshold: int = 12) -> dict:
if len(messages) <= threshold:
return {"messages": messages, "summary": ""}
# 保留 System + 最近 2 輪,其余送 LLM 摘要
system = [m for m in messages if isinstance(m, SystemMessage)]
to_compress = [m for m in messages if not isinstance(m, SystemMessage)][:-2]
recent = [m for m in messages if not isinstance(m, SystemMessage)][-2:]
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
text_blob = "\n".join(f"{m.type}: {m.content[:300]}" for m in to_compress)
summary = llm.invoke(SUMMARY_PROMPT.format(messages=text_blob)).content
# 顯式刪除被壓縮的消息
return {
"messages": system + recent + [SystemMessage(content=f"歷史摘要:{summary}")]
+ [RemoveMessage(id=m.id) for m in to_compress if hasattr(m, "id")],
"summary": summary,
}適用:長對話、連續(xù)多任務(wù)。成本:每次壓縮 1 次 LLM 調(diào)用,建議用 gpt-4o-mini 或 claude-haiku-4-5,省 80% 成本。
3.4 關(guān)鍵提取(PII/合規(guī)場景必選)
# 關(guān)鍵提?。褐槐A魧嶓w/數(shù)字/決策的骨架
import re
from typing import TypedDict
class ExtractedFacts(TypedDict):
entities: list[str] # 人名/地名/產(chǎn)品名
numbers: list[str] # 金額/日期/百分比
decisions: list[str] # 用戶做出的決定
def extract_key_facts(messages: list[BaseMessage]) -> ExtractedFacts:
"""規(guī)則版:正則抽實體/數(shù)字/LLM 抽決策"""
text = "\n".join(m.content for m in messages if hasattr(m, "content"))
# 實體:簡單正則(生產(chǎn)換 GLiNER / 小模型)
entities = list(set(re.findall(r"[A-Z][a-zA-Z]{2,}", text)))[:20]
# 數(shù)字:金額/日期
numbers = re.findall(r"\d{1,3}(?:,\d{3})*(?:\.\d+)?|\d{4}-\d{2}-\d{2}", text)[:20]
# 決策:用小模型判斷
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
decisions_prompt = (
f"從下面對話中提取用戶做出的關(guān)鍵決定,每條一行,無決定返回'NONE':\n{text[:2000]}"
)
decisions_text = llm.invoke(decisions_prompt).content
decisions = [d.strip() for d in decisions_text.split("\n") if d.strip() and d.strip() != "NONE"]
return {"entities": entities, "numbers": numbers, "decisions": decisions}
# 用法:把 facts 拼到 system prompt 里
def build_prompt_with_facts(messages, facts: ExtractedFacts) -> str:
fact_str = (
f"已知實體:{', '.join(facts['entities'][:10])}\n"
f"關(guān)鍵數(shù)字:{', '.join(facts['numbers'][:10])}\n"
f"用戶決定:{'; '.join(facts['decisions'][:5])}"
)
return fact_str適用:合規(guī)要求高(PII 不能進(jìn) LLM)、長文本檢索任務(wù)。優(yōu)勢:提取后從 10K token 壓到 ~200 token 幾乎是無損的。
3.5 神經(jīng)壓縮(LLMLingua-2)
# 神經(jīng)壓縮:Microsoft LLMLingua-2,逐 token 分類
# pip install llmlingua
from llmlingua import PromptCompressor
def neural_compress(prompt: str, target_ratio: float = 0.4) -> str:
"""target=0.4 表示壓縮到原文 40%"""
compressor = PromptCompressor(
model_name="microsoft/llmlingua-2-bert-base-multilingual-cased-meetingbank",
device_map="cpu", # GPU 改 "cuda"
)
result = compressor.compress_prompt(
prompt,
rate=target_ratio,
force_context_tokens=["IMPORTANT", "DECISION", "USER_PREF"],
)
return result["compressed_prompt"]
# 用法
raw_prompt = "用戶在前 20 輪的對話內(nèi)容..." * 50
compressed = neural_compress(raw_prompt, target_ratio=0.3)
print(f"原 {len(raw_prompt)} → 壓 {len(compressed)} chars")適用:超長 prompt(>50K)、RAG 多文檔合并。優(yōu)勢:壓縮率 60-80% 時仍保留關(guān)鍵信息,比純摘要快 10 倍。坑:首次下載 ~500MB 模型。
3.6 外部化(RAG-offload)
# 外部化:大塊內(nèi)容寫向量庫,prompt 里只留檢索片段
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_core.documents import Document
import uuid
class ContextOffloader:
"""把長內(nèi)容外置,prompt 只引用 ref_id"""
def __init__(self):
self.embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
self.store = FAISS.from_texts(["__init__"], self.embeddings)
self.ref_map: dict[str, str] = {"__init__": "__init__"}
def offload(self, content: str, metadata: dict | None = None) -> str:
"""返回 ref_id,content 寫進(jìn)向量庫"""
ref_id = f"ctx_{uuid.uuid4().hex[:8]}"
self.store.add_texts(
[content],
metadatas=[{**({"ref_id": ref_id}), **(metadata or {})}],
)
self.ref_map[ref_id] = content
return ref_id
def retrieve(self, ref_id: str, query: str, k: int = 3) -> str:
"""按 query 檢索回最相關(guān)片段(不是原文)"""
if ref_id not in self.ref_map:
return ""
full = self.ref_map[ref_id]
# 把引用內(nèi)容加進(jìn)去檢索
tmp_store = FAISS.from_texts([full], self.embeddings)
docs = tmp_store.similarity_search(query, k=k)
return "\n".join(d.page_content for d in docs)
# 用法
offloader = ContextOffloader()
ref = offloader.offload("(此處是 10K 字的會議記錄...)")
# 后續(xù)調(diào)用 LLM 時 prompt 里只寫:[REF:ref_id] 查"用戶決策"
# LLM 觸發(fā)工具調(diào)用時再 retrieve()適用:工具返回超長(PDF 解析、日志文件)、文檔處理任務(wù)。優(yōu)勢:上下文永遠(yuǎn)不爆,引用解耦。
四、4 個常見坑:選對了策略也不一定贏
坑 1:摘要觸發(fā)時機(jī)太晚
現(xiàn)象:等 prompt_too_long 報錯才壓縮
根因:觸發(fā)后狀態(tài)已污染,回滾困難,且此時調(diào)用 LLM 已經(jīng)失敗
解法:60% 窗口占用就主動壓縮,80% 強(qiáng)制壓縮(與上篇一致,Anthropic Claude Code 內(nèi)部建議)
坑 2:神經(jīng)壓縮把關(guān)鍵決策一起砍了
現(xiàn)象:LLMLingua 壓完后,user 說"以后別再給我推 5G 套餐"這條決定沒了
根因:默認(rèn)按"通用重要性"裁剪,沒保護(hù)業(yè)務(wù)關(guān)鍵詞
解法:傳 force_context_tokens=["禁止", "決定", "不", "以后"] 等業(yè)務(wù)關(guān)鍵詞,強(qiáng)制保留
坑 3:摘要破壞了"原子消息組"
現(xiàn)象:第 8 輪的 tool_call 還在,對應(yīng)的 tool_result 被砍了
根因:按"條數(shù)"截斷,沒考慮消息組完整性
解法:必須以 MessageGroup 為單位(tool_call + tool_result 配對),要么都留要么都刪
坑 4:外部化的"假檢索"
現(xiàn)象:把內(nèi)容 offload 后,retrieve 沒用 query 匹配,原文一字不差全塞回來
根因:把"外置"當(dāng)成了"備份",沒有真正做語義檢索
解法:retrieve 必須接用戶當(dāng)前 query 做 similarity_search,否則外部化就是脫褲子放屁
五、生產(chǎn)選型決策樹
面對 6 種策略怎么選?給你一個 4 維度決策框架:
- 內(nèi)容特征:是結(jié)構(gòu)化(JSON/日志)還是非結(jié)構(gòu)化(自然語言)?
- 延遲預(yù)算:單次響應(yīng)必須 <1s 還是有 3-5s 余量?
- 成本上限:每千次調(diào)用預(yù)算 1 美元還是 10 美元?
- 保真度要求:錯了能不能容忍(閑聊)還是錯了要命(醫(yī)療/法律)?
按這 4 維打分,能淘汰掉 80% 的不適用方案:
| 場景 | 內(nèi)容 | 延遲 | 成本 | 保真 | 推薦策略 |
|---|---|---|---|---|---|
| 閑聊機(jī)器人 | 非結(jié)構(gòu)化 | <1s | 極低 | 低 | 硬截斷 |
| 數(shù)據(jù)分析助手 | 半結(jié)構(gòu)化 | 3s | 中 | 中 | 滑動窗口 + 關(guān)鍵提取 |
| 寫作/創(chuàng)作 | 非結(jié)構(gòu)化 | 5s | 高 | 高 | 摘要壓縮(5 輪一次) |
| 合規(guī)咨詢 | 結(jié)構(gòu)化 | 3s | 中 | 極高 | 關(guān)鍵提取 + 摘要 |
| 長文檔 RAG | 非結(jié)構(gòu)化 | 5s | 高 | 中 | 神經(jīng)壓縮 + 外部化 |
| 工具調(diào)用密集 | 半結(jié)構(gòu)化 | 1s | 中 | 高 | 滑動窗口 + 外部化 |
核心原則:單一策略永遠(yuǎn)不夠。生產(chǎn)項目都是"截斷/滑窗打頭陣 → 摘要兜底 → 必要時外部化"分層組合。Claude Code 的 5 層壓縮(microcompact → autocompact → context collapse → 工具結(jié)果截斷 → 子代理隔離)就是這個套路。
六、6 大策略 + 決策總表
| 策略 | 核心思路 | 成本 | 保真度 | 延遲 | 適用場景 | 不適用 |
|---|---|---|---|---|---|---|
| 硬截斷 | 砍最早 N 條 | 0 | 低 | 0 | 閑聊/簡單問答 | 關(guān)鍵決策類 |
| 滑動窗口 | 保留最近 K 輪 | 0 | 中 | 0 | 固定長度任務(wù)流 | 長程依賴 |
| 摘要壓縮 | LLM 生成摘要 | 中 | 高 | 1-3s | 長對話/多任務(wù) | 極高頻調(diào)用 |
| 關(guān)鍵提取 | 抽實體/數(shù)字/決定 | 低-中 | 高 | 0.5-1s | 合規(guī)/檢索 | 自由對話 |
| 神經(jīng)壓縮 | 小模型逐 token 評分 | 中 | 高 | 1-2s | 超長 prompt | 強(qiáng)實時 |
| 外部化 | 內(nèi)容外置+檢索 | 低 | 中-高 | 0.5-1s | 工具結(jié)果超長 | 短上下文 |
決策樹簡化版:
你的上下文有多長? ├─ < 4K → 不用壓縮(裸跑) ├─ 4K-32K → 滑動窗口(最穩(wěn)) ├─ 32K-100K → 摘要壓縮(5 輪一次) ├─ 100K-500K → 神經(jīng)壓縮(LLMLingua) └─ > 500K → 外部化 + RAG 檢索 你的內(nèi)容能丟嗎? ├─ 閑聊可丟 → 硬截斷 / 滑窗 ├─ 決策不能丟 → 關(guān)鍵提取 + 摘要 └─ 合規(guī)不能錯 → 關(guān)鍵提取 + 外部化
七、面試官還會追問什么?
追問 1:神經(jīng)壓縮和摘要壓縮的本質(zhì)區(qū)別?
→ 摘要壓縮是"生成式"(LLM 重新組織語言),神經(jīng)壓縮是"判別式"(小模型給每個 token 打分)。摘要保留語義完整,神經(jīng)壓縮保留關(guān)鍵 token。1M token 場景優(yōu)先神經(jīng)壓縮(快),100K 以內(nèi)優(yōu)先摘要(準(zhǔn))。
追問 2:為什么不直接用 1M 窗口模型,省得壓縮?
→ 三個問題:(1) Context Rot——Chroma 2025 實驗 GPT-4o 準(zhǔn)確率從 98% 掉到 64%;(2) 成本線性增長,輸入 1M token 單次調(diào)用比 32K 貴 30 倍;(3) 延遲,1M token 推理首 token 延遲 5-10s。大窗口不是銀彈,分層管理才是。
追問 3:怎么評估壓縮策略好不好?
→ 看三個指標(biāo):(1) 任務(wù)完成率(最終對不對),(2) token 壓縮率(省了多少),(3) 關(guān)鍵信息保留率(重要決策是否還在)。
追問 4:長期記憶和壓縮的邊界?
→ 長期記憶是"跨會話"且"用戶畫像/歷史決策"類信息,存向量庫;壓縮是"單會話內(nèi)"的瘦身,存當(dāng)前 prompt。一個跨會話的事實(比如用戶忌口)應(yīng)該走長期記憶,不應(yīng)該每次會話都從歷史里壓縮出來。
追問 5:實時性要求極高(<100ms)時怎么壓縮?
→ 放棄所有 LLM 調(diào)用類策略,只用硬截斷 + 滑動窗口 + 關(guān)鍵提取(規(guī)則版)。規(guī)則版提?。ㄕ齽t/小分類器)能在 10ms 內(nèi)完成 10K 文本的實體抽取。
八、總結(jié):壓縮策略是"分層 + 組合",不是"選一個"
Context 壓縮不是"挑一個最好的策略"問題,是"按場景組合分層"問題:
- 默認(rèn)起手式:滑動窗口 + 關(guān)鍵提?。ń^大多數(shù)項目夠用)
- 長對話必加:摘要壓縮(5 輪一次,不要每輪都壓)
- 超長 prompt:神經(jīng)壓縮(LLMLingua-2 是事實標(biāo)準(zhǔn))
- 工具結(jié)果超長:外部化(寫向量庫 + 檢索回注)
- 合規(guī)場景:關(guān)鍵提取 + 長期記憶,不要讓 PII 走 LLM
讀完這篇你應(yīng)該能:
- 說出 6 種主流策略的代碼實現(xiàn)(不是只背概念)
- 用 4 維度決策框架給你的項目選型
- 避開 4 個常見坑(時機(jī)、關(guān)鍵詞、原子組、假檢索)
如果這篇文章讓你對壓縮選型少一些糾結(jié),歡迎點贊 + 在看。
最后一個問題留給你:你的項目現(xiàn)在 prompt 平均有多長?有沒有跑過 token 占用率統(tǒng)計?哪一段最值得壓縮?
到此這篇關(guān)于AI Agent Context 壓縮策略選型的文章就介紹到這了,更多相關(guān)AI Agent Context 壓縮內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!
相關(guān)文章
AI Agent Harness它是一套系統(tǒng)化工程方法論,專門設(shè)計、搭建、運(yùn)維這套 AI 管控運(yùn)行體系,解決 AI 干活不穩(wěn)定、越權(quán)、失憶、失控問題,簡單來說它讓AI智能體既跑得快,又跑2026-06-25
如何使用 AI Agent 做一個前端小游戲(從提示詞到可運(yùn)行Demo)
這段文章介紹了使用AI編程工具AIAgent制作一個簡單前端小游戲的過程,并分享了完整代碼和優(yōu)化建議,適合前端初學(xué)者和開發(fā)者學(xué)習(xí)和參考,感興趣的朋友跟隨小編一起看看吧2026-06-24
CI/CD中的AI如何用Agent自動生成Release Note
這篇教程教你如何使用GitHub Actions和AI工具daily-report-agent自動生成ReleaseNote,省時,提高效率,本文介紹的非常詳細(xì),感興趣的朋友一起看看吧2026-06-23
Hermes Agent vs OpenClaw:2026年兩大AI Agent框架深度對比分析
OpenClaw作為開源社區(qū)寵兒,Hermes Agent作為企業(yè)級解決方案,兩者在設(shè)計理念、架構(gòu)實現(xiàn)和適用場景上存在根本性差異,本文就對二者進(jìn)行了深度的對比分析,需要的朋友可以參考2026-04-21
Hermes Agent工具集大全:20+工具讓你的AI無所不能
工具集是Hermes Agent區(qū)別于普通AI聊天工具的關(guān)鍵,通過調(diào)用各種工具,Hermes Agent不僅僅是一個對話伙伴,而是一個能夠?qū)嶋H操作系統(tǒng)的智能代理,本文整理了20+個工具集,覆2026-04-20






