트랜스포머·PEFT 2일 과정7장 · SFT 데이터 구성과 Chat Template9 / 18← 이전목차다음 →MetaContents

7장. SFT 데이터 구성과 Chat Template

학습 입력과 추론 입력

받아쓰기 연습장을 생각해 봅니다. 연습할 때는 문제와 모범 답안이 함께 적힌 장을 보고, 답안 부분을 따라 쓰며 채점받습니다. 시험 볼 때는 문제와 "답:" 칸까지만 적힌 장을 받고 그 뒤를 스스로 채웁니다. 학습 입력과 추론 입력의 차이가 이것입니다.

학습 입력은 질문과 모범 답변과 끝 표시를, 추론 입력은 질문과 assistant 머리표를 담는다는 비교 그림

왼쪽 학습 입력에는 답변과 <|im_end|> 까지 넣어, 답변을 언제 끝내는지도 배우게 합니다. 오른쪽 추론 입력은 add_generation_prompt=True 로 <|im_start|>assistant 와 줄바꿈까지만 넣고, 그 뒤를 모델이 이어 씁니다. 이 옵션은 assistant 머리표를 붙일 뿐이고, 학습용과 추론용을 바꿔 주는 스위치가 아닙니다.

두 입력 견주기

구분넣는 것끝부분손실 계산
학습 입력system, user, assistant 의 모범 답변...답변<|im_end|> 와 줄바꿈답변과 <|im_end|> 에만
추론 입력system, user, add_generation_prompt=True<|im_start|>assistant 와 줄바꿈계산하지 않음(생성만)

짧은 예시

Python
from transformers import AutoTokenizer

tok = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-0.5B-Instruct")
question = [{"role": "user", "content": "환불은 언제까지 신청할 수 있나요?"}]
answer = [{"role": "assistant", "content": "수령 후 7일 이내에 신청하세요."}]

# 추론 입력: 질문 + assistant 머리표까지(add_generation_prompt=True)
infer_ids = tok.apply_chat_template(question, tokenize=True, add_generation_prompt=True)
# 학습 입력: 질문 + 모범 답변 + <|im_end|>
train_ids = tok.apply_chat_template(question + answer, tokenize=True)

print(len(infer_ids), len(train_ids))               # 결과: 42 57
# 학습 입력의 앞 42개가 추론 입력과 똑같은지 본다
print(train_ids[:len(infer_ids)] == infer_ids)      # 결과: True
# 뒤에 붙은 15개가 답변 부분이다. 마지막 두 개는 <|im_end|>(151645)와 줄바꿈(198)
print(len(train_ids) - len(infer_ids), train_ids[-2:])  # 결과: 15 [151645, 198]

이 코드가 뜻하는 것

시험지(추론 입력)는 42 토큰이고, 연습장(학습 입력)은 그 42 토큰 뒤에 답안 15 토큰을 더한 57 토큰입니다. 57 − 42 = 15 입니다. 앞부분이 한 글자도 다르지 않으므로, 학습 때 배운 "assistant 머리표 다음에 이렇게 쓴다"가 추론 때 그대로 쓰입니다. 답안의 마지막은 <|im_end|> 이므로 모델은 답을 끝내는 법도 함께 배웁니다.

줄하는 일쉽게 말하면
add_generation_prompt=True끝에 assistant 머리표를 붙인다"답:" 칸까지 적힌 시험지
question + answer질문과 답을 한 대화로 잇는다모범 답안이 적힌 연습장
train_ids[:len(infer_ids)] == infer_ids앞부분이 같은지 확인시험지가 연습장의 앞부분과 같은가
train_ids[-2:]마지막 두 토큰답안 끝의 마침 표시

주의할 점

  • 학습 데이터에서 <|im_end|> 가 빠지면 모델이 답을 끝내는 신호를 배우지 못합니다. 그러면 max_new_tokens 에 닿을 때까지 말을 이어 가거나 다음 user 턴까지 스스로 지어냅니다.
  • 추론할 때 add_generation_prompt=True 를 빼면 문자열이 user 턴에서 끝나므로, 모델이 답 대신 질문을 이어 쓸 수 있습니다.
← 이전 절7장 · 모델은 messages 를 직접 읽지 못한다: Chat Template다음 절 →7장 · input_ids, attention_mask, labels