該解決方案是為 Kaggle 上的 LMSYS - Chatbot Arena 人類偏好預測競賽開發的,參賽者面臨的挑戰是在由大型語言模型 (LLM) 驅動的聊天機器人之間的面對面對話中預測用戶偏好。該任務涉及利用Chatbot Arena的數據集,其中用戶與兩個匿名法學碩士進行互動並選擇他們的首選回應。透過創建一個能夠準確預測這些偏好的機器學習模型,我們的目標是幫助改善聊天機器人回應與人類偏好的一致性。
我們的團隊在 1849 個團隊中成功排名第四,憑藉我們的解決方案贏得了金牌和 20,000 美元的獎金! ?
首先,我們利用官方資料集 (55k) 以及 33k 去重數據,採用 20 倍交叉驗證 (n_splits=20),但僅進行一次訓練以最大化訓練資料量。此外,我們還為 ultrafeedback 資料集中的 30,000 個條目建立了偽標籤,以進一步補充該資料集。
我們設計了一個獨特的提示,這是有益的,因為當對話長度超過最大令牌長度( max_length
)時,它允許對最後一輪對話進行合理的截斷。這樣可以確保提示、回應A和回應B都能充分顯示,避免出現只有提示或回應A被截斷的情況。如果最後一輪的剩餘令牌數少於 80,則整個對話輪(以及後續輪)將被丟棄。這些閾值和比例是透過觀察訓練集來確定的。
def tokenize_cls_p3 ( example , tokenizer , max_length , is_train ):
input_ids = []
attention_mask = []
dot_tokens = tokenizer ( "......" , add_special_tokens = False )[ "input_ids" ]
final_p_tokens = tokenizer ( " n n --- n Which response is better? [A or B or tie] n Answer: " , add_special_tokens = False )[ "input_ids" ]
for ps , ras , rbs in zip ( example [ 'prompt' ], example [ 'response_a' ], example [ 'response_b' ]):
one_input_ids = [ tokenizer . bos_token_id ]
prev_tokens_num = 2 + len ( final_p_tokens ) # 2 for bos_token and eos_token
for idx , ( p , ra , rb ) in enumerate ( zip ( ps , ras , rbs )):
r_tokens = tokenizer ( f' n n ## Round { idx + 1 } :' if idx else f'## Round { idx + 1 } :' , add_special_tokens = False )[ "input_ids" ]
p_tokens = tokenizer ( f' n ### Prompt: n { p } ' , add_special_tokens = False )[ "input_ids" ]
ra_tokens = tokenizer ( f' n n ### Response A: n { ra } ' , add_special_tokens = False )[ "input_ids" ]
rb_tokens = tokenizer ( f' n n ### Response B: n { rb } ' , add_special_tokens = False )[ "input_ids" ]
all_tokens_num = prev_tokens_num + len ( r_tokens ) + len ( p_tokens ) + len ( ra_tokens ) + len ( rb_tokens
if all_tokens_num > max_length :
remain_tokens_num = max_length - prev_tokens_num - len ( r_tokens ) - 3 * len ( dot_tokens )
if remain_tokens_num >= 80 :
p_tokens = p_tokens [: int ( remain_tokens_num * 0.2 )] + dot_tokens if len ( p_tokens ) > int ( remain_tokens_num * 0.2 ) else p_tokens
ra_tokens = ra_tokens [: int ( remain_tokens_num * 0.4 )] + dot_tokens if len ( ra_tokens ) > int ( remain_tokens_num * 0.4 ) else ra_tokens
rb_tokens = rb_tokens [: int ( remain_tokens_num * 0.4 )] + dot_tokens if len ( rb_tokens ) > int ( remain_tokens_num * 0.4 ) else rb_tokens
one_input_ids += r_tokens + p_tokens + ra_tokens + rb_tokens
break
else :
prev_tokens_num = all_tokens_num
one_input_ids += r_tokens + p_tokens + ra_tokens + rb_tokens
one_input_ids += final_p_tokens + [ tokenizer . eos_token_id ]
one_attention_mask = [ 1 ] * len ( one_input_ids )
input_ids . append ( one_input_ids )
attention_mask . append ( one_attention_mask )
if is_train :
labels = [ 0 if a_win else 1 if b_win else 2 for a_win , b_win , tie in zip ( example [ 'winner_model_a' ], example [ 'winner_model_b' ], example [ 'winner_tie' ])]
return {
"input_ids" : input_ids ,
"attention_mask" : attention_mask ,
"labels" : labels ,
}
else :
return {
"input_ids" : input_ids ,
"attention_mask" : attention_mask ,
}
我們選擇gemma-2-9b-it作為起始模型,它顯著優於其他模型,例如Llama3 8b和Llama3.1 8b 。我們使用Gemma2ForSequenceClassification進行三類分類任務,並使用lora以bf16精度對模型進行微調。最好的實驗結果是在四個 A100 GPU 上取得的。
每個實驗在具有 4 個 A100 GPU (40G) 的系統上第一階段大約需要 10 小時,第二階段大約需要 15 小時。
推理階段使用與訓練階段類似的程式碼結構,但有一些關鍵差異: max_length
增加到 3072,並且作為測試時間增強 (TTA) 策略的一部分, response_a和response_b被交換。最終結果是兩者的平均輸出。
後處理應用於兩個特定場景(可能重疊):
df2 = pd . read_csv ( '/kaggle/input/lmsys-chatbot-arena/test.csv' )
df2 [ 'id' ] = df2 [ 'id' ]. astype ( str )
a_null_df = df2 [( df2 [ "response_a" ] == '[null]' ) | ( df2 [ "response_a" ] == '[]' ) | ( df2 [ "response_a" ] == '[ ]' ) | ( df2 [ "response_a" ] == '[ ]' ) | ( df2 [ "response_a" ] == '[""]' ) | ( df2 [ "response_a" ] == '["",""]' )]
a_null_id_list = a_null_df [ "id" ]. tolist ()
submission_df . loc [ submission_df [ 'id' ]. isin ( a_null_id_list ), [ 'winner_model_a' , 'winner_model_b' , 'winner_tie' ]] = [ 0.04 , 0.88 , 0.08 ]
b_null_df = df2 [( df2 [ "response_b" ] == '[null]' ) | ( df2 [ "response_b" ] == '[]' ) | ( df2 [ "response_b" ] == '[ ]' ) | ( df2 [ "response_b" ] == '[ ]' ) | ( df2 [ "response_b" ] == '[""]' ) | ( df2 [ "response_b" ] == '["",""]' )]
b_null_id_list = b_null_df [ "id" ]. tolist ()
submission_df . loc [ submission_df [ 'id' ]. isin ( b_null_id_list ), [ 'winner_model_a' , 'winner_model_b' , 'winner_tie' ]] = [ 0.88 , 0.04 , 0.08 ]
same_a_b_df2 = df2 [( df2 [ "response_a" ] == df2 [ "response_b" ])]
same_a_b_id_list = same_a_b_df2 [ "id" ]. tolist ()
submission_df . loc [ submission_df [ 'id' ]. isin ( same_a_b_id_list ), [ 'winner_model_a' , 'winner_model_b' , 'winner_tie' ]] = [ 0.06 , 0.06 , 0.88 ]
概述:基於gemma-2-9b-it模型開發並優化了對話系統的人類偏好預測模型,提高了對話系統中預測使用者偏好回應的準確性。
關鍵技術:
李道元 - Kaggle 個人資料
如有任何疑問,請聯絡李道元,電子郵件:[email protected]。