別再靠感覺選模型:用 Promptfoo 把 LLM 應用的評測、紅隊與 CI 變成可重跑流程
LLM 應用最難維護的,往往不是把模型接上,而是回答品質一變差時,你能不能快速知道原因。Promptfoo 把 prompt、模型、測試案例、評測斷言與紅隊掃描收進同一套 CLI/library 流程,讓模型比較、回歸測試與安全檢查可以在本機重跑,也能接到 CI/CD。本文從一個可落地的評測流程開始,拆解它適合解決的問題、導入步驟與不能忽略的限制。
別再靠感覺選模型:用 Promptfoo 把 LLM 應用的評測、紅隊與 CI 變成可重跑流程
我認為,LLM 應用從 prototype 走到 production 之後,最先暴露的通常不是「模型不夠聰明」,而是團隊沒有一套穩定的方式回答三個問題:這次改動有沒有讓回答變好?它是不是只在少數案例變好?安全性與成本是否因此變差?如果每次都靠人工打幾個 prompt、看幾個結果,再憑印象決定要不要合併,這個流程很快就會失去可重現性。
Promptfoo 是一個開源的 CLI 與 library,定位是評估與 red teaming LLM 應用。它把 prompt、provider、測試資料、assertion,以及結果檢視整合在同一個工作流中;官方文件也提供 CI/CD、code scanning 與 vulnerability scanning 的入口。對我來說,它最值得注意的地方不是「又一個 prompt 工具」,而是它把原本散落在聊天視窗、試算表與人工審查中的判斷,逐步變成可以版本控制、可以重跑、可以在 Pull Request 中檢查的工程資產。
先講結論:Promptfoo 解決的是「變更之後,如何相信結果」
如果你的團隊只是偶爾比較兩個模型,直接呼叫 API 再人工閱讀輸出,Promptfoo 可能顯得太正式。但只要應用開始有多個 prompt、多個模型、不同供應商、固定業務案例,或每次部署都可能改變輸出,就需要把「評測」從一次性實驗提升成回歸測試。
Promptfoo 的基本單位可以理解成四層:
- Prompts:要測試的提示詞,可以是內嵌文字,也可以放在檔案中。
- Providers:要比較的模型或 LLM API。官方文件展示了 OpenAI 等 provider,也支援更多模型服務與本機模型整合。
- Tests:輸入變數與預期條件,讓同一批案例可以重複跑。
- Assertions:對輸出做判斷,例如是否包含某段文字、是否符合結構、是否通過模型評分,或是否觸發安全性條件。
這四層的價值在於,模型不再是唯一被評估的東西。你可以固定同一批測試案例,比較不同 prompt;也可以固定 prompt,比較不同 provider;更可以把輸出品質與安全檢查放到同一個變更流程裡。當結果變差時,至少有一個可追溯的差異,而不是只剩下「我覺得新版比較怪」。
為什麼傳統的人工試 prompt 很快會失效
人工測試不是沒有價值,問題是它很難成為唯一的品質門檻。第一個問題是案例漂移:今天測的是三個簡單問題,下一次換了資料來源、語言或上下文,卻還拿今天的印象當作判斷。第二個問題是比較不公平:如果不同模型看到的 prompt、參數或輸入不完全相同,最後的優劣很可能只是測試設計造成的。
第三個問題是負面案例常被忽略。正常使用者問「請摘要這篇文章」時,所有模型看起來都不錯;但當輸入混入越權要求、敏感資料、提示注入或不完整條件時,差異才會浮現。第四個問題是部署節奏:人工檢查可以幫你發現一次問題,卻不會自動在下一次 commit 時重現同一個檢查。
因此,我會把 Promptfoo 放在「模型呼叫」與「產品測試」中間。它不是取代產品端的整合測試,也不是保證模型永遠正確的魔法,而是提供一個專門處理 LLM 輸出不穩定性的評測層。這一層的任務,是讓團隊能夠用同一批案例持續觀察品質、差異與風險。
實際開始:先建立一個最小可驗證的 eval
官方 Quick Start 要求使用 Node.js >=22.22.0,並建議使用 Node.js 24 LTS。可以先用 npx,不必把 CLI 安裝成全域工具;若團隊已經固定使用全域安裝,也可以用 npm 或 Homebrew 安裝。下面的流程刻意不把任何真實憑證寫進檔案,API key 應該由環境變數或 CI secret 管理。
npx promptfoo@latest init --example getting-started
cd getting-started
export OPENAI_API_KEY="$YOUR_PROVIDER_API_KEY"
npx promptfoo@latest eval
npx promptfoo@latest view這四個步驟各自有清楚的責任。init 建立可修改的範例目錄;設定環境變數讓 provider 能夠呼叫模型;eval 執行評測;view 開啟結果檢視介面。第一個成功標準不是「模型回答得像人」,而是你可以在另一台乾淨環境,以相同設定重跑並得到一份可比較的結果。
接著可以把設定收斂成一個很小的 promptfooconfig.yaml。以下範例使用官方文件中的設定概念,讓兩個 prompt 對同一個輸入進行比較:
description: customer support answer evaluation
prompts:
- file://prompt1.txt
- file://prompt2.txt
providers:
- openai:gpt-5-mini
tests:
- vars:
question: "退款需要哪些資料?"
assert:
- type: contains
value: "退款"實際使用時,provider 名稱應依官方 provider 文件與你目前可用的模型調整;不要把範例中的模型名稱視為永遠不變的產品承諾。測試案例也不該只用一題。我的建議是先建立三組資料:一組代表最常見的正常輸入,一組代表容易出錯的邊界輸入,另一組則代表你不希望系統洩漏或執行的請求。這樣即使第一版只有幾十筆,也比單次手動示範更接近可以持續維護的品質基線。
Assertion 不只是「有沒有包含關鍵字」
最簡單的 assertion 是檢查輸出是否包含或不包含某段文字,適合驗證明確的產品規則,例如回答必須提到退款期限、不得出現內部欄位名稱。然而,關鍵字只適合處理表面條件,不代表內容真的正確。像「必須給出三個步驟」這種要求,即使文字包含三個序號,也不代表步驟順序、資訊完整度與事實都合格。
所以我會把 assertion 分成三個層次。第一層是 deterministic checks:字串、JSON 結構、正規表達式、長度與禁止內容。它們快速、便宜、容易在 CI 中穩定執行。第二層是語意評分:把輸出交給評分器,檢查相關性、完整性、語氣或與參考答案的相似程度。它比較能處理開放式回答,但需要留意評分器本身的偏差與不穩定性。第三層是 domain review:由熟悉業務的人定期檢視測試案例與失敗樣本,確認指標仍然對產品有意義。
這三層不能互相取代。只做關鍵字檢查,容易讓團隊得到虛假的安全感;只做 LLM judge,則可能把不穩定的判斷再交給另一個模型。比較務實的做法,是把便宜且確定的規則放前面,把昂貴的語意檢查留給真正需要的案例,再用人工抽樣校準結果。
從 eval 走向模型比較:先定義成本與風險,再看分數
Promptfoo 很適合做 side-by-side model comparison,但「分數最高」不應該直接等於「最適合上線」。模型選擇至少要同時看四件事:品質、延遲、成本與失敗型態。
品質可以由測試通過率、評分器分數與人工抽樣組成;延遲要看平均值之外的尾端表現,因為使用者通常會感受到慢的那幾次;成本不能只比較單價,還要看 prompt 長度、重試次數與輸出長度;失敗型態則要看模型是在不知道答案時誠實拒答,還是用流暢文字補出錯誤內容。
我會把這些資訊放進版本控制的評測報告,而不是只截一張 dashboard 圖。每次改 prompt 或換 provider 時,至少記下測試資料版本、設定檔、執行日期與通過/失敗案例。當某個模型在平均分數上略勝,但在敏感案例中有更高的錯誤率時,這個差異才不會被漂亮的總分掩蓋。
還有一個常被忽略的細節:快取與非決定性。官方 README 把 caching 與 live reload 列為 developer-first 特性,但快取會影響你看到的結果,隨機性也會讓同一案例多次執行產生不同輸出。因此,在評測規格中要明確記錄哪些結果可以重用、哪些測試需要重跑,以及如何處理邊界分數。可重跑不代表每次輸出逐字相同,而是代表條件、案例與判斷方法一致。
Red teaming:把安全檢查放進同一條管線
品質評測回答「正常情況下好不好」,red teaming 則是在問「被刻意挑戰時會不會失守」。Promptfoo 官方提供 red teaming 與 vulnerability scanning 文件入口,也能在 CLI 中執行 redteam run。這使安全測試不必停留在一次性的人工攻擊演示,而可以成為定期執行的檢查。
npx promptfoo@latest redteam run --config promptfooconfig.yaml實際紅隊測試要先定義範圍。哪些資料不可被洩漏?哪些工具呼叫必須拒絕?哪些角色權限不可被輸入內容改寫?哪些輸出格式若破壞就會造成下游系統誤動作?如果沒有先寫出這些政策,掃描結果很容易變成一串看似嚴重、卻無法排序的 finding。
我會把結果分成至少三類:可接受的拒絕、需要人工檢視的模糊案例、以及應該阻擋部署的高風險案例。對每個高風險案例,都應保留最小化的重現輸入與修正後的回歸測試。這裡要特別注意資料治理:測試用的敏感內容應使用去識別化或合成資料,報告與 CI log 也不能把 API key、個人資料或完整機密 prompt 原樣印出。
另外,紅隊工具不是安全保證書。它能幫你擴大攻擊面與測試覆蓋率,但不會自動知道你的授權模型、資料保留規則或業務風險。安全團隊仍需要審查測試政策、確認 finding 的嚴重度,並檢查模型之外的 API、資料庫與工具執行層。
接到 CI/CD:讓 Pull Request 先回答「這次變更有沒有退步」
當評測設定與測試資料進入 repository,下一步就是在 CI 中執行。官方 CI/CD 文件展示了使用 npx promptfoo@latest eval 輸出結果,以及執行 redteam run 的方式。最小化的 pipeline 可以長這樣:
npx promptfoo@latest eval -c promptfooconfig.yaml -o results.json
npx promptfoo@latest redteam run promptfooconfig.yaml但不要一開始就把所有測試、所有模型、所有紅隊案例都放進每個 Pull Request。比較穩健的分層方式是:快速 smoke eval 在每個 PR 執行;完整回歸測試在合併到主分支或排程執行;成本較高的模型比較與深度紅隊掃描則在夜間或發布前執行。這樣既能維持回饋速度,也不會因為 CI 太慢而被團隊繞過。
CI 的失敗門檻也應該與測試類型對應。確定性 assertion 失敗,可以直接阻擋;語意評分接近門檻時,可以標記為需要人工檢視;外部 provider 暫時不可用,則要和真正的產品退化分開記錄。否則一個供應商的短暫網路錯誤,就可能讓團隊把錯誤方向當成 prompt 回歸問題。
在安全上,CI secret 只應注入執行環境,不應放在 promptfooconfig.yaml、測試輸出或 issue comment。結果分享也要先確認是否含有使用者輸入、模型輸出或內部 system prompt。評測自動化的終點不是「每次都把全部結果公開」,而是讓正確的人在正確的權限下看到足夠的證據。
哪些地方不要過度期待
第一,Promptfoo 不能替你定義「好回答」。它提供執行與比較能力,但測試資料、assertion、評分門檻與風險分類仍需由產品與工程團隊負責。垃圾測試資料只會產生更自動化的錯誤結論。
第二,LLM judge 不是絕對客觀的裁判。評分 prompt、參考答案、模型版本與上下文都可能影響結果。重要功能應保留 deterministic checks 與人工抽樣,不要讓單一分數成為唯一上線依據。
第三,外部 provider 與本機環境會影響可重現性。模型更新、服務限制、網路錯誤、速率限制與成本變化,都可能使一次評測失敗。報告中應記錄 provider、模型識別、設定與執行環境;必要時使用固定版本或建立容錯重試策略。
第四,CLI 的快速上手不等於完整治理。正式導入還需要處理測試資料版本、輸出保存期限、權限控管、PII 遮罩、secret 管理、失敗案例 triage 與變更審批。這些是產品生命週期的一部分,不是安裝工具之後自然得到的功能。
我會怎麼安排第一週導入
第一天只選一個高價值流程,例如客服摘要或知識庫問答,建立十到二十個正常案例與五個邊界案例。第二天把 prompt、provider 與測試資料放入設定檔,先只做 deterministic assertions,確認團隊知道怎麼閱讀結果。第三天加入一個語意品質檢查,並用人工抽樣比較評分器與專家判斷是否一致。
第四天整理三到五個安全政策,加入最小化的 red-team 測試,不追求一次涵蓋所有攻擊。第五天把 smoke eval 接到 Pull Request,讓團隊實際經歷一次通過與一次失敗;失敗之後要能找到案例、理解原因、修正設定,並把回歸案例留下來。第一週的成功標準不是測試數量,而是大家開始用同一套證據討論模型與 prompt 的變更。
之後再逐步加入模型比較、完整 CI、排程掃描與團隊報告。當測試套件累積到一定規模,要定期刪除失去辨識力的案例,合併重複案例,並重新檢查門檻。評測套件和產品程式一樣會腐化;只增加測試、不維護測試,最後仍然會變成沒人信任的儀表板。
結語:把「感覺變好」改成「證據足夠」
Promptfoo 的核心價值,不是替團隊選出一個永遠最好的模型,而是把模型與 prompt 的變更放進一條可檢查的工程流程。你可以從 npx promptfoo@latest init --example getting-started 開始,用一小組案例建立基線,再把 assertion、模型比較、red teaming 與 CI/CD 逐層加上去。
我會把它推薦給已經有 LLM 應用、開始頻繁改 prompt 或需要在多個 provider 之間做選擇的團隊。若目前還沒有穩定的測試資料、沒有定義產品品質,或只是想找一個按鈕保證模型安全,先不要急著導入;先把成功條件與風險政策寫清楚,工具才有可以執行的對象。真正成熟的做法不是追求一個漂亮分數,而是每次變更都能說明:我們測了什麼、哪裡變好、哪裡退步,以及為什麼現在仍然敢發布。