该解决方案是为 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]。