跳至主要內容
林承翰
所有文章

閱讀約 3 分鐘

讓 AI 不能亂講話:RAG 的觸發門檻該設在哪裡

用檢索增強生成擋住幻覺只是第一步。真正難的是決定什麼時候該檢索,而門檻設錯的兩種方式,代價完全不同。

  • rag
  • llm

在心理健康的場景裡,讓大型語言模型自由生成建議是不能接受的。它會產出讀起來非常專業、結構完整、語氣溫暖的內容,而那些內容可能完全是編造的。正因為它看起來可信,所以比明顯的胡說更危險。

檢索增強生成(RAG)解決的就是這件事:先從可信文件中檢索相關段落,再要求模型只能根據檢索到的內容回答。這部分是標準做法。

真正花掉我最多思考時間的不是 RAG 本身,而是一個看起來很小的問題:什麼時候該啟動檢索?

為什麼不是每次都檢索

最直覺的答案是每一次都檢索。這個答案有三個問題。

第一是成本。每次檢索都是一次向量查詢,並讓送進模型的提示(prompt)顯著變長。對自架的 GPU 推論服務來說,這是實際的延遲與運算負擔。

第二是品質。更長的 prompt 不等於更好的回答。當使用者寫的是「今天有點累」,硬塞三段 WHO 的壓力管理指南進去,模型會產出一段套用了臨床語言、但其實不切題的回應。

第三是信任,這也是最重要的一點。如果系統對每一句日常抱怨都引用心理學文獻,使用者很快就會學會跳過那個區塊。而一個被跳過的提醒,等於不存在的提醒。

第三點值得說清楚:在這類系統裡,過度觸發並不是比較安全的那一邊。它是另一種失敗,只是失敗得比較安靜。不是漏掉該接住的訊號,而是提醒得太頻繁,讓每一次提醒都失去份量。

兩種錯誤的代價不對稱

門檻的位置,是在兩種錯誤之間取捨。

門檻太高、容易觸發時,系統會對輕微的情緒波動也搬出臨床文件。代價是說教感、被忽略,最終使用者關掉這個功能。

門檻太低、不易觸發時,那些寫得含蓄、但其實需要被接住的內容會被放過。代價是漏掉一個本來可以被注意到的低潮。

這兩者的代價不對稱,但不對稱的方向跟直覺相反。在高壓日的預警上,我刻意把 recall(真正的高壓日裡有多少被系統抓到)拉到 88%,寧可誤報也不要漏抓——那是一次多餘提醒的成本,對上一次漏接的成本。

但在「要不要引用臨床文件」這件事上,過度觸發的成本不是一次多餘的提醒,而是整個功能的可信度。使用者對「又來了」的容忍度,遠低於對「偶爾沒說話」的容忍度。

我選的位置:−0.4

情緒分數的範圍是 −1 到 +1,最後設在 −0.4。完整流程如下:

  1. 使用者寫日記
  2. 模型判讀情緒,給出分數
  3. 分數低於 −0.4 才觸發檢索
  4. 系統把 7 份臨床文件(WHO、APA、NHS、NIMH)事先轉成向量索引存在 ChromaDB,再以 BGE-M3 embeddings 取出語意最接近的三個段落
  5. 模型必須在檢索到的內容範圍內生成回饋

這個位置讓明確的負面情緒會觸發,一般的日常抱怨不會。

必須誠實說的部分

這個數字是判斷出來的,不是實驗出來的。

我拿實際的日記樣本,看不同分數的內容各自屬於哪一類,然後選了一個看起來合理的切點。我沒有做敏感度分析——也就是逐一改動門檻、觀察結果如何隨之變化——所以不知道門檻在 −0.3 時誤觸發率會上升多少,也不知道 −0.5 會漏掉多少原本該接住的內容。

那個實驗並不昂貴,我只是把時間花在功能上了,這是個判斷失誤。如果要重做,量化門檻的影響會排在很前面。

還有一件更根本的事:我從來沒有評估過檢索本身的品質。

整個 RAG 的價值建立在「檢索回來的段落確實相關」這個前提上,但我沒有建立檢索評估集,也沒有量測過 top-3 的命中率。模型引用了來源,不等於引用了對的來源。這是我在這個專案裡最大的未驗證假設。

可以帶走的部分

RAG 的教學通常停在「怎麼把檢索接上生成」。但在真實產品裡,決定什麼時候不要檢索,跟決定怎麼檢索一樣重要。

而且觸發條件不是一個技術參數,是一個產品決策:它決定使用者會不會繼續看你的輸出。這件事沒辦法用 embedding 的相似度分數回答。

HeartBox 完整案例研究裡有另外六個工程決策的取捨過程。