🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Midtraining으로 AI에게 대화 능력 부여하기 - 슬라이드 1/7
A

AI Generated

2025. 11. 28. · 15 Views

Midtraining으로 AI에게 대화 능력 부여하기

사전학습된 언어 모델에 대화 능력을 부여하는 Midtraining 과정을 살펴봅니다. SmolTalk 데이터셋 구조부터 학습 코드 분석, Learning Rate 전략까지 실무에 필요한 핵심을 다룹니다.


목차

  1. Midtraining이란
  2. Base_모델과의_차이
  3. 대화_데이터셋_구조_SmolTalk
  4. mid_train_py_소스_분석
  5. Learning_Rate_조정_전략
  6. 대화_템플릿_적용

1. Midtraining이란

김개발 씨는 최근 회사에서 자체 AI 챗봇을 만들라는 미션을 받았습니다. 오픈소스 언어 모델을 다운로드했는데, 질문을 해도 이상한 문장만 이어서 생성할 뿐 대화가 되지 않았습니다.

"분명 똑똑한 모델이라던데, 왜 대화를 못 하는 거지?"

Midtraining은 사전학습(Pretraining)과 미세조정(Fine-tuning) 사이에 위치하는 학습 단계입니다. 마치 외국어를 배운 학생에게 실제 회화 연습을 시키는 것과 같습니다.

이 과정을 통해 모델은 단순한 텍스트 생성기에서 진정한 대화 파트너로 변신하게 됩니다.

다음 코드를 살펴봅시다.

# Midtraining의 핵심 개념을 보여주는 구조
from transformers import AutoModelForCausalLM, AutoTokenizer

# 1단계: Pretraining - 대량의 텍스트로 언어 학습
# (이미 완료된 상태의 모델을 불러옴)
base_model = AutoModelForCausalLM.from_pretrained("HuggingFaceTB/SmolLM2-135M")

# 2단계: Midtraining - 대화 데이터로 상호작용 학습
# 대화 형식의 데이터셋 로드
from datasets import load_dataset
chat_dataset = load_dataset("HuggingFaceTB/smoltalk", "everyday-conversations")

# 3단계: 대화 템플릿 적용 후 학습
# 모델이 user/assistant 역할을 구분하도록 훈련

김개발 씨는 입사 2년 차 ML 엔지니어입니다. 팀장님이 갑자기 부르더니 이런 요청을 했습니다.

"우리 서비스에 맞는 AI 어시스턴트를 만들어야 해요. 오픈소스 모델 써서 해볼 수 있겠어요?" 자신 있게 "네!"라고 대답한 김개발 씨는 곧 벽에 부딪혔습니다.

HuggingFace에서 유명한 언어 모델을 다운로드했는데, 이 모델은 질문을 던지면 답변 대신 질문과 비슷한 문장을 계속 이어서 생성했습니다. 그렇다면 대체 무엇이 문제였을까요?

답은 바로 Midtraining의 부재에 있었습니다. 우리가 흔히 접하는 ChatGPT나 Claude 같은 AI는 사실 여러 단계의 학습을 거친 결과물입니다.

가장 먼저 Pretraining 단계에서 인터넷의 방대한 텍스트를 학습하여 언어 자체를 이해합니다. 하지만 여기서 끝나면 모델은 그저 다음 단어를 예측하는 기계에 불과합니다.

마치 영어 문법책을 달달 외운 학생과 같습니다. 문법은 완벽하게 알지만, 실제 외국인 앞에서는 한마디도 못하는 상황이죠.

이때 필요한 것이 바로 Midtraining입니다. Midtraining은 모델에게 대화의 규칙을 가르치는 과정입니다.

"사용자가 질문하면 답변해야 한다", "공손하게 응대해야 한다", "모르면 모른다고 말해야 한다" 같은 상호작용의 기본을 학습시킵니다. 쉽게 비유하자면, Pretraining은 학교에서 이론을 배우는 것이고, Midtraining은 실제 현장에서 인턴십을 하는 것과 같습니다.

