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

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

실습 3 — Qwen 의 Chat Template 들여다보기

messages 를 Qwen 의 대본 양식(ChatML)으로 바꿔 보고, system 메시지와 여러 턴 대화가 어떻게 들어가는지 확인합니다. 6장의 준비 코드(셀 3, 6)를 먼저 실행해 둡니다. 셀 6 이 tokenizer 를 불러옵니다. 이 실습은 토크나이저만 쓰므로 GPU 가 없어도 됩니다.

코드를 단계별로 따라가기 전에 실행 흐름을 한 장으로 봅니다. 두 갈래는 따로 실행할 수 있는 셀 묶음입니다.

실습 3 코드의 실행 흐름도. 6차시 준비 코드의 tokenizer 를 쓴 뒤 A 갈래는 user 와 assistant 한 턴짜리 messages 에 템플릿을 입혀 system 기본 문구가 붙고 im_end 로 끝나는 문자열을 보고, B 갈래는 system 과 네 턴짜리 multi_turn 에 add_generation_prompt=True 로 템플릿을 입혀 assistant 머리표로 끝나는 문자열을 본다
갈래단계반복과 조건핵심 한 줄
A. 한 턴 대화1~2없음tokenizer.apply_chat_template(messages, tokenize=False)
B. system·여러 턴3없음tokenizer.apply_chat_template(multi_turn, tokenize=False, add_generation_prompt=True)
  • 갈래의 색: A 는 짙은 청록, B 는 살구입니다. 두 갈래는 서로 쓰는 변수가 없어서, tokenizer 만 있으면 3단계만 따로 실행해도 됩니다.
  • A 의 끝: 답변 뒤에 <|im_end|> 가 붙어 끝납니다. 질문과 모범 답이 다 들어 있는 학습 입력의 모양입니다.
  • B 의 끝: <|im_start|>assistant 머리표로 끝납니다. 모델이 답을 이어 쓸 자리를 열어 둔 추론 입력의 모양입니다.
  • 마름모가 없는 까닭: 메시지를 하나씩 돌며 머리표를 붙이는 일은 apply_chat_template 안에서 일어나고 코드에는 보이지 않으므로, 네모 하나로 그렸습니다.

1단계. 한 턴 대화 messages 만들기

손님 질문 한 줄과 상담원 답 한 줄짜리 짧은 대본을 준비합니다. 이 셀은 변수만 만듭니다.

Python
# messages에 Qwen Chat Template 적용
# messages: role 과 content 를 담은 사전의 리스트. user 질문 하나와 assistant 답 하나
messages = [  # 사용자 질문과 정답 답변이 있는 한 턴 대화입니다.
    {"role": "user", "content": "환불은 언제까지 신청할 수 있나요?"},  # 사용자 메시지입니다.
    # assistant: 모델이 해야 할 모범 답
    {"role": "assistant", "content": "수령 후 7일 이내에 마이페이지에서 신청하실 수 있습니다."},
]

2단계. Chat Template 을 입혀 문자열로 보기

대본을 Qwen 의 양식에 옮겨 적어, 이름표가 어떻게 붙는지 봅니다.

Python
print("[messages -> 문자열]")
# apply_chat_template = 대본 양식 입히기. tokenize=False: 토큰 ID 가 아니라 사람이 읽을 문자열로 돌려준다
# 결과: system 기본 문구, user 질문, assistant 답이 <|im_start|>역할 ... <|im_end|> 로 감싸져 나온다
print(tokenizer.apply_chat_template(messages, tokenize=False))
출력
[messages -> 문자열]
<|im_start|>system
You are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>
<|im_start|>user
환불은 언제까지 신청할 수 있나요?<|im_end|>
<|im_start|>assistant
수령 후 7일 이내에 마이페이지에서 신청하실 수 있습니다.<|im_end|>

3단계. system 메시지와 여러 턴 대화

