이 솔루션은 Kaggle의 LMSYS - Chatbot Arena Human Preference Predictions 대회를 위해 개발되었습니다. 참가자들은 LLM(대형 언어 모델)을 기반으로 하는 챗봇 간의 일대일 대화에서 사용자 선호도를 예측해야 했습니다. 이 작업에는 사용자가 두 명의 익명 LLM과 상호 작용하고 선호하는 응답을 선택하는 Chatbot Arena 의 데이터 세트를 활용하는 작업이 포함되었습니다. 이러한 선호도를 정확하게 예측하는 기계 학습 모델을 만들어 챗봇 응답과 인간 선호도의 정렬을 개선하는 데 기여하는 것을 목표로 했습니다.
우리 팀은 성공적으로 1849개 팀 중 4위를 차지하여 솔루션으로 금메달과 상금 $20,000를 획득했습니다! ?
먼저, 우리는 20겹 교차 검증(n_splits=20)을 사용하여 33,000개의 중복 제거 데이터와 함께 공식 데이터 세트(55k)를 활용했지만 훈련 데이터의 양을 최대화하기 위해 한 가지만 훈련했습니다. 또한 데이터세트를 추가로 보완하기 위해 울트라피드백 데이터세트에서 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 ,
}
우리는 Llama3 8b 및 Llama3.1 8b 와 같은 다른 모델보다 훨씬 뛰어난 성능을 보이는 gemma-2-9b-it를 시작 모델로 선택했습니다. 3개 클래스 분류 작업을 위해 Gemma2ForSequenceClassification을 사용했고, bf16 정밀도로 lora를 사용하여 모델을 미세 조정했습니다. 최고의 실험 결과는 4개의 A100 GPU에서 달성되었습니다.
4개의 A100 GPU(40G)를 갖춘 시스템에서 각 실험은 첫 번째 단계에서 약 10시간, 두 번째 단계에서 15시간이 걸렸습니다.
추론 단계에서는 훈련 단계와 유사한 코드 구조를 사용하지만 몇 가지 주요 차이점이 있습니다. 즉, max_length
가 3072로 늘어나고 response_a 와 response_b가 TTA(테스트 시간 확대) 전략의 일부로 교체됩니다. 최종 결과는 두 가지의 평균 출력입니다.
후처리는 두 가지 특정 시나리오(겹칠 수 있음)에 적용되었습니다.
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 모델을 기반으로 대화 시스템에 대한 인간 선호도 예측 모델을 개발 및 최적화하여 대화 시스템에서 사용자 선호도 응답 예측의 정확도를 향상시켰습니다.
주요 기술 :
Daoyuan Li - Kaggle 프로필
질문이 있는 경우 [email protected]으로 Daoyuan Li에게 문의하세요.