最近在用 AI coding agent 開發功能的時候,踩了一個讓我差點翻桌的坑——它很認真地、很自信地,幫我生成了一整組資料庫根本不存在的欄位。
事情是這樣的
我們的專案架構是 .NET Core + React,後端有一套 DataModel 層負責對應資料庫 schema。開發流程中,我把幾個功能需求丟給 AI coding agent 去實作,包含一些查詢頁面的改進。
需求本身不複雜:幾個列表頁面需要顯示額外的資訊,像是操作人員名稱、時間戳記之類的。聽起來很直覺對吧?
然後災難就開始了。
它到底做了什麼
AI agent 拿到需求後,非常積極地開始工作。它分析了現有的程式碼結構,理解了我們的 DataModel pattern,然後——自己決定資料庫裡「應該」有哪些欄位。
它無中生有了這些東西:
ValidOperatorId、AcceptOperatorId、EndOperatorIdValidTime、AcceptTime、EndTimeCreatorName、PermitterName、EndOperatorName
看起來很合理對吧?命名規範也很標準。問題是:這些欄位在資料庫裡根本不存在。
更可怕的是,它不只改了 DataModel。它順著整條鏈路一路往上改:
- DataModel — 加了假欄位的 property
- SQL Query — 寫了 SELECT 這些不存在欄位的查詢
- BLL(Business Logic Layer) — 用這些假欄位做邏輯判斷
- DTO — 把假資料往前端送
整條鏈路都被汙染了。如果沒有 code review 直接合併,上線後就是一連串的 SQL error。
為什麼 AI 會這樣做
這其實是 LLM 的經典問題——幻覺(hallucination)。
AI agent 看到了現有的 DataModel 結構,理解了命名慣例(我們的欄位確實有類似的 pattern),然後根據需求「推理」出資料庫裡應該有這些欄位。它的邏輯鏈是:
- 需求要顯示操作人員名稱 ✓
- 現有 DataModel 有類似的 Operator 欄位 ✓
- 所以資料庫裡「一定」有
ValidOperatorId這種欄位 ✗
第三步就是幻覺。它沒有能力去驗證資料庫 schema,所以只能靠推理。而推理的結果,看起來很合理,實際上完全錯誤。
這跟你問 ChatGPT 一個它不確定的問題,它會很自信地給你一個聽起來正確但完全編造的答案,是一模一樣的機制。只是這次它編造的不是知識,是程式碼。
我們的防線:自動生成機制
好在我們早就預料到這類問題,所以在架構上設了一道硬防線。
我們的 DataModel 層有一個鐵規矩:所有 DataModel 只能由自動生成工具產出,絕對不能手動修改。
具體來說,我們有一個 RenewDalController 提供兩個 API:
POST /aux/renew/dal/db— 從資料庫 schema 直接生成 DataModelPOST /aux/renew/dal/file— 從 SQL query 檔案生成對應的 Model
這意味著 DataModel 永遠是資料庫的真實映射。你不可能在 DataModel 裡加一個資料庫沒有的欄位,因為下次重新生成就會被覆蓋掉。
這個機制在沒有 AI 的時代就已經存在了——當初是為了防止人類開發者手動改 DataModel 造成不一致。沒想到現在最大的受益場景,是防止 AI 幻覺。
修復過程
發現問題後,處理方式其實很直接:
- 把所有 AI 生成的假欄位全部清掉
- 用
RenewDalController重新生成正確的 DataModel - 在 BLL 層改用資料庫中實際存在的欄位來實現同樣的功能
- 把整個 branch 的 commit 做 squash,清理掉汙染的歷史
說實話,功能本身不難實現。資料庫裡有其他欄位可以達成同樣的目的,只是 AI 沒有去查,而是自己編了一組「看起來更漂亮」的欄位名稱。
從這次經驗學到的事
1. AI 最危險的不是寫錯,是寫得「很像對的」
如果 AI 寫出明顯的語法錯誤,反而好辦——build 就會擋住。真正危險的是這種「語法正確、邏輯合理、但事實錯誤」的輸出。它通過了所有靜態檢查,code review 時如果不夠仔細,很容易就放行了。
2. 架構層面的防線比人工 review 更可靠
我們的自動生成機制就是一個好例子。不管是人還是 AI 寫的程式碼,只要違反了「DataModel 必須自動生成」這個規則,就會在下次生成時被修正。這種架構層面的約束,比「記得要 review」強太多了。
3. AI agent 需要存取資料庫 schema 的能力
這次的根本問題是 AI agent 無法驗證資料庫結構。如果它能查詢 DB schema,就不會幻覺出不存在的欄位。這給了我一個方向:以後在設定 AI coding agent 的工作環境時,應該把資料庫 schema 的查詢能力納入它的工具集。
flowchart LR
A[AI Agent 收到需求] --> B{能查 DB Schema?}
B -->|否| C[根據程式碼推理欄位]
C --> D[幻覺風險 ⚠️]
B -->|是| E[查詢實際 Schema]
E --> F[生成正確 DataModel]
F --> G[安全 ✅]
D --> H{有自動生成防線?}
H -->|是| I[下次生成時修正]
H -->|否| J[汙染上線 💀]
4. 不要因為一次踩坑就否定 AI 輔助開發
這很重要。我看到不少人因為 AI 寫出 bug 就說「AI 寫程式不靠譜」。但人類開發者也會寫 bug,也會記錯欄位名稱,也會假設資料庫有某個欄位。差別在於 AI 犯錯的模式跟人不一樣,所以我們需要針對 AI 的錯誤模式建立對應的防線。
給同樣在用 AI 輔助開發的人
幾個實際的建議:
- 建立不可手動修改的自動生成層:DataModel、API client、型別定義這些跟外部系統對接的程式碼,盡量用自動生成。這是防幻覺最有效的手段。
- 讓 AI 能存取它需要的事實來源:資料庫 schema、API 文件、型別定義。減少它需要「猜」的範圍。
- 特別注意「跨層汙染」:AI 不只會在一個檔案犯錯,它會順著程式碼結構一路錯下去。review 時要追蹤整條鏈路。
- build 是最低標準,不是最終防線:能 build 過不代表邏輯正確。SQL query 裡查了不存在的欄位,build 是抓不到的。
寫在最後
AI coding agent 是我目前用過最強大的開發輔助工具,這點毫無疑問。但「強大」跟「可以無腦信任」之間還有一段距離。
這次的經驗讓我更確信一件事:AI 輔助開發的關鍵不是 AI 有多聰明,而是你的架構有多健壯。好的架構能讓 AI 的錯誤被快速發現和修正,壞的架構會讓 AI 的錯誤悄悄滲透到每個角落。
說到底,這跟管理人類團隊是一樣的道理——你不能期待每個人都不犯錯,但你可以建立一個犯錯後能快速修正的系統。
如果你也在用 AI 寫程式,希望這篇血淚能幫你少踩一個坑 😂