"너는 쇼핑몰 상담원이다"라는 배역 설명을 붙이고, 질문과 답을 두 번 주고받는 대본을 만들어, 다음 답을 생성시킬 시험지 모양으로 바꿉니다.

Python
# system 지시와 여러 번 주고받은 대화가 채팅 템플릿에 어떻게 들어가는지 확인합니다.
multi_turn = [  # system 메시지와 두 번의 사용자 질문을 담습니다.
    # system: 대화 내내 지킬 역할과 규칙을 적는 자리
    {"role": "system", "content": "너는 쇼핑몰 상담원이다."},
    {"role": "user", "content": "배송비는 얼마인가요?"},
    {"role": "assistant", "content": "3만 원 이상 무료, 그 미만은 3,000원입니다."},
    # 마지막은 user 턴이다. 모델이 이어서 답할 차례
    {"role": "user", "content": "제주도는요?"},
]
# add_generation_prompt=True: 끝에 "<|im_start|>assistant" 머리표를 붙여 모델이 답을 이어 쓸 자리를 연다
# 결과: 우리가 준 system 문구가 기본 문구 대신 들어가고, 맨 끝이 <|im_start|>assistant 로 끝난다
print(tokenizer.apply_chat_template(multi_turn, tokenize=False, add_generation_prompt=True))  # 다음 답변을 생성할 문자열을 출력합니다.
출력
<|im_start|>system
너는 쇼핑몰 상담원이다.<|im_end|>
<|im_start|>user
배송비는 얼마인가요?<|im_end|>
<|im_start|>assistant
3만 원 이상 무료, 그 미만은 3,000원입니다.<|im_end|>
<|im_start|>user
제주도는요?<|im_end|>
<|im_start|>assistant

이 실습이 뜻하는 것

짧은 대본(1단계)을 Qwen 의 대본 양식에 옮겨 적어 보고(2단계), 배역 설명과 여러 번 주고받는 대본을 시험지 모양으로 바꿔 본(3단계) 일입니다. 2단계는 끝이 답변과 <|im_end|> 이므로 학습 입력의 모양이고, 3단계는 끝이 <|im_start|>assistant 이므로 추론 입력의 모양입니다.

단계출력뜻
1. messages출력 없음user 와 assistant 한 턴짜리 대화를 만들었습니다
2. 템플릿 적용system 기본 문구가 붙은 세 턴system 을 안 주면 Qwen 이 기본 문구를 넣습니다
3. system·멀티턴우리가 준 system, 네 턴, assistant 머리표턴마다 머리표와 <|im_end|> 로 나뉘고, 끝은 답할 자리입니다

한 줄로 줄이면, messages 리스트는 <|im_start|>역할 과 <|im_end|> 로 감싼 문자열 하나가 되어 모델에 들어가며, 이 양식을 손으로 조립하지 않고 apply_chat_template 에 맡깁니다.

코드 설명

  • tokenizer 는 6장 셀 6 에서 AutoTokenizer.from_pretrained(MODEL_NAME) 로 불러온 Qwen 토크나이저입니다. 템플릿 규칙이 토크나이저 안에 들어 있습니다.
  • tokenize=False 는 눈으로 확인하려고 문자열로 받는 것입니다. 학습과 생성에서는 보통 토큰 ID 로 받습니다.
  • 2단계에서 system 을 주지 않았는데도 "You are Qwen, ..." 이 들어갔습니다. 3단계처럼 system 을 주면 그 문구가 기본 문구를 대신합니다.
  • 3단계 출력의 맨 끝 <|im_start|>assistant 다음 줄이 비어 있습니다. 모델은 여기서부터 "제주도는요?"에 대한 답을 이어 씁니다.
  • 실습 2 에서 만든 prompt-completion 데이터도 8장 학습 때 SFTTrainer 가 이 템플릿을 입혀 2단계 같은 문자열로 바꿉니다.
← 이전 절7장 · 실습 2 — 대화 형식으로 바꾸고 나누기다음 절 →7장 · 프로젝트 1 — 고객 문의를 SFT 데이터로 바꾸기