본문 바로가기

프로그래밍/Python

[python] HF transformers 메시지 템플릿, 토큰화

모델의 메시지 템플릿 확인

구글의 Gemma3 모델의 chat_template 항목을 출력해 본다.

 

허깅페이스 모델

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("google/gemma-3-4b-it")
print(tokenizer.chat_template)

 

로컬 모델

from transformers import AutoTokenizer

model_path = "/local_path/models/gemma-3-4b-it"
tokenizer = AutoTokenizer.from_pretrained(model_path, local_files_only=True)

print(tokenizer.chat_template)

 

 

출력 결과를 살펴보면 tokenizer_config.json 의 chat_template 값을 가져온것과 같다.

해당 내용을 보면 어떻게 메시지를 처리하는지 확인 할 수 있는데, gemma-3 의 경우 아래와 같다

{{ bos_token }}
{%- if messages[0]['role'] == 'system' -%}
    {%- if messages[0]['content'] is string -%}
        {%- set first_user_prefix = messages[0]['content'] + '

' -%}
    {%- else -%}
        {%- set first_user_prefix = messages[0]['content'][0]['text'] + '

' -%}
    {%- endif -%}
    {%- set loop_messages = messages[1:] -%}
{%- else -%}
    {%- set first_user_prefix = "" -%}
    {%- set loop_messages = messages -%}
{%- endif -%}
{%- for message in loop_messages -%}
    {%- if (message['role'] == 'user') != (loop.index0 % 2 == 0) -%}
        {{ raise_exception("Conversation roles must alternate user/assistant/user/assistant/...") }}
    {%- endif -%}
    {%- if (message['role'] == 'assistant') -%}
        {%- set role = "model" -%}
    {%- else -%}
        {%- set role = message['role'] -%}
    {%- endif -%}
    {{ '<start_of_turn>' + role + '
' + (first_user_prefix if loop.first else "") }}
    {%- if message['content'] is string -%}
        {{ message['content'] | trim }}
    {%- elif message['content'] is iterable -%}
        {%- for item in message['content'] -%}
            {%- if item['type'] == 'image' -%}
                {{ '<start_of_image>' }}
            {%- elif item['type'] == 'text' -%}
                {{ item['text'] | trim }}
            {%- endif -%}
        {%- endfor -%}
    {%- else -%}
        {{ raise_exception("Invalid content type") }}
    {%- endif -%}
    {{ '<end_of_turn>
' }}
{%- endfor -%}
{%- if add_generation_prompt -%}
    {{'<start_of_turn>model
'}}
{%- endif -%}

 

"role", "content" 등으로 메시지 분류하는 부분들이 보이는데, 이 부분을 사용해 모델로 전달할 메시지가 만들어지 지게 된다.

추가로 필요한 토큰 정보가 있으면 tokenizer_config.json 에서 확인하면 된다.

 

 

 

 

허깅 페이스 입력 메시지 구조

보통 트레이닝을 위한 메시지셋과 같은 데이터들은 각 모델의 메시지 템플릿과 일치되는 형태로 제공되지 않으며, 해당 데이터들을 허깅페이스 입력 형태로 구성하고, 모델의 입력 데이터 형태로 변환하게 된다.

 

허깅 페이스의 입력 메시지는 아래의 키를 사용한 map 구조로 구성된다.

"role" : 메시지 역할 지정, 반드시 "system", "user", "assistant" 중 하나
"content" : 메시지 텍스트
"name" : 역할을 좀 더 세분화할때 사용
"function_call" : 함수 호출 기반 모델에서 사용
"tool_calls" : 외부 도구 호출하는 메시지에 사용
"tool_response" : 도구 호출에 대한 응답을 포함할 때 사용

 

https://huggingface.co/docs/transformers/v4.56.1/ko/chat_templating

 

채팅 모델을 위한 템플릿

(번역중) 효율적인 학습 기술들

huggingface.co

 

 

 

 

 

챗 템플릿 적용

apply_chat_template 메쏘드는 map 구조의 데이터를 모델의 입력 메시지 형태로 변경해 주는 메쏘드이다.

인자중 tokenize=False 로 넣으면 인코딩되지 않은 템플릿 스트링을 확인할 수 있다

messages = [
  {"role": "system", "content": "시스템 메시지"},
  {"role": "user", "content": "요청 메시지"},
  {"role": "assistant", "content": "답변 메시지"}
]

template_message = tokenizer.apply_chat_template(messages, tokenize=False)
print(template_message)

 

 

생성 프롬프트를 포함하는 메시지 템플릿

tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)

 

 

 

 

 

 

 

여러 메시지 토큰화

data = [
  {
    "messages": [
      {"role": "system", "content": "시스템 프롬프트"},
      {"role": "user", "content": "유저 프롬프트"},
      {"role": "assistant", "content": "답변 프롬프트"}
    ]
  },
  {
    "messages": [
      {"role": "system", "content": "시스템 프롬프트"},
      {"role": "user", "content": "유저 프롬프트"},
      {"role": "assistant", "content": "답변 프롬프트"}    
    ]
  },
  {
    "messages": [
      {"role": "system", "content": "시스템 프롬프트"},
      {"role": "user", "content": "유저 프롬프트"},
      {"role": "assistant", "content": "답변 프롬프트"}   
    ]
  }
]

def preprocess(example):
  return {
    "input_ids": tokenizer.apply_chat_template(example["messages"], tokenize=True)
  }
  
  
dataset = Dataset.from_list(data)
tokenized_dataset = dataset.map(preprocess)
print(tokenized_dataset)