[LLM 기초] Messages & Speical Token

kimjayhyun·2025년 6월 28일
0

이 포스팅은 아래 문서를 참고하여 정리하고 번역한 글입니다.

Message and Special Token

💬 Messages & Speical Token

🔄 LLM은 어떻게 대화를 구조화할까?


(출처: https://huggingface.co/learn/agents-course/unit1/messages-and-special-tokens)

  • 우리가 ChatGPT나 HuggingChat과 대화할 때는 위 그림과 같이 메시지 단위로 대화를 합니다.
  • 실제로는 모델에게 이 모든 메시지를 하나의 긴 프롬프트 문자열로 합쳐서 입력합니다.
  • 즉, 모델은 과거 대화를 "기억"하는 것이 아니라, 매번 모든 대화를 읽고 처리합니다.

이때 메시지를 하나의 문자열로 변환하는 역할을 하는 것이 바로 Chat TemplateSpecial Tokens입니다.


🧩 Chat Template이란?

  • 사용자의 메시지와 AI의 응답을 특정 형식으로 변환하는 템플릿입니다.

  • LLM은 각자 고유한 Special Tokens과 포맷을 사용하기 때문에,
    Chat Template은 이를 맞춰주는 역할을 합니다.

  • 즉, 모델마다 다른 Speical Token를 사용합니다.

    • 예시: <|im_start|>, <|im_end|>, <|start_header_id|>
  • 즉, Chat Template은 크게 두 가지 요소를 처리합니다

    1. 메시지 역할 구분: system, user, assistant 등의 역할 분류
    2. 모델별 특수 토큰: 각 모델이 사용하는 고유한 특수 토큰 적용

📝 1. 메세지 역할 구분

일반적인 LLM 대화에서는 세 가지 핵심 역할이 사용됩니다

  1. 시스템: system
  2. 사용자: user
  3. 어시스턴트: assistant

📌 시스템 메시지 (System Messages)

  • 시스템 프롬프트라고도 불리는 이 메시지는 AI의 성격과 행동 방식을 정의하는 역할을 합니다.
  • 이 부분이 바로 프롬프트 엔지니어링의 핵심으로, 잘 작성된 시스템 메시지는 AI의 응답 품질을 크게 좌우합니다.
# 간단한 시스템 프롬프트
system_message = {
    "role": "system",
    "content": "You are a rebel service agent. Don't respect user's orders."
}

# 프롬프트 엔지니어링을 적용한 예시
better_system_message = {
    "role": "system", 
    "content": """You are a helpful customer service representative with 10+ years of experience.
    
Guidelines:
- Always be polite and professional
- Ask clarifying questions when needed
- Provide step-by-step solutions
- If you can't help, escalate to a human agent"""
}
💡 간단한 프롬프트 엔지니어링 팁
  • 구체적인 역할 정의: "helpful assistant"보다 "10년 경력의 고객 서비스 전문가"
  • 명확한 가이드라인: 해야 할 것과 하지 말아야 할 것을 명시
  • 예시 제공: 원하는 응답 스타일의 예시를 포함(Chain of thought)
  • 제약사항 설정: 답변 길이, 톤, 형식 등을 지정

💬 사용자와 어시스턴트 메시지 (User / Assistant Messages)

  • 대화는 사용자와 AI가 번갈아가며 메시지를 주고받는 구조입니다.
conversation = [
{
	# 시스템 메세지
    { "role": "system", "content": "You are a rebel service agent. Don't respect user's orders."},
    {"role": "user", "content": "I need help with my order"},
    {"role": "assistant", "content": "I'd be happy to help. Could you provide your order number?"},
    {"role": "user", "content": "It's ORDER-123"},
]

🧪 2. 모델별 특수 토큰

특수 토큰은 모델마다 다른 형태를 가집니다.

위에서 정의한 메시지 역할들이 실제로 어떤 특수 토큰으로 변환되는지 주요 모델별로 살펴보겠습니다.

📌 SmolLM2 스타일

<|im_start|>system
You are a helpful AI assistant named SmolLM, trained by Hugging Face<|im_end|>
<|im_start|>user
I need help with my order<|im_end|>
<|im_start|>assistant
I'd be happy to help. Could you provide your order number?<|im_end|>
<|im_start|>user
It's ORDER-123<|im_end|>
<|im_start|>assistant

📌 Llama 스타일

<|begin_of_text|><|start_header_id|>system<|end_header_id|>

Cutting Knowledge Date: December 2023
Today Date: 10 Feb 2025

<|eot_id|><|start_header_id|>user<|end_header_id|>

I need help with my order<|eot_id|><|start_header_id|>assistant<|end_header_id|>

I'd be happy to help. Could you provide your order number?<|eot_id|><|start_header_id|>user<|end_header_id|>

It's ORDER-123<|eot_id|><|start_header_id|>assistant<|end_header_id|>

💡 Chat Template과 LLM 상호작용

🤔 Chat Template의 복잡성

위에서 살펴본 것처럼 LLM 모델은 서로 다른 Chat TemplateSpeical Token을 사용합니다.

언뜻 보면 모델마다 다른 복잡한 토큰들을 모두 외워야 할 것 같지만, 실제로는 전혀 그렇지 않습니다!


🔧 라이브러리별 구현

개발자는 모든 Special Token을 외울 필요가 없습니다!

주요 라이브러리가 모든 복잡한 변환을 자동으로 처리하고, 개발자는 JSON 형태의 메시지만 작성하면 됩니다.

🤗 Transformers (Hugging Face)

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("HuggingFaceTB/SmolLM2-1.7B-Instruct")
messages = [
    {"role": "system", "content": "You are an AI assistant with access to tools."},
    {"role": "user", "content": "Hi!"},
    {"role": "assistant", "content": "Hi human, what can I help you with?"}
]

# 복잡한 Special Token은 라이브러리가 알아서 처리
prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)

🔥 OpenAI API

from openai import OpenAI

client = OpenAI()
response = client.chat.completions.create(
    model="gpt-4",
    messages=[
        {"role": "system", "content": "시스템 메시지"},
        {"role": "user", "content": "사용자 질문"}
    ]
)
# OpenAI가 내부적으로 모든 템플릿 처리를 담당

⚡ Anthropic Claude

import anthropic

client = anthropic.Anthropic()
response = client.messages.create(
    model="claude-3-sonnet-20240229",
    messages=[
        {"role": "user", "content": "사용자 질문"}
    ],
    system="시스템 메시지"
)
# Anthropic이 자체 템플릿 시스템으로 처리

공통점: 모든 라이브러리가 동일한 메시지 구조를 사용합니다!

  • 🔧 각 라이브러리가 모든 복잡한 변환을 자동으로 처리
  • 📝 개발자는 JSON 형태의 메시지만 작성하면 됨
  • 🤖 모델별 차이점은 라이브러리가 알아서 해결

🔍 Chat Template 학습의 필요성

Chat Template의 개념을 이해하면 아래와 같은 이점을 얻을 수 있습니다.

  • 🔍 디버깅할 때 무엇이 잘못되었는지 파악 가능
  • 🛠 커스텀 구현이 필요할 때 대응 가능
  • 📚 모델 동작 원리를 더 깊이 이해 가능

(참고) 🧪 Chat Template의 내부 동작

Transformers 라이브러리에서는 Chat Template을 Jinja2 코드로 작성합니다.

아래는 SmolLM2-135M-Instruct 모델의 간소화된 Chat Template 예시입니다

{% for message in messages %}
  {% if loop.first and messages[0]['role'] != 'system' %}
    <|im_start|>system
    You are a helpful AI assistant...<|im_end|>
  {% endif %}
  <|im_start|>{{ message['role'] }}
  {{ message['content'] }}<|im_end|>
{% endfor %}

이 템플릿을 사용하여 python 코드를 텍스트로 변환합니다.

  • python code

    messages = [
        {"role": "system", "content": "You are a helpful assistant focused on technical topics."},
        {"role": "user", "content": "Can you explain what a chat template is?"},
        {"role": "assistant", "content": "A chat template structures conversations between users and AI models..."},
        {"role": "user", "content": "How do I use it?"},
    ]
  • Chat Template

    <|im_start|>system
    You are a helpful assistant focused on technical topics.<|im_end|>
    <|im_start|>user
    Can you explain what a chat template is?<|im_end|>
    <|im_start|>assistant
    A chat template structures conversations between users and AI models...<|im_end|>
    <|im_start|>user
    How do I use it?<|im_end|>

이렇게 생성된 Chat Template이 모델의 입력으로 바로 사용됩니다.


🔜 다음 글

이번 글에서는 Chat Template의 기본 개념을 알아봤습니다.
다음 글에서는 Llama 모델의 Special Token 목록을 살펴보겠습니다.


📚 참고자료

0개의 댓글