
做 AI 工程落地的人可能都有同感模型效果一不好第一反應永遠是“改 prompt”第二反應是“換模型”但很少有人先問一句——這個功能的驗收標準是什么當初為什么這么設計如果項目里的文檔只停留在“接口文檔”和“產品 PRD”那 AI 項目跑得越久越容易變成一座沒人敢動的黑箱。這也是我寫“AI 開發文檔驅動實踐”系列的原因。上一篇聊了從 idea 到原型怎么用文檔梳理需求這一次我們把視角拉長聊聊工程流交付怎么讓文檔成為 AI 項目從開發、評估到上線運維的主線而不是可有可無的附件。剛做 AI 項目時我也覺得文檔驅動是“敏捷開發的反動派”寫著寫著就變成負擔。直到一個做了半年的客服工單分類項目換個人就無法迭代時我才意識到AI 項目里最貴的不是 GPU不是 API 調用費而是丟失的上下文。一個 prompt 為什么加某句話、一個評估集為什么刪掉某條樣本、一個 agent 為什么只暴露三個工具這些背景如果不落在文檔里所有經驗都會慢慢蒸發。下面這些內容來自我真實踩坑后的實踐希望能對正在把 AI 能力往生產環境推的朋友有點用。它不適合那種 demo 完了就走的活動項目而更適合要維護半年以上的 AI 產品。1. 為什么 AI 項目特別需要文檔驅動1.1 AI 的交付物不只是代碼而是“可運行的經驗”傳統軟件開發里代碼是穩定、可測試、可評審的文檔更多是“事后補充”。但 AI 應用不一樣一個完整的交付物至少包含四樣東西模型或 API 配置、prompt 模板、評估數據集、以及編排這些組件的代碼。更關鍵的是其中 prompt 和評估集的改動往往比代碼更頻繁而且很難用“單元測試”把所有問題都守住。舉個例子你寫了一個客服工單分類 prompt要求模型“如果工單語氣比較急優先判斷為高優”。這句話在代碼里只占一行但它背后的業務邏輯是歷史上發生過“用戶罵了幾句但其實是咨詢”的樣本導致高優誤判率飆升。如果沒有文檔記錄這條經驗三個月后另一個同事看到這個 prompt大概率會直接刪掉“語氣比較急”這半句理由是“太主觀”。于是模型回歸線上投訴暴增。所以 AI 項目的文檔驅動核心不是“寫文檔給審計看”而是把團隊的判斷和上下文沉淀下來讓每一次 prompt 改動、模型升級、工具增刪都有依據。這種文檔不是解釋代碼的注釋它本身就是交付物的一部分。1.2 什么樣的文檔才叫“能驅動工程的文檔”很多人一聽文檔驅動下意識想到一個 wiki 系統里面堆滿幾十篇沒人看的文章。我在工程流里對文檔只有三個硬性要求可版本化、可執行、可解釋。可版本化意味著文檔跟著代碼走用 git 管理改一個條件、加一條評估樣本都能 diff 出來??蓤绦幸馕吨臋n里的接口定義、評估用例、模型參數可以被腳本直接讀取用來生成測試代碼或者跑回歸??山忉寗t要求每條關鍵決策都寫明“為什么這樣做”“當時有哪些選擇”“放棄了什么”。這樣的文檔才是活的否則只是又一份靜態文檔。我推薦用 Markdown Git 倉庫來維護而不是放到企業 wiki。原因很直接wiki 的編輯權限往往太寬松誰都能改但沒有版本回退意識而 Git 天然適合多人協作每個改動都有作者、有時間、有理由還能和 issue、MR 關聯起來。1.3 文檔驅動真正解決的是“知識斷層”做 AI 項目的團隊很容易出現一個怪圈模型效果好時大家不愿意動文檔覺得“反正能跑”模型效果變差時大家又忙著調參更沒時間寫文檔。結果就是項目啟動三個月后唯一完整的文檔是產品和運維一起寫的部署手冊而 prompt 怎么設計、數據清洗規則是什么、評估集怎么來的全都散落在聊天記錄和個人筆記里。文檔驅動能有效緩解這個問題。它迫使團隊在每個里程碑結束前把當時的方案、實驗結果、階段性結論寫下來哪怕只有半頁紙。這樣做的好處是新人接手時不用靠“口口相傳”模型劣化時能快速回退到某個已知 good 的版本業務方提出新需求時也能直接用舊文檔作為需求討論的錨點。我見過太多項目死就死在“會做的人走了解釋沒人懂”文檔驅動就是給項目上的一道保險。2. 工程流交付的文檔體系2.1 第一層業務需求如何轉成 AI 任務定義工程流交付的第一步是把業務語言翻譯成 AI 可執行、可評估的任務定義。很多團隊在這里就翻車了比如只寫“提高客服效率”完全沒定義輸入輸出導致后面既沒法做 prompt也沒法做評估。我常用的模板是四段式業務背景、任務公式、約束條件、評估方式。以工單自動分類為例維度內容業務背景客服系統每天約 3000 張工單需要人工按 8 個類目分配部門平均耗時 2 分鐘任務公式輸入是工單標題描述文本輸出是 1 個或 2 個預定義類目標簽約束條件單次推理延遲小于 800ms必須支持中英文混排錯誤標簽不能把投訴單分到咨詢類評估方式精確匹配準確率Top-1 和 Top-2、人工抽檢通過率、高優工單的召回率這份文檔不用寫得很長但一定要讓一個沒參加過前期討論的工程師看完就能明白“到底要建一個什么 AI 能力怎么驗證它做得好不好”。后面所有 prompt、代碼、評估集都圍繞這份任務定義展開。2.2 第二層技術方案和架構決策記錄ADR接下來是技術選型和架構層面的決策記錄。這一層最容易被忽視但它恰恰是將來返工成本最高的一環。舉個例子項目初期為了快速出 demo直接調用云端大模型 API等上線后要求數據不出內網才被迫換成本地部署的小模型。如果一開始在 ADR 里寫清楚“數據安全等級較高必須支持私有化部署”這個約束選型就不會走彎路。ADR 的寫法可以很輕量不需要重型的架構設計文檔。通常包含五個部分背景、決策、理由、替代方案、影響。我建議固定成一個簡單的 Markdown 模板存在 docs/adr/ 目錄下編號管理# ADR-003客服工單分類采用自部署小模型方案 ## 背景 業務要求數據不出內網云端大模型 API 無法滿足合規要求。 ## 決策 采用本地部署的通義千問或 Qwen 系列 7B/14B 模型通過 vLLM 提供 OpenAI 兼容接口。 ## 理由 - 數據不出內網滿足安全要求 - 7B/14B 在工單分類這類文本任務上已能接近 GPT-4 的基線準確率 - 單卡 A10 可承載線上流量成本可控 ## 替代方案 - 繼續使用云端 API被合規否決 - 使用更小的 1.8B 模型準確率差 6 個百分點不可接受 ## 影響 - 需要一個 GPU 節點運維復雜度增加 - prompt 風格需適配本地模型部分指令理解能力弱于云端模型 - 后續模型升級需重新跑評估集這類 ADR 的價值在于它把一段歷史判斷固定下來未來任何人看到模型選型都能知道“當時為什么沒有選另一個方案”。如果你用的 AI 編程工具能讀取 docs/adr/ 下的內容它生成的代碼也會更貼合項目的技術約束。2.3 第三層接口契約與 Prompt 版本說明第三層是技術契約層包括 API 接口定義、數據結構、prompt 模板和 agent 工具定義。這一層是和代碼結合最緊密的文檔也是最容易做到“從文檔生成代碼”的地方。以 Spring AI 為例Java 服務里通常會定義一個工具方法和一個 prompt 模板。接口契約文檔可以這樣寫## 工具create_ticket_classification 功能將工單文本分類并返回類目編碼 入參 - text: string工單正文 - history: string[]聊天歷史可選 出參 - category: string枚舉[BILL, TECHNICAL, COMPLAINT, CONSULT, OTHER] - confidence: number0-1 之間的置信度 錯誤處理入參為空時返回 error.code EMPTY_TEXT有了這份契約AI 編程工具在生成 Spring Boot 的 Controller、Service 和 DTO 時就不會自己發明類目名稱或參數結構。你會發現“文檔驅動”在 AI 編程場景里不是一句口號而是實實在在的約束手段——把 prompt 和接口的規則喂給 AI它能少發揮不少。同樣prompt 模板也要版本化。我不建議直接在代碼庫里放一個prompt.txt完事最好加上變更說明# prompt: 工單分類 v2.1 更新日期2025-06-18 變更人xxx 變更原因v2.0 對“退款失敗但語氣平和”的工單誤判為咨詢類補充了“已發生交易問題”的判定條件。2.4 第四層評估報告與回歸基線最后一層是質量觀測層也是工程流交付能不能“閉環”的關鍵。AI 項目的質量標準不能靠感覺。我要求每個版本至少產出一份評估報告內容是評估集版本、測試樣本數量、各項指標數據、與上一版本的對比、異常樣例分析。這里要特別說一句評估報告不是只在發版前做一次而是每次 prompt 或模型改動后都要跑。一個小技巧是把評估報告直接提交到倉庫里的 docs/eval/ 目錄文件名帶上版本號比如eval_report_v2.1.md。這樣 git log 就自動變成了一條“效果趨勢圖”哪次改動讓準確率掉了一目了然。3. 從需求到交付一個完整的實操流程3.1 第一步用 Context Spec 錨定項目上下文很多 AI 項目的失敗不是模型不夠強而是上下文沒有對齊。我建議每個項目在啟動時先寫一份 Context Spec上下文規格放到docs/context.md。它比 PRD 輕但比會議紀要重核心目的是讓“人、AI 編程工具、模型”使用同一套背景知識。一份 Context Spec 至少包含以下幾塊項目背景為什么做這個功能期望解決什么問題目標用戶誰在用使用場景是什么數據樣例5-10 條真實輸入輸出展示邊界情況禁忌項明確不要做什么比如“不要生成不屬于 8 個類目的新類目”已確認的評估指標準確率、召回率、延遲、成本上限等寫完 Context Spec 之后后續所有 prompt 優化、代碼生成、測試用例設計都引用這份文檔避免每次開會或者改代碼時重新對齊背景。3.2 第二步讓 AI 編程工具按文檔生成代碼如果你已經在用 AI 編程工具比如 IDE 里的 AI 插件或者 Spring AI 等框架可以嘗試“文檔即提示詞”的姿勢。把接口契約和 Context Spec 喂給 AI 工具然后讓它生成代碼。不用每次都把背景重新輸入一遍工具會把上下文帶入后續對話。以生成一個工單分類 REST 接口為例我在 Java 工程里會這樣下指令根據 docs/context.md 中的任務定義以及 docs/contracts/ticket_classification.md 中的接口契約生成 Spring Boot Controller 和 Service 實現。方法簽名不要修改請求和響應 DTO 字段按照契約定義。模型推理走本地的 OpenAPI 兼容端點。這樣生成的代碼至少能保證結構符合約定類目枚舉不會寫錯錯誤處理也能對應得上。當然AI 生成的代碼仍然需要人工 review但至少省掉了大部分重復勞動。3.3 第三步評估集歸入版本庫prompt 改動必須綁定報告我在團隊里定了一條鐵律不允許“改完 prompt 口頭同步”。任何 prompt 改動必須附帶一次評估結果。評估集放在 git 倉庫里可以是 JSON Lines 或者 CSV每條樣本標注好“期望輸出”和“是否作為回歸關鍵項”。常見結構data/eval/ golden_v1.jsonl golden_v1.1.jsonl regression_v2.jsonl docs/eval/ eval_report_v2.1.md跑評估的腳本單獨維護注意不要一次性把所有測試樣本全塞給模型那樣成本太高。CI 里跑一個小的 smoke test比如 20 條關鍵樣本完整評估放到發版前或每天晚上跑一次。改 prompt 的時候把變更內容寫進報告的“變更說明”里。比如版本變更點準確率高優召回率備注v2.0初始版本87.2%91.0%基線v2.1增加“已發生交易問題”判定88.5%92.3%誤判減少延遲無波動v2.2將“語氣過激”權重降低87.8%90.1%高優召回下降回滾這種表一旦長期維護下來幾乎就是項目的“AI 效果賬本”誰改了什么東西、帶來了什么影響一筆一筆都清清楚楚。3.4 第四步部署模型時模型卡與運行時配置缺一不可模型部署不是“把接口起起來”就完事。真正進入工程流交付我要求每個部署單元必須附帶一張模型卡Model Card記錄模型來源和版本比如 Qwen2.5-7B-Instructprompt 模板版本部署時綁定的那份依賴環境Python 版本、推理框架、CUDA 版本推理超參溫度、top_p、max_tokens、并發數觀測指標請求量、延遲分位數、token 用量、成本預估這張模型卡最好寫成MODEL_CARD.md放在項目倉庫里和部署配置Dockerfile、K8s deployment放一起。你看這就把文檔驅動延伸到了運維側任何一個人看到這張卡就能回答“線上這個服務到底是什么模型、用的什么 prompt、資源夠不夠”這些最常見的問題。另外一定要關注成本觀測。我見過不少團隊上線后只盯準確率結果月底收到云賬單才發現成本超了預算五倍。所以在模型卡里寫上“每千次請求成本預估”并且通過日志統計真實 token 消耗是文檔驅動在成本治理上的一個延伸。4. 常見問題與排查技巧實錄4.1 文檔和代碼脫節過兩周就沒人維護了這個問題幾乎每個團隊都會遇到。我的解法不是靠自覺而是靠自動化。在 CI 里加一個文檔檢查任務內容包括Markdown 格式規范檢查markdownlint文檔中引用的文件路徑是否存在接口契約里定義的數據結構是否有對應的代碼類如果使用 OpenAPI 規范可以用腳本對比生成代碼和 spec 是否一致一旦某個文件引用了不存在的路徑或者 OpenAPI 定義改了但沒有更新接口文檔CI 直接失敗。這樣能把“文檔過期”的問題擋在合并代碼之前。4.2 新人不理解評估集隨便往 golden set 里加樣本評估集是 AI 項目最敏感的資產。很多人會隨手把線上新出現的一條樣本加進測試集然后發現指標“變好”了其實只是模型見過類似的內容。我的做法是評估集不直接往 master 提交所有新增樣本必須走 MR并且要有“為什么加這條”的說明。比如“某用戶反饋投訴單被分到咨詢類補充該場景回歸”。這樣至少能保證每一條樣本都有業務來源而不是拍腦袋。4.3 模型輸出不符合 JSON 格式導致下游解析崩潰這可以說是生產環境里最經典的問題了。文檔驅動的價值在于在契約文檔里明確約定輸出格式并且在代碼里做校驗和重試不能只靠 prompt“保證”。實操中我會讓模型首先輸出一個寬松的文本然后用代碼做后處理或者要求模型通過 function calling 方式返回結構化參數。對于自部署模型建議在推理服務層加一層 response schema 校驗不符合就重試一次還不符合就記一條異常日志。這些規則也要寫進文檔不然下次換上另一個模型問題會反復出現。4.4 多個模型對比時團隊內部爭論“誰更好”文檔驅動不解決模型效果本身的問題但它能規范對比方式。我建議所有模型對比都基于同一個評估集、同一份抽樣標準并且做“盲評”把模型 A 和模型 B 的輸出結果隨機打亂讓人工 reviewer 只評價“是否達到了期望效果”不評價“是誰生成的”。這樣能極大減少“我覺得新模型更像人”這類主觀干擾。4.5 AI 寫文檔寫得很像但它可能是幻覺現在很多團隊用 AI agent 輔助生成文檔效果很驚艷但也帶來了新風險AI 編造數據集、編造“最佳實踐”、甚至編造不存在的依賴版本。我在文檔驅動里有一條原則AI 生成的文檔只能作為初稿必須由人工標注“經過核驗”并在文檔頭部注明日期和審核人。對于技術決策類文檔AI 最多做資料整理不能替代 ADR 的最終決策記錄。5. 工具鏈與落地配置參考5.1 文檔倉庫怎么搭我習慣一個 AI 工程服務對應一個 Git 倉庫根目錄下docs/結構如下docs/ context.md # 上下文規格 adr/ # 架構決策記錄 0001-intro.md contracts/ # 接口契約、prompt 模板、工具定義 ticket_classification.md eval/ # 評估報告 eval_report_v2.1.md MODEL_CARD.md # 模型卡配合.markdownlintrc做格式約束pre-commit 鉤子里加上 markdownlint 和鏈接檢查。如果你想可視化瀏覽這些文檔可以用 MkDocs 或 Docusaurus但純 Git 倉庫也已經夠用。5.2 從文檔生成 prompt 和代碼的姿勢在 Spring AI 項目里可以把docs/contracts/下的內容直接作為知識庫提供給 agent讓它在生成代碼時參考。也可以手動在 AI 編程工具里指定“先讀這個文件再開始編碼”。另一個實用技巧是把常用 prompt 模板放到src/main/resources/prompts/目錄Spring AI 運行時加載這樣 prompt 能跟著 jar 包發布避免線上還在用本地改過的臨時 prompt。你要保證“線上跑的 prompt 文檔里記錄的 prompt”最穩妥的方式就是讓模型卡記錄資源文件版本部署時校驗哈希值。5.3 CI/CD 里的“質量門禁”我在 GitLab CI 里通常會加這幾個 jobstages: - doc-check - test - eval-smoke - deploy doc-check: stage: doc-check script: - markdownlint docs/**/*.md - python scripts/check_links.py docs/ - python scripts/validate_contracts.py docker-compose.yml eval-smoke: stage: eval-smoke script: - python scripts/run_eval.py --subset golden_smoke.jsonl artifacts: paths: - docs/eval/latest_report.md請注意不要在每次提交時都跑完整評估集成本太高。把完整評估放到定時任務或者發版前手動觸發CI 只保證“核心樣本不劣化”。5.4 可選本地模型部署時的最小配置如果你的項目需要私有化部署模型可以用 vLLM 起一個 OpenAI 兼容服務模型卡里記錄參數。推薦配置示例vllm serve Qwen/Qwen2.5-7B-Instruct \ --host 0.0.0.0 \ --port 8000 \ --max-model-len 8192 \ --gpu-memory-utilization 0.9 \ --served-model-name ticket-classifier部署之后所有調用方都走統一的/v1/chat/completions接口prompt 模板由業務服務讀取這樣文檔、代碼、模型三者就能對得上。如果你用的是 OpenAI 等云端 API模型卡上就寫 “cloud provider model name temperature max_tokens”邏輯一樣。6. 最后分享兩個小技巧文檔驅動不要理解成“文檔越多越好”。真正有用的文檔是能回答“為什么”和“怎么驗證”的那幾份。我建議你從最小集開始一份 Context Spec、一份模型卡、一個 golden set。三個東西加起來可能不超過十頁但足以讓一個新人快速接手項目。另外一個很個人的經驗每當有人跑來問我 prompt 為什么這么寫我不直接回答而是給他一個命令git log --follow -p -- src/main/resources/prompts/ticket_classification_v2.txt。讓他在 git 歷史里找到當初的變更說明比當面解釋十遍都有效。當團隊習慣了從文檔和 git 歷史里找答案文檔驅動才算真正落地了。