목차
오늘은 오랜만에 다시 “나만의 한국어 AI 만들기”의 3번째 이야기로 SentencePiece 토크나이저를 정의하고 Hugging face 라이브러리로 wrapping하는 방법까지 살펴 보겠습니다. 나만의 AI 만들기 프로젝트는 지난 7월 초에 시작했어요. 오늘이 9월 3일인데, 아직도 뭔가 보여드릴 만한 결과물이 나오지 않고, 여전히 삽질만 하고 있었어요. 비전공자가 관심만 갖고 하기 하는 정말 쉽지 않은 프로젝트이기는 한 것 같습니다.
SentencePiece 토크나이저와 Hugging Face Wrapping
앞선 두 편의 이야기에서는 한국어 전용 모델을 위한 기본적인 토크나이저(Tokenizer)와 코퍼스(말뭉치)에 대한 이론적인 설명과 내 프로젝트에 어떻게 적용할 지에 대한 이야기를 다뤘었죠. 오늘 실제 토크나이저 구현에 대해 이야기 해 보겠습니다. 언어 모델의 가장 기본적인 부분이지만, 실제 구현해 보니 가장 중요한 부분이기도 하더라고요.
SentencePiece 토크나이저
이미 앞에서 비교한 대로 한국어에 적합한 sentencepiece 토크나이저(tokenizer) 모델을 생성해야 합니다. 그러기 위해서는 실제 train이 필요하죠.
실제 구현한 코드 부분을 볼게요.
import sentencepiece as spm
...
spm.SentencePieceTrainer.Train(
input=input_text,
model_prefix=model_prefix,
model_type="unigram", # 한국어 → unigram 추천 (BPE보다 단어 경계 안정적)
vocab_size=32000, # 32k 권장, 16k는 모바일/온디바이스 최적화일 때 선택
character_coverage=0.9997, # 한국어 포함 다국어 잡음 방어, 0.9995 적절
# GPT-2 규약: BOS/EOS/PAD는 SPM 레벨에서 비활성화, 종료 기호는 사용자 정의로 넣기
unk_id=0,
bos_id=-1,
eos_id=-1,
pad_id=-1,
user_defined_symbols=["<|endoftext|>"],
input_sentence_size=25_000_000, # full corpus 샘플링 → 충분
shuffle_input_sentence=True,
...
)
인공지능 모델이 텍스트를 이해하려면 먼저 문장을 의미 있는 조각, 즉 토큰(token)으로 나눠야 하죠. 이 과정을 토큰화(Tokenization)이라고 이 전에 설명했었죠. 위 코드에서 import한 Sentencepiece는 이러한 토큰화를 수행하는 도구가 됩니다.
그런데, 라이브러리만 갖다 붙인다고 Sentencepiece가 주어지는 문장을 어떻게 구분지어야 하는지 처음에는 알지 못합니다. 때문에 위 코드와 같이 Train() 함수를 통해 주어진 코퍼스(텍스트)를 분석하여 해당 데이터에 최적화된 토큰화 규칙(model)과 단어 목록(vocab)을 생성해야 하는 것입니다.
위 코든 한국어 특성에 맞게 구성한 부분이에요. 영어나 다국어를 고려한다면 변경되어야 해요. 저는 한국어 전용 모델을 목표하기 때문에 위와 같이 구성했어요.
- input: 한국어 코퍼스를 입력합니다. 대용량 코퍼스를 준비해야 해요. 이 데이터셋을 준비하는게 쉽지 않더라고요. 처음에는 그냥 많은 문자만 있으면 되는 줄 알았어요. 그랬더니 정말 모델이 엉망이 되더군요. 때문에 좀 더 신뢰성 있는 데이터셋이 필요했어요. 그리고 가능한 한 곳에서 제공하는 데이터를 활용하는게 좋겠다 싶더군요. 때문에 가능한 AI-hub의 데이터만 사용하기도 했어요. AI-Hub의 데이터는 사용 약관 수락 후 다운로드됩니다. 꼭 사용 약관을 확인해 보세요.
- model_type: 입력한 코퍼스를 분석하는 알고리즘을 선택하는 거예요. 당연히 unigram이죠. 텍스트 분석 알고리즘에는 대표적으로 BPE, Unigram, WordPiece 가 가장 유명하다고 합니다.
- vocab_size: 앞에서 분석한 결과를 바탕으로 지정된 vocab_size 만큼의 서브워드(subword) 조각들로 구성된 어휘 집합을 만듭니다. 이 집합에는 단어, 형태소, 또는 자주 사용되는 글자 조합 등이 포합됩니다. 이 부분이 크면 좋겠죠. 하지만 내 시스템 환경 조건에 따라 정해야 합니다. 지금은 32k로 설정했는데요, 이전 테스트에서는 16k로 설정해 보니 확실히 언어 능력에 차이를 보이는 것 같더라고요.
- input_sentence_size: A100이나 대형 시스템을 사용할 수 있으면 이런 부분은 설정이 필요 없을 거예요. 원래 사용하려 했던 코퍼스의 문장은 3천 5백만 개가 넘었어요. 이 코퍼스를 다 입력하니 메모리가 터지더군요(Out Of Memory). 어쩔수 없이 2천 5백만개 문장으로 줄여서 적용했습니다.
나머지는 기초 모델의 구성에 맞게 적용했어요. 이리저리 기초 모델을 바꿔보고 삽질을 여러번 하다가 결국 GPT-2 모델을 기준으로 진행 중입니다.

