載入中

生產環境中的評估:CI、批次處理與漂移

第 4 課10 分鐘
載入中

生產環境中的評估:CI、批次處理與漂移

評估在發布後仍有工作要做。在每一次 pull request 中,它會在客戶收到錯誤答案之前,攔截破壞測試案例的提示變更。它也會為即時流量評分,以捕捉漂移——一種隨著真實輸入變化而出現的緩慢準確度下降。

本影片中的示範錄製於 2026 年 8 月。它在 Claude Haiku 4.5、Claude Sonnet 5 和 Claude Opus 5 上執行。較新的模型上結果會有所不同。每堂課的示範都是獨立的評估執行,因此其分數與成本不會與其他課程中的相符。

您的評估在發布後仍會持續執行,因為有兩件事一直在變化。 您的團隊會編輯提示,而一次編輯可能會破壞原本正確的答案。真實輸入也會變化,直到它們不再與您測試過的輸入相似。因此,評估會在每次編輯上線前執行,並在上線後對即時流量執行。

本課程以 Meridian 為例,這是一家虛構的工程顧問公司,其提示會讀取每月的專案報告,並回傳三個欄位:專案 ID、進度狀態和主要風險。Meridian 的評估有 50 個測試案例。每個測試案例是一份報告加上您預期的答案,全部 50 個合起來構成完整的評估套件。

這四個步驟讓 Meridian 的評估在發布後持續運作:

  1. 在每一次 pull request 上執行少量測試案例。
  2. 在通過之前,阻止 pull request 合併。
  3. 將完整套件作為一個批次執行。
  4. 每晚對即時流量的樣本進行評分。

在每一次 pull request 上執行少量測試案例

在 CI(持續整合的縮寫)中新增一個工作流程,讓它在每一次 pull request 上執行。 這個工作流程會執行一個煙霧評估,它只取完整套件中足夠少的測試案例,讓您可以等待它完成。它的分數會讓 pull request 上的檢查通過或失敗。Meridian 從其 50 個測試案例中挑選 10 個,以涵蓋每一種報告類型,並在大約一分鐘內於 Claude Haiku 4.5 上執行它們。

閾值是通過的最低分數,Meridian 的閾值是 88%,因此十個測試案例中必須有九個成功。這個工作流程依以下順序執行四項任務:

  1. 執行評估腳本,並將其回傳的結果儲存為 JSON。
  2. 根據閾值為這些結果評分。
  3. 在 pull request 上留言說明結果。
  4. 如果分數低於閾值,則讓檢查失敗。

Meridian 為此使用 GitHub Actions,但任何能夠執行您評估腳本的 CI 系統都可以完成同樣的四項任務。檔案本身位於下方的方框中。

載入中

在通過之前,阻止 pull request 合併

啟用一個分支保護規則,讓煙霧評估成為一項必要檢查,也就是一項必須在 pull request 可以合併之前通過的檢查。 這項規則屬於分支,而不屬於工作流程檔案,如果沒有它,紅色的 X 只是一個警告。

在 Meridian,一位工程師開啟了一個名為「簡化擷取提示」的 pull request,其中移除了兩條規則。其中一條告訴 Claude,當報告沒有給出主要風險時要回傳 null,另一條則要求 Claude 在回答之前引用風險所在的那一行。

這次執行得分 80%,低於 88% 的閾值。兩個失敗案例都是缺少風險的測試案例,即沒有風險段落的報告,因此每個案例都應該回傳 null,但 Claude 卻還是指出了一個風險。

pull request 上的一則 github-actions 留言:提示評估為 80%,10 個案例中有 8 個通過,低於 88% 的閾值,並列出了兩個失敗的缺少風險案例

這次煙霧評估得分 80%,未達 88% 的閾值,因為在兩個缺少風險的案例中,Claude 指出了報告中從未給出的風險。

這個紅色檢查讓合併按鈕保持灰色,而它的留言向工程師顯示了哪些案例失敗了:r041 和 r042。一旦提示修正並推送之後,檢查就會變成綠色,合併就可以繼續進行,因此從來沒有客戶看到過那個有問題的提示。