아무리 이론을 많이 알아도 실무 경험 없이는 제대로 된 일을 할 수 없듯이, 언어 모델도 대화 연습 없이는 제대로 된 대화를 나눌 수 없습니다. 선배 개발자 박시니어 씨가 김개발 씨에게 조언했습니다.

"Base 모델을 바로 쓰면 안 돼요. Midtraining이나 Instruction Tuning을 거친 모델을 써야 대화가 가능해요.

아니면 직접 학습시키든지요." Midtraining의 핵심은 대화 구조의 학습에 있습니다. 모델은 이 과정에서 입력과 출력의 경계, 화자의 구분, 대화의 맥락 유지 방법을 배웁니다.

이런 학습이 이루어져야 비로소 우리가 기대하는 AI 어시스턴트의 모습이 완성됩니다. 김개발 씨는 고개를 끄덕였습니다.

"아하, 그래서 모델 이름에 -Instruct나 -Chat이 붙은 버전이 따로 있었군요!"

실전 팁

💡 - Base 모델과 Instruct 모델의 차이를 반드시 확인하세요

  • 직접 Midtraining을 하려면 충분한 대화 데이터셋이 필요합니다

2. Base 모델과의 차이

김개발 씨는 HuggingFace에서 같은 모델의 두 가지 버전을 발견했습니다. 하나는 SmolLM2-135M이고, 다른 하나는 SmolLM2-135M-Instruct였습니다.

둘 다 같은 크기인데, 왜 굳이 두 버전이 존재하는 걸까요?

Base 모델은 다음 토큰을 예측하도록 학습된 순수한 언어 모델입니다. 반면 Instruct 모델은 Midtraining을 통해 지시사항을 따르고 대화할 수 있도록 추가 학습된 모델입니다.

마치 원석과 가공된 보석의 차이와 같습니다.

다음 코드를 살펴봅시다.

from transformers import AutoModelForCausalLM, AutoTokenizer

# Base 모델의 동작
base_tokenizer = AutoTokenizer.from_pretrained("HuggingFaceTB/SmolLM2-135M")
base_model = AutoModelForCausalLM.from_pretrained("HuggingFaceTB/SmolLM2-135M")

prompt = "What is the capital of France?"
inputs = base_tokenizer(prompt, return_tensors="pt")
outputs = base_model.generate(**inputs, max_new_tokens=50)

print(base_tokenizer.decode(outputs[0]))
# 출력: "What is the capital of France? What is the capital of Germany? What is..."
# Base 모델은 질문에 답하지 않고 비슷한 패턴을 이어서 생성합니다

# Instruct 모델은 대화 템플릿을 적용하여 답변을 생성합니다

박시니어 씨가 김개발 씨를 회의실로 불렀습니다. 화이트보드에 두 개의 원을 그리며 설명을 시작했습니다.

"자, 여기 왼쪽 원이 Base 모델이고, 오른쪽이 Instruct 모델이야. 둘 다 같은 아키텍처, 같은 파라미터 수를 가지고 있어.

그런데 행동 방식은 완전히 달라." Base 모델은 인터넷에서 수집한 수조 개의 텍스트로 학습됩니다. 위키백과, 뉴스 기사, 책, 코드 등 다양한 텍스트를 보면서 "다음에 어떤 단어가 올 확률이 높은가"를 학습합니다.

이것이 바로 Causal Language Modeling입니다. 이 학습 방식의 결과로 Base 모델은 놀라운 언어 능력을 갖추게 됩니다.

문법을 완벽하게 이해하고, 다양한 주제에 대한 지식을 습득합니다. 하지만 치명적인 한계가 있습니다.

바로 "대화"라는 개념을 모른다는 점입니다. 왜 그럴까요?

인터넷의 텍스트 대부분은 독백 형태이기 때문입니다. 기사, 백과사전, 소설 등은 누군가 질문하고 답하는 구조가 아닙니다.