코드를 실행하면 위와 같이 두 개의 파일이 생성됩니다. 앞에서 설명한 대로 말이죠. 2천 5백만 개 문장을 분석해도 32k 어휘 안에 모두 담을 수 있다는 것에 약간은 놀랍더라고요. 물론 언어 전문가들 입장에서는 또 다르겠죠?
Hugging Face Wrapping
자, 그런데 이렇게 생성된 sentencepiece 토크나이저를 그냥 사용하기에는 조금 껄끄러워요. 왜냐고요? 인공지능 모델 튜닝과 관련해서 자주 사용하는 라이브러리는 보통 Hugging face의 라이브러리에요. 특히 transformers 라이브러리가 매우 유명하죠. 문제는 이 Hugging face 라이브러리를 활용하기 위해서는 위와 같은 형태의 토크나이저는 직접 사용할 수 없고, wrapping 작업을 해 줘야 해요.
이 Hugging face wrapping 방법도 지난 8월 말부터 가능해진 방법이에요. 그 전에는 이런 방법도 불가능했죠. 때문에 여기저기 wrapping 방법에 대해 의견이 많던데, Hugging face의 tokenizer 라이브러리를 최신으로 업데이트하고 코드를 구현하면 됩니다.

from transformers import PreTrainedTokenizerFast
from tokenizers.implementations import SentencePieceUnigramTokenizer as HFSPM
SPM_MODEL = Path(".myKOR_tokenizer_v2.model")
...
def load_spm():
if hasattr(HFSPM, "from_spm"):
return HFSPM.from_spm(str(SPM_MODEL))
try:
return HFSPM(str(SPM_MODEL))
except Exception as e:
raise RuntimeError(
"Exception !"
) from e
spm_tok = load_spm()
tok_hf = PreTrainedTokenizerFast(
tokenizer_object=spm_tok._tokenizer, # 내부 Rust 토크나이저
model_max_length=1024,
...
)
...
tok_hf.save_pretrained(str(OUT_DIR))
위 코드와 같이 sentencepiece 토크나이저를 HF wrapping에서 가장 중요한 부분은
- SentencePieceUnigramTokenizer 클래스를 임포트하는 것
- tokenizer_object에 spm_tok._tokenizer와 같이 라이브러리 내부의
tokenizers.Tokenizer
인스턴스를 할당하는 것 - 마지막으로 save_pretrained로 반드시 저장.
위와 같이 하면 이제 HF(Hugging Face) 형식인 Tokenizer.json
이 생성됩니다.
여기까지 나의 한국어 모델을 위한 한국어 전용 토크나이저를 생성하고 이를 Hugging Face 라이브러리에 맞게 Wrapping하는 방법을 구현해 보았습니다. 다음에는 이제 드디어 모델을 만들어 보죠.
- SentencePiece 토크나이저 정의와 HF 래핑 – 나만의 모델 만들기 #3
- Gemini CLI로 텍스트를 JSON으로 변환하기 – 코드 없이 구현하기 #1
- ComfyUI 간단한 사용 방법 – 워크플로우 구성, 이미지 생성 가이드 #1
- GPT-5 모델 업그레이드, 성능 벤치마크, GPT-4o/4.5 비교
- Corpus(말뭉치) 준비와 데이터 전처리 – 한국어 AI 모델 만들기 #2