同一個 pull request 在修正之後:提示評估為 100%,所有檢查都已通過,合併按鈕已啟用

修正之後,每個案例都以 100% 通過,因此合併不再被阻擋。

將完整套件作為一個批次執行

每當您變更提示或模型時,執行完整套件,並透過 Batch API 傳送它。 Meridian 的評估會比較 Haiku 4.5、Claude Sonnet 5 和 Claude Opus 5,因此其批次包含 150 個請求,每個模型都有全部 50 個案例。Batch API 會以輸入與輸出 token 通常價格的一半執行所有這些請求,而您可以稍後收集答案,通常在一小時內。

ModelStandard priceBatch API price
Haiku 4.5$0.0468$0.0234
Sonnet 5$0.1301$0.0650
Opus 5$0.3432$0.1716

截至 2026 年 8 月,針對 Meridian 50 個案例在每個模型上執行一輪的標準價格與 Batch API 價格。今日價格。

將沒有人等待的請求批次處理,而在有人等待的地方使用標準請求。只有合併會等待的煙霧評估,才會繼續使用 client.messages.create(...)。

評估腳本需要做兩項變更。

用 custom_id 為每個請求加上標籤。 結果可能以任意順序抵達,因此您要用這個標籤來比對它們,而且它在批次中必須是唯一的。每個案例會送到三個模型,因此請將案例 ID 與模型連接起來,例如 r041_claude-haiku-4-5。

python
batch = client.messages.batches.create(
    requests=[
        {
            "custom_id": f"{case['id']}_{model}",
            "params": {
                "model": model,
                "max_tokens": 1024,
                "messages": [{"role": "user", "content": case["prompt"]}],
            },
        }
        for model in MODELS
        for case in CASES
    ]
)

在評分之前先讀取 request_counts。 它會計算各種結束方式的請求數量,藉此顯示何時一次執行的結果不完整。24 小時內未完成的批次會過期,而過期的請求不會產生費用,但也不會有答案。

python
batch = client.messages.batches.retrieve(batch.id)
print(batch.request_counts)

answers = {}
for result in client.messages.batches.results(batch.id):
    if result.result.type == "succeeded":
        answers[result.custom_id] = result.result.message

每晚對即時流量的樣本進行評分

每晚對一小部分即時流量,也就是您應用程式處理的真實請求,進行評分。 完整套件只知道您在建置時所擁有的報告,因此如果有新客戶開始傳送一種您的案例都沒有涵蓋的格式報告,即使答案變差,您的 CI 仍會保持綠色。這種緩慢的準確度流失就是漂移。

做法如下:

  1. 取樣。 從即時流量中挑出 1% 到 5% 之間的部分。
  2. 用 LLM 評審為樣本評分。 這是第二個模型,它會根據一套書面規則的評分標準來為每個答案評分,只使用報告、Claude 的答案和評分標準,因此不需要即時流量所缺乏的預期答案。不過,您仍要時不時親自閱讀幾個答案,因為評審也需要由人來檢查。
  3. 只在真正下滑時發出警示。 也就是某一晚的分數低於近期各晚平均值(稱為追蹤基準線)超過兩個標準差的情況。兩個標準差比正常一晚會帶來的變化還要大。
  4. 將評審標記為不正確的每個答案製作成一個案例。 寫下它的預期答案,然後將該案例加入完整套件,因為來自真實失敗的案例能讓套件貼近真實使用情況。

即時流量會顯示完整套件遺漏了什麼,而您加入的每個失敗案例都會縮小這個落差。請將 1% 到 5% 和兩個標準差視為起點,依您自己的流量進行調整。

重點總結

  1. 讓煙霧評估在每一次 pull request 上執行,並讓它的分數來決定檢查通過或失敗。
  2. 將該檢查設為必要,這樣低分才會真正阻止合併。
  3. 將完整套件作為批次執行,這樣只需花費一半的成本,因為沒有人在等待它。
  4. 每晚對即時流量的樣本進行評分,當分數下降幅度超過平常時發出警示,並將每個失敗案例轉變成完整套件中的新案例。