토크나이저
토크나이저 (Tokenizers)
토크나이저는 텍스트를 모델의 입력인 텐서로 변환해요. 텍스트를 정규화하고 분할하며, 토크나이제이션 알고리즘을 적용하고, 특수 토큰을 추가하며, 출력 id를 다시 텍스트로 디코딩해요.
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
tokenizer("Sphinx of black quartz, judge my vow.", return_tensors="pt")
{
'input_ids': tensor([[ 2, 235277, 82913, 576, 2656, 30407, 235269, 11490, 970, 29871, 235265]]),
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
}
이 가이드는 로딩, 인코딩, 디코딩, 배치 처리, 그리고 사용 가능한 토크나이저 백엔드를 다뤄요.
출처: 문서
본문
토크나이저 로드하기
AutoTokenizer 클래스나 모델별 토크나이저 클래스로 토크나이저를 로드해요.
AutoTokenizer.from_pretrained()은 모델 config를 읽고 올바른 토크나이저 클래스를 해석한 다음, 그 인스턴스를 반환해요. 토크나이저 클래스를 미리 알 필요가 없어요. 대부분의 토크나이저는 Tokenizers 라이브러리의 빠른 Rust 기반 토크나이저인 TokenizersBackend의 서브클래스로 해석돼요.
AutoTokenizer로 로드하는 것이 권장되는 방법이에요.
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
모델별 토크나이제이션 클래스는 모델이 학습된 정확한 토크나이제이션 구성(normalizer, pre-tokenizer, 특수 토큰 규칙 등)을 사용하는 사전 구성된 TokenizersBackend예요.
모델별 클래스는 학습을 위해 빈 토크나이저를 초기화하거나 vocab, merges 같은 모델별 인자를 전달할 때 사용해요 (Customizing tokenizers 가이드에서 방법 확인). 빈 토크나이저는 최소 구성으로, 모델의 특수 토큰(<pad>, <eos>, <bos> 같은)만 포함해요.
from transformers import GemmaTokenizer
tokenizer = GemmaTokenizer()
corpus = [
["Sphinx of black quartz, judge my vow."],
["Pack my box with five dozen liquor jugs."],
["How vexingly quick daft zebras jump!"],
]
new_tokenizer = tokenizer.train_new_from_iterator(corpus, vocab_size=1000)
인코딩과 디코딩
TokenizersBackend.call() 메서드는 텍스트 또는 텍스트 배치를 input_ids, attention_mask 및 기타 모델 입력으로 인코딩해요. 패딩, 트렁케이션, 특수 토큰 삽입도 제어해요.
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
tokenizer("Sphinx of black quartz, judge my vow.", return_tensors="pt")
{
'input_ids': tensor([[ 2, 235277, 82913, 576, 2656, 30407, 235269, 11490, 970, 29871, 235265]]),
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
}
TokenizersBackend.encode()는 비슷하지만 input_ids만 반환해요.
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
input_ids = tokenizer.encode("Sphinx of black quartz, judge my vow.")
[2, 235277, 82913, 576, 2656, 30407, 235269, 11490, 970, 29871, 235265]
TokenizersBackend.decode()는 토크나이즈된 input_ids의 단일 시퀀스 또는 배치를 다시 텍스트로 변환해요.
tokenizer.decode(input_ids)
'<bos>Sphinx of black quartz, judge my vow.'
TokenizersBackend.decode()는 정확한 토크나이제이션 공백(spacing)을 보존해요. clean_up_tokenization_spaces를 설정하면 문장 부호 앞의 공백을 제거하고, skip_special_tokens를 설정하면 출력에서 특수 토큰을 제거해요.
tokenizer.decode(input_ids, skip_special_tokens=True)
'Sphinx of black quartz, judge my vow.'
특수 토큰
특수 토큰은 시퀀스의 구조적 경계(시퀀스 시작 또는 패딩 위치 같은)를 표시해요. 각 모델은 자신만의 특수 토큰 세트를 정의해요. 토크나이저를 호출하면 토크나이저가 이런 토큰을 추가해요.
input_ids = tokenizer.encode("Sphinx of black quartz, judge my vow.")
[2, 235277, 82913, 576, 2656, 30407, 235269, 11490, 970, 29871, 235265]
tokenizer.decode(input_ids)
'<bos>Sphinx of black quartz, judge my vow.'
extra_special_tokens 인자로 추가 이름 있는 특수 토큰을 등록해요. 멀티모달 모델은 이미지, 비디오, 오디오의 자리 표시자로 이들을 사용해요.
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained(
"google/gemma-3-4b-pt",
extra_special_tokens={"image_token": "<image>"}
)
배치 처리
배치 처리는 단일 호출로 여러 시퀀스를 토크나이즈해요. TokenizersBackend는 Rust 기반 백엔드가 스레드에 걸쳐 작업을 병렬화하기 때문에 큰 배치를 더 빠르게 처리해요.
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
tokenizer(
[
"Sphinx of black quartz, judge my vow.",
"Pack my box with five dozen liquor jugs.",
"How vexingly quick daft zebras jump!"
],
return_tensors="pt"
)
배치 처리는 모든 시퀀스가 동일한 길이를 공유해야 해요. 패딩과 트렁케이션은 다양한 길이의 시퀀스를 처리하는 전략이에요.
패딩 (Padding)
패딩은 짧은 시퀀스가 배치에서 가장 긴 시퀀스와 일치하도록 특수 토큰을 덧붙여요. attention mask는 패딩 위치를 0으로 표시해서 모델이 무시하게 해요. padding=True로 설정하면 가장 긴 시퀀스로 패딩하고, max_length를 전달하면 고정 크기로 패딩해요.
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
tokenizer(
[
"Sphinx of black quartz, judge my vow.",
"Pack my box with five dozen liquor jugs.",
"How vexingly quick daft zebras jump!"
],
return_tensors="pt",
padding=True,
)
{
'input_ids': tensor([
[ 2, 235277, 82913, 576, 2656, 30407, 235269, 11490, 970, 29871, 235265],
[ 0, 2, 6519, 970, 3741, 675, 4105, 25955, 42184, 225789, 235265],
[ 0, 2, 2299, 73378, 17844, 4320, 224463, 4949, 48977, 9902, 235341]
]),
'attention_mask': tensor([
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
])
}
[!NOTE] 대규모 언어 모델은 오른쪽에서 다음 토큰을 예측하는 생성을 방해하지 않도록 왼쪽에 패딩합니다.
트렁케이션 (Truncation)
트렁케이션은 시퀀스가 최대 길이 안에 들어가도록 토큰을 잘라내요. truncation=True로 설정하고 max_length를 지정하면 활성화돼요.
패딩과 트렁케이션은 함께 동작해요. 짧은 시퀀스는 패딩 토큰을 얻고, 긴 시퀀스는 뒤쪽 토큰을 잃어요. 함께 사용하면 촘촘한 직사각형 텐서를 만들어내요.
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
tokenizer(
[
"Sphinx of black quartz, judge my vow.",
"Pack my box with five dozen liquor jugs.",
"How vexingly quick daft zebras jump!"
],
return_tensors="pt",
padding=True,
truncation=True,
max_length=5
)
{
'input_ids': tensor([
[ 2, 235277, 82913, 576, 2656],
[ 2, 6519, 970, 3741, 675],
[ 2, 2299, 73378, 17844, 4320]
]),
'attention_mask': tensor([
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1]
])
}
백엔드
각 모델 토크나이저는 단일 파일에 정의되며 네 가지 토크나이제이션 백엔드를 지원해요.
| backend | implementation | description |
|---|---|---|
| TokenizersBackend | Tokenizers | 대부분의 모델에 대한 기본값 |
| SentencePieceBackend | SentencePiece | SentencePiece가 필요한 모델 |
| PythonBackend | Python | 특수한 커스텀 토크나이저가 필요한 모델 |
| MistralCommonBackend | mistral-common | Mistral 및 Pixtral 모델 |
모든 백엔드는 PreTrainedTokenizerBase를 상속하며 인코딩, 디코딩, 패딩, 트렁케이션, 저장, 로딩을 위한 동일한 API를 공유해요. 차이는 아래에서 어떤 토크나이제이션 파이프라인이 실행되느냐예요.
AutoTokenizer는 from_pretrained()을 호출할 때 사용 가능한 최상의 백엔드를 선택해요.
tokenizer_class필드를 위해tokenizer_config.json파일을 읽어요.- 레지스트리가
tokenizer_class를 클래스 이름과 매칭해요. 해석된 클래스는 네 백엔드 중 하나를 상속해요. 예를 들어 GemmaTokenizer는 TokenizersBackend를 상속하고, SiglipTokenizer는 SentencePieceBackend를 상속해요. GLM 같은 몇몇 모델은tokenizer.json파일이 파이프라인을 완전히 설명하므로 TokenizersBackend에 직접 매핑돼요. GemmaTokenizer는tokenizer.json이 담지 못하는 모델별 설정을 Python에서 추가로 정의하므로 서브클래스로 존재해요. mistral-common 같은 백엔드가 설치되지 않으면 AutoTokenizer는 TokenizersBackend로 폴백해요.
TokenizersBackend로의 폴백
일부 모델은 전용 토크나이저 클래스가 없고, 일부 체크포인트는 실제 tokenizer.json 파일과 일치하지 않는 tokenizer_class를 갖고 있어요. AutoTokenizer는 일반 TokenizersBackend를 통해 tokenizer.json에서 파이프라인을 로딩해서 두 경우를 모두 처리해요. Hub의 클래스 이름보다 직렬화된 토크나이저를 우선시하는데, 이는 일치하지 않는 tokenizer_class가 잘못된 토큰 id를 만들어내는 문제를 고쳐줘요.
체크포인트가 일반 TokenizersBackend로 해석되는 이유는 세 가지 중 하나예요.
| Reason | Behavior | Examples |
|---|---|---|
| 전용 토크나이저 클래스 없음 | tokenizer.json이 파이프라인을 완전히 설명하므로 모델 타입이 TokenizersBackend로 바로 매핑돼요. |
GLM, Granite, OLMo 2, GPT BigCode |
| Hub의 알려진-잘못된 토크나이저 클래스 | Hub에 기록된 tokenizer_class가 모델 타입에 맞지 않아서 AutoTokenizer가 이를 무시하고 tokenizer.json을 대신 로드해요. |
DeepSeek V3, LLaVA, Qwen2, ModernBERT |
| 특정 체크포인트 덮어쓰기 | Hub config가 아직 수정이 필요한 체크포인트는 모델 id로 매칭되어 해당 백엔드로 강제돼요. | deepseek-ai/DeepSeek-R1-Distill-*, Salesforce/blip2-*, google/umt5-small |
Hub에서 config가 수정되면 영향을 받는 모델 타입과 체크포인트가 늘어나요. 현재 목록은 tokenization_auto.py의 MODELS_WITH_INCORRECT_HUB_TOKENIZER_CLASS와 MODEL_IDS_TO_TOKENIZERS_BACKEND 정의를 확인해요.
폴백은 자동이며 from_pretrained() 호출 방식을 바꾸지 않아요. 결과 토크나이저는 tokenizer.json이 지정한 대로 정확히 인코딩하고 디코딩해요. 선택을 덮어쓰려면 backend="tokenizers" 또는 backend="sentencepiece"를 전달해요.
토크나이저가 사용 중인 백엔드는 backend 속성으로 확인해요.
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
tokenizer.backend
'tokenizers'
토크나이저 구조 검사하기
_tokenizer 속성으로 토크나이저의 내부 구성 요소(normalizer, pre-tokenizer, model, decoder)를 검사해요.
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
print(tokenizer._tokenizer.normalizer)
print(tokenizer._tokenizer.pre_tokenizer)
print(tokenizer._tokenizer.model)
print(tokenizer._tokenizer.decoder)
더 알아보기 (Learn more)
- Tokenization in Transformers v5 글은 새 토크나이제이션 백엔드의 동기와 배경을 다뤄요.
- 토크나이제이션 변경 개요는 migration guide를 확인해요.