對(duì)話上下文管理與記憶調(diào)度方案)
1. 為什么我在本地寫了個(gè)“context-mode”來(lái)解決上下文管理問(wèn)題作為一個(gè)常年跟 AI 輔助開發(fā)工具打交道的人我最崩潰的場(chǎng)景不是模型答錯(cuò)而是同一個(gè)會(huì)話里模型明明幾輪前還記得的關(guān)鍵設(shè)定說(shuō)忘就忘。你反復(fù)強(qiáng)調(diào)別動(dòng) service 層之后它下一輪照樣給你生成一個(gè)改了 service 層接口的代碼。你放進(jìn)去的依賴版本、接口協(xié)議、目錄結(jié)構(gòu)它在十輪對(duì)話之后就像從來(lái)沒(méi)看過(guò)一樣。這類問(wèn)題的根源其實(shí)不在模型能力上而在上下文管理策略上。絕大多數(shù)人是把所有內(nèi)容一股腦塞進(jìn)對(duì)話里覺得塞得越多模型就越懂。實(shí)際情況恰恰相反上下文窗口是有限的塞進(jìn)去的內(nèi)容會(huì)互相稀釋。放了兩萬(wàn)字的接口文檔模型記住的可能是文檔里無(wú)關(guān)緊要的日志格式而不是你最在意的幾條約束。真正該被模型記住的核心指令和那些只用一兩次就能丟棄的臨時(shí)信息被丟進(jìn)了同一個(gè)池子里。我用過(guò)很多現(xiàn)成方案比如給會(huì)話寫固定 preamble、做角色設(shè)定、整理項(xiàng)目規(guī)范文檔但都不夠系統(tǒng)。后來(lái)我干脆自己寫了一個(gè)叫 context-mode 的小工具核心思路是把上下文分成長(zhǎng)期記憶區(qū)和短期工作區(qū)并根據(jù)當(dāng)前任務(wù)類型動(dòng)態(tài)調(diào)整兩側(cè)的比例和權(quán)重。用大白話說(shuō)就是給對(duì)話上一套記憶管理策略——該記住的死死摁住不該記住的用完就扔。這個(gè)工具不是傳統(tǒng)意義上的插件不需要改模型推理代碼也不依賴某個(gè)特定 AI 產(chǎn)品。它是一層運(yùn)行在你和模型之間的上下文調(diào)度層在把請(qǐng)求發(fā)給模型之前由它來(lái)決定哪些信息必須帶上哪些可以打折哪些干脆丟棄。用完這套東西之后我在代碼生成、文檔總結(jié)、架構(gòu)設(shè)計(jì)這幾類任務(wù)上的返工率明顯下降尤其是那種上一輪說(shuō)的約定下一輪就忘的問(wèn)題基本被根治了。這個(gè)項(xiàng)目適合誰(shuí)如果你經(jīng)常用 AI 做長(zhǎng)對(duì)話、需要跨多輪保持一致的開發(fā)規(guī)范或者你處理的任務(wù)類型跨度很大一會(huì)兒寫代碼、一會(huì)兒寫方案、一會(huì)兒查文檔那么 context-mode 的思路和實(shí)現(xiàn)方式你肯定用得上。即使你不打算復(fù)刻我的代碼光把上下文分區(qū)這個(gè)思考模型拿走就能顯著改善你跟模型對(duì)話的效率。2. context-mode 的整體設(shè)計(jì)思路為什么分區(qū)模式比塞滿窗口更好用2.1 一個(gè)生活化的類比你的大腦不可能同時(shí)記住所有事先打個(gè)比方。你上班的時(shí)候不會(huì)把過(guò)去十年的工作經(jīng)歷全部放在腦子里最前的位置你只會(huì)臨時(shí)把今天要用的資料攤在桌面上而把那些重要但當(dāng)前用不到的東西收進(jìn)抽屜里。桌面上這張紙就是短期工作區(qū)抽屜里那些文件就是長(zhǎng)期記憶區(qū)。如果今天只是寫一封郵件桌面只需要一張紙就夠了抽屜里那些資料壓根不用打開。如果你今天要寫一份年度規(guī)劃那就得從抽屜里翻出好幾份過(guò)往數(shù)據(jù)桌面攤開的內(nèi)容就多。AI 對(duì)話也是同一個(gè)道理。模型的工作記憶是有限的每輪生成回復(fù)都要基于當(dāng)前可見的全部?jī)?nèi)容。如果一上來(lái)就把公司背景、代碼倉(cāng)庫(kù)結(jié)構(gòu)、歷史決策記錄、本次需求、臨時(shí)備注全部塞進(jìn)去那模型每次都要消化大量低權(quán)重信息反應(yīng)變慢不說(shuō)關(guān)鍵約束還容易被淹沒(méi)。context-mode 最核心的設(shè)計(jì)就是把可見上下文顯式分成兩個(gè)區(qū)域A 區(qū)長(zhǎng)期指令區(qū)存放那些每輪對(duì)話都必須遵守的穩(wěn)定規(guī)則比如編碼規(guī)范、禁止觸碰的模塊、輸出格式要求、項(xiàng)目關(guān)鍵路徑。B 區(qū)臨時(shí)工作區(qū)存放當(dāng)前任務(wù)相關(guān)的材料比如這次要修的問(wèn)題描述、上游接口文檔、報(bào)錯(cuò)日志、相關(guān)代碼片段。每次發(fā)起請(qǐng)求前工具會(huì)重新計(jì)算兩個(gè)區(qū)域的內(nèi)容。A 區(qū)幾乎恒定不變B 區(qū)則跟隨任務(wù)推進(jìn)持續(xù)滾動(dòng)更新過(guò)期的信息自動(dòng)出隊(duì)新的信息按優(yōu)先級(jí)入隊(duì)。這樣模型永遠(yuǎn)在一個(gè)干凈、聚焦的上下文里做推理而不是在雜物堆里猜重點(diǎn)。2.2 三種內(nèi)建模式分別解決什么場(chǎng)景光有分區(qū)還不夠因?yàn)椴煌蝿?wù)對(duì)上下文的消耗方式完全不同。context-mode 內(nèi)置了三套模式分別對(duì)應(yīng)我在實(shí)際開發(fā)中最常遇到的三種任務(wù)類型。第一套是速戰(zhàn)速?zèng)Q模式short-context mode。典型的場(chǎng)景是只問(wèn)一個(gè)小問(wèn)題比如這個(gè)函數(shù)的正則表達(dá)式哪里寫錯(cuò)了或者這個(gè)報(bào)錯(cuò)是什么意思。這種任務(wù)根本不需要把項(xiàng)目背景全塞進(jìn)去只需要把報(bào)錯(cuò)信息和相關(guān)十幾行代碼放進(jìn)去就夠了。這個(gè)模式下B 區(qū)會(huì)限制得非常小A 區(qū)也只保留最基礎(chǔ)的角色設(shè)定保證模型拿到的是最小可用上下文響應(yīng)速度最快、最不容易被無(wú)關(guān)信息干擾。第二套是深度任務(wù)模式deep-work mode。適用于需要多輪迭代的復(fù)雜任務(wù)比如實(shí)現(xiàn)一個(gè)用戶認(rèn)證模塊或者重構(gòu)整個(gè)數(shù)據(jù)層。這種任務(wù)要求模型跨多輪保持高度一致A 區(qū)必須包含完整的項(xiàng)目結(jié)構(gòu)、技術(shù)選型、約束條件B 區(qū)則要支撐不斷增大的中期產(chǎn)出比如已經(jīng)生成的接口定義、數(shù)據(jù)結(jié)構(gòu)、依賴版本。這個(gè)模式下上下文窗口的利用率最高但代價(jià)是單輪請(qǐng)求的 token 消耗會(huì)大不少。第三套是緊急搶救模式debug mode。專門為線上出了個(gè) bug 你只想趕緊定位這種高壓場(chǎng)景設(shè)計(jì)的。它會(huì)自動(dòng)壓低 A 區(qū)的占比把盡可能多的空間讓給 B 區(qū)的報(bào)錯(cuò)棧信息、日志片段、線上配置。因?yàn)樵谂芫然鹑蝿?wù)時(shí)你的核心訴求是讓模型集中精力看現(xiàn)場(chǎng)而不是反復(fù)強(qiáng)調(diào)代碼規(guī)范。換句話說(shuō)這種模式允許你暫時(shí)犧牲規(guī)則約束換取上下文聚焦上的極限收益。三種模式的本質(zhì)是把上下文分配做成一個(gè)可調(diào)策略而不是一刀切。這也是我認(rèn)為 context-mode 跟簡(jiǎn)單拼 prompt最大的區(qū)別后者是靜態(tài)的前者是有彈性的。2.3 上下文調(diào)度的核心流程從輸入到請(qǐng)求的四步流水線context-mode 在向模型發(fā)起請(qǐng)求之前會(huì)走一套四步流水線。我把它寫在項(xiàng)目 README 的第一行因?yàn)槔斫膺@四步你就理解了整個(gè)工具的核心。第一步叫清洗sanitize。把輸入里的廢話、重復(fù)內(nèi)容、格式雜亂的日志壓縮成結(jié)構(gòu)化信息。比如你把一整段 JSON 日志丟進(jìn)來(lái)工具會(huì)把時(shí)間戳、非關(guān)鍵字段全部剝掉只保留 error message 和堆棧關(guān)鍵行。第二步叫歸類classify把清洗后的內(nèi)容按長(zhǎng)期規(guī)則和臨時(shí)材料分揀進(jìn)對(duì)應(yīng)的區(qū)。第三步叫壓縮compress。這一步對(duì) B 區(qū)特別重要因?yàn)榕R時(shí)工作區(qū)如果無(wú)限膨脹最終還是會(huì)變成新的雜物堆。工具會(huì)按照內(nèi)容的新鮮度和引用頻次做衰減對(duì)超過(guò) N 輪沒(méi)有被再次引用的信息做摘要壓縮。第四步叫組裝assemble按當(dāng)前模式指定的比例把 A 區(qū)和 B 區(qū)的內(nèi)容拼接成最終發(fā)給模型的請(qǐng)求。這套流程單獨(dú)看每一步都不復(fù)雜但合在一起效果比手工整理 prompt強(qiáng)得多。最關(guān)鍵的差異在于它是自動(dòng)化的、持續(xù)運(yùn)行的而不是每次對(duì)話時(shí)靠你手動(dòng)去復(fù)制粘貼。3. 核心功能拆解長(zhǎng)期指令權(quán)重、上下文衰減與模式切換機(jī)制3.1 A 區(qū)長(zhǎng)期指令的權(quán)重管理讓模型至死不忘三條鐵律A 區(qū)想解決的問(wèn)題是模型為什么總是忘記我說(shuō)過(guò)的重要要求。我檢查過(guò)很多次對(duì)話記錄發(fā)現(xiàn)模型忘事分兩種一種是它真的沒(méi)有收到那個(gè)信息信息壓根沒(méi)出現(xiàn)在上下文中另一種是它收到了但上下文里同類信息太多導(dǎo)致它無(wú)法判斷哪條優(yōu)先級(jí)最高。context-mode 處理第二種問(wèn)題的手段是給 A 區(qū)的每條指令顯式設(shè)置權(quán)重。權(quán)重最高的指令不僅放在請(qǐng)求的最前部還會(huì)在前綴加上強(qiáng)調(diào)標(biāo)記。以當(dāng)前主流模型對(duì)指令的敏感程度來(lái)看當(dāng)若干條約束在上下文中彼此競(jìng)爭(zhēng)時(shí)權(quán)重和位置差異就能起到?jīng)Q定性作用。舉個(gè)例子我的一個(gè)實(shí)際項(xiàng)目里有三條鐵律代碼禁止使用 any 類型所有數(shù)據(jù)庫(kù)操作必須走 repository 層生成的注釋必須用中文這三條我會(huì)設(shè)置為最高權(quán)重每次請(qǐng)求都會(huì)原樣出現(xiàn)在 A 區(qū)頂部。而像我記得你上次給過(guò)一個(gè)分頁(yè)函數(shù)這種偶爾用到的信息權(quán)重就低很多放在 A 區(qū)末尾被壓縮的優(yōu)先級(jí)也最高。在實(shí)際使用中我發(fā)現(xiàn)一個(gè)關(guān)鍵細(xì)節(jié)A 區(qū)的內(nèi)容不是越多越好。如果 A 區(qū)里塞了三十條重要規(guī)則那模型會(huì)把這些規(guī)則平均對(duì)待最后沒(méi)有一條真正重要。context-mode 的默認(rèn)策略是 A 區(qū)最多保留約 12 條權(quán)重最高的指令超出的部分強(qiáng)制降級(jí)到 B 區(qū)。這樣做的效果非常明顯——規(guī)則條目越少模型對(duì)每一條的遵從度越高。3.2 上下文衰減機(jī)制超過(guò)三輪沒(méi)被引用對(duì)不起請(qǐng)讓位B 區(qū)最大的隱患是陳舊信息堆積。舉個(gè)例子你第一輪讓模型分析了某個(gè)報(bào)錯(cuò)報(bào)錯(cuò)信息被放進(jìn)了 B 區(qū)。之后五輪你都在討論解決方案那個(gè)報(bào)錯(cuò)原文還躺在 B 區(qū)里占著位置。你要不是刻意清理它可能會(huì)一直占據(jù)幾百個(gè) token 的空間直到窗口耗盡。context-mode 的衰減機(jī)制模仿的是人類記憶規(guī)律一個(gè)信息如果在最近幾輪對(duì)話中完全沒(méi)有被引用它就會(huì)被判定為低熱度自動(dòng)觸發(fā)壓縮流程。默認(rèn)的熱度衰減系數(shù)是每輪 0.7也就是說(shuō)一個(gè)信息如果連續(xù)三輪都沒(méi)被模型中任何一條回復(fù)引用過(guò)它的熱度就會(huì)從 1.0 降到大約 0.34這時(shí)候它占用的 token 會(huì)被壓縮到原來(lái)的四分之一只保留摘要。如果連續(xù)六輪沒(méi)被引用熱度降到 0.1 以下工具會(huì)直接把它從上下文中移除。這里要注意衰減機(jī)制不是無(wú)腦丟信息。如果某個(gè)信息雖然多輪沒(méi)被引用但它在 A 區(qū)被標(biāo)記為會(huì)話級(jí)必需那它就不會(huì)被移除只會(huì)被壓縮。所以 B 區(qū)的自動(dòng)清理本質(zhì)上只針對(duì)那些臨時(shí)用一下、用完即棄的材料。我最初實(shí)現(xiàn)的時(shí)候直接按輪數(shù)做衰減后來(lái)發(fā)現(xiàn)不準(zhǔn)確。因?yàn)橛械妮喆斡脩糁换亓藗€(gè)好字換來(lái)的是模型刷新了一整版代碼這時(shí)候舊信息的引用熱度其實(shí)是被刷新的。后來(lái)我改成了引用感知衰減就是當(dāng)模型回復(fù)中出現(xiàn)與舊信息相關(guān)的片段時(shí)該信息的熱度會(huì)被自動(dòng)重置。這個(gè)改動(dòng)讓衰減機(jī)制的誤殺率大幅下降。3.3 模式切換的觸發(fā)策略手動(dòng)為主自動(dòng)提示為輔最理想的模式切換是AI 自動(dòng)識(shí)別任務(wù)類型并切換但以當(dāng)前的技術(shù)水平純自動(dòng)切換在復(fù)雜對(duì)話里經(jīng)常判斷失誤。所以我采用了比較務(wù)實(shí)的策略手動(dòng)切換為主自動(dòng)提示為輔。用戶輸入的指令里如果包含特定觸發(fā)詞比如重構(gòu)實(shí)現(xiàn)新功能工具就會(huì)提示當(dāng)前任務(wù)疑似深度任務(wù)模式是否切換如果包含修 bug報(bào)錯(cuò)就會(huì)提示當(dāng)前任務(wù)疑似緊急搶救模式是否切換——但最終決定權(quán)在用戶手里絕不自動(dòng)越權(quán)。這個(gè)設(shè)計(jì)是有原因的。我在真實(shí)使用中發(fā)現(xiàn)模式切換一旦自動(dòng)化錯(cuò)誤切換的代價(jià)非常高。試過(guò)在實(shí)現(xiàn)新功能的對(duì)話中誤切成短上下文模式結(jié)果模型把之前定義的數(shù)據(jù)結(jié)構(gòu)全忘了所有代碼推倒重來(lái)。手動(dòng)切換雖然多了一步操作但勝在確定性和可控性。工具類軟件最重要的不是聰明而是可預(yù)期。4. 實(shí)操記錄從零配置一個(gè)可用的 context-mode 環(huán)境4.1 環(huán)境配置與依賴準(zhǔn)備context-mode 的使用前提是你已經(jīng)有一個(gè)可以調(diào)用大模型 API 的開發(fā)環(huán)境。我用的是 Python 3.10 FastAPI 做成本地服務(wù)核心依賴只有三個(gè)openai 客戶端庫(kù)、pydantic 做配置校驗(yàn)、sqlite 做會(huì)話狀態(tài)持久化。你如果不需要做成獨(dú)立服務(wù)也可以直接把 context-mode 的核心函數(shù)嵌入到你自己的腳本里連 FastAPI 都不用裝。安裝依賴的完整命令如下pip install openai pydantic sqlite3注意sqlite3 是 Python 標(biāo)準(zhǔn)庫(kù)不需要單獨(dú)裝。openai 庫(kù)版本建議用 1.x 以上因?yàn)?0.x 的老版本接口差異太大我的代碼是基于新接口寫的。配置文件是我建議所有使用者首先看的入口。context-mode 使用一個(gè) YAML 文件來(lái)管理所有模式參數(shù)核心配置項(xiàng)如下modes: short: a_ratio: 0.2 b_ratio: 0.5 max_tokens: 2000 deep: a_ratio: 0.4 b_ratio: 0.8 max_tokens: 8000 debug: a_ratio: 0.1 b_ratio: 0.9 max_tokens: 4000 decay: factor: 0.7 remove_threshold: 0.1 compress_threshold: 0.34 long_term: max_rules: 12 top_priority_prefix: __RULE__這幾個(gè)參數(shù)背后都是有講究的。a_ratio 和 b_ratio 表示該模式下 A 區(qū)和 B 區(qū)占上下文窗口的最大比例b_ratio 通常比 a_ratio 高因?yàn)榇蠖鄶?shù)任務(wù)中臨時(shí)材料本來(lái)就比長(zhǎng)期規(guī)則多。max_tokens 不是模型的完整上下文窗口尺寸而是你允許 context-mode 實(shí)際占用的上限留出來(lái)的空間給模型生成回復(fù)用。4.2 核心實(shí)現(xiàn)上下文組裝函數(shù)下面這段代碼是 context-mode 最核心的函數(shù)負(fù)責(zé)把兩個(gè)區(qū)域的內(nèi)容按模式比例拼接成一個(gè)最終請(qǐng)求。我只保留了最小實(shí)現(xiàn)去掉了一些細(xì)節(jié)方便你直接理解。def assemble_context(mode: str, long_term: list, short_term: list, config: dict) - str: mode_cfg config[modes][mode] decay_cfg config[decay] # 第一步衰減和壓縮短期工作區(qū) compressed_short [] for item in short_term: if item[recency] decay_cfg[remove_threshold]: continue if item[recency] decay_cfg[compress_threshold]: item[content] summarize(item[content]) compressed_short.append(item) # 第二步按比例分配 token 預(yù)算 a_max_tokens mode_cfg[max_tokens] * mode_cfg[a_ratio] b_max_tokens mode_cfg[max_tokens] * mode_cfg[b_ratio] # 第三步組裝長(zhǎng)期指令區(qū) result_parts [] used_tokens 0 for rule in long_term[:config[long_term][max_rules]]: prefix config[long_term][top_priority_prefix] if rule[priority] high else rule_text f{prefix}{rule[content]} rule_tokens estimate_tokens(rule_text) if used_tokens rule_tokens a_max_tokens: break result_parts.append(rule_text) used_tokens rule_tokens # 第四步組裝臨時(shí)工作區(qū) for item in compressed_short: item_tokens estimate_tokens(item[content]) if used_tokens item_tokens b_max_tokens a_max_tokens: continue result_parts.append(item[content]) used_tokens item_tokens return \n\n---SEPARATOR---\n\n.join(result_parts)這段代碼里幾個(gè)細(xì)節(jié)值得說(shuō)。衰減判斷用的是 recency 字段每輪對(duì)話結(jié)束后全局減一次被引用的條目重置為 1.0。estimate_tokens 是一個(gè)估算函數(shù)中英文混合場(chǎng)景下我采用中文按 1.5 token/字、英文按 0.3 token/字符的經(jīng)驗(yàn)估算雖然不完全準(zhǔn)確但用于預(yù)算控制足夠了。summarize 函數(shù)建議直接調(diào)用模型做一次摘要不要把幾百行日志原樣留著。4.3 首次配置的最佳實(shí)踐哪些內(nèi)容進(jìn) A 區(qū)哪些進(jìn) B 區(qū)配置 context-mode 最讓人犯難的問(wèn)題就是到底什么東西該放進(jìn) A 區(qū)我的建議很簡(jiǎn)單只放那些如果你不讓模型遵守它就會(huì)犯錯(cuò)的內(nèi)容。舉個(gè)例子如果你做的是 Java 項(xiàng)目你希望模型生成的類名是駝峰式這屬于 A 區(qū)如果你希望模型在每次回復(fù)前先列出一個(gè) TODO 清單這也屬于 A 區(qū)但如果你只是想在一輪對(duì)話里讓模型參考一下某個(gè)開源項(xiàng)目的寫法這種材料就該在 B 區(qū)用完就走。還有個(gè)容易被忽略的點(diǎn)A 區(qū)的內(nèi)容必須用命令式語(yǔ)氣寫不要用描述性語(yǔ)氣。禁止在代碼中使用 any 類型是命令式項(xiàng)目中通常不會(huì)使用 any 類型就是描述式。實(shí)測(cè)下來(lái)模型對(duì)命令式指令的遵從度比描述式高很多。這大概是因?yàn)槊钍街噶罡裼脩糁苯咏o出的要求而描述式指令更像項(xiàng)目文檔摘錄容易被模型歸入?yún)⒖夹畔⒍皇切袨榧s束。首次配置時(shí)不要貪多。我建議第一版先只配 3 到 5 條 A 區(qū)規(guī)則跑一周看模型在哪些地方依然反復(fù)出錯(cuò)再逐步補(bǔ)上。一次性配滿 12 條你會(huì)很難定位到底是哪條規(guī)則未被遵守因?yàn)楦蓴_太多了。4.4 調(diào)用接口設(shè)計(jì)一次完整的帶 context-mode 的對(duì)話請(qǐng)求配置好之后實(shí)際調(diào)用流程就是先更新狀態(tài)再組裝上下文最后發(fā)給模型。下面是用 FastAPI 暴露接口的示例from fastapi import FastAPI from pydantic import BaseModel app FastAPI() session_store {} class ChatRequest(BaseModel): session_id: str user_message: str mode: str deep app.post(/chat) def chat(req: ChatRequest): session session_store.get(req.session_id, {long_term: [], short_term: []}) # 更新短期工作區(qū)把新的用戶消息加進(jìn)去 session[short_term].append({ content: req.user_message, recency: 1.0, timestamp: time.time() }) # 衰減舊信息 for item in session[short_term]: item[recency] * config[decay][factor] # 組裝上下文 context assemble_context(req.mode, session[long_term], session[short_term], config) # 調(diào)用大模型 response client.chat.completions.create( modelyour-model-name, messages[ {role: system, content: 你是該項(xiàng)目的高級(jí)開發(fā)助手。}, {role: user, content: context} ] ) # 引用感知如果回復(fù)里包含舊的短期信息片段重置其 recency for item in session[short_term]: if item[content][:50] in response.choices[0].message.content: item[recency] 1.0 session_store[req.session_id] session return {reply: response.choices[0].message.content}這個(gè)接口描述的是核心回調(diào)流程實(shí)際部署時(shí)建議加上歷史消息的持久化存儲(chǔ)和線程鎖避免并發(fā)請(qǐng)求時(shí)狀態(tài)錯(cuò)亂。5. 踩坑記錄context-mode 落地過(guò)程中最常見的五個(gè)問(wèn)題5.1 衰減誤殺頻率低但重要的信息被提前清除這是我遇到的第一個(gè)坑。原本的衰減機(jī)制只看引用頻率但有些信息雖然引用頻率低重要性卻極高。比如某個(gè)數(shù)據(jù)庫(kù)表的結(jié)構(gòu)說(shuō)明只在最開始討論字段時(shí)用過(guò)一次后續(xù)十輪都在寫業(yè)務(wù)邏輯按照原版衰減規(guī)則它大概率會(huì)在第五輪左右被壓縮掉但等到第八輪突然要寫一個(gè)關(guān)聯(lián)查詢時(shí)模型已經(jīng)把表結(jié)構(gòu)忘干凈了生成出來(lái)的 SQL 全是錯(cuò)的。解決辦法我前面提到過(guò)把這類信息手動(dòng)標(biāo)記為會(huì)話級(jí)必需。context-mode 里我給短期工作區(qū)增加了一個(gè) optional 字段optionalfalse 的條目不參與衰減移除只參與壓縮。代價(jià)是這類條目會(huì)一直占著 token所以標(biāo)記必需時(shí)要想清楚——只有那些后面一定會(huì)再用到的材料才值得這樣標(biāo)。5.2 壓縮摘要導(dǎo)致信息丟失模型復(fù)述的能力被削弱壓縮機(jī)制雖然節(jié)省了 token但摘要永遠(yuǎn)有損。我最開始用摘要替換原始內(nèi)容的時(shí)候遇到一個(gè)很尷尬的情況模型知道報(bào)錯(cuò)發(fā)生過(guò)但不記得報(bào)錯(cuò)的具體行號(hào)導(dǎo)致修復(fù)建議一直跑偏。后來(lái)我調(diào)整了策略摘要里強(qiáng)制保留關(guān)鍵結(jié)構(gòu)化字段。對(duì)日志類內(nèi)容摘要必須包含錯(cuò)誤碼、行號(hào)、模塊名對(duì)代碼類內(nèi)容摘要必須包含函數(shù)名、入?yún)㈩愋?、返回值類型。這個(gè)改動(dòng)之后壓縮的可用性明顯提升。說(shuō)到底壓縮的目標(biāo)是去噪不是去信息關(guān)鍵信息字段的完整性必須保證。5.3 模式切換錯(cuò)誤上下文聚焦反而讓模型變蠢有一次我用緊急搶救模式去跑一個(gè)本該用深度模式的任務(wù)結(jié)果非常慘。當(dāng)時(shí)要重構(gòu)一個(gè)核心模塊我圖省事直接用調(diào)試模式進(jìn)入B 區(qū)占比拉滿A 區(qū)長(zhǎng)期規(guī)則被壓縮到只剩 10% 的空間結(jié)果模型連項(xiàng)目最基本的命名約定都忘了生成了大量風(fēng)格不統(tǒng)一的代碼。那次之后我徹底改變了思路模式切換刀一定要握在用戶手里工具的自動(dòng)提示只能當(dāng)參考不能當(dāng)替身。5.4 多會(huì)話狀態(tài)混亂session 隔離不干凈導(dǎo)致上下文串線早期版本我只有一個(gè)全局上下文存儲(chǔ)沒(méi)有按會(huì)話隔離。有一次同時(shí)開兩個(gè)會(huì)話一個(gè)在改前端一個(gè)在寫后端文檔結(jié)果兩側(cè)的內(nèi)容互相混進(jìn)對(duì)方的上下文里。模型在前端會(huì)話里開始輸出后端接口文檔場(chǎng)面一度非常尷尬。后來(lái)我把 session 狀態(tài)徹底隔離每個(gè)會(huì)話獨(dú)立維護(hù)自己的 A 區(qū)和 B 區(qū)串線問(wèn)題才徹底解決。這個(gè)教訓(xùn)也提醒我凡是帶狀態(tài)的系統(tǒng)隔離的設(shè)計(jì)必須放在第一天做不能等出了事故再補(bǔ)。5.5 估算 token 與實(shí)際不一致預(yù)算控制失真estimate_tokens 函數(shù)畢竟只是估算跟真實(shí) API 返回的 token 數(shù)經(jīng)常差 20% 到 30%。如果預(yù)算算得太緊上下文會(huì)遺漏關(guān)鍵材料算得太松又容易觸發(fā)模型的真實(shí)上下文窗口溢出。我的解決方案是在每次請(qǐng)求返回后用 API 返回的 usage 信息反向校準(zhǔn)估算函數(shù)。具體做法是維護(hù)一個(gè)最近 50 次請(qǐng)求的平均偏差系數(shù)估算值乘以偏差系數(shù)后再納入預(yù)算計(jì)算。這樣跑幾輪之后預(yù)算控制會(huì)越來(lái)越貼近真實(shí)。老實(shí)說(shuō)做 context-mode 這個(gè)工具的過(guò)程比工具本身的代碼更有價(jià)值。它逼著我去思考一個(gè)之前一直忽略的問(wèn)題我們跟 AI 協(xié)作時(shí)效率的瓶頸往往不是模型不夠聰明而是我們沒(méi)有給它足夠好的信息結(jié)構(gòu)。A 區(qū)和 B 區(qū)的劃分、衰減機(jī)制、模式切換本質(zhì)上都在做一件事把上下文的布局顯式化讓最重要的信息永遠(yuǎn)出現(xiàn)在最該出現(xiàn)的位置。我現(xiàn)在已經(jīng)把這個(gè)思路用在了日常的所有 AI 對(duì)話里就算脫離工具本身我也會(huì)下意識(shí)地做分區(qū)先把核心約束寫清楚再把材料按重要程度排列最后才發(fā)出去。這個(gè)習(xí)慣的收益比任何工具都大。如果你也在用 AI 輔助工作到長(zhǎng)對(duì)話我建議你先別急著寫代碼而是試著用手動(dòng)的方式做三天的上下文分區(qū)把每輪對(duì)話前要發(fā)的信息分類整理一次你會(huì)有一種豁然開朗的感覺。之后你再?zèng)Q定要不要像這樣寫個(gè)工具來(lái)固化流程都來(lái)得及。