그래서 Base 모델에게 질문을 던지면, 모델은 이것을 질문으로 인식하지 않습니다. 그저 "질문 형태의 텍스트" 다음에 올 법한 텍스트를 생성할 뿐입니다.

박시니어 씨가 예를 들어주었습니다. "Base 모델에게 '프랑스의 수도는 어디야?'라고 물으면, 모델은 이걸 퀴즈 문제집의 한 줄이라고 생각해.

그래서 다음 문제인 '독일의 수도는 어디야?'를 이어서 생성하는 거지." 반면 Instruct 모델은 다릅니다. Midtraining 과정에서 수많은 대화 데이터를 학습했기 때문에, 질문에는 답변해야 한다는 것을 알고 있습니다.

사용자의 의도를 파악하고, 그에 맞는 응답을 생성하는 능력을 갖추게 됩니다. 김개발 씨가 물었습니다.

"그러면 Base 모델은 쓸모가 없는 건가요?" 박시니어 씨가 고개를 저었습니다. "아니, Base 모델도 중요해.

특정 도메인에 맞게 커스터마이징하려면 오히려 Base 모델부터 시작하는 게 좋을 때도 있어. Instruct 모델은 이미 특정 방식으로 학습되어 있어서 새로운 스타일을 학습시키기 어려울 수 있거든." 결국 Base 모델과 Instruct 모델은 목적에 따라 선택해야 합니다.

당장 대화형 서비스를 만들고 싶다면 Instruct 모델을, 처음부터 원하는 방식으로 학습시키고 싶다면 Base 모델을 선택하면 됩니다.

실전 팁

💡 - 프로토타입은 Instruct 모델로 빠르게 검증하세요

  • 커스텀 페르소나가 필요하면 Base 모델부터 학습을 고려하세요

3. 대화 데이터셋 구조 SmolTalk

김개발 씨는 직접 Midtraining을 해보기로 결심했습니다. 그런데 막상 시작하려니 가장 먼저 드는 의문이 있었습니다.

"대화 데이터는 어떤 형식으로 만들어야 하지?" 다행히 HuggingFace에서 좋은 예시를 찾을 수 있었습니다.

SmolTalk는 HuggingFace에서 공개한 합성 대화 데이터셋입니다. 일상 대화부터 수학 문제 풀이까지 다양한 시나리오를 포함하며, 각 대화는 user와 assistant 역할이 명확히 구분된 messages 형태로 구성됩니다.

다음 코드를 살펴봅시다.

from datasets import load_dataset

# SmolTalk 데이터셋 로드
dataset = load_dataset("HuggingFaceTB/smoltalk", "everyday-conversations")

# 데이터 구조 확인
sample = dataset["train"][0]
print(sample)
# 출력 형태:
# {
#   "messages": [
#     {"role": "user", "content": "Hi there! How are you today?"},
#     {"role": "assistant", "content": "Hello! I'm doing well, thank you..."},
#     {"role": "user", "content": "What's your favorite season?"},
#     {"role": "assistant", "content": "I find autumn particularly..."}
#   ]
# }

# 각 대화는 user와 assistant가 번갈아가며 발화
for msg in sample["messages"]:
    print(f"{msg['role']}: {msg['content'][:50]}...")

김개발 씨가 SmolTalk 데이터셋을 처음 열어보았을 때, 그 구조의 단순함에 놀랐습니다. 복잡한 형식일 거라 예상했는데, 실제로는 아주 직관적이었습니다.

SmolTalk의 기본 단위는 messages라는 배열입니다. 이 배열 안에는 대화의 각 발화가 순서대로 들어있습니다.

마치 카카오톡 대화창을 JSON으로 옮겨놓은 것과 같습니다. 각 발화는 두 가지 정보를 담고 있습니다.

role은 누가 말했는지를 나타내고, content는 무슨 말을 했는지를 담습니다. role은 보통 user, assistant, system 중 하나입니다.

