節省 Token 的 8 種方案

前言

最近有球友問:「三哥,我們團隊在做 AI 客服,對話一長 token 消耗扛不住。有沒有一種方案,既能保留完整上下文記憶,又能省 token?」

這位朋友的問題,恰恰戳中了當下 AI 應用開發最頭痛的痛點。

既要馬兒跑得快,又要馬兒不吃草。

這聽起來像是矛盾,但經過這兩年的摸索,我發現在某些條件下,確實存在「相對兩全」的解法。

今天這篇文章就專門跟大家一起聊聊這個話題,希望對你會有所幫助。

更多項目實戰在 Java 突擊隊網:susan.net.cn

一、為什麼記憶必然消耗 token?

很多小夥伴可能覺得,大模型就像一個人,你說過的話它應該天然記得住。

錯!

大模型本質上是一個無狀態的函數

每次呼叫都是獨立的,它沒有任何「記憶細胞」。

為了讓 AI 記住之前聊過什麼,唯一的辦法就是:把歷史對話拼接到下一次請求裡

這就是所謂的「上下文注入」。

image

看到沒?

第 N 次請求攜帶的歷史,是前 N-1 輪的總和

token 消耗隨著對話輪數線性增長——更準確地說,是 O(n) 級別的增長。

但事情沒這麼簡單。

Transformer 模型的核心是自注意力機制,它的計算複雜度是O(n²)

也就是說,輸入長度翻一倍,計算量翻四倍。

更可怕的是,當輸入過長時,模型會患上「中間迷失症」——位於長文本中間的資訊被嚴重忽略。

所以,我們的真實困境是:

保留全部歷史 → token 爆炸 + 注意力稀釋 → 又貴又笨

丟棄歷史 → 資訊丟失 → AI 變「金魚腦」

有沒有一條中間道路?

有。

下面我會介紹 8 種方案,從簡單到複雜,從廉價到智能,你可以根據自己的場景按需選擇。

二、方案一:全量記憶

簡單粗暴,但不推薦。

這是最直覺的實現:把所有對話都存下來,每次請求全部帶上。

程式碼解析:邏輯非常直接——fullHistory 列表保存所有訊息,buildContext() 把它們全部拼接成字串。沒有任何優化。

優點

  • 資訊零損失,完美保留每句話
  • 實現極簡單,5 分鐘寫完

缺點

  • token 消耗隨輪數線性增長,100 輪可能幾萬 token
  • 達到模型上下文上限後(比如 8K/128K),舊訊息會被截斷
  • 回應時間越來越慢,帳單越來越高

適用場景:只適合 Demo 演示、除錯測試,或者保證對話不超過 10 輪的極短場景。

生產環境慎用

三、方案二:滑動視窗

省 token,但記性差。

滑動視窗只保留最近 N 輪對話,超出視窗的直接丟棄。

程式碼解析ArrayDeque 作為佇列,offer() 在尾部新增,當大小超出 windowSize * 2(因為一輪包含使用者和助理兩條訊息)時,poll() 移除最舊的。

這樣視窗始終保持固定大小。

優點

  • token 消耗嚴格可控,不會無限增長
  • 實現簡單,效能高
  • 回應速度快

缺點

  • 早期資訊永久丟失。使用者第一句說「我是 VIP 會員」,第 20 輪問「我的會員權益」,AI 已經忘了
  • 無法處理需要長期記憶的任務

適用場景:客服快速問答、閒聊機器人、臨時對話——那些不需要記住早期資訊的場景。

四、方案三:摘要壓縮

讓 AI 自己總結記憶。

這個方案的想法很巧妙:不保留原始對話,而是定期讓大模型把舊對話「壓縮」成一段摘要,只保留關鍵資訊。

程式碼詳解

  • summary 欄位儲存壓縮後的歷史摘要,初始為空。
  • recentMessages 儲存尚未被壓縮的新訊息。
  • 每次新增訊息後,估算總 token 數(摘要 + 新訊息),如果超過閾值,呼叫 compress()
  • 壓縮時,將舊摘要和新訊息一起發給大模型,讓它生成一個新的、更精煉的摘要。
  • 壓縮完成後清空 recentMessages,但也可以選擇保留最後 1-2 輪,防止摘要丟失近期細節。
  • buildContext() 回傳摘要 + 最近訊息的拼接,作為下次請求的上下文。

優點

  • 壓縮比極高:100 輪對話可能壓縮成 200 字摘要,token 節省 90% 以上
  • 關鍵資訊被提煉出來,比滑動視窗聰明得多
  • 成本可控,摘要生成的呼叫次數不多(每隔 N 輪一次)

缺點

  • 摘要可能失真:模型可能漏掉重要細節或產生幻覺
  • 每次壓縮需要額外呼叫 LLM,增加幾十毫秒延遲
  • 摘要的「資訊密度」隨著壓縮次數增加而下降(反覆壓縮會丟失細節)

適用場景:長週期對話(幾十到幾百輪),對資訊完整性要求不是 100% 嚴謹的場景,比如教育輔導、角色扮演。

五、方案四:向量記憶(RAG)

檢索相關而不是保留全部。

這是目前工業界最主流的方案。

思路是:不保存全部歷史,而是把歷史訊息向量化後存入資料庫,每次只檢索最相關的幾條歷史

程式碼詳解

  • 每條訊息單獨儲存,呼叫 embeddingClient.embed() 將其轉為高維向量(比如 1536 維)。
  • 向量資料庫儲存向量 + 原始文本 + 元資料(角色、時間戳等)。
  • 當使用者發來新問題時,同樣將問題向量化,然後到資料庫中做餘弦相似度搜尋,找到最相似的 topK 條歷史訊息。
  • 這些檢索出的歷史訊息就是「與當前問題最相關的記憶」,拼接進上下文。

