前面幾天把 Prompt、資料、RAG、輸出格式慢慢拆開之後,我原本以為只要每一層都能正常運作,AI 系統應該就已經差不多了,但真的開始把這些東西接在一起,我很快又遇到一個更難處理的問題。
系統可以正常回覆,API 沒有報錯,畫面也成功顯示答案,可是我不知道這個答案到底算不算好。
這件事在人直接使用 ChatGPT 的時候還沒有那麼明顯,因為看到答案之後可以自己判斷,但如果今天做的是一個要讓很多人使用的 AI 服務,就不能每一次都坐在旁邊人工確認。
假設我做了一個文件問答系統,使用者問「退貨期限是幾天」,模型回答「商品可以在收到後七天內申請退貨」,整句話看起來很合理,語氣也很自然。
問題是,文件裡真的寫七天嗎?
如果資料來源其實寫十四天,那這個回答在系統層面還是完全成功,Request 有進來、RAG 有搜尋、LLM 有輸出、前端也有顯示,只是最後答案錯了。
這種錯誤很難靠傳統的程式測試直接抓出來,因為程式本身沒有壞掉,壞的是內容品質。
所以做到這裡,我才比較理解 AI Engineering 裡 Evaluation 為什麼會一直被提到,因為一個 AI 系統如果沒有評估方式,每次修改 Prompt、換模型、調整 chunk size 或搜尋方式之後,其實很難知道系統到底有變好還是變差。
我現在比較能接受的做法,是先不要一開始就想做幾百題 Benchmark,而是自己整理一小組很確定答案的問題。
例如準備 20 題,每一題都記錄使用者問題、正確答案、答案所在文件,以及有哪些重點一定要回答到,接著每次修改系統之後都重新跑一次這 20 題。
這個方法看起來有點笨,但它至少給了我一個固定基準。
假設今天把 RAG 的 chunk size 從 500 改成 1000,原本回答正確的 20 題突然有 4 題抓錯資料,那就代表這次修改可能沒有想像中那麼好;反過來,如果原本常常失敗的幾題開始穩定答對,我也比較有依據留下這次設定。
而且這些測試題不用全部都是簡單問題,我反而覺得應該刻意放一些容易出錯的情況,例如文件裡有兩個相似數字、不同版本規定同時存在、問題需要跨兩段內容才能回答,甚至答案根本不存在於文件裡。
最後一種特別重要,因為很多 AI Demo 最大的問題不是回答錯,而是不知道答案的時候還是會想辦法生一個答案出來。
做到這裡之後,我發現 Evaluation 其實不是系統做完才補上的東西,反而會一路影響前面的設計。
如果我希望系統可以檢查引用來源,那輸出格式一開始就要保留 citation;如果我要判斷 RAG 有沒有找到正確資料,就需要另外記錄 retrieval result;如果我要比較不同模型,就不能只看最後一句回答,還要把當時的 Prompt、模型版本、temperature 甚至資料版本一起留下來。
這些東西在做 Demo 的時候很容易被忽略,因為當下只要畫面可以動,看起來就已經很完整,但一旦開始修改第二版、第三版,很快就會遇到「我記得上一版好像比較準」這種完全靠感覺的狀況。
Day 10 做到這裡,我開始覺得 AI Engineering 很大一部分工作,其實是在把這些原本只能靠感覺判斷的東西慢慢留下紀錄,讓下一次調整至少可以知道自己改了什麼,以及改完之後到底發生了什麼。
接下來我想把這組固定問題真的整理成一個小型 evaluation set,再試著比較不同 Prompt 或不同 RAG 設定,看那些平常聽起來很抽象的「模型品質」,能不能開始變成一些真的看得到的差異。