發(fā)如何精準(zhǔn)管理上下文)
做AI輔助開(kāi)發(fā)時(shí)間長(zhǎng)了你會(huì)發(fā)現(xiàn)一個(gè)很有意思的現(xiàn)象同樣一個(gè)模型在不同人手里產(chǎn)出質(zhì)量能差出好幾個(gè)檔次。差距不在會(huì)不會(huì)寫(xiě)提示詞而在有沒(méi)有把context-mode這個(gè)環(huán)節(jié)想清楚。如果你最近也在折騰AI編程工具、智能代碼補(bǔ)全或者基于大模型的項(xiàng)目分析大概率會(huì)撞上上下文模式這個(gè)詞——它本質(zhì)上就是決定AI看哪些代碼、按什么順序看、看完之后記多久的一套規(guī)則。我自己的體會(huì)是context-mode不是某個(gè)產(chǎn)品獨(dú)有的功能而是一套可以復(fù)用到所有AI協(xié)作場(chǎng)景里的方法論。這篇文章不聊虛的直接把我在實(shí)際項(xiàng)目里沉淀下來(lái)的理解、落地步驟和踩坑記錄整理出來(lái)適合正在用AI輔助寫(xiě)代碼、做代碼審查、或者想在團(tuán)隊(duì)里推AI工具落地的朋友參考——不管你是新手還是已經(jīng)玩過(guò)一陣子應(yīng)該都能在這套思路上找到自己需要的那塊拼圖。1. context-mode 到底是什么先解決AI憑什么懂你的問(wèn)題1.1 從一次低效對(duì)話說(shuō)起沒(méi)有上下文模式的AI有多難用先講個(gè)真實(shí)場(chǎng)景。以前我拿通用聊天式AI輔助寫(xiě)業(yè)務(wù)代碼時(shí)經(jīng)常在對(duì)話里貼大段代碼問(wèn)這段邏輯有什么問(wèn)題。模型通常能給出一些泛泛的建議比如注意空指針建議加日志但幾乎不會(huì)告訴我你第三個(gè)分支的邊界條件寫(xiě)錯(cuò)了或者這個(gè)函數(shù)和上面那個(gè)函數(shù)職責(zé)重疊了。原因很簡(jiǎn)單它只見(jiàn)樹(shù)木不見(jiàn)森林。后來(lái)我試著把整個(gè)項(xiàng)目的文件樹(shù)、核心接口定義、數(shù)據(jù)庫(kù)表結(jié)構(gòu)全部貼進(jìn)去效果立刻不一樣了但新的麻煩又來(lái)了——上下文窗口是有限的。一個(gè)中大型后端項(xiàng)目的核心代碼動(dòng)輒幾十萬(wàn)字符不可能全部塞進(jìn)去塞進(jìn)去要么超出模型的上下文上限要么因?yàn)樾畔⑻s導(dǎo)致模型抓不住重點(diǎn)回答反而比之前更差。這個(gè)問(wèn)題就是context-mode要解決的核心矛盾如何在有限的上下文空間里裝載最關(guān)鍵的工程信息。所謂上下文模式就是一套決定哪些信息進(jìn)入模型視野、以什么結(jié)構(gòu)進(jìn)入、什么時(shí)候更新的規(guī)則。說(shuō)直白點(diǎn)它像是給AI配了一個(gè)挑食的秘書(shū)——不是把所有材料都端上來(lái)而是根據(jù)當(dāng)前要辦的事挑出最相關(guān)的幾份文件放在臺(tái)面上。1.2 顯式、自動(dòng)、會(huì)話式三種模式到底在解決什么問(wèn)題在實(shí)際工具里context-mode通常表現(xiàn)為三種形態(tài)但我發(fā)現(xiàn)很多人把它們混為一談。第一種是顯式上下文模式也就是由人手動(dòng)指定AI需要關(guān)注的文件或目錄。這種模式最可控適合任務(wù)邊界清晰的場(chǎng)景比如只重構(gòu)這個(gè)controller下的代碼只分析這個(gè)模塊的測(cè)試覆蓋情況。你指哪AI打哪不會(huì)被無(wú)關(guān)文件帶偏。第二種是自動(dòng)上下文模式由工具根據(jù)當(dāng)前任務(wù)意圖去代碼庫(kù)里檢索相關(guān)內(nèi)容。這種模式省心適合探索性問(wèn)題比如訂單超時(shí)未支付的狀態(tài)目前在哪幾個(gè)文件里流轉(zhuǎn)但缺點(diǎn)也很明顯——檢索質(zhì)量直接決定回答質(zhì)量碰到冷門函數(shù)或者跨模塊調(diào)用鏈自動(dòng)檢索經(jīng)常漏東西。第三種是會(huì)話上下文模式強(qiáng)調(diào)跨多輪對(duì)話保持狀態(tài)。AI需要記住你之前說(shuō)過(guò)什么、確認(rèn)過(guò)什么、修改過(guò)什么。這種模式在代碼重構(gòu)場(chǎng)景里最關(guān)鍵因?yàn)槟阃趾脦纵喿孉I逐步調(diào)整代碼如果它每輪都把之前改的東西忘了你就有無(wú)窮無(wú)盡的返工。理解這三種形態(tài)之后你會(huì)發(fā)現(xiàn)context-mode不是一個(gè)開(kāi)關(guān)鍵而是一個(gè)上下文管理策略。好的策略是在合適的場(chǎng)景用合適的模式甚至把三種模式組合起來(lái)用。后面我會(huì)詳細(xì)演示怎么組合。2. 為什么上下文質(zhì)量比模型能力更決定產(chǎn)出效果2.1 算一筆賬喂進(jìn)去的信息里有多少是模型真正需要的我在一次代碼遷移項(xiàng)目里做過(guò)一個(gè)粗糙的數(shù)據(jù)統(tǒng)計(jì)。我要把一個(gè)老的后端服務(wù)從內(nèi)部框架遷移到新的Web框架涉及大約40個(gè)文件。如果用聊天式AI直接問(wèn)怎么遷移它給我的建議基本是教科書(shū)級(jí)別的正確但完全不可用。后來(lái)我把這40個(gè)文件的目錄結(jié)構(gòu)、每個(gè)文件的職責(zé)說(shuō)明、核心接口的出入?yún)⒍x整理成了一份大約3000字的上下文文檔喂給AI它的遷移方案立刻變得非常具體——能直接指出這幾個(gè)路由需要改注冊(cè)方式這個(gè)Filter需要替換成中間件寫(xiě)法。同樣的模型產(chǎn)出質(zhì)量天差地別。差別不在模型而在上下文。我后來(lái)養(yǎng)成了一個(gè)習(xí)慣在準(zhǔn)備讓AI干活之前先問(wèn)自己三個(gè)問(wèn)題。第一這個(gè)任務(wù)涉及哪些具體的代碼位置第二這些位置上最關(guān)鍵的信息是什么——是接口簽名、數(shù)據(jù)結(jié)構(gòu)、還是業(yè)務(wù)流程第三哪些信息是模型大概率不知道的比如項(xiàng)目特有的規(guī)范、歷史決策背景你把這幾個(gè)問(wèn)題想清楚上下文就已經(jīng)整理得七七八八了。很多人在AI編程上受挫不是模型不行而是喂料出了問(wèn)題。2.2 信息密度與信噪比為什么給更多不等于給更好這里有一個(gè)反直覺(jué)的點(diǎn)給AI更多上下文不等于給AI更好的上下文。模型的注意力是有限的信息越多噪聲越大關(guān)鍵信號(hào)反而被稀釋。我用一個(gè)具體例子說(shuō)明。假設(shè)你想讓AI幫你檢查一個(gè)支付回調(diào)函數(shù)的并發(fā)安全。你有兩種做法一種是把整個(gè)controller文件、service文件、工具類文件全部貼進(jìn)去大約800行代碼另一種是只貼出這個(gè)回調(diào)函數(shù)、它調(diào)用的核心service方法、以及操作的那張表的定義大約150行。試驗(yàn)下來(lái)后者的回答準(zhǔn)確率高得多。因?yàn)榍罢呃镉写罅繜o(wú)關(guān)的業(yè)務(wù)代碼模型的注意力被分散甚至?xí)涯隳硞€(gè)完全不相關(guān)的定時(shí)任務(wù)邏輯誤當(dāng)成支付邏輯的一部分。這里有個(gè)不太嚴(yán)謹(jǐn)?shù)軐?shí)用的信噪比判斷法在準(zhǔn)備上下文材料時(shí)如果一段代碼或說(shuō)明拿掉之后你認(rèn)為AI依然能正確完成這個(gè)任務(wù)那就果斷拿掉。上下文不是存檔文件寧可少而精也不要多而雜。2.3 上下文模式的本質(zhì)它其實(shí)是一種工程化思維如果把context-mode抽象出來(lái)看它就是在做一件事對(duì)軟件工程知識(shí)的結(jié)構(gòu)化篩選與動(dòng)態(tài)維護(hù)。你篩選什么、以什么結(jié)構(gòu)呈現(xiàn)、怎么更新這背后全是工程判斷。我記得有一次團(tuán)隊(duì)里一個(gè)同事讓我?guī)退碅I生成的代碼為什么總是風(fēng)格不一致。我打開(kāi)他的對(duì)話記錄發(fā)現(xiàn)他每次新建會(huì)話都只貼一段代碼問(wèn)幫我優(yōu)化一下AI根本不知道這個(gè)項(xiàng)目的命名規(guī)范、分層約定、異常處理風(fēng)格。后來(lái)我們整理了一份項(xiàng)目級(jí)上下文文件包含編碼規(guī)約、目錄結(jié)構(gòu)說(shuō)明、常見(jiàn)代碼范式示例他的AI生成代碼質(zhì)量肉眼可見(jiàn)地上來(lái)了。這件事讓我意識(shí)到context-mode的價(jià)值遠(yuǎn)不止讓AI更懂你的代碼它實(shí)際上迫使你把項(xiàng)目里隱性知識(shí)顯性化。很多團(tuán)隊(duì)里存在大量靠人傳人、靠口口相傳的約定它們從來(lái)沒(méi)有被寫(xiě)下來(lái)而context-mode恰好給了你一個(gè)理由去整理和沉淀。哪怕最終不用AI這份上下文文檔本身對(duì)團(tuán)隊(duì)也有巨大價(jià)值。3. 實(shí)操?gòu)念^搭建一套屬于你的 context-mode 工作流3.1 第一步用五分鐘跑一遍項(xiàng)目畫(huà)像我建議你在動(dòng)手之前先給項(xiàng)目做一個(gè)快速畫(huà)像不需要很重五分鐘就能搞定。打開(kāi)終端用tree命令拿到當(dāng)前項(xiàng)目的目錄結(jié)構(gòu)重點(diǎn)關(guān)注幾個(gè)地方入口文件在哪里路由在哪定義數(shù)據(jù)模型在哪個(gè)目錄核心業(yè)務(wù)邏輯集中在哪個(gè)模塊配置文件有哪些。拿到結(jié)構(gòu)之后動(dòng)手寫(xiě)一份context.md或AGENTS.md文件放在項(xiàng)目根目錄。這份文件就是你的項(xiàng)目級(jí)上下文底座。我自己的模板大概是這樣的# 項(xiàng)目上下文說(shuō)明 ## 項(xiàng)目定位 一句話說(shuō)清楚這個(gè)服務(wù)是干什么的。 ## 技術(shù)棧 - 語(yǔ)言/框架/版本 - 核心依賴 ## 目錄結(jié)構(gòu)指北 - src/main/java/com/xxx/controllerHTTP入口只做參數(shù)校驗(yàn)和結(jié)果封裝 - src/main/java/com/xxx/service業(yè)務(wù)邏輯層事務(wù)邊界在這層 - src/main/java/com/xxx/repository數(shù)據(jù)訪問(wèn)層禁止寫(xiě)業(yè)務(wù)邏輯 ## 核心約定 - 異常統(tǒng)一拋出 BizException由全局異常處理器轉(zhuǎn)換 - 新接口必須寫(xiě) OpenAPI 注解 - 所有金額字段用 BigDecimal禁止使用 double ## 關(guān)鍵鏈路 - 下單流程Controller A - Service B - Repository C - 庫(kù)存服務(wù)外部這份文件不需要一開(kāi)始就完備先搭出框架后面在實(shí)際使用中持續(xù)補(bǔ)。它的核心作用是給AI一個(gè)項(xiàng)目世界觀——讓它知道你代碼里什么最重要、什么約定必須遵守。3.2 第二步把上下文分成三個(gè)抽屜按任務(wù)類型取用項(xiàng)目畫(huà)像搭好之后你會(huì)發(fā)現(xiàn)不同任務(wù)的上下文需求完全不同。我把它們分成三個(gè)抽屜用不同的方式加載。第一層是全局上下文就是那份context.md適合任何任務(wù)——AI每次開(kāi)工前都應(yīng)該知道項(xiàng)目是干什么的、代碼怎么組織。這一層信息量小、穩(wěn)定、復(fù)用率高我建議每次任務(wù)都帶上。第二層是模塊上下文按業(yè)務(wù)域劃分比如訂單域、支付域、用戶域。每個(gè)域一個(gè)說(shuō)明文件包含這個(gè)域的核心實(shí)體定義、關(guān)鍵服務(wù)接口、典型的調(diào)用鏈路。只有當(dāng)任務(wù)涉及這個(gè)域時(shí)才加載。第三層是任務(wù)上下文也就是當(dāng)前這個(gè)具體任務(wù)相關(guān)的代碼文件和數(shù)據(jù)結(jié)構(gòu)。我通常會(huì)在發(fā)起任務(wù)時(shí)把涉及的3到5個(gè)關(guān)鍵文件貼進(jìn)去而不是整個(gè)目錄丟給AI。用抽屜的邏輯管理上下文最大的好處是可控。你永遠(yuǎn)不會(huì)把所有代碼塞進(jìn)一次對(duì)話但每個(gè)任務(wù)都能拿到它最需要的那部分信息。3.3 第三步編寫(xiě)一個(gè)上下文自動(dòng)打包小腳本如果每次都要手工復(fù)制文件內(nèi)容還是挺煩的。我寫(xiě)了一個(gè)小腳本用來(lái)快速把指定目錄的核心文件打包成一份上下文內(nèi)容直接粘貼到對(duì)話里用。這里分享一個(gè)簡(jiǎn)化版你可以根據(jù)自己的語(yǔ)言和項(xiàng)目結(jié)構(gòu)調(diào)整#!/bin/bash # pack_context.sh - 把指定目錄下的代碼文件打包成上下文markdown # 用法: ./pack_context.sh src/main/java/com/xxx/service TARGET_DIR${1:?請(qǐng)傳入目錄路徑} OUTPUT_FILEcontext_bundle.md DEPTH${2:-3} echo # 上下文打包: $TARGET_DIR $OUTPUT_FILE # 生成目錄樹(shù) echo $OUTPUT_FILE echo ## 目錄結(jié)構(gòu) $OUTPUT_FILE echo $OUTPUT_FILE tree -L $DEPTH $TARGET_DIR $OUTPUT_FILE echo $OUTPUT_FILE # 遞歸讀取代碼文件 find $TARGET_DIR -type f \( -name *.java -o -name *.kt -o -name *.ts \) \ -not -path */target/* -not -path */node_modules/* | sort | while read -r file; do echo $OUTPUT_FILE echo ## 文件: $file $OUTPUT_FILE echo ${file##*.} $OUTPUT_FILE cat $file $OUTPUT_FILE echo $OUTPUT_FILE done echo 上下文已打包到 $OUTPUT_FILE共 $(wc -l $OUTPUT_FILE) 行這個(gè)腳本的邏輯很簡(jiǎn)單先給一個(gè)目錄樹(shù)再按文件逐個(gè)讀取內(nèi)容。但我在實(shí)際使用中做了一個(gè)重要改進(jìn)——腳本默認(rèn)不讀取test目錄因?yàn)榇蟛糠智闆r下測(cè)試代碼會(huì)干擾AI對(duì)業(yè)務(wù)邏輯的判斷。你可以在find命令里加-not -path */test/*或者反過(guò)來(lái)在寫(xiě)測(cè)試場(chǎng)景時(shí)專門加載測(cè)試目錄。3.4 第四步設(shè)計(jì)注入策略——什么時(shí)候喂什么料有了打包工具下一步就是決定在任務(wù)流程的哪個(gè)節(jié)點(diǎn)注入哪一層上下文。我把一次AI輔助開(kāi)發(fā)的完整流程拆成三個(gè)階段。第一階段是任務(wù)啟動(dòng)。在這個(gè)階段注入全局上下文模塊上下文讓AI建立項(xiàng)目認(rèn)知。我會(huì)用這樣的開(kāi)場(chǎng)白請(qǐng)基于項(xiàng)目上下文說(shuō)明先復(fù)述一下這個(gè)項(xiàng)目的核心架構(gòu)和你對(duì)訂單模塊的理解然后我們?cè)匍_(kāi)始討論重構(gòu)方案。讓AI先復(fù)述是為了確認(rèn)它真的讀進(jìn)去了上下文而不是假裝看到了。第二階段是方案設(shè)計(jì)。在這個(gè)階段注入任務(wù)上下文把涉及的具體文件貼進(jìn)去。這時(shí)候最適合做代碼審查、方案對(duì)比、影響面分析。我的習(xí)慣是讓AI先輸出一個(gè)改動(dòng)影響清單——列出它認(rèn)為需要?jiǎng)拥奈募⒚總€(gè)文件要改什么、風(fēng)險(xiǎn)點(diǎn)在哪我再逐條確認(rèn)。這套流程能避免AI直接甩出一大坨改動(dòng)導(dǎo)致后面review無(wú)從下手。第三階段是編碼實(shí)現(xiàn)。在這個(gè)階段AI需要的是局部深聚焦上下文反而要收窄。我會(huì)只貼當(dāng)前要改的那個(gè)函數(shù)或文件片段配合全局上下文中相關(guān)的約定讓它生成代碼。因?yàn)榉桨敢呀?jīng)定了這時(shí)候AI的角色更像一個(gè)超級(jí)打字員不該再讓它看到太多無(wú)關(guān)代碼否則它又開(kāi)始自由發(fā)揮。3.5 第五步用增量更新保持上下文保鮮最后一個(gè)實(shí)操環(huán)節(jié)是上下文的更新。代碼是活的你的上下文說(shuō)明如果停更很快會(huì)變成僵尸文檔。我踩過(guò)的坑是兩周沒(méi)更新context.md項(xiàng)目里新增了一個(gè)消息隊(duì)列模塊AI完全不知道它的存在每次涉及異步任務(wù)的處理建議都是錯(cuò)的。我現(xiàn)在用一套很輕的更新機(jī)制。第一每周五下午用15分鐘過(guò)一遍項(xiàng)目的git log看看這周改了什么順手更新context.md里的目錄指北和關(guān)鍵鏈路。第二每次做完一個(gè)比較大的重構(gòu)立刻把上下文里對(duì)應(yīng)的關(guān)鍵鏈路章節(jié)重寫(xiě)一遍——因?yàn)槟莻€(gè)時(shí)刻你對(duì)全貌最清楚拖到以后再補(bǔ)往往就忘了。第三在AI生成了正確且復(fù)雜的代碼之后把它的思路和關(guān)鍵決策記錄到上下文里這樣以后問(wèn)類似問(wèn)題時(shí)AI能調(diào)用過(guò)去的成功經(jīng)驗(yàn)不是每次從零開(kāi)始。這套更新機(jī)制聽(tīng)起來(lái)不起眼但上下文管理的真正難點(diǎn)不在建立而在維護(hù)。我之前見(jiàn)過(guò)很多團(tuán)隊(duì)的AI輔助開(kāi)發(fā)熱度下降核心原因不是模型不夠好而是他們的上下文文檔停留在第一天越往后越?jīng)]人用。4. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄我在上下文實(shí)踐中踩過(guò)的坑4.1 Token超限上下文塞太多模型直接拒絕工作這是最常遇到的第一個(gè)坎。我最早打包上下文時(shí)試過(guò)把整個(gè)微服務(wù)幾十個(gè)文件全部塞進(jìn)去結(jié)果對(duì)話一開(kāi)始就提示超出上下文長(zhǎng)度限制被迫各種截?cái)唷⒉眉舴浅@仟N。后來(lái)我找到了一個(gè)夠用的估算公式中文字符大概每1.5到2個(gè)字符算一個(gè)token英文字符大概4個(gè)字符算一個(gè)token不同模型略有差異可以按這個(gè)量級(jí)估。拿到這個(gè)估算值之后我在打包腳本里加了行數(shù)限制——核心代碼文件超過(guò)300行的默認(rèn)只截取文件頭部的類型定義、常量聲明、方法簽名列表不讀取完整實(shí)現(xiàn)。這樣既保住了接口信息又減少了大量token占用。另外我還養(yǎng)成一個(gè)習(xí)慣先用wc -l快速看文件行數(shù)再?zèng)Q定要不要全量貼入。一個(gè)文件超過(guò)500行我基本只貼它的方法簽名和關(guān)鍵邏輯片段或者請(qǐng)AI先針對(duì)某個(gè)具體函數(shù)分析。把大文件切碎成接口視圖和實(shí)現(xiàn)細(xì)節(jié)兩層能極大降低token壓力。4.2 上下文過(guò)期代碼已經(jīng)改了AI還在用舊信息這個(gè)坑非常隱蔽。有一次我讓AI幫我看一個(gè)訂單狀態(tài)機(jī)的代碼但訂單狀態(tài)定義在兩天前剛從三個(gè)狀態(tài)擴(kuò)展成五個(gè)狀態(tài)我給的上下文里還寫(xiě)著舊定義。AI基于舊狀態(tài)機(jī)給出了完整的重構(gòu)建議我照著改了一半才發(fā)現(xiàn)狀態(tài)枚舉對(duì)不上整個(gè)方案作廢返工了將近一個(gè)下午。排查這類問(wèn)題我在上下文里加了一個(gè)信息新鮮度標(biāo)記。在context.md的項(xiàng)目畫(huà)像里我專門列了一張表關(guān)鍵文件最后變更時(shí)間是否需要AI重點(diǎn)核對(duì)OrderStatusEnum.java2025-01-12狀態(tài)機(jī)關(guān)鍵定義必須核對(duì)最新版PaymentService.java2025-01-08支付回調(diào)邏輯近期重構(gòu)過(guò)UserRepository.java2024-12-20穩(wěn)定可直接使用每次準(zhǔn)備給AI喂上下文時(shí)我先把這張表過(guò)一遍凡是最后變更時(shí)間在最近一周以內(nèi)的文件我會(huì)強(qiáng)制重新讀取一遍最新內(nèi)容再貼進(jìn)去。這個(gè)方法很土但真的能避免大量無(wú)效對(duì)話。4.3 上下文遺漏關(guān)鍵文件沒(méi)被帶入AI答非所問(wèn)自動(dòng)檢索型context-mode最容易出現(xiàn)這個(gè)問(wèn)題。我有一次讓AI分析用戶注冊(cè)完成后發(fā)送歡迎消息的鏈路結(jié)果它基于注冊(cè)接口 - 調(diào)用消息服務(wù)的假設(shè)分析得頭頭是道但代碼里的真實(shí)鏈路是注冊(cè)接口 - 發(fā)MQ事件 - 消費(fèi)者異步處理 - 再發(fā)消息。AI漏掉了MQ消費(fèi)者這個(gè)關(guān)鍵環(huán)節(jié)因?yàn)槲野褭z索范圍限定在了controller和service目錄生產(chǎn)者消費(fèi)者代碼在另一個(gè)模塊。這種問(wèn)題的排查手段我總結(jié)了一個(gè)反問(wèn)法讓AI在給出結(jié)論之前先列出它判斷依據(jù)的具體代碼位置。比如在提示詞里加一句請(qǐng)先列出你做出以上判斷所依據(jù)的文件路徑和函數(shù)名逐一標(biāo)注出處。如果AI羅列的文件里有明顯的缺失或者它含糊其辭那基本可以斷定上下文沒(méi)喂全。這時(shí)候再回頭檢查是不是有跨目錄、跨模塊的調(diào)用鏈沒(méi)有被納入??缒K調(diào)用是上下文中最容易漏的部分。我現(xiàn)在會(huì)在context.md里為每個(gè)核心業(yè)務(wù)鏈路單獨(dú)寫(xiě)一個(gè)調(diào)用鏈清單把涉及的所有模塊挨個(gè)列一遍這樣至少在下一次打包時(shí)有個(gè)核對(duì)清單不會(huì)漏得離譜。4.4 上下文干擾帶入了無(wú)關(guān)信息反而誤導(dǎo)AI這一類問(wèn)題最隱蔽。有一次我讓AI幫忙review一個(gè)支付對(duì)接代碼順手把整個(gè)pom.xml文件也貼了進(jìn)去因?yàn)槲矣X(jué)得依賴也是上下文的一部分。AI居然根據(jù)pom里某個(gè)老版本的HTTP客戶端庫(kù)建議我調(diào)整代碼寫(xiě)法但實(shí)際上那個(gè)庫(kù)在運(yùn)行時(shí)根本不會(huì)被用到——項(xiàng)目里已經(jīng)有另一個(gè)BOM管理了版本pom里的坐標(biāo)只是占位。這完全是被我多余的上下文帶偏了。這類問(wèn)題的教訓(xùn)是上下文要圍繞任務(wù)真實(shí)需要的決策邊界來(lái)裁剪而不是圍繞看起來(lái)相關(guān)的文件來(lái)堆積。我現(xiàn)在準(zhǔn)備上下文之前都會(huì)寫(xiě)一行任務(wù)目標(biāo)放在最頂部比如只關(guān)注支付回調(diào)的簽名校驗(yàn)和冪等邏輯不關(guān)注HTTP客戶端的選用。這個(gè)目標(biāo)就像給AI劃了一條線讓它知道哪些信息可以忽略。如果你發(fā)現(xiàn)AI的回答里反復(fù)出現(xiàn)某個(gè)你沒(méi)打算討論的技術(shù)點(diǎn)比如動(dòng)不動(dòng)就提日志框架、提緩存策略大概率是上下文里混入了太多氛圍組信息。把這些信息從上下文里拿掉比任何提示詞技巧都管用。4.5 排查思路小結(jié)四個(gè)問(wèn)題快速定位Context問(wèn)題把上面的經(jīng)驗(yàn)收攏一下我遇到AI回答質(zhì)量拉胯時(shí)會(huì)按這個(gè)順序做體檢癥狀排查方向解決辦法回答大而空不夠具體上下文是否缺少項(xiàng)目特定信息補(bǔ)全context.md增加技術(shù)棧、目錄說(shuō)明、核心約定回答涉及無(wú)關(guān)內(nèi)容跑偏上下文信噪比太低精簡(jiǎn)上下文只保留任務(wù)相關(guān)的3到5個(gè)文件回答基于過(guò)時(shí)信息上下文更新不及時(shí)檢查文件變更時(shí)間表重新讀取最新代碼回答關(guān)鍵鏈路缺失、邏輯斷點(diǎn)自動(dòng)檢索漏了跨模塊文件用反問(wèn)法讓AI列出依據(jù)核調(diào)用鏈清單這套體檢流程我大概用了兩三個(gè)月解決了我九成以上的AI協(xié)作問(wèn)題。剩下那一成大多是大模型本身能力邊界導(dǎo)致的換更好的模型或者調(diào)整任務(wù)拆分方式才能解決。5. 把 context-mode 推進(jìn)到團(tuán)隊(duì)協(xié)作層面的擴(kuò)展玩法5.1 團(tuán)隊(duì)級(jí)上下文把個(gè)人經(jīng)驗(yàn)變成組織資產(chǎn)context-mode如果只是一個(gè)人在用價(jià)值有限。真正讓它發(fā)揮杠桿作用的地方在團(tuán)隊(duì)。我后來(lái)在團(tuán)隊(duì)里推行了一個(gè)AI輔助開(kāi)發(fā)規(guī)范核心就是那份context.md文件。每個(gè)服務(wù)一個(gè)由服務(wù)owner維護(hù)任何人在這個(gè)服務(wù)上用AI工具都必須先加載這份文件。推行一個(gè)季度之后效果超出我的預(yù)期。新人上手項(xiàng)目的速度明顯快了——以前新同學(xué)要花兩周才能搞清楚這個(gè)服務(wù)里有什么、改了哪里會(huì)炸現(xiàn)在拿著context.md的結(jié)構(gòu)指北再讓AI按圖索驥地解釋三天就能把核心鏈路摸清。團(tuán)隊(duì)reviewAI生成代碼時(shí)也有了統(tǒng)一的審美標(biāo)準(zhǔn)——上下文里寫(xiě)清楚的約定AI不會(huì)違反人也不用反復(fù)強(qiáng)調(diào)。5.2 上下文模板沉淀一套可復(fù)用的骨架我還沉淀了一套上下文模板骨架方便其他服務(wù)快速?gòu)?fù)用。核心包含幾個(gè)固定章節(jié)項(xiàng)目定位、技術(shù)棧、目錄結(jié)構(gòu)指北、核心約定、關(guān)鍵鏈路、最近變更記錄。每個(gè)章節(jié)我都規(guī)定了必須包含什么、禁止寫(xiě)什么。比如目錄結(jié)構(gòu)指北里禁止寫(xiě)大段解釋只允許寫(xiě)路徑 一句話職責(zé)。關(guān)鍵鏈路里必須寫(xiě)入口 中間環(huán)節(jié) 出口 失敗分支缺一不可。這套模板的初衷非常簡(jiǎn)單——上下文質(zhì)量取決于信息是否結(jié)構(gòu)化。你讓每個(gè)工程師自由發(fā)揮寫(xiě)項(xiàng)目說(shuō)明大概率寫(xiě)出一堆這個(gè)模塊負(fù)責(zé)X功能的正確廢話。但如果你給出固定的框架和禁區(qū)每個(gè)人產(chǎn)出的上下文就能保持穩(wěn)定的可用性。5.3 與Git工作流的聯(lián)動(dòng)讓上下文自動(dòng)更新一半最后一個(gè)擴(kuò)展玩法是把上下文更新跟Git工作流綁定。我在腳本里加了一個(gè)小功能跑git diff --stat對(duì)比最近一次上下文打包時(shí)的分支狀態(tài)如果有文件變動(dòng)腳本會(huì)提示以下文件在本次會(huì)話期間被修改建議重新讀取然后自動(dòng)把變更文件列表輸出出來(lái)。這個(gè)功能幫了大忙。因?yàn)槿斯ぞS護(hù)上下文更新最大的痛點(diǎn)是容易忘而Git天然記錄了所有變動(dòng)。你不需要自動(dòng)化到什么程度——哪怕只是在打包腳本里加一句提醒都能減少大量上下文過(guò)期的尷尬。我甚至見(jiàn)過(guò)有人把git log --oneline -15直接追加到上下文末尾讓AI知道最近這一周項(xiàng)目發(fā)生過(guò)什么效果也不錯(cuò)。這套玩法擴(kuò)展下來(lái)context-mode就從一個(gè)給AI貼代碼的小技巧變成了一個(gè)項(xiàng)目級(jí)的工程實(shí)踐。我個(gè)人現(xiàn)在的感受是它像是一份項(xiàng)目的使用說(shuō)明書(shū)AI是那個(gè)讀說(shuō)明書(shū)的人而你是那個(gè)不斷修訂說(shuō)明書(shū)的人。只要說(shuō)明書(shū)靠譜AI就能幫你干很多臟活累活說(shuō)明書(shū)要是稀爛AI再?gòu)?qiáng)也幫不上忙。我最后再分享一個(gè)心得別把context-mode想得太玄乎。它就是你在跟AI協(xié)作之前花十分鐘想清楚這個(gè)任務(wù)需要什么信息的那個(gè)過(guò)程。你每一次為AI精心準(zhǔn)備的上下文本質(zhì)上都在幫你理解自己的項(xiàng)目——我都數(shù)不清有多少次是為了喂給AI才第一次真正梳理清楚某個(gè)模塊的調(diào)用鏈。就沖這一點(diǎn)養(yǎng)成這個(gè)習(xí)慣就絕對(duì)不虧。