這是某 RAG 系統的輸出,它對一個其上下文無法回答的問題,宣稱了一個從未被提供的價格資訊。我把這個輸出交給兩種最受歡迎的 LLM-as-judge 忠實度指標,各跑了五次,評分模型皆使用 gpt-4o 且 temperature 設為 0——這是對評分穩定性最有利的設定。
RAGAS 給出 0.000。
DeepEval 給出 1.000——五次皆如此,並解釋:「得分 1.00 是因為實際輸出與檢索上下文之間沒有任何矛盾。」其中一次還補充:「非常棒地維持了準確與一致性!」
兩種指標都稱為「忠實度」(faithfulness),也都具內部一致性。但只有其中一種能察覺到虛構內容。
我想說明為什麼會這樣、當我真正測量後還發現了什麼,以及為什麼我的結論是「兩者並用」——同時使用 LLM 評分與確定性檢查——而非你可能預期的「打倒 LLM-as-judge」。
我為什麼需要測量這件事
我為醫療保健領域打造 AI 工具——包含供醫學作家使用的索賠驗證、已註冊為醫療器材的病人端文字簡化器,以及臨床去識別化。在這個領域,答案只有在能從來源材料得到佐證時才有用,而真正致命的失敗模式往往很安靜:簡化後的出院摘要裡少了用藥劑量、模型擅自發明參考範圍、系統在上下文毫無依據時仍自信回答。
我需要根據這些特性來把關發佈——當提示詞更動使系統變得不可信時,就讓建置失敗。而 LLM-as-judge 指標要拿來把關建置很麻煩:每次執行都要花錢、結果不確定,而且(事實證明)兩種「相同」指標的實作測量的是不同的東西。
因此我建立了 OpenGATE:每項檢查都是輸出與人工標註金標準的純函式——必要事實必須出現(允許可接受的改寫)、答案中的每個數字都必須能追溯到上下文、當上下文無法回答時系統必須棄答。整個流程完全沒有評分模型。接著我對 RAGAS 與 DeepEval 進行了受控比較,以了解每種方法實際能看到什麼。
實驗設計
凍結了 27 筆輸出:6 筆真實系統輸出(其中 3 筆來自生產環境),加上針對每筆輸出各注入單一已知缺陷的突變版本——包含遺漏事實、虛構數字、未能棄答、附加矛盾、或原地意義反轉。每組各重複五次,評分模型皆使用 gpt-4o、temperature 0。
有三個設計選擇對公平性很重要。缺陷類別依範圍分組且從不加總——確定性檢查「無法」偵測意義反轉,因此把所有東西塞進單一準確率數字會是操縱結果(無論哪個方向)。偵測率是相對於同一案例的未突變基礎輸出來測量注入缺陷的反應,因此不會把原有的小問題誤算成抓到缺陷。而只有在「每一次重複」都被標記時,才算被偵測到——偶爾失效的把關機制不算把關。所有輸入、腳本與每次重複的分數都已提交至 論文附件。
結果是雙面的
評分模型大幅勝出之處。 在意義反轉(「飯後服用」變成「空腹服用」,但所有錨點與數字都原封不動)的案例中,RAGAS 抓到 4/5,DeepEval 抓到 5/5。確定性檢查則抓到 0/5——而且永遠抓不到。字串檢查沒有意義模型。這是評分模型的類別優勢,而非邊際優勢,也是為什麼這篇文章不是在打倒它。
評分模型失守之處。
遺漏。 遺漏抗生素劑量不會宣稱任何未被支持的內容——因此忠實度指標本質上對此視而不見。評分模型抓到 0/5 與 1/5 的遺漏事實。確定性錨點檢查則抓到 5/5。在那份被我刪除 500 mg 劑量的出院摘要上,DeepEval 回傳 1.00,並給出理由:「沒有任何矛盾。」 一個對通過分數的自信解釋,卻針對一個遺漏抗生素劑量的輸出。
成本與速度。 每 1,000 次評估,RAGAS 花費 $11.49,DeepEval 花費 $8.29,而確定性檢查則是 $0.00。每次重複分別耗時 194 秒與 119 秒,而確定性檢查只需 3.8 毫秒。這個差異決定了你「能否」在每次 commit 或每次回答時執行檢查。
定位能力。 當確定性檢查失敗時,它會指出失敗原因:缺少事實「500 mg」。RAGAS 只回傳純量。DeepEval 回傳理由,有時很有幫助,有時就是上面那句「沒有矛盾」。
我最在意的發現是定義上的差異。 RAGAS 問的是:「每個主張是否都有上下文支持?」 DeepEval 的忠實度問的是:「是否有任何主張與上下文矛盾?」 一個虛構的數字不會與任何東西矛盾——上下文對它保持沉默。因此在這六筆宣稱了來源未包含內容的輸出上,RAGAS 抓到 5 筆,DeepEval 抓到 0 筆。在明顯矛盾的案例上,兩者則相當接近(7/10 vs 9/10)。這種分歧是系統性的,而非雜訊。
令人不安的推論是:一個團隊若在未閱讀實作細節的情況下採用「LLM-as-judge 忠實度」,並不是選擇了嚴謹程度,而是無意中選擇了「要對哪種失敗模式視而不見」。對於病人端醫療工具而言,虛構劑量是最需要避免的失敗——而這正是基於矛盾的評分模型會放行的。
我撤回的一個主張
我設計這個實驗原本預期要證明評分模型的「不穩定性」。在強大評分模型上,這個發現其實很弱,我選擇如實呈現而非隱藏:在 gpt-4o/temp 0 的設定下,單筆輸出的平均分數範圍在 RAGAS 為 0.026、在 DeepEval 為 0.013。同一語料庫在 gpt-4o-mini 上則明顯更不穩定(27 筆中有 11 筆在不同重複間改變結論)——因此不穩定性是評分「模型」的屬性,而非評分機制本身的屬性。不用評分模型來把關建置的理由,來自遺漏盲點、定義性分歧,以及成本——這些都不是更好的評分模型就能修復的。
確定性把關在生產環境抓到的問題
這個框架已在四個生產系統的 CI 中運行。首次運行的結果(此前皆未知):多重索賠判定中約 50% 因靜默解析失敗而預設為「不被支持」;去識別化引擎中有兩個姓名擷取錯誤(帶撇號的姓氏如 O'Brien 會掉出擷取模式);以及簡化器從出院摘要中遺漏抗生素劑量。
我最喜歡的一個失敗案例發生在數月後。在劑量遺漏問題修復之後,同一個系統產生了一個「虛構」的數字:「通常我們希望血紅素高於 12 g/dL」——臨床上正確,但來源信件中並不存在。先前的提示詞修復只說「絕對不要省略或更改數字」;它禁止遺漏數字,但對發明數字則保持沉默。針對上一個缺陷強化的提示詞,並不會對下一個缺陷防禦——這正是為什麼需要一個在每次更動時都運行的把關機制,而不是只做一次的審計。綠燈計分卡是一次測量,而不是一個屬性。
誠實的限制說明
這些突變版本是合成的,來自我觀察到的缺陷,而非從真實世界抽樣。語料庫只有 27 筆輸出。只使用一個評分模型。而且我同時撰寫了缺陷分類法與其中一個對照組——這也是為什麼各範圍分別呈報,以及為什麼連我的方法得零分的反轉類別也包含在語料庫中。完整論文 包含效度威脅章節,以及我已預先註冊但尚未執行的實驗(由獨立第二位標註者標註金標準集)。
我真正建議的做法
兩者並用,各取所長。LLM 評分用於語義層面——意義反轉、矛盾、開放式品質——這是它類別上更擅長的地方。確定性檢查則作為「把關機制」:必要事實必須出現、數字可追溯、棄答被遵守——可重現、能指出失敗原因、免費、速度足以在每次 commit 與每次回答時執行。
如果你想試用確定性那一端,它採用 MIT 授權,只需一行指令即可執行,無需 API 金鑰:
npx @pharmatools/opengate
進入全螢幕模式 離開全螢幕模式
Python(pip install opengate-grounding):
from opengate_grounding import check_grounding
result = check_grounding(
answer,
context, # 檢索到的證據
anchors=["500 mg", "twice daily"], # 答案必須包含的事實
)
result.grounded # 確定性——相同證據、相同結論、每次執行皆同
進入全螢幕模式 離開全螢幕模式
此外還有 pytest 輔助函式、DeepEval 的 GroundingMetric(是的——整合可以和評分指標並行運作;這正是重點)、可在偵測到回歸時讓建置失敗的 GitHub Action,以及讓代理能在回覆前自行檢查答案的 MCP 伺服器。
儲存庫:github.com/nickjlamb/opengate · 論文:doi.org/10.5281/zenodo.21365095
我原本是醫學作家,後來轉向為醫療保健打造 AI 工具。這篇文章的所有內容都可以從已提交的附件中重現——如果你發現任何站不住腳的地方,請開 issue;這正是把關機制存在的目的。
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.