박시니어 씨가 설명을 덧붙였습니다. "이 구조가 왜 중요하냐면, 모델이 학습할 때 '어디까지가 입력이고 어디부터가 출력인지'를 알아야 하기 때문이야.

role 정보가 없으면 모델은 전체를 하나의 텍스트로 인식해버려." SmolTalk는 everyday-conversations 서브셋 외에도 여러 종류의 대화를 포함합니다. 수학 문제를 푸는 대화, 코딩 질문에 답하는 대화, 글쓰기를 도와주는 대화 등 다양한 시나리오가 있습니다.

이렇게 다양한 유형의 대화를 학습해야 모델이 범용적인 대화 능력을 갖추게 됩니다. 흥미로운 점은 SmolTalk가 합성 데이터라는 것입니다.

실제 사람들의 대화가 아니라, 더 큰 AI 모델이 생성한 대화입니다. 왜 이런 방식을 사용할까요?

실제 대화 데이터를 대량으로 수집하는 것은 개인정보 문제도 있고, 품질 관리도 어렵습니다. 반면 합성 데이터는 원하는 품질과 형식으로 대량 생산이 가능합니다.

김개발 씨가 데이터셋을 살펴보다가 한 가지를 발견했습니다. "assistant의 답변이 꽤 길고 자세하네요.

이건 의도적인 건가요?" 박시니어 씨가 고개를 끄덕였습니다. "맞아.

모델이 학습할 때 본 답변 스타일대로 생성하거든. 짧은 답변만 학습시키면 짧게만 대답하고, 자세한 답변을 학습시키면 자세하게 대답해.

그래서 데이터셋 설계가 정말 중요해." 또 하나 눈여겨볼 점은 대화의 턴 수입니다. SmolTalk의 대화들은 보통 2~4턴 정도로 구성됩니다.

너무 긴 대화는 학습 효율이 떨어지고, 너무 짧으면 맥락 유지 능력을 기르기 어렵습니다. 이 데이터 구조를 이해했다면, 이제 자신만의 대화 데이터셋도 만들 수 있습니다.

중요한 건 messages 배열, role 구분, 그리고 일관된 품질입니다.

실전 팁

💡 - 자체 데이터셋을 만들 때도 SmolTalk와 같은 messages 구조를 따르세요

  • 다양한 대화 유형을 포함해야 범용적인 모델이 됩니다

4. mid train py 소스 분석

김개발 씨는 이제 실제 학습 코드를 살펴볼 차례입니다. HuggingFace의 smol-course에서 제공하는 mid_train.py 파일을 열어보았습니다.

생각보다 코드가 짧아서 놀랐습니다. "이게 전부야?"

mid_train.py는 SFTTrainer를 활용한 Midtraining 스크립트입니다. 모델 로드, 데이터셋 준비, 학습 설정, 그리고 학습 실행까지 핵심 단계를 담고 있습니다.

복잡해 보이지만 핵심은 단 몇 줄의 설정에 있습니다.

다음 코드를 살펴봅시다.

from transformers import AutoModelForCausalLM, AutoTokenizer
from datasets import load_dataset
from trl import SFTConfig, SFTTrainer

# 1. 모델과 토크나이저 로드
model_name = "HuggingFaceTB/SmolLM2-135M"
model = AutoModelForCausalLM.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)

# 2. 데이터셋 로드
dataset = load_dataset("HuggingFaceTB/smoltalk", "everyday-conversations", split="train")

# 3. 학습 설정 - 핵심 하이퍼파라미터
training_args = SFTConfig(
    output_dir="./smol_mid",
    learning_rate=1e-4,           # Base 모델보다 낮은 학습률
    num_train_epochs=1,
    per_device_train_batch_size=8,
    gradient_accumulation_steps=4,
)

# 4. Trainer 생성 및 학습 시작
trainer = SFTTrainer(model=model, args=training_args, train_dataset=dataset, tokenizer=tokenizer)
trainer.train()

