免費全文 工具與工作流 進階

把 AI 功能寫成可測試的程式:假模型與快照測試

每次跑測試都真的呼叫模型,既慢又貴又不穩定。有更好的做法。

工具與工作流教程封面

AI 功能的測試困境是:輸出不確定、呼叫要花錢、速度慢。解法是把「呼叫模型」隔離成一個可替換的介面。

抽出介面

from typing import Protocol

class LLM(Protocol):
    def complete(self, prompt: str, **kw) -> str: ...

class FakeLLM:
    def __init__(self, responses): self.responses, self.calls = responses, []
    def complete(self, prompt, **kw):
        self.calls.append(prompt)
        return self.responses.pop(0)

def classify(text, llm: LLM):
    raw = llm.complete(PROMPT.format(text=text))
    return json.loads(raw)

三層測試

  1. 單元測試(假模型):測解析、驗證、錯誤處理、重試邏輯。快、免費、可在 CI 跑。
  2. 快照測試(錄製回放):第一次真的呼叫並存下回應,之後回放。介面改動時能發現差異。
  3. 線上評測(真呼叫):只在發布前跑,用固定評測集,數量控制在幾十題。

假模型要涵蓋失敗情境

def test_handles_bad_json():
    llm = FakeLLM(['這不是 JSON', '{"type":"oom"}'])
    assert classify('...', llm)['type'] == 'oom'   # 第一次失敗後重試成功
    assert len(llm.calls) == 2

實務上最常出問題的不是模型,而是「模型回了奇怪東西時你的程式怎麼辦」。這一層完全可以用假模型測到。

CI 不要打真 API

把真呼叫的測試標記起來,只在特定情況執行。CI 每次 push 都打模型,帳單與不穩定的失敗會很快讓團隊關掉測試。

把每次線上評測的結果存成檔案並提交。程式碼審查時能直接看到「這次改動讓分數如何變化」。
下一步

這個主題還有更深入的實戰教程

VIP 專區收錄 50 篇進階內容:架構設計、生產環境取捨、成本與合規。 每週五新增 3 篇。

看訂閱方案 → 先逛逛 VIP 專區