從生產日誌建立微調資料集

Back
Category : News

Multigrid

生產日誌是你能擁有的最佳訓練資料,也是最危險的。它們是真實分布中的真實輸入——但充滿了你目前模型的輸出,而這正是你絕對不能用來訓練的內容。



選擇就是全部的工作

日誌傾印不是資料集。百分之九十的生產流量是模型已經在正確執行的事,訓練這些內容不會教會你任何原本沒有的知識。值得納入的範例,是那些攜帶目前模型所缺乏資訊的案例。

  • 人類編輯過輸出的請求。 任何有審核步驟的產品中最高訊號的來源。編輯本身就是標籤:輸入加上修正後的輸出就是完美的訓練配對,而差異告訴你正在修正哪一種失敗模式。
  • 未通過驗證器的請求。 結構違規、JSON 解析失敗、破壞下游合約的輸出。將輸入與手寫或修復後的正確輸出配對。
  • 被重試的請求。 使用者重新產生是一個未標記的負面範例。它告訴你該去看哪裡,即使它沒有告訴你使用者真正想要什麼。
  • 被路由到更昂貴模型的請求。 如果存在後備或升級路徑,所有走過該路徑的內容都是微調最適合的候選:教導廉價模型學會昂貴模型擁有的行為。
  • 普通流量的分層抽樣。 不是因為它能教導,而是因為一個完全由失敗案例組成的資料集會讓模型認為一切都是失敗案例。百分之十到三十的普通流量能讓分布保持真實。



正確輸出從哪裡來

選擇給了你輸入。目標則是另一個問題,而且只有三種來源,依品質與成本由高到低排序。

目標來源 描述
人類編輯的輸出 如果你的產品已經有審核步驟則免費,若沒有則極為昂貴。品質最高,也是唯一能反映使用者真正想要什麼、而非模型認為他們想要什麼的來源。
更強模型(已過濾) 前沿模型的回答,僅在通過驗證器或評分標準時保留。便宜且可擴展。會繼承教師的盲點,並受限於教師的使用條款——見 /learn/fine-tuning-licenses。
你自己模型的輸出 免費,但未經過濾幾乎總是錯誤的。你無法透過模仿自己來學習原本沒有的行為。只有在有嚴格外部過濾器時才合理——例如通過的單元測試、已對帳的交易。



清理而不壓扁分布

直覺是把一切都正規化:去除空白、統一大小寫、統一日期格式、將樣板內容模板化。大部分都要抵抗。推論時的輸入會以日誌中同樣混亂的方式呈現,而只在乾淨輸入上訓練的模型,處理混亂輸入時會表現更差。

真正需要做的事:

  • 遮蔽而非刪除。 個人資料必須移除,但把名字替換成空字串會改變句子的結構。請替換成同類型且長度類別合理且一致的替代值。
  • 以兩個門檻進行去重。 基於雜湊的完全匹配去重能捕捉重放。但無法捕捉僅一個識別碼不同的模板化請求,而日誌資料充滿這類內容。以 Jaccard 門檻約 0.8 進行 MinHash 近似去重則可以,在來自日誌的語料上通常能移除遠多於完全去重的資料。
  • 限制每個來源的貢獻比例。 單一企業客戶若產生 60% 的流量,就會產生 60% 的資料集,你會針對他們特別微調模型。請對任何單一租戶、模板或端點設定固定的比例上限。
  • 丟棄被截斷的內容。 任何在 max_tokens 而非結束序列 token 停止的完成,都是在教導模型在中途句子停止。請根據結束原因而非長度來過濾。



兩個洩漏陷阱



分割後的近似重複洩漏

以隨機抽樣分割後,出現 400 次的模板化請求會同時出現在訓練集與測試集。你的評估會因此測量到記憶而誤報為泛化,數字會非常漂亮,直到生產環境與其不符為止。

請在分割之前先去重,並根據分組鍵而非單列來分割——依租戶、文件、工作階段、模板 ID 來分割。如果兩個範例有可能來自同一個底層事物,它們就應該屬於分割的同一側。



時間洩漏

隨機分割也會讓模型在下個月資料上訓練,卻在上個月資料上測試。對於任何輸入分布會漂移的情況——而產品流量總是會漂移——請依時間分割:在截止時間之前的所有資料用於訓練,之後的所有資料用於測試。得到的數字會較低,但才是能預測生產環境的那一個。



沒人注意到的回饋迴路

這是專屬於日誌衍生資料的陷阱,而且它很安靜。你的日誌包含目前模型的輸出。如果你拿來訓練並部署,下個月的日誌就會包含新模型的輸出,然後你又拿來訓練。每一個世代都是在擬合前一個世代,而不是擬合使用者真正想要的內容。

可見的症狀是收窄:輸出變得更一致、避險消失、模型發展出語言上的抽搐,而稀有但有效的回應形式則完全消失。這與 Shumailov 等人在 2024 年《Nature》論文中描述的合成資料動態相同,只是透過日誌管線的後門進入。

防禦方式是硬性規則而非警覺:只有當目標來自模型外部——人類編輯、通過的測試、已對帳的交易、不同的模型——時,範例才能進入資料集。將來源記錄為一個欄位,並讓訓練作業拒絕沒有來源的列。



格式化與損失遮罩

最後一步是機械性的,也是許多執行在無聲中失敗的地方。有兩個規則。

使用基礎模型自己的聊天模板。 不是看起來像的那個。特殊 token、角色標記與空白字元都很重要,如果訓練時使用的模板與服務堆疊套用的模板不同,適配器就會被要求在格式偏移中進行無謂的泛化。在啟動執行前,請渲染一個範例並印出可見的特殊 token。

在提示上遮罩損失。 許多訓練腳本預設會計算整個序列的損失,因此模型同時被訓練去預測你的指令以及它的答案。對於指令微調,你幾乎總是想要僅完成部分的損失:

tokens   <|system|> You are ... <|user|> Summarise ... <|assistant|> The report ... <|eot|>
labels   -100 -100 -100 ... -100 -100 -100 ...        The report ... <|eot|>
         ________________ masked ________________/  ____ supervised ____/

Enter fullscreen mode

Exit fullscreen mode

結束回合的 token 必須位於受監督的區域內。如果遮罩它,模型就永遠不會被訓練如何停止,這會產生最常見的「微調搞壞了一切」報告:一個正確回答後卻不斷持續下去的模型。



相關文章

https://dev.to/multigrid/building-a-fine-tuning-dataset-from-production-logs-e95

https://www.worldprogramming.org/posts/building-a-fine-tuning-dataset-from-production-logs-y3ppn0