박시니어 씨가 김개발 씨의 모니터를 보며 말했습니다. "자, 이 코드를 하나씩 뜯어보자.

생각보다 단순해." 먼저 가장 위에서 필요한 라이브러리를 불러옵니다. transformers에서 모델과 토크나이저를, datasets에서 데이터셋 로드 기능을, trl에서 학습 도구를 가져옵니다.

TRL은 Transformer Reinforcement Learning의 약자입니다. 이름과 달리 강화학습뿐 아니라 SFT(Supervised Fine-Tuning)도 지원합니다.

Midtraining에서는 주로 SFTTrainer를 사용합니다. 첫 번째 단계는 모델과 토크나이저 로드입니다.

AutoModelForCausalLM은 텍스트 생성에 특화된 모델 클래스입니다. from_pretrained 메서드로 HuggingFace Hub에서 모델을 자동으로 다운로드합니다.

토크나이저도 함께 로드해야 합니다. 토크나이저는 텍스트를 모델이 이해할 수 있는 숫자로 변환하는 역할을 합니다.

모델마다 자신만의 토크나이저가 있으므로 반드시 같이 로드해야 합니다. 두 번째 단계는 데이터셋 로드입니다.

load_dataset 함수로 SmolTalk 데이터셋을 가져옵니다. split="train"을 지정하면 학습용 데이터만 로드됩니다.

세 번째 단계가 핵심인 SFTConfig 설정입니다. 여기서 학습의 모든 세부사항을 결정합니다.

output_dir은 학습된 모델을 저장할 경로입니다. learning_rate는 학습 속도를 결정하는 중요한 값입니다.

김개발 씨가 물었습니다. "learning_rate가 1e-4인데, 이게 적절한 값인가요?" 박시니어 씨가 설명했습니다.

"Pretraining에서는 보통 1e-3 정도를 쓰는데, Midtraining에서는 더 낮춰야 해. 이미 학습된 지식을 망치지 않으면서 새로운 능력만 추가해야 하거든.

이걸 Catastrophic Forgetting을 방지한다고 해." num_train_epochs는 전체 데이터셋을 몇 번 반복할지 정합니다. Midtraining에서는 보통 1~3 에포크면 충분합니다.

per_device_train_batch_size와 gradient_accumulation_steps는 메모리와 학습 효율의 균형을 맞추는 설정입니다. 마지막으로 SFTTrainer를 생성하고 train() 메서드를 호출하면 학습이 시작됩니다.

Trainer가 내부적으로 데이터를 배치로 나누고, 그래디언트를 계산하고, 가중치를 업데이트하는 모든 과정을 처리합니다. 김개발 씨는 감탄했습니다.

"정말 이게 전부군요. 복잡한 학습 루프를 직접 작성할 필요가 없네요."

실전 팁

💡 - SFTTrainer는 내부적으로 대화 템플릿을 자동 적용합니다

  • gradient_accumulation_steps로 GPU 메모리 부족 문제를 해결할 수 있습니다

5. Learning Rate 조정 전략

학습을 시작한 김개발 씨는 이상한 현상을 발견했습니다. 학습 초반에는 loss가 잘 줄어들더니, 어느 순간부터 오히려 올라가기 시작했습니다.

"뭔가 잘못된 건가?" 박시니어 씨가 그래프를 보더니 바로 원인을 짚어냈습니다.

Learning Rate는 모델이 얼마나 빠르게 학습할지 결정하는 핵심 하이퍼파라미터입니다. Midtraining에서는 Pretraining보다 훨씬 낮은 학습률을 사용해야 합니다.

또한 WarmupDecay 스케줄을 적용하여 안정적인 학습을 유도합니다.

다음 코드를 살펴봅시다.

from trl import SFTConfig

