
1. 從廚房到代碼為什么“備料”是智能體編程的第一性原理如果你在廚房里待過或者看過任何一檔像樣的烹飪節(jié)目一定會對一個詞印象深刻Mise en Place。這是一個法語詞直譯過來是“各就各位”在烹飪界它指的是一種工作哲學——在真正開火烹飪之前把所有食材洗凈、切配、稱量好分門別類地放在小碗里工具也擺放就緒。廚師只需專注于烹飪本身而無需在油鍋冒煙時手忙腳亂地去找一顆蒜。聽起來很基礎對吧但正是這個基礎區(qū)分了專業(yè)廚房的井然有序和家庭廚房的兵荒馬亂?,F(xiàn)在讓我們把這個概念平移到另一個看似毫不相干的領域智能體編程。當我們在談論讓AI智能體去編寫、調(diào)試、重構(gòu)代碼時我們是否也陷入了“油鍋冒煙才找蒜”的混亂答案是絕大多數(shù)時候是的?!癕ise en Place for Agentic Coding”這個標題正是將這種廚房里的“備料”哲學提煉為一種嚴謹?shù)纳舷挛墓こ谭椒ㄕ摗K皇窃谥v某個具體的AI模型或代碼生成工具而是在講一個更底層、更決定成敗的環(huán)節(jié)我們?nèi)绾螢橹悄荏w準備“上下文”這就像是為一位頂級廚師準備一個完美的備料臺。你給智能體的上下文就是它的“工作臺”。臺面是雜亂無章、堆滿未處理的原始食材還是井井有條、分門別類、隨時可取的半成品將直接決定它產(chǎn)出的“菜肴”即代碼的質(zhì)量、效率和可靠性。這篇文章就是寫給那些已經(jīng)嘗過AI編碼甜頭但也飽受其“幻覺”、上下文溢出、指令漂移之苦的開發(fā)者、技術負責人和AI應用架構(gòu)師的。我們將深入拆解為什么“有意識的準備”不是可選項而是智能體編碼時代的必選項。我會結(jié)合大量一線實戰(zhàn)中的踩坑經(jīng)驗告訴你如何系統(tǒng)性地構(gòu)建你的“智能體備料臺”把看似玄學的“提示工程”變成一套可重復、可評估、可優(yōu)化的工程化流程。2. 智能體編碼的“油鍋困境”為什么上下文準備如此關鍵在深入方法論之前我們必須先理解我們面臨的核心挑戰(zhàn)。直接給智能體比如ChatGPT、Claude、Cursor等丟一個模糊的需求然后指望它吐出完美的代碼這就像讓一位廚師在堆滿帶泥土豆和整只雞的臺面上30分鐘內(nèi)做出一道法式燉雞——結(jié)果要么是災難要么廚師智能體會用自己的“想象力”幻覺來填補空白比如用番茄醬代替紅酒因為你沒告訴它需要紅酒而它“覺得”番茄醬可能也行。2.1 智能體的“工作記憶”局限性當前的AI編碼智能體無論其底層模型多么強大都有一個無法回避的物理限制上下文窗口。你可以把它想象成廚師工作臺的面積。面積再大也是有限的。當你在對話中不斷追加需求、發(fā)送文件、進行調(diào)試時這個“臺面”很快就會被占滿。更糟糕的是模型對于長上下文中不同位置信息的“注意力”是不均勻的。早期的、中間的關鍵信息可能會被“遺忘”或稀釋。注意這里說的“遺忘”不是真的丟失而是指在模型生成下一個詞時那些信息對決策的影響權(quán)重降低了。這會導致智能體前后行為不一致即“指令漂移”。我曾在一個微服務重構(gòu)項目中讓智能體基于一個復雜的領域模型接口生成實現(xiàn)類。一開始我提供了清晰的接口定義和業(yè)務規(guī)則。但在十幾輪來回調(diào)試和優(yōu)化后智能體突然開始生成與最初業(yè)務規(guī)則相悖的代碼?;厮萆舷挛陌l(fā)現(xiàn)最初的規(guī)則描述已經(jīng)被淹沒在大量調(diào)試日志和代碼片段中智能體的“注意力”已經(jīng)完全被最近的錯誤信息所吸引。2.2 “垃圾進垃圾出”的放大效應在傳統(tǒng)編程中一個模糊的需求可能導致開發(fā)者產(chǎn)出有偏差的代碼但開發(fā)者的人類常識和經(jīng)驗會起到一定的糾偏作用。然而智能體極度依賴你輸入的上下文質(zhì)量。你給的上下文如果模糊、矛盾、信息不全“垃圾進”那么智能體不僅會產(chǎn)出有問題的代碼“垃圾出”還會以一種極其自信且邏輯自洽的方式呈現(xiàn)出來極具迷惑性。例如你只說“寫一個用戶登錄函數(shù)。” 智能體可能會生成一個僅驗證用戶名密碼的簡單函數(shù)。但你的真實上下文可能包括需要集成OAuth 2.0、需要記錄安全日志、需要防范暴力破解、需要返回特定的JWT令牌結(jié)構(gòu)……這些缺失的“食材”智能體不會主動去“市場”采購它只會用臺面上現(xiàn)有的東西一個模糊的“登錄”概念來湊合。2.3 調(diào)試成本的非線性增長當智能體產(chǎn)出的代碼基于一個糟糕的上下文時調(diào)試會變得異常痛苦。因為你不僅要調(diào)試代碼本身的語法或邏輯錯誤更要先逆向工程出“智能體當時到底理解了什么”。這相當于你要先猜出廚師腦子里那個殘缺的菜譜才能知道為什么他往燉雞里加了草莓。這種雙重調(diào)試的認知負荷常常比從頭自己寫代碼還要高。因此“Mise en Place”的核心價值就在于通過前置的、系統(tǒng)性的上下文準備將智能體的“工作記憶”從存儲和回憶原始、雜亂信息的負擔中解放出來讓它100%的“算力”都聚焦于“烹飪”即代碼的推理、生成和組裝這一核心創(chuàng)造性任務上。這本質(zhì)上是一種認知卸載將人類擅長的規(guī)劃、結(jié)構(gòu)化、明確化工作與AI擅長的模式匹配、代碼生成工作進行最優(yōu)分工。3. 構(gòu)建你的“智能體備料臺”上下文工程的四大核心食材理解了“為什么”我們來看“怎么做”。一個專業(yè)的“智能體備料臺”應該準備哪些“食材”我將其歸納為四大類它們共同構(gòu)成了高質(zhì)量上下文的基石。3.1 食材一清晰明確的任務規(guī)格說明書這是你的“主菜食譜”。它必須超越自然語言的模糊描述達到接近“機器可讀”的精確度。輸入/輸出契約像寫API文檔一樣明確。函數(shù)/模塊的輸入?yún)?shù)名稱、類型、約束、示例、返回值類型、結(jié)構(gòu)、可能的狀態(tài)。例如不只是“處理用戶數(shù)據(jù)”而是“輸入UserRegistrationForm對象包含email, password, name字段其中email需符合RFC 5322標準輸出ApiResponse對象成功時包含userId和jwtToken失敗時包含errorCode和message?!彬炇諚l件與邊界案例明確告訴智能體什么是“完成”。包括正常流主流程的成功場景。異常流各種錯誤處理網(wǎng)絡超時、數(shù)據(jù)庫連接失敗、輸入驗證失敗、權(quán)限不足等。邊界案例空輸入、極大/極小值、并發(fā)情況、數(shù)據(jù)一致性要求。非功能性需求性能指標如響應時間100ms、安全性要求如密碼必須加鹽哈希?!安灰鍪裁础钡呢撁媲鍐芜@往往比“要做什么”更重要。明確禁止的模式、已棄用的庫、特定的實現(xiàn)方式如“禁止使用eval()”“避免全局變量”“不要直接拼接SQL語句”。實操心得我習慣用一個結(jié)構(gòu)化的注釋塊來承載這些信息直接作為給智能體的初始提示的一部分。這比在對話中零散描述要有效得多。## 任務創(chuàng)建用戶積分扣除服務函數(shù) **函數(shù)簽名**: deductUserPoints(userId: string, points: number, reason: string): PromiseDeductionResult **輸入**: - userId: 用戶ID必須是存在的、狀態(tài)為激活的用戶。 - points: 扣除積分數(shù)必須為正整數(shù)且不大于用戶當前可用積分。 - reason: 扣除原因枚舉值[PURCHASE, REFUND, ADMIN_ADJUSTMENT, PENALTY]。 **輸出**: - success: boolean。 - remainingPoints: number扣除后的積分余額。 - transactionId: string本次積分變動的唯一事務ID。 - error: string | null失敗時的錯誤信息。 **業(yè)務規(guī)則**: 1. 必須是原子操作查詢當前積分和扣除操作必須在同一個數(shù)據(jù)庫事務中。 2. 需要記錄完整的積分流水points_ledger表包含操作前余額、變動值、操作后余額、原因、時間戳。 3. 如果userId不存在或用戶狀態(tài)非激活立即失敗錯誤碼USER_INVALID。 4. 如果points超過可用積分立即失敗錯誤碼INSUFFICIENT_POINTS。 **禁止**: - 直接使用UPDATE ... SET points points - ?而不做前置查詢校驗。 - 在函數(shù)內(nèi)進行任何形式的HTTP調(diào)用或IO阻塞操作日志除外。3.2 食材二精選的代碼范例與風格指南這是你的“調(diào)味料和經(jīng)典菜式樣本”。智能體通過示例學習的速度和效果遠超純文本描述。架構(gòu)與模式范例提供1-2個項目中類似模塊的完整、簡潔的代碼文件。例如如果要生成一個GraphQL Resolver就提供一個現(xiàn)有的、設計良好的Resolver文件。這能傳遞項目整體的架構(gòu)風格、分層邏輯、依賴注入方式等隱性知識。代碼風格片段不是給一個通用的ESLint配置鏈接而是提供具體的代碼片段對比。好的例子// 使用具名導出而非默認導出// 錯誤處理使用Result模式而非try-catch遍地開花。壞的例子// 避免嵌套超過三層的回調(diào)函數(shù)。領域特定語言如果你的項目有自己的一些術語、工具函數(shù)或設計模式提供它們的定義和用法。例如“我們使用Injectable()裝飾器來自動處理依賴”“查詢數(shù)據(jù)庫統(tǒng)一使用queryBuilder()工具函數(shù)它內(nèi)置了連接池管理和超時重試”。踩坑經(jīng)驗最初我只給智能體看“好”的代碼后來發(fā)現(xiàn)它有時會模仿一些過時的模式?,F(xiàn)在我會有意準備一個“模式進化說明”例如“本項目早期使用X模式處理錯誤但現(xiàn)在已全面遷移到Y(jié)模式。請參考service/authV2.ts而非service/auth.ts?!?.3 食材三精確的依賴與環(huán)境上下文這是你的“廚具和灶臺狀態(tài)”。智能體需要知道在哪個“廚房”里工作。技術棧清單精確到主版本號。Node.js 18 LTS,TypeScript 5.0,React 18,Prisma ORM 4.0。避免只說“用最新的”。關鍵依賴的API風格如果你用了某個特定的庫說明你期望的用法。例如“我們使用axios進行HTTP請求并且已經(jīng)配置了全局的請求攔截器添加JWT令牌所以直接使用axios.get(/api/endpoint)即可無需手動處理認證頭?!表椖拷Y(jié)構(gòu)導航用簡短文字描述關鍵目錄的作用。/src/models/存放Prisma生成的數(shù)據(jù)庫模型和自定義的領域模型/src/services/存放核心業(yè)務邏輯每個文件對應一個領域服務/src/api/routes/存放Express路由定義它們只負責接收請求和返回響應邏輯委托給service層。運行時約束代碼將運行在什么環(huán)境服務器less函數(shù)有冷啟動時間限制Docker容器特定的Linux環(huán)境特定的云平臺如AWS Lambda需要處理特定的環(huán)境變量3.4 食材四動態(tài)的會話狀態(tài)與思維鏈錨點這是你在烹飪過程中的“火候控制和嘗味記錄”。對于復雜的、多輪的任務你需要管理對話本身。思維鏈顯式化要求智能體在給出最終代碼前先輸出其思考過程。例如“請先分析需求列出實現(xiàn)步驟和可能遇到的坑然后再生成代碼?!?這讓你能中途糾正它的思路偏差而不是等到代碼生成后才發(fā)現(xiàn)問題。關鍵決策記錄在多輪對話中當你們共同做出一個重要技術決策時比如“決定采用策略模式來解耦不同的支付方式”用一句總結(jié)的話記錄下來并在后續(xù)提示中簡要提及作為“會話記憶錨點”。例如“【決策記錄】支付處理器采用策略模式已定義PaymentStrategy接口。”問題-解決方案對在調(diào)試過程中將已識別的問題和已驗證的解決方案明確記錄下來避免智能體在后續(xù)步驟中重蹈覆轍或遺忘。這就像廚師在菜譜邊上標注“上次鹽放多了這次減半”。4. 實戰(zhàn)演練一個用戶注冊API的“備料”到“出鍋”全流程讓我們通過一個具體的例子看看如何應用這套方法論。假設我們要為一個已有后端項目添加一個用戶注冊API。4.1 步驟一準備“備料臺”編寫上下文提示我不會直接打開AI對話窗口就開始打字。而是先創(chuàng)建一個臨時的文檔或注釋系統(tǒng)性地組裝上下文。# 智能體任務上下文添加用戶注冊API ## 1. 項目上下文 - **項目類型**: Node.js TypeScript后端服務采用分層架構(gòu)。 - **核心框架**: Express.js, Prisma ORM, JWT for auth. - **代碼風格**: Airbnb ESLint基礎擴展規(guī)則見 .eslintrc.js。使用async/await錯誤處理統(tǒng)一使用try/catch包裹并在頂層中間件處理。 - **參考范例**: 請參考 src/api/routes/auth/login.ts 和 src/services/authService.ts 的現(xiàn)有模式。注意登錄API的請求驗證、錯誤響應格式。 ## 2. 任務規(guī)格說明書 **功能**: 實現(xiàn)用戶注冊端點。 **端點**: POST /api/v1/auth/register **請求體 (JSON)**: json { email: string, 必須符合郵箱格式且唯一, password: string, 最小長度8位必須包含字母和數(shù)字, username: string, 可選如未提供則使用郵箱前綴 }成功響應 (201 Created):{ success: true, data: { user: { id: uuid, email: string, username: string }, token: JWT字符串用于后續(xù)認證 } }錯誤響應 (400 Bad Request):郵箱格式無效:{ success: false, error: INVALID_EMAIL_FORMAT }郵箱已存在:{ success: false, error: EMAIL_ALREADY_EXISTS }密碼強度不足:{ success: false, error: WEAK_PASSWORD }業(yè)務邏輯:驗證請求體字段格式和強度。檢查郵箱在User表中是否已存在。對密碼進行加鹽哈希使用bcrypt強度因子12。創(chuàng)建新用戶記錄寫入數(shù)據(jù)庫。生成JWT令牌payload包含userId和email有效期7天。返回用戶基本信息不含密碼哈希和JWT令牌。非功能需求:密碼明文絕不可出現(xiàn)在日志中。郵箱唯一性檢查需考慮數(shù)據(jù)庫并發(fā)注冊情況使用Prisma的create唯一約束或先findUnique后create在事務中處理。3. 給智能體的明確指令請按照以下步驟操作首先分析上述需求并列出你認為的實現(xiàn)計劃1. 創(chuàng)建路由文件2. 創(chuàng)建或更新服務層函數(shù)3. 更新Prisma模型如果需要...。然后根據(jù)計劃先生成src/api/routes/auth/register.ts文件。接著生成或修改src/services/userService.ts添加createUser函數(shù)。最后確保生成的代碼遵循項目現(xiàn)有風格并處理所有提到的錯誤情況。 請分步驟進行在每個步驟后暫停等待我的確認或反饋。### 4.2 步驟二執(zhí)行與交互“烹飪”過程 將上述精心準備的上下文提示復制到AI對話中。由于上下文清晰智能體通常能給出一個非??孔V的實現(xiàn)計劃。我會審閱這個計劃確保它和我的架構(gòu)理解一致。 然后讓它按步驟生成代碼。在每一步我都會重點檢查 * **路由文件**是否正確地引入了依賴錯誤處理中間件是否使用正確響應格式是否符合規(guī)范 * **服務層函數(shù)**密碼哈希的邏輯是否正確是否考慮了并發(fā)返回的數(shù)據(jù)結(jié)構(gòu)是否匹配 * **代碼風格**導入語句順序、命名規(guī)范、異步處理方式是否與項目現(xiàn)有代碼一致 如果在某一步發(fā)現(xiàn)偏差例如它可能用了一個舊的驗證庫而不是我們項目正在使用的Joi我會立即中斷并糾正“停。我們項目使用 Joi 進行請求驗證請參考 login.ts 中 validateLoginRequest 函數(shù)的寫法重寫注冊請求的驗證邏輯?!?### 4.3 步驟三驗證與收尾“擺盤”與“嘗味” 代碼生成后我的工作并未結(jié)束。 1. **靜態(tài)檢查**將生成的代碼放入IDE運行ESLint和TypeScript編譯器檢查是否有類型錯誤或風格問題。智能體有時會忽略一些邊緣的類型定義。 2. **邏輯復查**人工通讀代碼特別是業(yè)務邏輯部分。檢查密碼哈希、唯一性約束處理、JWT生成等關鍵環(huán)節(jié)是否正確無誤。 3. **集成測試**編寫或運行一個簡單的集成測試可以是手動調(diào)用也可以是簡單的測試腳本驗證API的完整流程。這是發(fā)現(xiàn)上下文理解偏差的最后一道防線。 4. **上下文歸檔**如果這個任務模式具有可復用性比如“添加一個標準的CRUD API”我會將這次成功的“上下文提示”作為一個模板保存下來下次類似任務只需做少量修改即可復用極大提升效率。 ## 5. 高級技巧應對復雜任務與避免常見陷阱 當任務從“炒個菜”升級為“籌辦一場宴席”例如重構(gòu)一個模塊或?qū)崿F(xiàn)一個包含多個交互組件的功能時簡單的線性提示就不夠了。 ### 5.1 分治與迭代不要試圖一口吃成胖子 對于復雜任務絕對不要試圖在一個提示里解決所有問題。采用“分治”策略。 * **第一步架構(gòu)設計對話**。提示智能體“我們需要實現(xiàn)一個帶實時通知的任務管理系統(tǒng)。請先給出一個高層次的技術架構(gòu)設計包括主要模塊、數(shù)據(jù)流和技術選型建議?!?基于它的建議進行討論和修正形成共識。 * **第二步契約先行**?;诠沧R讓智能體先定義核心的接口Interface、類型Type和數(shù)據(jù)傳輸對象DTO。例如“請根據(jù)上述設計先定義 Task, User, Notification 的TypeScript接口以及創(chuàng)建任務、更新任務狀態(tài)的DTO類型?!?* **第三步模塊化實現(xiàn)**。然后按照模塊逐個擊破?!艾F(xiàn)在請先實現(xiàn) TaskService 的核心方法包括 createTask, assignTask, updateTaskStatus。請確保它們符合你剛才定義的接口?!?每一輪都基于上一輪確定的、無歧義的“契約”進行確保上下文像搭積木一樣穩(wěn)步構(gòu)建而不是推倒重來。 ### 5.2 幻覺檢測與事實錨定 智能體的“幻覺”在復雜任務中尤為危險。對抗幻覺最有效的方法是“事實錨定”。 * **引用真實代碼**當討論現(xiàn)有代碼時不要描述而是直接粘貼相關代碼片段。例如不要說“我們的錯誤處理中間件是這么做的”而是說“請看現(xiàn)有的錯誤處理中間件代碼[粘貼代碼]請確保新的API使用相同的方式?!?* **要求提供出處**當智能體給出一個建議或陳述一個關于你項目的事實時比如“Prisma模型里有一個createdAt字段”可以要求它“請指出這個信息是基于我提供的上下文還是你的通用知識如果是基于我的上下文請引用相關部分。” 這能迫使它檢查自己的“記憶”減少信口開河。 * **交叉驗證**對于關鍵邏輯可以讓智能體從不同角度實現(xiàn)兩次或者要求它解釋代碼的每一行在做什么。解釋不通的地方往往就是幻覺或錯誤所在。 ### 5.3 上下文的版本管理與迭代 一個項目的“備料臺”不是一成不變的。隨著項目演進、技術棧升級、最佳實踐變化你的上下文模板也需要迭代。 * **建立上下文庫**為不同類型的任務CRUD API、數(shù)據(jù)遷移腳本、前端組件、配置部署文件建立標準化的上下文模板。 * **記錄失敗案例**當一次智能體交互因為糟糕的上下文而失敗時事后分析原因并更新對應的上下文模板補充當時缺失的關鍵信息或糾正誤導性描述。 * **團隊共享**在團隊中推廣這種“備料”文化并共享優(yōu)化后的上下文模板。這能極大統(tǒng)一團隊內(nèi)AI輔助編碼的輸出質(zhì)量減少因個人提示風格差異導致的代碼風格不一致問題。 ## 6. 工具化與未來展望將方法論沉淀為工作流 最高效的實踐最終都會沉淀為工具或固化的工作流。 * **提示模板化**使用像Cursor IDE的.cursorrules文件或是將精心設計的提示保存為代碼片段在需要時快速插入。 * **上下文文件化**為項目創(chuàng)建一個AGENT_CONTEXT.md文件存放項目的技術棧摘要、代碼風格公約、常用范例鏈接、以及常見任務的提示模板。新成員或新的智能體會話都可以以此為基礎。 * **與開發(fā)流程集成**在創(chuàng)建新的功能分支、或初始化一個新模塊時將“編寫智能體上下文提示”作為開發(fā)流程的第一步納入代碼審查的一部分。審查一個清晰的上下文提示往往能提前發(fā)現(xiàn)很多需求歧義和設計缺陷。 “Mise en Place for Agentic Coding”遠不止是一個酷炫的類比。它代表了一種思維模式的轉(zhuǎn)變從將AI智能體視為一個“許愿機”輸入模糊愿望輸出完美結(jié)果轉(zhuǎn)變?yōu)閷⑵湟暈橐粋€擁有強大執(zhí)行力的“專業(yè)協(xié)作者”。而作為人類開發(fā)者我們最核心、最不可替代的價值就在于成為那個**專業(yè)的“備料師”**——通過深思熟慮的上下文工程定義清晰的問題邊界提供精準的約束和素材從而將智能體的能力引導向正確、高效、可靠的方向。 這個過程本身就是對問題更深層次的思考和解構(gòu)它強迫你厘清需求、明確邊界、審視架構(gòu)。最終即使沒有智能體經(jīng)過這番“備料”思考后你自己去實現(xiàn)代碼的思路也會清晰數(shù)倍。這或許就是人機協(xié)同編程帶給我們的、超越工具本身的額外獎賞一種更嚴謹、更工程化的思維方式。