Notes
多選題怎麼訂正?關於我如何修正後續優化領域的 prompt
拆解後續優化領域的多掛與漏掛,從評分與錯誤歸因中找出 prompt 的判斷邊界
經歷了漫長的前期準備,終於要正式跑分了。
在第一次跑後續優化領域的評分時,exact match 只有 14.81%。只有當 agent 選出的整組後續優化領域與 golden dataset 完全一致時,這筆資料才算 exact match;多掛或漏掛任何一個標籤都算錯。
根據當時的數據,27 筆 issue 裡只有 4 筆是完全吻合的。第一次看到這個數字的時候,我心中的想法是:「原來我內心所想的評斷標準,跟我下給 AI 的 prompt 差這麼多嗎?」
但是冷靜下來之後,發現這個 exact match 並沒有告訴我太多資訊——我該怎麼改?是哪一個優化領域出了問題?
上一篇文章《用 100 筆維運資料,建立 Golden Dataset》中提到,我們要如何知道現在的 prompt 是哪裡不好?哪裡該修正?「好不好」的標準是什麼?在這篇文章裡,我會提到關於我如何設計評分,找到該修正的地方,以及我如何讓 exact match 由 14.81% 提升到 48.15%。畢竟以前考完試,老師都會要求我們要訂正答案。對完答案後,如果只知道分數卻不知道錯在哪,就無法知道我們該往哪裡改進。
評分的分層架構
讓我們稍微回顧一下 postmortem agent 在做些什麼吧!
postmortem agent 會分析過去的每個 issue,並為各個 issue 產生後續優化領域以及 postmortem note。後續優化領域共有六種分類,postmortem note 則是以三句話描述的事後檢討資訊。
在 postmortem agent 中,這一套評分系統,需要面對兩種不同的題目。
「後續優化領域」是個多選題,從六個領域中選取複數領域,agent 只要劃卡、讓讀卡機讀取就能知道各個 issue 答題是否正確,以及每個標籤在各個 issue 上是多掛了還是漏掛了,在計算分數的過程中不需要呼叫 LLM。
但是 postmortem note 是個申論題,同一件事有 100 種寫法,沒有辦法用字串比對 agent 產生的結果是否跟 golden dataset 裡面的答案完全吻合。在這個情況下,我們只好請另一個 AI 擔任我們的閱卷老師,這個閱卷老師會拿到完整的團隊討論紀錄,並以 golden dataset 中的內容為輔,逐題核對:問題描述是否正確?根因描述是否正確?解法是否與事實一致?有沒有憑空生出討論紀錄中不存在的東西?
但申論題很花時間,而且這個閱卷老師很貴,所以在請閱卷老師讀考卷並且打分數之前,我先請助教協助篩選掉不符合答題格式的考卷。舉例來說,在 note 進入到評分階段前,我先讓程式碼檢查這個 note 是否為空、句數是否多於 prompt 中所規定的三句話,或是 golden dataset 將該筆 issue 標記為資訊不足,但 note 未照實反映。如果符合以上的情況,就跳過 judge 階段,不請貴貴的閱卷老師來評分(aka 省下 token)。
這其實跟整個系統的成本安排是同樣的邏輯:確定性的工作交給程式碼(助教),語意判斷交給 AI(閱卷老師),而最貴的判斷——這個標籤到底該不該掛——則交給人類。
多選題的分數怎麼算
在文章的一開始,我提到第一次跑後續優化領域的評分時,exact match 只有 14.81%。但這個數字沒有告訴我,每個後續優化領域的表現如何?所以除了 exact match 之外,我們另外加入了 macro precision 以及 macro recall 這兩個分數。
P 是什麼?R 又是什麼?
macro precision 和 macro recall 分別以 precision(精確率)與 recall(召回率)為基礎,而這兩個指標分別反映不同類型的錯誤:precision 主要反映多掛,recall 主要反映漏掛。
- Precision(精確率):agent 掛上的,有多少是對的?
- agent 在 10 筆 issue 裡掛上了「監控」,其中 6 筆在 golden dataset 中確實也有掛上「監控」這個後續優化領域。此時 precision 為 6/10,即 60%。
- precision 的分子為 agent 掛上、且 golden dataset 中也認為該掛的筆數,分母則為 agent 實際跑過掛上該領域的筆數。precision 低,則代表 agent 偏向在 issue 上多掛這個領域。
- Recall(召回率):該掛的領域裡,agent 掛了多少?
- golden dataset 中有 8 筆掛上「可加入 Playbook」,agent 只掛了其中 6 筆。此時 recall 為 6/8,即 75%。
- recall 的分子同樣為 agent 掛上、且 golden dataset 中也認為該掛的筆數,而分母則為 golden dataset 中認為該領域該掛的筆數。recall 低,則代表 agent 偏向在 issue 上少掛這個領域。
這兩者的分數可以說是互相拉扯。它們兩個的分子相同,但分母不同,precision 除以「agent 掛了幾筆」,而 recall 除以「golden dataset 標記了幾筆」。如果 prompt 中對於某個後續優化領域的描述比較寬鬆,造成 agent 偏向幾乎每個 issue 都掛上這個後續優化領域,recall 就會非常高,但相較之下,precision 的分數就會變得很低。
如果 prompt 中對於某個後續優化領域的描述過於保守,此時會造成 agent 偏向不掛某個後續優化領域,此時 precision 會變高,但 recall 就會變低。
這兩者換成在寫多選題時,大概就是「隱約覺得符合答案的就選」跟「隱約覺得不符合答案就不選」這兩種差別。
macro 又是什麼?
我總共有 6 個後續優化領域,macro 就是取這六個領域 P 跟 R 的算術平均數。譬如說,6 種後續優化領域的 precision 分別是 90%、80%、85%、70%、60%、20%,macro precision 就是這六個數字的平均 ≈ 67.5%。
與 macro 對照的是 micro:把所有類別的結果全部加總在一起,再統一計算整體的指標。在 postmortem agent 的情境下,就會是把所有的掛對/漏掛/多掛全部倒進一個池子裡,加總後只算一次 P 和 R,因此在樣本數中佔大多數的優化領域會主導分數。
在 macro 裡,每個後續優化領域的權重是相同的,而這也正符合這項評分的需求。有些優化領域天生就比較稀少,像是「增加 Log」和「操作體驗」,但即便如此,稀少的後續優化領域與其他領域也是同樣重要。
不過採用 macro 分數的狀況之下,只要某個稀少優化領域的分數掉下來了,對於 macro precision 跟 macro recall 的分數就會產生顯著的影響。尤其第一次跑分時,樣本數只有 27 筆,其中稀少優化領域可能只有 3-4 筆,只要錯一題,對整體分數影響就會很大,而這也是為什麼後續持續擴充 golden dataset 的樣本數非常重要。如同上一篇文章的標題,我後續逐漸將 golden dataset 擴充至 100 筆,同時增加特定領域在 golden dataset 中的樣本數,以減少稀少優化領域對於分數的波動影響程度。
錯誤歸因——同一個錯,兩種原因
在跑完第一次的評分後,我審視 agent 掛錯的 issue,發現有不少筆 issue 身上被掛了「產品技術改善」,但 golden dataset 裡面沒有掛——因為這個問題已經完成修正,我認為這種情況不該掛「產品技術改善」。
我發現後續優化領域的「掛錯」其實有兩種原因:
- 資訊漏讀:agent 根本沒有讀到討論紀錄中已經附上修正資訊,所以它以為還沒修好。在讀取討論紀錄的過程中,可能會因為一些技術上的因素,所以沒有順利讀取到完整的討論紀錄,造成資訊缺漏。這個情況下,要修的是「讀」的環節,例如檢查討論紀錄的抓取流程,確認輸入內容是否完整。
- 判斷錯誤:agent 讀到了問題修正資訊,在 note 裡也寫上「已修復」,但它還是掛上了標籤——因為第一版的「產品技術改善」確實沒有描述「問題修好了就不掛」,agent 不懂這條規則。此時要修的是「判斷」,把「要不要掛」的規則寫進 prompt 中。
在答題的過程中,可能是題目根本沒有看完、或是題目看懂了,卻沒有用正確的公式去解題,這兩種都會造成失分,但修正的方式完全不同。
那我是如何分辨這兩種區別的?一開始,我採取了最土法煉鋼的方法,把掛錯的 issue 抓出來看,對照 agent 產出的 note。如果 note 中提到問題已經修復、但卻仍然掛上標籤,那就是判斷問題;如果問題已經修復,但 note 裡卻沒有提到,那就是漏讀了。
這套歸因在現階段並沒有被自動化,因為此時 golden dataset 的樣本數還少,逐筆對照並不會花我太多時間。但是如果在樣本數大的情況下,可以把 issue 中的關鍵事實拆成欄位(像是問題是否解決、issue 中是否明確指出後續優化項目等等),讓這些歸因可以自動統計。
評估結果除了分數之外,更大的價值在於提供了可歸因的錯誤。分數告訴你錯了多少、這個 prompt 是否維持在相同水準;而歸因則是告訴你錯在哪裡,要如何修。
一天之內改了三個版本
第一次跑分,exact match 只有 14.81%。我當天就正式踏上修 prompt 之旅。
v1——什麼都掛
第一次跑分時,發現橫跨在 27 筆 issue 之中,agent 漏掛了 7 個後續優化領域,但多掛了 36 個後續優化領域。問題很明顯:prompt 寫得太寬鬆了,agent 偏向在每個 issue 上多掛標籤。
回過頭來審視 v1 的 prompt,各個後續優化領域只有用一句話定義。以「產品技術改善」這個後續優化領域來說,v1 只有短短一句話:
有系統性 / 結構性改善空間的問題。
除此之外,也沒有任何描述告訴 agent 什麼情況該掛哪個標籤、什麼情況不該掛。
v2——加了規則,但矯枉過正
v1 太寬鬆了,那就加點規則吧!在 v2,我加上了更明確的說明。以「產品技術改善」這個後續優化領域來說:
有系統性 / 結構性改善空間的問題——例如設計缺陷、技術債、缺乏防護機制(retry、fallback、requeue)、套件升級相容性風險等等。討論紀錄中已明確排入後續優化的也算。單次 bug 已修復、且同類問題不會再次發生的,不算。
除了修改各個後續優化領域的描述之外,我同時也加上了掛標籤的原則:
- 標籤代表「後續仍值得投入的方向」。如果討論紀錄中已確認問題修復、且修復後同類問題沒有預防空間的,或是所需的機制(像是監控、log)已經存在,就不要掛。
- 寧缺勿濫:只選討論紀錄中有明確證據支持、最核心的選項(通常為 0-2 個)。「加 log 對 debug 總是有幫助」「任何調查都可以寫成 SOP」這類對大多 issue 都成立的泛用理由,不足以掛標籤。
- 空列表是常見且正確的答案:客戶誤解或誤操作經澄清後即結案、純粹人為疏失、單次事件已根治且無後續的,就掛空標籤。
第二次跑分,結果令人振奮:exact match 提升到 44.44%。precision 提升了將近 22 個百分點,但是 recall 反而比 v1 低了。
調查了 v2 recall 降低的原因,發現「已修復就不掛」的模式,把一些案例給壓掉了。舉例來說,有一筆外部資料規格的問題,雖然已經從資料端進行修正了,但如果我們沒有做出相對應的改善,這個問題還是有可能會重複發生。對於這種案例,agent 套用了「已解決就不掛」的規則,所以 recall 降低了。
透過第二次跑分,我發現真的不能只看其中一個指標的分數。雖然在這一次的跑分中,exact match 跟 precision 都提升了,但 recall 降低了。如果我只看其中任何一個指標,都會讓 prompt 的改進方向變得不精準。
v3——不加通則,專修邊界
在 v3 裡,我沒有修改太多關於各個後續優化領域定義,只有加上明確的邊界:
外部資料規格:這類問題無法由我方單方面修復,後續仍需通知外部資料異常、需由外部修正,因此即使該筆事件已解決,仍應掛此標籤,標記外部資料規格面的風險。 操作體驗:必須「系統這一側有可改善空間」才掛,例如加上提示文案、防呆設計等。單純客戶看錯或誤解、經澄清後即結案,且系統無需改動的,不掛。
v3 的跑分結果,三個指標分數都提升。雖然指標分數看起來都有不小的上升幅度,不過若只看 exact match,v3 也只比 v2 多答對一筆而已。而根據後續同一版本多次跑分的經驗顯示,單次跑分本來就會有 2-4 個百分點的隨機波動,所以 v3 的分數確實是變好看了,但實際上的幫助有多少,其實還是很難說。不過在 v2 矯枉過正的案例裡,有兩筆在 v3 都被修正,因此修改邊界而救回特定案例的貢獻是確實存在的。
| 指標 | v1 | v2 | v3 |
|---|---|---|---|
| exact match | 14.81% (4/27) | 44.44% (12/27) | 48.15% (13/27) |
| macro precision | 32.86% | 54.37% | 59.72% |
| macro recall | 72.22% | 65.48% | 73.41% |
| 漏掛/多掛(個) | 7 / 36 | 8 / 11 | 6 / 11 |
註:本文章內所有分數為事後以同一版 golden dataset、同條件下回溯重跑的數值,與當天看到的原始數字略有差異;回溯是為了讓三個版本可以互相比較。
多選題有讀卡機,那申論題呢?
修到 v3 之後,我發現樣本數仍然太少了,此時繼續調整後續優化領域的 prompt,也很難獲得實質上的幫助。於是當時我停留在 v3,繼續增加 golden dataset 中的樣本數。透過這次實際跑分,真正的收穫不在於那些數字變得好看,而是讓 prompt 的修改變得更有依據。
在這一篇文章談論的大多都是多選題——後續優化領域的評分,那關於申論題呢?那當然是留給下一篇文章啦。下一篇就來聊聊這個閱卷老師的評分基準是什麼、以及這個老師究竟可不可信吧。
Comments