# Learning Rate 조정 전략이 적용된 설정
training_args = SFTConfig(
    output_dir="./smol_mid",

    # 핵심: Pretraining(1e-3)보다 10배 낮은 학습률
    learning_rate=1e-4,

    # Warmup: 처음에는 천천히 시작
    warmup_ratio=0.1,          # 전체 스텝의 10%는 워밍업

    # Decay: 학습 후반에는 점점 줄이기
    lr_scheduler_type="cosine",  # 코사인 스케줄러 사용

    # 기타 설정
    num_train_epochs=1,
    per_device_train_batch_size=8,
    logging_steps=10,          # 10스텝마다 로그 출력
)

# 학습률 변화 패턴:
# Step 0~100: 0 → 1e-4 (Warmup, 서서히 증가)
# Step 100~900: 1e-4 → 0 (Cosine Decay, 부드럽게 감소)

박시니어 씨가 화이트보드에 그래프를 그리기 시작했습니다. "Learning Rate는 마치 자동차의 액셀러레이터와 같아.

너무 세게 밟으면 길을 벗어나고, 너무 약하게 밟으면 목적지에 도달하지 못해." Learning Rate가 높으면 모델은 빠르게 학습하지만, 최적점을 지나쳐버릴 위험이 있습니다. 반대로 너무 낮으면 학습이 너무 느리거나 지역 최적점에 갇힐 수 있습니다.

Midtraining에서 특히 주의해야 할 점이 있습니다. 바로 Catastrophic Forgetting 문제입니다.

이미 Pretraining에서 학습한 지식을 잊어버리는 현상입니다. 높은 학습률로 대화 데이터를 학습시키면, 모델이 언어 자체를 잊어버릴 수 있습니다.

"그래서 Pretraining에서 1e-3을 썼다면, Midtraining에서는 1e-4나 1e-5를 쓰는 거야. 기존 지식은 보존하면서 새로운 능력만 살짝 얹는 느낌이지." Warmup은 학습 초반에 학습률을 점진적으로 높이는 기법입니다.

자동차로 치면 출발할 때 천천히 속도를 올리는 것과 같습니다. warmup_ratio=0.1은 전체 학습 스텝의 10%를 워밍업에 사용한다는 의미입니다.

왜 Warmup이 필요할까요? 학습 초반에는 그래디언트가 불안정합니다.

모델이 아직 데이터의 패턴을 파악하지 못한 상태에서 큰 학습률을 적용하면 가중치가 급격히 변하면서 학습이 불안정해집니다. lr_scheduler_type은 학습률이 어떻게 변할지 결정합니다.

가장 많이 쓰이는 것은 cosine 스케줄러입니다. 코사인 곡선처럼 부드럽게 학습률을 줄여나갑니다.

김개발 씨가 자신의 문제를 이해했습니다. "아, 제가 학습률을 너무 높게 잡았군요.

그래서 중간에 loss가 오히려 올라간 거네요." 박시니어 씨가 덧붙였습니다. "맞아.

그리고 logging_steps를 10 정도로 설정해서 자주 loss를 확인해봐. 그래야 문제가 생겼을 때 빨리 발견할 수 있어." 학습률 설정에 정답은 없습니다.

모델 크기, 데이터셋 크기, 배치 크기에 따라 최적값이 달라집니다. 하지만 Midtraining에서는 "낮게 시작하고, 천천히 올려본다"는 원칙을 따르면 대부분 안전합니다.

실전 팁

💡 - loss가 발산하면 학습률을 10분의 1로 줄여보세요

  • Wandb나 TensorBoard로 학습 곡선을 시각화하면 문제 파악이 쉬워집니다

6. 대화 템플릿 적용

김개발 씨가 학습을 마치고 모델을 테스트해보았습니다. 그런데 이상합니다.

분명 대화 데이터로 학습했는데, 여전히 대화가 어색합니다. 박시니어 씨가 코드를 보더니 한숨을 쉬었습니다.

"대화 템플릿을 적용 안 했구나..."

**대화 템플릿(Chat Template)**은 대화 데이터를 모델이 이해할 수 있는 형식으로 변환하는 규칙입니다. 각 모델마다 고유한 템플릿이 있으며, 학습과 추론 시 동일한 템플릿을 적용해야 모델이 올바르게 동작합니다.

