🎯 什麼情境該想到我

當你「要 LLM 產一個有結構的東西(圖、設定檔、報表、SQL、IaC),但沒辦法用肉眼一個一個檢查」的時候。

⚙️ 怎麼用(步驟 / 公式)

核心是一句話:不要讓模型產最終產物,讓它產 typed IR,最終產物由確定性的程式編出來。

模型 → typed IR(有 schema 的中介表示)→ 確定性編譯器 → 最終產物
                    ↓
              驗證閘(失敗回結構化診斷)
  1. 切開「判斷」與「計算」。把需要語義判斷的部分留給模型(該有哪些節點、誰接誰、什麼是主路徑),把可以精確算的部分交給程式(座標、間距、繞線、渲染)。模型不擅長的算術,就不要讓它算。

  2. 給 IR 一份 schema。有 schema 才能自動驗、才能明確告訴模型「欄位長什麼樣」,也才能給它一份範例——但要講清楚「範例是給你看欄位形狀,不是給你抄內容的」。

  3. 設分級的驗證閘,並明講哪一級才算通過。
    例:4 項檢查=基本驗證,9 項全過 + 0 錯誤 + 0 警告=可交付。不明講的話,模型會拿低標當通過。

  4. 失敗要回「修復收據」,不是堆疊追蹤。一份好的診斷要有三件事:

    • subject——出問題的確切那一項
    • evidence——量到的數值(不是「看起來怪怪的」)
    • supportedFixes——可用的修法清單(而不是讓模型自由發揮)

    然後在指令裡限制:只改被診斷的那一項、一次只套一個修正。

  5. 寫死收斂條件。例:「持續修正,只要客觀錯誤數還在創新低;若連續兩輪沒有刷新最佳值,就停下來、如實回報未解決的診斷。」

  6. 通過即凍結、交付要原子。驗證通過的產物不准再編輯;交付時先在私有快照上渲染檢查,通過才原子替換目標檔案,並回報 SHA-256 與 byte count。

★ 為什麼「讓模型直接產最終產物」是錯的

❌ 模型 → 最終產物(SQL、程式碼、設定檔、圖表、報告)
   ★ 你只能「看」它對不對 —— 而你看不出微妙的錯誤
   ★ 每次產出都不同,無法 diff、無法回歸測試
   ★ 錯了只能重新生成,不能修

✅ 模型 → typed IR → 確定性編譯器 → 最終產物
   ★ IR 有 schema → 可以「程式化驗證」
   ★ IR 是結構化的 → 可以 diff、可以存版控、可以手動修
   ★ 編譯器是確定性的 → 同一個 IR 永遠產生同一個產物

★ 核心洞察:把「無法驗證的創造」縮小成「可以驗證的一小步」,其餘交給確定性的程式。
模型負責「決定要什麼」,程式負責「正確地做出來」。

★ 驗證閘的層次(由便宜到貴)

層檢查什麼成本
① Schema結構對不對、欄位齊不齊、型別對不對★ 極低(約束解碼可以直接保證,見 Function Calling 與結構化輸出)
② 語義/業務規則引用的欄位存在嗎?數值在合理範圍嗎?狀態轉換合法嗎?低
③ ★ 執行編譯得過嗎?測試過嗎?查詢跑得動嗎?中——但這一層的訊號最強
④ 比對和既有的 golden output 比中
⑤ 人工/裁判主觀品質高(見 LLM-as-Judge)

★ 關鍵:驗證失敗時要回傳「結構化的診斷」而不是「失敗」。

{ "ok": false, "errors": [
    { "path": "$.filters[0].field", "code": "UNKNOWN_FIELD",
      "got": "user_nmae", "expected_one_of": ["user_name","user_id","email"] }
]}

★ 模型修正錯誤的能力,取決於錯誤訊息的品質。
validation failed → 它只能瞎猜;上面那種訊息 → 它幾乎一定能一次修對。
這和 工具-讓測試失敗訊息有用 是同一條原則。

★ 什麼任務適合(判準很明確)

✅ 適合❌ 不適合
★ 有明確的目標語言/格式(SQL、圖表、設定、API 呼叫)自由寫作、摘要
★ 產物的正確性可被程式檢查主觀品質(文案好不好)
★ 同樣的輸入該產生同樣的輸出需要創意多樣性
產物需要被版控與審查一次性的對話回應

典型應用:

自然語言 → 查詢 IR → SQL          (見 [[AI 系統設計框架]] 的 Text-to-SQL)
需求描述 → 圖表 IR → Mermaid/SVG
設定意圖 → 設定 IR → YAML/Terraform
資料需求 → 轉換 IR → dbt model

★ IR 該怎麼設計

原則說明
★ 比目標語言「窄」不要讓 IR 能表達 SQL 的全部——只支援你要支援的子集。
★ 窄 = 好驗證、好編譯、模型也比較不會亂寫
★ 用判別聯集每個節點有 kind,不合法的組合在型別上就不存在(見 工具-判別聯集)
可序列化JSON。可存、可 diff、可 review
★ 人可讀可改使用者要能手動微調 IR 而不是重新產生
扁平優於巢狀深層巢狀的 schema 會讓模型與約束解碼都變差

★ 「IR 比目標語言窄」是最重要的一條:

你不需要支援 SQL 的所有語法,只需要支援「使用者實際會問的那幾種查詢」。
窄的 IR 讓安全性(不會產生 DROP TABLE)、驗證、編譯全部變簡單。

★ 和相鄰概念的關係

概念關係
Function Calling 與結構化輸出★ 約束解碼保證「語法合法」,但不保證「語意正確」——IR 的驗證閘補上後者
GRPO 與 RLVR★ 同一個思路的訓練版:可驗證的獎勵
工具-把命令變成可驗證的目標同一條原則用在 agent 的目標設定上
直譯器模式IR 就是一個小 DSL 的 AST

🧪 我實際套用的紀錄

  • 2026-08-27:(待填)

⚠️ 注意 / 什麼時候不適用

  • ★ 編譯器本身要被測試。IR 對了但編譯器有 bug → 產物還是錯的,而且更難發現(因為你信任它)。
  • ★ IR 的表達力是天花板。IR 不支援的東西,使用者就做不到 → 要有「逃生口」
    (允許手寫原生語法,但標記為「未經驗證」)。
  • 不要讓 IR 太通用。變成「另一個程式語言」就失去了驗證的價值(見 直譯器模式 的警告)。
  • ★ 驗證失敗的重試要有上限。模型修不好就該回報給人,不要無限迴圈(見 ReAct 與 Agent Loop)。
  • schema 驗證通過 ≠ 內容正確。{"limit": 999999} 完全合法但可能是災難——業務規則要另外驗。
  • 這個模式有前期成本:要設計 IR、寫編譯器、寫驗證器。一次性任務不值得;
    ★ 它的價值在「同一類任務會重複很多次」。

🔗 相關工具