優點

  • token 消耗極低:每次只帶 5-10 條最相關的歷史,而不是幾百條
  • 可以存取非常久遠的記憶:只要存了,就能檢索到,不受視窗限制
  • 彈性高:可以混入知識庫、FAQ 等外部知識

缺點

  • 檢索可能不準確:如果 embedding 模型品質差,或者問題與歷史的相關性未被捕捉到,就會漏掉關鍵資訊
  • 需要額外元件:向量資料庫、embedding 服務,增加系統複雜度
  • 有延遲:embedding 呼叫 + 向量檢索,大約增加 50-200ms

適用場景:絕大多數生產環境——智能客服、AI 助手、個人化推薦等。

這是目前最推薦的方案

六、方案五:分層混合記憶

它是工業級最強方案。

沒有單一方案是完美的。真正的工業級系統,往往會組合多種策略,形成分層記憶。

下面這張圖展示了一個典型的混合記憶架構:

Java 實現的核心骨架:

程式碼解析

  • L1 短期:滑動視窗保留最近 5 輪,保證對話連貫性,延遲最低。
  • L2 中期:摘要壓縮,當訊息累積到一定程度(比如 token 超 2000 或每 10 輪)就壓縮一次,保留全局脈絡。
  • L3 長期:向量資料庫儲存每條訊息,支援按語義檢索,解決「長尾記憶」問題。
  • 建構上下文時:優先保證短期(最可靠),然後加上向量檢索出的相關歷史(彌補視窗丟棄的),最後補充摘要(作為兜底)。

優點

  • 兼具短時連貫、長時檢索、全局摘要,覆蓋幾乎所有場景
  • token 消耗可控(短期固定 + 檢索 topK + 摘要)
  • 即使檢索失敗,摘要和短期視窗也能兜底

缺點

  • 實作複雜,需要維護多個元件
  • 需要精細調參(視窗大小、摘要頻率、檢索數量)

適用場景:大型生產系統、企業級 AI 應用,對體驗和成本都有高要求的場景。

七、方案六:狀態變數提取

該方案需要極致的結構化壓縮。

有些場景下,真正需要記憶的不是整個對話,而是幾個關鍵狀態變數

比如訂票機器人只需要知道:{目的地: "北京", 日期: "2026-05-01", 人數: 2}

優點

  • 極致省 token:幾 KB 的狀態就能代替幾十 KB 的對話
  • 結構化,模型更容易理解

缺點

  • 只適合高度結構化的任務(訂票、填表、參數收集)
  • 提取狀態本身需要呼叫 LLM,有額外成本

適用場景:任務型對話、表單填寫、配置導引。

八、方案七:工具/函式呼叫

把記憶「外包」給外部系統。

大模型不是萬能的,記憶完全可以交給外部資料庫。

模型只需要學會呼叫「儲存記憶」和「查詢記憶」的工具。

這種方案讓模型自主管理記憶——它覺得重要就存,需要就用。這是目前 AI Agent 的主流做法。

優點:極其彈性,模型可以按需存取;token 消耗幾乎為零(只傳工具呼叫結果)。
缺點:依賴模型自身的函式呼叫能力,容易出錯或漏存。

適用場景:Agent 系統、自主決策類應用。

九、終極對比

方案 token 節省效果 資訊保留能力 實作複雜度 推薦指數
全量記憶 0%(無節省) 100% ❌ 不推薦
滑動視窗 極高(固定) 差(只留近期) ⭐⭐ ⭐⭐⭐ 短對話可用
摘要壓縮 高(70-90%) 中(可能失真) ⭐⭐⭐ ⭐⭐⭐⭐ 長對話
向量檢索(RAG) 高(每次 topK) 高(語義檢索) ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ 首選
分層混合 高極高 高極高 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ 工業級
狀態變數 極高(近乎 0) 中(僅結構化) ⭐⭐⭐ ⭐⭐⭐⭐ 任務型
工具呼叫 極高 中(靠模型) ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ Agent 場景

更多項目實戰在 Java 突擊隊網:susan.net.cn

總結

回到最初的問題:有沒有方案既能保留上下文記憶,又能省 token?

我的答案是:有,但不存在「免費午餐」

每一分 token 的節省,都換來了系統複雜度的增加或記憶精度的下降。

根據我的實戰經驗,給你幾條直接的建議:

  1. 如果你剛開始做 MVP:直接用滑動視窗(最近 10 輪),上線跑起來再說。先驗證產品價值,再優化成本。
  2. 如果你做的是通用客服/AI 助手:首選向量檢索(RAG)。這是目前最成熟、性價比最高的方案。配合一個小的滑動視窗(3-5 輪)保證對話連貫性,效果已經很好了。
  3. 如果你的對話輪次非常長(100+)且資訊密度高:上分層混合記憶。短期視窗 + 中期摘要 + 長期向量,三者配合才能既省 token 又不丟資訊。
  4. 如果你做的是表單/訂票/參數收集狀態變數提取是王道。幾十個欄位就能代表整個會話,token 幾乎不增長。
  5. 永遠不要在生產環境用全量記憶——除非你預算無限且使用者只聊 5 句話。

posted @ 蘇三說技術 閱讀(0) 評論(0) MD 編輯 收藏 檢舉


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


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

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝4   💬4   ❤️2
347
🥈
我愛JS
📝1   💬2   ❤️2
107
🥉
Gigi
2
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登