다음 코드를 살펴봅시다.

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("HuggingFaceTB/SmolLM2-135M")

# 대화 데이터
messages = [
    {"role": "user", "content": "What is machine learning?"},
    {"role": "assistant", "content": "Machine learning is a subset of AI..."}
]

# 대화 템플릿 적용
# 내부적으로 특수 토큰과 구조를 추가합니다
formatted = tokenizer.apply_chat_template(
    messages,
    tokenize=False,        # 문자열로 반환
    add_generation_prompt=True  # assistant 응답 시작 프롬프트 추가
)

print(formatted)
# 출력 예시:
# <|im_start|>user
# What is machine learning?<|im_end|>
# <|im_start|>assistant
# Machine learning is a subset of AI...<|im_end|>
# <|im_start|>assistant

박시니어 씨가 설명을 시작했습니다. "대화 템플릿을 이해하려면, 모델 입장에서 생각해봐야 해.

모델한테는 모든 게 그냥 텍스트야. user가 뭔지, assistant가 뭔지 모르거든." 대화 템플릿의 역할은 구조 정보를 텍스트에 인코딩하는 것입니다.

messages 배열의 role과 content 정보를 특수한 토큰과 형식을 사용해 하나의 문자열로 변환합니다. 예를 들어 SmolLM2 모델은 ChatML 형식을 사용합니다.

이 형식에서는 <|im_start|><|im_end|> 같은 특수 토큰으로 각 발화의 시작과 끝을 표시합니다. <|im_start|>user는 사용자의 발화가 시작됨을, <|im_end|>는 발화가 끝났음을 나타냅니다.

"이 특수 토큰들이 왜 중요하냐면," 박시니어 씨가 말을 이었습니다. "모델이 학습할 때 이 토큰들을 보고 '아, 여기서부터 내가 생성해야 하는구나'를 알게 되거든." apply_chat_template 메서드가 바로 이 변환을 수행합니다.

tokenize=False로 설정하면 토큰화하지 않고 문자열 형태로 반환합니다. 이렇게 하면 어떻게 변환되었는지 눈으로 확인할 수 있습니다.

add_generation_prompt=True는 매우 중요한 옵션입니다. 이 옵션을 켜면 마지막에 <|im_start|>assistant를 추가합니다.

이것이 모델에게 "이제 네가 대답할 차례야"라는 신호가 됩니다. 김개발 씨가 깨달았습니다.

"그러니까 학습할 때 이 템플릿으로 데이터를 변환했으면, 추론할 때도 똑같은 템플릿을 써야 하는 거네요?" "정확해. 학습 때 본 형식과 다른 형식으로 입력을 주면, 모델은 혼란에 빠지게 돼.

마치 한국어로 배운 사람한테 갑자기 영어로 말하는 것과 같아." SFTTrainer는 기본적으로 tokenizer의 chat_template을 자동으로 적용합니다. 하지만 커스텀 템플릿을 사용하거나 직접 데이터를 전처리할 때는 이 과정을 명시적으로 수행해야 합니다.

각 모델마다 템플릿이 다르다는 점도 기억해야 합니다. Llama 모델은 [INST][/INST] 태그를 사용하고, Mistral 모델은 또 다른 형식을 사용합니다.

모델을 바꿀 때는 반드시 해당 모델의 템플릿을 확인해야 합니다. 김개발 씨가 다시 코드를 수정하고 테스트해보니, 이번에는 모델이 제대로 대화를 이어갔습니다.

"드디어 됐다!"

실전 팁

💡 - tokenizer.chat_template 속성으로 현재 템플릿을 확인할 수 있습니다

  • 모델을 바꿀 때는 반드시 chat_template도 함께 확인하세요

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#LLM#Midtraining#Fine-tuning#SmolTalk#ChatTemplate#AI,LLM,Deep Learning

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.