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

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

모델은 messages 를 직접 읽지 못한다: Chat Template

연극 대본을 떠올려 봅니다. 대본에는 "철수: 안녕?", "영희: 응, 안녕." 처럼 말한 사람의 이름표가 줄마다 붙어 있습니다. 배우는 이 이름표로 누가 말할 차례인지 압니다. 파이썬의 [{"role": "user", "content": "..."}] 리스트는 사람이 보기 편한 모양일 뿐이고, 모델에 들어가는 것은 이름표가 붙은 긴 대본 한 편을 토큰 숫자로 바꾼 목록입니다. 이 대본 양식이 Chat Template 입니다.

messages, 템플릿 적용, 토큰화, 모델 입력의 네 걸음을 이은 흐름도

그림처럼 messages 리스트는 템플릿을 거쳐 머리표가 붙은 문자열 하나가 되고, 토크나이저를 거쳐 숫자 목록이 됩니다. 모델마다 머리표 모양이 다르고, 그 규칙은 토크나이저 설정 파일(tokenizer_config.json)에 함께 저장되어 있습니다. 그래서 문자열을 손으로 조립하지 않고 tokenizer.apply_chat_template() 을 씁니다. Qwen 의 양식은 ChatML 이라고 부릅니다.

Qwen(ChatML)의 머리표

표시토큰 ID뜻
<|im_start|>system151644 + 낱말모델의 역할과 응답 지침 시작. 따로 주지 않으면 기본 문구가 들어간다
<|im_start|>user151644 + 낱말사용자 발화 시작
<|im_start|>assistant151644 + 낱말모델 답변 시작
<|im_end|>151645한 턴의 끝. 모델이 이것을 생성하면 답변이 끝난다
<|endoftext|>151643이 토크나이저가 패딩에 쓰는 토큰

짧은 예시

Python
from transformers import AutoTokenizer

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

# apply_chat_template = 대본 양식 입히기. tokenize=False 면 문자열로, True 면 토큰 ID 목록으로 돌려준다
text = tok.apply_chat_template(messages, tokenize=False)
ids = tok.apply_chat_template(messages, tokenize=True)
print(text.count("<|im_start|>"), "개의 턴")  # 결과: 3 개의 턴 (system 기본 문구, user, assistant)
print("토큰 수:", len(ids))                    # 결과: 토큰 수: 57
print("앞 세 토큰:", ids[:3])                  # 결과: [151644, 8948, 198] → <|im_start|>, system, 줄바꿈
# convert_ids_to_tokens: ID 를 토큰 글자로 되돌린다
print(tok.convert_ids_to_tokens(ids[:2]))      # 결과: ['<|im_start|>', 'system']

이 코드가 뜻하는 것

두 줄짜리 대사를 대본 양식에 옮겨 적었더니 이름표가 셋 붙었습니다. 우리가 주지 않은 system 턴을 Qwen 템플릿이 "You are Qwen, created by Alibaba Cloud. ..." 기본 문구로 채웠기 때문입니다. 대본 전체는 57 토큰이고, 맨 앞은 <|im_start|>(151644), system(8948), 줄바꿈(198)입니다.

줄하는 일쉽게 말하면
apply_chat_template(messages, tokenize=False)머리표를 붙인 문자열을 만든다대본 양식에 옮겨 적기
apply_chat_template(messages, tokenize=True)같은 문자열을 토큰 ID 로 바꾼다대본을 상품 번호 열로
text.count("<|im_start|>")턴 수를 센다이름표가 몇 개인가
convert_ids_to_tokens(ids[:2])번호를 토큰 글자로 되돌린다번호표 읽어 보기

주의할 점

  • 템플릿은 모델마다 다릅니다. Qwen 데이터를 Llama 템플릿으로 학습하거나, 학습 때와 다른 템플릿으로 추론하면 답이 이상해집니다. 언제나 그 모델의 apply_chat_template 을 씁니다.
  • Qwen 은 system 을 주지 않으면 기본 문구를 넣습니다. 학습 때와 쓸 때 system 을 같게 맞춰야 학습한 말투가 잘 나옵니다.
← 이전 절7장 · 학습·검증·평가 데이터 나누기다음 절 →7장 · 학습 입력과 추론 입력