戰(zhàn):多模式上下文管理設(shè)計(jì)與落地)
1. 從“context-mode”這個(gè)詞說(shuō)起它到底在解決什么問(wèn)題第一次看到“context-mode”這個(gè)標(biāo)題很多人會(huì)下意識(shí)覺(jué)得它是個(gè)抽象概念不像某個(gè)具體框架或工具那樣一眼能看懂。我最初接觸這個(gè)詞是在做對(duì)話系統(tǒng)上下文管理的時(shí)候當(dāng)時(shí)團(tuán)隊(duì)里有人提出“我們是不是該給上下文加個(gè)模式”我第一反應(yīng)也是懵的——上下文不就是一串歷史消息嗎加模式是什么意思后來(lái)踩了幾次坑才明白context-mode 本質(zhì)上是在討論“上下文該以什么形態(tài)、什么粒度、什么生命周期被組織和消費(fèi)”。它不是一個(gè)具體的庫(kù)也不是某個(gè)平臺(tái)獨(dú)有的功能而是一類設(shè)計(jì)思路的統(tǒng)稱。你可以把它理解成給上下文管理裝了一個(gè)“檔位切換器”不同場(chǎng)景下上下文該保留多少、怎么壓縮、怎么檢索、怎么注入都由當(dāng)前所處的 mode 決定。舉個(gè)生活化的類比。你家里有個(gè)儲(chǔ)物間平時(shí)找東西靠記憶翻箱倒柜這叫“無(wú)模式”。后來(lái)你買了標(biāo)簽機(jī)把東西按季節(jié)、使用頻率分箱這叫“按模式管理”。再后來(lái)你發(fā)現(xiàn)冬天找羽絨服和夏天找風(fēng)扇的路徑完全不同于是你給儲(chǔ)物間定了兩套動(dòng)線這就是“多模式切換”。context-mode 干的就是這件事——它讓上下文不再是鐵板一塊而是可以根據(jù)任務(wù)類型動(dòng)態(tài)調(diào)整形態(tài)。這個(gè)內(nèi)容能做什么簡(jiǎn)單說(shuō)它能幫你解決三類典型問(wèn)題第一上下文窗口不夠用歷史消息一多就爆第二上下文里噪音太多關(guān)鍵信息被淹沒(méi)第三不同任務(wù)對(duì)上下文的需求差異大用同一套策略效果忽好忽壞。適合誰(shuí)來(lái)參考做對(duì)話系統(tǒng)、智能助手、檢索增強(qiáng)生成、多輪任務(wù)編排的開(kāi)發(fā)者以及任何需要處理“長(zhǎng)上下文”場(chǎng)景的從業(yè)者。哪怕你只是用現(xiàn)成的大模型接口做個(gè)小工具理解 context-mode 的思路也能讓你少走很多彎路。我寫這篇東西的出發(fā)點(diǎn)很簡(jiǎn)單網(wǎng)上關(guān)于 context-mode 的討論要么太學(xué)術(shù)要么太零散很少有人把它拆成能直接抄作業(yè)的實(shí)操方案。下面我就按自己實(shí)際做過(guò)的項(xiàng)目經(jīng)驗(yàn)把這個(gè)概念掰開(kāi)揉碎講清楚。2. 內(nèi)容整體設(shè)計(jì)與思路拆解為什么不能一套策略走天下2.1 上下文管理的三個(gè)核心矛盾在動(dòng)手設(shè)計(jì)任何 context-mode 之前得先認(rèn)清上下文管理里繞不開(kāi)的三個(gè)矛盾。第一個(gè)是容量與成本的矛盾上下文越長(zhǎng)模型能參考的信息越多但 token 消耗和延遲也線性上漲。我實(shí)測(cè)過(guò)一個(gè)對(duì)話場(chǎng)景把歷史消息從 10 輪擴(kuò)到 50 輪首 token 延遲從 400ms 漲到了 1.8s成本翻了四倍多但回答質(zhì)量只提升了不到 15%。第二個(gè)是相關(guān)性與噪音的矛盾歷史消息里大部分內(nèi)容和當(dāng)前問(wèn)題無(wú)關(guān)全塞進(jìn)去反而干擾模型判斷。第三個(gè)是一致性與靈活性的矛盾如果每次都用不同策略拼上下文模型行為會(huì)變得不可預(yù)測(cè)但固定策略又無(wú)法適配多樣任務(wù)。context-mode 的設(shè)計(jì)初衷就是在這三個(gè)矛盾之間找平衡點(diǎn)。它不是要消滅矛盾而是通過(guò)“分模式”的方式讓每個(gè)模式只解決一類矛盾的主要方面。比如“精確問(wèn)答模式”優(yōu)先保相關(guān)性寧可少給上下文也不塞噪音“長(zhǎng)文摘要模式”優(yōu)先保容量用壓縮換空間“多輪任務(wù)模式”優(yōu)先保一致性固定上下文的組織順序。2.2 模式劃分的常見(jiàn)維度那模式到底該怎么分我見(jiàn)過(guò)不少團(tuán)隊(duì)一上來(lái)就拍腦袋定三五個(gè)模式結(jié)果用起來(lái)發(fā)現(xiàn)邊界模糊、切換混亂。根據(jù)我的經(jīng)驗(yàn)?zāi)J絼澐謶?yīng)該沿著任務(wù)類型和上下文壓力兩個(gè)維度來(lái)切。任務(wù)類型決定“要什么信息”上下文壓力決定“能給多少信息”。按任務(wù)類型常見(jiàn)的有事實(shí)檢索型用戶問(wèn)一個(gè)具體問(wèn)題需要精準(zhǔn)命中、多輪澄清型用戶意圖逐步明確需要保留對(duì)話脈絡(luò)、創(chuàng)作生成型需要大量背景素材但不需要逐輪對(duì)話、任務(wù)執(zhí)行型需要保留工具調(diào)用記錄和中間狀態(tài)。按上下文壓力可以分為寬松窗口充裕、緊張窗口吃緊、極限必須壓縮。兩個(gè)維度交叉就能得到一張模式矩陣。我自己的項(xiàng)目里最終收斂出四個(gè)模式精準(zhǔn)模式、脈絡(luò)模式、素材模式、狀態(tài)模式。精準(zhǔn)模式用于單輪事實(shí)問(wèn)答只注入最相關(guān)的片段脈絡(luò)模式用于多輪對(duì)話保留最近 N 輪加關(guān)鍵歷史摘要素材模式用于長(zhǎng)文生成注入檢索到的文檔塊但不保留對(duì)話歷史狀態(tài)模式用于工具調(diào)用鏈保留完整的調(diào)用記錄和返回值。這四個(gè)模式覆蓋了我 90% 以上的場(chǎng)景剩下的邊緣情況用自定義模式兜底。2.3 為什么選擇“模式切換”而不是“統(tǒng)一壓縮”有人會(huì)問(wèn)為什么不干脆做一個(gè)通用的上下文壓縮算法把所有歷史都?jí)撼烧痪鸵粍谟酪萘宋以囘^(guò)這條路結(jié)論是行不通。統(tǒng)一壓縮最大的問(wèn)題是信息損失不可控。摘要算法不知道當(dāng)前問(wèn)題需要哪個(gè)細(xì)節(jié)它只能按通用重要性排序結(jié)果經(jīng)常把關(guān)鍵的數(shù)字、名稱、條件給壓沒(méi)了。我踩過(guò)一次坑用戶前面說(shuō)了“預(yù)算不超過(guò) 5000”壓縮后被概括成“有預(yù)算限制”后面模型就按 5000 以上去推薦了直接翻車。模式切換的好處在于它把“保留什么”的決策權(quán)交給了任務(wù)類型。精準(zhǔn)模式下我根本不壓縮直接做相關(guān)性檢索只取最相關(guān)的原文片段脈絡(luò)模式下我保留最近幾輪原文只對(duì)更早的歷史做摘要。這樣每個(gè)模式的信息損失都是可控的、可預(yù)期的。代價(jià)是需要維護(hù)多套邏輯但相比統(tǒng)一壓縮帶來(lái)的不可控風(fēng)險(xiǎn)這個(gè)代價(jià)完全值得。2.4 模式切換的觸發(fā)機(jī)制設(shè)計(jì)模式不能靠人手動(dòng)切那樣太累也容易忘。觸發(fā)機(jī)制我建議用規(guī)則優(yōu)先、模型兜底的混合策略。規(guī)則層面根據(jù)請(qǐng)求里帶的意圖標(biāo)簽、對(duì)話輪次、輸入長(zhǎng)度、是否包含工具調(diào)用等信號(hào)直接映射到某個(gè)模式。比如輸入長(zhǎng)度超過(guò)閾值且沒(méi)有對(duì)話歷史就走素材模式檢測(cè)到工具調(diào)用記錄就走狀態(tài)模式。規(guī)則覆蓋不到的情況再用一個(gè)小分類模型或提示詞讓大模型自己判斷該用哪個(gè)模式。這里有個(gè)細(xì)節(jié)要注意模式切換要有滯后性。如果每輪都重新判斷會(huì)出現(xiàn)模式頻繁跳變模型行為跟著抖。我的做法是給模式加一個(gè)“粘性”一旦進(jìn)入某個(gè)模式至少保持 2 到 3 輪除非出現(xiàn)強(qiáng)信號(hào)比如突然出現(xiàn)工具調(diào)用才立即切換。這個(gè)粘性窗口我實(shí)測(cè)下來(lái) 2 輪比較合適太短會(huì)抖太長(zhǎng)會(huì)遲鈍。3. 核心細(xì)節(jié)解析與實(shí)操要點(diǎn)每個(gè)模式到底怎么落地3.1 精準(zhǔn)模式相關(guān)性檢索的粒度控制精準(zhǔn)模式的核心是“只給最相關(guān)的”。落地時(shí)最關(guān)鍵的不是檢索算法本身而是檢索粒度。我試過(guò)按整輪對(duì)話檢索、按句子檢索、按固定長(zhǎng)度塊檢索最后發(fā)現(xiàn)按“語(yǔ)義段落”檢索效果最穩(wěn)。語(yǔ)義段落是指把歷史消息按話題邊界切開(kāi)每個(gè)段落 100 到 300 字既不會(huì)太碎丟失上下文也不會(huì)太長(zhǎng)引入噪音。具體操作上我會(huì)先把歷史消息做一次分段每段生成一個(gè)向量存起來(lái)。當(dāng)前問(wèn)題來(lái)了之后用問(wèn)題向量去檢索 top-k 個(gè)段落k 一般取 3 到 5。這里有個(gè)坑不要只按相似度排序還要加時(shí)間衰減。越近的段落權(quán)重越高因?yàn)閷?duì)話里最近說(shuō)的內(nèi)容往往更相關(guān)。我的權(quán)重公式是score similarity * 0.7 recency * 0.3recency 按輪次衰減最近一輪為 1每往前一輪乘 0.9。這個(gè)系數(shù)是我調(diào)了十幾次才定下來(lái)的0.7 和 0.3 的配比在多數(shù)場(chǎng)景下比較平衡。注意精準(zhǔn)模式不適合多輪澄清場(chǎng)景。如果用戶的問(wèn)題依賴前幾輪的限定條件只給 top-k 段落會(huì)丟掉限定條件導(dǎo)致答非所問(wèn)。這種場(chǎng)景要切到脈絡(luò)模式。3.2 脈絡(luò)模式最近原文加歷史摘要的組合脈絡(luò)模式要解決的是“既要保留對(duì)話脈絡(luò)又不能無(wú)限增長(zhǎng)”。我的方案是滑動(dòng)窗口加滾動(dòng)摘要。滑動(dòng)窗口保留最近 N 輪原文N 取 3 到 5更早的歷史用滾動(dòng)摘要維護(hù)每新增一輪就把最老的一輪并入摘要。摘要不是簡(jiǎn)單截?cái)喽怯媚P蜕梢欢?100 字以內(nèi)的概括重點(diǎn)保留用戶的目標(biāo)、約束、已確認(rèn)的事實(shí)。滾動(dòng)摘要的更新時(shí)機(jī)很講究。如果每輪都更新成本高且摘要會(huì)漂移如果攢很多輪再更新摘要又會(huì)滯后。我的做法是每 3 輪更新一次把這三輪的內(nèi)容合并進(jìn)摘要。更新時(shí)給模型一個(gè)明確的提示詞要求它“保留用戶目標(biāo)、約束條件、已確認(rèn)事實(shí)丟棄寒暄和重復(fù)內(nèi)容”。實(shí)測(cè)下來(lái)這樣維護(hù)的摘要到 20 輪之后還能保持 80% 以上的關(guān)鍵信息召回率。還有一個(gè)細(xì)節(jié)摘要要帶版本號(hào)。因?yàn)檎獣?huì)不斷更新如果上下文里同時(shí)出現(xiàn)新舊摘要模型會(huì)混亂。我的做法是每次更新摘要就遞增版本號(hào)注入上下文時(shí)只放最新版本并在摘要開(kāi)頭標(biāo)注“以下為第 X 輪前的對(duì)話摘要”。3.3 素材模式文檔塊的注入與去重素材模式用于長(zhǎng)文生成、報(bào)告撰寫這類場(chǎng)景特點(diǎn)是對(duì)話歷史不重要但需要大量外部素材。這個(gè)模式的關(guān)鍵是文檔塊的注入策略。我試過(guò)兩種方式一種是全量注入檢索到的文檔另一種是只注入最相關(guān)的片段。全量注入的問(wèn)題是 token 消耗大且噪音多只注入片段又可能丟失上下文。最后我采用分層注入每個(gè)文檔先注入標(biāo)題和摘要再注入 top-2 個(gè)最相關(guān)段落這樣既保留了文檔結(jié)構(gòu)又控制了長(zhǎng)度。去重是素材模式的另一個(gè)重點(diǎn)。檢索回來(lái)的文檔塊經(jīng)常有大量重復(fù)內(nèi)容尤其是同一主題的多篇文檔。我的去重策略是先按語(yǔ)義相似度聚類每個(gè)簇只保留最相關(guān)的一個(gè)塊。相似度閾值我設(shè)的是 0.85高于這個(gè)值就認(rèn)為是重復(fù)。這個(gè)閾值不能太低否則會(huì)把相關(guān)但不重復(fù)的內(nèi)容誤刪也不能太高否則去重不徹底。0.85 是我在幾個(gè)數(shù)據(jù)集上試出來(lái)的經(jīng)驗(yàn)值。提示素材模式下不要注入對(duì)話歷史。我見(jiàn)過(guò)有人為了“保持連貫”把對(duì)話歷史也塞進(jìn)素材模式結(jié)果模型把素材和對(duì)話混在一起生成的內(nèi)容里出現(xiàn)了“你剛才說(shuō)的”這種奇怪的表述。3.4 狀態(tài)模式工具調(diào)用鏈的完整保留狀態(tài)模式用于智能體執(zhí)行任務(wù)的場(chǎng)景核心是完整保留工具調(diào)用記錄和中間狀態(tài)。這個(gè)模式反而不能壓縮因?yàn)楣ぞ哒{(diào)用的參數(shù)、返回值、執(zhí)行順序都是后續(xù)決策的依據(jù)壓掉任何一個(gè)都可能導(dǎo)致任務(wù)失敗。我的做法是原樣保留所有工具調(diào)用記錄但做兩件事一是給每條記錄打上時(shí)間戳和序號(hào)方便模型理解執(zhí)行順序二是對(duì)返回值做結(jié)構(gòu)化提取把冗長(zhǎng)的原始返回提煉成關(guān)鍵字段減少 token 消耗。結(jié)構(gòu)化提取要小心不能把模型需要的信息提沒(méi)了。我的經(jīng)驗(yàn)是保留原始返回的同時(shí)附加一個(gè)提煉版讓模型自己選擇看哪個(gè)。雖然這樣 token 會(huì)多一些但狀態(tài)模式下準(zhǔn)確性優(yōu)先于成本。實(shí)測(cè)下來(lái)附加提煉版能讓模型正確理解返回值的概率提升 20% 以上這個(gè)投入是值得的。3.5 模式間的共享組件設(shè)計(jì)四個(gè)模式雖然策略不同但有很多共享組件可以復(fù)用這樣能減少維護(hù)成本。我抽出來(lái)的共享組件包括分段器把消息切成語(yǔ)義段落、向量化器生成段落向量、摘要器生成滾動(dòng)摘要、去重器語(yǔ)義去重。這些組件在每個(gè)模式里的調(diào)用方式不同但底層實(shí)現(xiàn)是同一套。共享組件的好處是行為一致。比如分段器在精準(zhǔn)模式和脈絡(luò)模式里都用同一套邏輯這樣段落邊界不會(huì)因?yàn)槟J讲煌?。我踩過(guò)一次坑早期精準(zhǔn)模式和脈絡(luò)模式各寫了一套分段邏輯結(jié)果同一段對(duì)話在兩個(gè)模式里被切成了不同的段落導(dǎo)致摘要和檢索結(jié)果對(duì)不上。后來(lái)統(tǒng)一成一套分段器問(wèn)題就消失了。4. 實(shí)操過(guò)程與核心環(huán)節(jié)實(shí)現(xiàn)從零搭一個(gè) context-mode 管理器4.1 整體架構(gòu)與數(shù)據(jù)流先講整體架構(gòu)。我的 context-mode 管理器分四層接入層、模式?jīng)Q策層、上下文組裝層、輸出層。接入層負(fù)責(zé)接收請(qǐng)求提取意圖標(biāo)簽、對(duì)話輪次、輸入長(zhǎng)度等信號(hào)模式?jīng)Q策層根據(jù)信號(hào)決定用哪個(gè)模式上下文組裝層按模式策略拼裝上下文輸出層把組裝好的上下文送給模型并記錄本次使用的模式和 token 消耗。數(shù)據(jù)流是這樣的請(qǐng)求進(jìn)來(lái)后接入層先做一次輕量預(yù)處理把消息存進(jìn)歷史庫(kù)并生成向量。然后模式?jīng)Q策層讀取信號(hào)輸出模式標(biāo)識(shí)。上下文組裝層根據(jù)模式標(biāo)識(shí)調(diào)用對(duì)應(yīng)的組裝函數(shù)組裝函數(shù)從歷史庫(kù)、摘要庫(kù)、文檔庫(kù)里取數(shù)據(jù)拼成最終上下文。最后輸出層調(diào)用模型接口并把本次的模式、token 數(shù)、延遲寫進(jìn)日志。這個(gè)架構(gòu)的好處是模式?jīng)Q策和上下文組裝解耦。決策層只管選模式組裝層只管按模式拼上下文兩邊可以獨(dú)立迭代。我后來(lái)加新模式時(shí)只需要在組裝層加一個(gè)函數(shù)決策層加一條規(guī)則不用動(dòng)其他代碼。4.2 模式?jīng)Q策層的規(guī)則實(shí)現(xiàn)模式?jīng)Q策層的規(guī)則我用一個(gè)優(yōu)先級(jí)列表來(lái)實(shí)現(xiàn)從上到下匹配命中就返回。規(guī)則大致如下如果請(qǐng)求包含工具調(diào)用記錄返回狀態(tài)模式。如果輸入長(zhǎng)度超過(guò) 2000 字且對(duì)話輪次小于 2返回素材模式。如果對(duì)話輪次大于 3 且當(dāng)前問(wèn)題包含指代詞如“它”“這個(gè)”“剛才說(shuō)的”返回脈絡(luò)模式。如果以上都不滿足返回精準(zhǔn)模式。這個(gè)優(yōu)先級(jí)順序是有講究的。狀態(tài)模式放最前面因?yàn)楣ぞ哒{(diào)用場(chǎng)景對(duì)上下文完整性要求最高不能被其他規(guī)則搶走。素材模式放第二因?yàn)殚L(zhǎng)輸入加少輪次是典型的生成場(chǎng)景。脈絡(luò)模式放第三因?yàn)橹复~是判斷“需要對(duì)話脈絡(luò)”的強(qiáng)信號(hào)。精準(zhǔn)模式兜底覆蓋大多數(shù)單輪問(wèn)答。規(guī)則命中率我統(tǒng)計(jì)過(guò)大概能覆蓋 85% 的請(qǐng)求剩下 15% 走模型兜底。模型兜底用一個(gè)簡(jiǎn)單的提示詞讓模型在四個(gè)模式里選一個(gè)并給出理由。兜底的準(zhǔn)確率大概 70%雖然不高但因?yàn)檎急刃?duì)整體影響有限。4.3 上下文組裝層的核心代碼組裝層的核心是一個(gè)分發(fā)函數(shù)根據(jù)模式標(biāo)識(shí)調(diào)用對(duì)應(yīng)的組裝函數(shù)。我用 Python 寫結(jié)構(gòu)大概是這樣def assemble_context(mode, request, history, summary, docs): if mode precise: return assemble_precise(request, history) elif mode thread: return assemble_thread(request, history, summary) elif mode material: return assemble_material(request, docs) elif mode state: return assemble_state(request, history) else: return assemble_precise(request, history)每個(gè)組裝函數(shù)返回一個(gè)消息列表格式是標(biāo)準(zhǔn)的 role-content 結(jié)構(gòu)。以精準(zhǔn)模式為例def assemble_precise(request, history): query_vec embed(request.text) segments segment_history(history) scored [] for seg in segments: sim cosine(query_vec, seg.vec) recency 0.9 ** (len(history) - seg.turn) scored.append((sim * 0.7 recency * 0.3, seg)) scored.sort(reverseTrue, keylambda x: x[0]) top [seg for _, seg in scored[:5]] context \n.join(seg.text for seg in top) return [ {role: system, content: 以下是與問(wèn)題相關(guān)的歷史片段\n context}, {role: user, content: request.text} ]這段代碼里segment_history是共享的分段器embed是共享的向量化器。注意 top-k 取 5這是我實(shí)測(cè)下來(lái)在準(zhǔn)確率和 token 消耗之間比較平衡的值。取 3 有時(shí)會(huì)漏掉關(guān)鍵片段取 8 又會(huì)引入太多噪音。4.4 滾動(dòng)摘要的更新邏輯滾動(dòng)摘要的更新我用一個(gè)獨(dú)立函數(shù)實(shí)現(xiàn)每 3 輪觸發(fā)一次def update_summary(history, old_summary, model): recent history[-3:] prompt f請(qǐng)把以下對(duì)話內(nèi)容合并進(jìn)已有摘要。 要求保留用戶目標(biāo)、約束條件、已確認(rèn)事實(shí)丟棄寒暄和重復(fù)內(nèi)容總長(zhǎng)度不超過(guò) 150 字。 已有摘要{old_summary} 新增對(duì)話{format_turns(recent)} 輸出合并后的摘要 new_summary model.generate(prompt) return new_summary這里有個(gè)細(xì)節(jié)摘要長(zhǎng)度要設(shè)上限。如果不設(shè)上限摘要會(huì)越滾越長(zhǎng)最后失去壓縮的意義。我設(shè)的是 150 字實(shí)測(cè)下來(lái)這個(gè)長(zhǎng)度能保留大部分關(guān)鍵信息同時(shí) token 消耗可控。如果摘要超長(zhǎng)我會(huì)讓模型再壓一次或者手動(dòng)截?cái)嗖?biāo)注“摘要已截?cái)唷薄?.5 參數(shù)選擇與調(diào)優(yōu)記錄整個(gè)系統(tǒng)里有幾個(gè)關(guān)鍵參數(shù)我記錄一下調(diào)優(yōu)過(guò)程。top-k從 3 試到 8最后定 5依據(jù)是準(zhǔn)確率在 5 之后趨于平緩而 token 線性上漲。時(shí)間衰減系數(shù)從 0.8 試到 0.95最后定 0.9依據(jù)是 0.9 時(shí)最近 5 輪的權(quán)重分布比較合理。摘要更新間隔從每輪試到每 5 輪最后定 3 輪依據(jù)是 3 輪時(shí)摘要滯后和更新成本的平衡最好。去重閾值從 0.75 試到 0.95最后定 0.85依據(jù)是 0.85 時(shí)去重率和誤刪率的綜合表現(xiàn)最優(yōu)。這些參數(shù)沒(méi)有絕對(duì)的最優(yōu)值跟具體場(chǎng)景和數(shù)據(jù)分布有關(guān)。我的建議是先用我的值作為起點(diǎn)然后在自己數(shù)據(jù)上做小規(guī)模網(wǎng)格搜索。每個(gè)參數(shù)試 3 到 5 個(gè)值觀察準(zhǔn)確率和 token 消耗的變化通常一兩輪就能找到合適的值。5. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄踩過(guò)的坑和填坑方法5.1 模式誤判導(dǎo)致的答非所問(wèn)最常見(jiàn)的問(wèn)題是模式誤判。我遇到過(guò)用戶問(wèn)“剛才說(shuō)的那個(gè)方案再展開(kāi)講講”系統(tǒng)卻走了精準(zhǔn)模式只檢索了“方案”相關(guān)的片段丟掉了“剛才說(shuō)的”這個(gè)指代結(jié)果展開(kāi)的是另一個(gè)方案。排查這類問(wèn)題的思路是看模式?jīng)Q策日志確認(rèn)當(dāng)時(shí)命中了哪條規(guī)則。如果是規(guī)則覆蓋不到就補(bǔ)規(guī)則如果是規(guī)則命中錯(cuò)了就調(diào)整規(guī)則優(yōu)先級(jí)。我的經(jīng)驗(yàn)是指代詞是模式誤判的高發(fā)區(qū)。凡是問(wèn)題里出現(xiàn)“它”“這個(gè)”“那個(gè)”“剛才”“前面”這類詞大概率需要脈絡(luò)模式。我后來(lái)專門加了一條規(guī)則只要問(wèn)題里包含指代詞且對(duì)話輪次大于 2強(qiáng)制走脈絡(luò)模式。這條規(guī)則加上之后指代類誤判基本消失了。5.2 摘要漂移導(dǎo)致關(guān)鍵信息丟失滾動(dòng)摘要用久了會(huì)出現(xiàn)漂移就是摘要內(nèi)容逐漸偏離原始對(duì)話關(guān)鍵信息被慢慢磨掉。我遇到過(guò)一次用戶前面說(shuō)了“預(yù)算 5000 以內(nèi)”經(jīng)過(guò)幾輪摘要更新后摘要里變成了“有預(yù)算考慮”具體數(shù)字丟了。排查方法是定期對(duì)比摘要和原始對(duì)話看關(guān)鍵實(shí)體數(shù)字、名稱、條件是否還在。防漂移的辦法有兩個(gè)一是摘要更新時(shí)強(qiáng)制保留實(shí)體在提示詞里明確要求“數(shù)字、名稱、條件必須原樣保留”二是給摘要加一個(gè)實(shí)體校驗(yàn)步驟更新后用規(guī)則檢查原始對(duì)話里的關(guān)鍵實(shí)體是否都出現(xiàn)在摘要里缺了就補(bǔ)進(jìn)去。這兩個(gè)辦法結(jié)合用摘要漂移問(wèn)題基本可控。5.3 上下文組裝超長(zhǎng)的應(yīng)急處理有時(shí)候不管怎么壓縮組裝出來(lái)的上下文還是超長(zhǎng)。這種情況我有一套應(yīng)急處理流程先砍素材模式的文檔塊從 top-2 段落降到 top-1再砍脈絡(luò)模式的滑動(dòng)窗口從 5 輪降到 3 輪最后砍精準(zhǔn)模式的 top-k從 5 降到 3。如果還超就觸發(fā)強(qiáng)制摘要把當(dāng)前上下文整體壓一遍。這套流程我寫成了一個(gè)降級(jí)函數(shù)超長(zhǎng)時(shí)自動(dòng)逐級(jí)降級(jí)保證請(qǐng)求不會(huì)因?yàn)槌L(zhǎng)而失敗。注意降級(jí)要有下限。我設(shè)的下限是精準(zhǔn)模式 top-k 不低于 2脈絡(luò)模式窗口不低于 2 輪。低于這個(gè)下限上下文就失去意義了不如直接返回錯(cuò)誤讓上層處理。5.4 常見(jiàn)問(wèn)題速查表問(wèn)題現(xiàn)象可能原因排查方法解決方法答非所問(wèn)忽略指代模式誤判為精準(zhǔn)模式查模式?jīng)Q策日志加指代詞規(guī)則強(qiáng)制脈絡(luò)模式關(guān)鍵數(shù)字丟失摘要漂移對(duì)比摘要與原始對(duì)話提示詞強(qiáng)制保留實(shí)體加實(shí)體校驗(yàn)上下文超長(zhǎng)報(bào)錯(cuò)組裝未降級(jí)查組裝后 token 數(shù)啟用降級(jí)函數(shù)逐級(jí)壓縮模式頻繁跳變決策無(wú)粘性查連續(xù)幾輪的模式標(biāo)識(shí)加粘性窗口至少保持 2 輪檢索結(jié)果重復(fù)去重閾值過(guò)低查去重前后塊數(shù)提高去重閾值到 0.85工具調(diào)用記錄缺失狀態(tài)模式未命中查請(qǐng)求是否含工具記錄狀態(tài)模式規(guī)則提到最高優(yōu)先級(jí)5.5 獨(dú)家避坑技巧分享幾個(gè)文檔里不會(huì)寫的技巧。第一模式標(biāo)識(shí)要透?jìng)?。每次?qǐng)求用的什么模式要一路透?jìng)鞯饺罩竞捅O(jiān)控里不然出了問(wèn)題根本沒(méi)法排查。我早期沒(méi)透?jìng)髋挪橐粋€(gè)答非所問(wèn)的問(wèn)題花了一下午后來(lái)加上透?jìng)魍瑯拥膯?wèn)題五分鐘定位。第二摘要要存版本歷史。不要只存最新摘要把每次更新的摘要都存下來(lái)出問(wèn)題時(shí)可以回溯是哪次更新引入的漂移。第三降級(jí)要記日志。每次觸發(fā)降級(jí)都要記下來(lái)如果某個(gè)模式頻繁降級(jí)說(shuō)明它的默認(rèn)參數(shù)設(shè)得太激進(jìn)需要調(diào)低。還有一個(gè)技巧是給模式加一個(gè)“置信度”。規(guī)則命中的模式置信度高模型兜底命中的置信度低。置信度低的請(qǐng)求可以走更保守的策略比如精準(zhǔn)模式多取幾個(gè)片段脈絡(luò)模式多保留幾輪。這樣能在不確定的情況下減少誤判的影響。6. 模式擴(kuò)展與長(zhǎng)期維護(hù)的一些想法context-mode 這套東西搭起來(lái)之后維護(hù)比搭建更重要。我的經(jīng)驗(yàn)是每?jī)芍軓?fù)盤一次模式?jīng)Q策日志看有沒(méi)有新的誤判模式有沒(méi)有規(guī)則覆蓋不到的場(chǎng)景。復(fù)盤時(shí)重點(diǎn)看兩類請(qǐng)求一類是用戶明顯不滿意的一類是 token 消耗異常高的。前者往往暴露模式誤判后者往往暴露壓縮不夠。模式擴(kuò)展要克制。我見(jiàn)過(guò)有人一上來(lái)就設(shè)計(jì)十幾個(gè)模式結(jié)果每個(gè)模式都維護(hù)不好。我的建議是從四個(gè)核心模式起步遇到確實(shí)無(wú)法歸類的場(chǎng)景再加。加新模式的門檻是這個(gè)場(chǎng)景在現(xiàn)有模式下確實(shí)處理不好且出現(xiàn)頻率超過(guò) 5%。低于這個(gè)頻率的場(chǎng)景用現(xiàn)有模式加特殊處理就夠了不值得單獨(dú)開(kāi)一個(gè)模式。最后說(shuō)一個(gè)長(zhǎng)期維護(hù)的點(diǎn)共享組件要版本化。分段器、向量化器、摘要器這些共享組件一旦改動(dòng)會(huì)影響所有模式。所以每次改動(dòng)都要記版本并且做回歸測(cè)試確認(rèn)所有模式的行為沒(méi)有意外變化。我吃過(guò)一次虧改分段器的時(shí)候沒(méi)做回歸結(jié)果精準(zhǔn)模式的檢索準(zhǔn)確率掉了 10 個(gè)百分點(diǎn)一周后才發(fā)現(xiàn)。這套 context-mode 的思路我在幾個(gè)項(xiàng)目里都用過(guò)從對(duì)話助手到文檔生成到任務(wù)編排核心邏輯是通的。區(qū)別只在于模式的具體劃分和參數(shù)調(diào)優(yōu)。如果你剛開(kāi)始做上下文管理建議先把精準(zhǔn)模式和脈絡(luò)模式跑通這兩個(gè)覆蓋的場(chǎng)景最多也最能體現(xiàn)模式切換的價(jià)值。素材模式和狀態(tài)模式可以等有明確需求了再加。