VAETKI tokenizer — CJK repair update

원본 토크나이저 NC-AI-consortium-VAETKI/VAETKI의 파생물입니다. vocab 크기(137,216)와 기존 토큰 id 는 그대로 유지되며, 언어 비율 조정 메커니즘 적용 단계에서 발생한 오류를 수정하여, 도달 불가능했던 한자 슬롯 문제를 수정합니다.

VAETKI 토크나이저(vocab 137,216, byte-fallback BPE)의 구현 오류를 수정한 버전입니다. 모델 가중치는 포함하지 않고 토크나이저와 설정만 배포합니다. 현재 배포되고 있는 모델에서는, 수정된 부분에 따라 중/일 문자가 표현되는 영역에 대한 추가 학습이 필요하니, 단순히 추론만 활용하는 경우에는 사용하지 않도록 주의 부탁드립니다.

요약

vocab 에 다문자 한자 항목 21,895(我们 中国 一个 …)에 대해 조립 seed가 되는 문자가 존재하지 않아 도달하지 않는 토큰 영역이 발생하고, 이 때문에 CJK 한자 파트가 과도하게 byte-fallback 되는 문제가 발생합니다. 이 토크나이저는 해당 오류를 제거합니다.

  • 기존 중국어 텍스트의 93%(예: <0xE6><0x88><0x91>), 기존 한자 포함 일본어의 67% 가 byte-fallback됩니다.
  • 문자당 토큰: 중국어 2.4, 일본어 1.2 (독일어는 0.30)으로, 해당 다문자 한자 임베딩 21,895행의 업데이트가 올바르게 되지 않는 문제를 해결했습니다.

수정된 항목

기존 vocab에는 我们, 中国, 一个 등 다문자 한자 항목 21,895개가 포함되어 있으나, 이들을 구성하는 단일 한자가 충분히 vocab에 존재하지 않아 해당 BPE merge에 도달할 수 없는 문제가 있습니다. 그 결과 한자를 포함한 중국어와 일본어 입력의 상당 부분이 UTF-8 byte token으로 분해됩니다.

기존 토크나이저에서는 중국어 텍스트의 약 93%, 한자를 포함한 일본어 텍스트의 약 67%에서 byte-fallback이 발생합니다. 이에 따라 중국어는 문자당 약 2.4 token, 일본어는 약 1.2 token을 사용하며, vocab에 존재하는 다문자 한자 토큰 21,895개 역시 정상적으로 선택되기 어렵습니다.

본 버전에서는 다음과 같이 vocab과 merge를 재구성했습니다.

CJK 코퍼스 문자 빈도를 기준으로 단일 한자 4,960자를 추가했습니다. 기존 다문자 한자 토큰 가운데 BPE rank가 높은 16,935개를 유지했습니다. 유지된 다문자 한자가 새 단일 문자 토큰으로부터 조립될 수 있도록 16,935개의 merge를 재생성했습니다. 필요한 vocab slot은 기존 다문자 한자 토큰 중 BPE rank가 낮은 4,960개를 대체하여 확보했습니다. 한글, 기호, CJK 문장부호, byte token 256개, 특수 및 reserved token 2,167개는 변경하지 않았습니다. 최종 vocab 크기는 기존과 동일한 137,216입니다.

토큰의 우선순위는 기존 vocab id를 BPE rank로 간주하여 유지했습니다. 변경 후 vocab에 남아 있는 다문자 한자 토큰은 모두 단일 문자 및 하위 merge로부터 구성 가능합니다.

기존 embedding 및 LM head와의 shape 호환성을 유지하기 위해 token id 자체는 재배치하지 않습니다. 제거된 4,960개 토큰의 id에 새 단일 한자를 대응시키는 방식입니다.

특수 토큰 정리

기존 vocab에서 <s></s>는 special token으로 표시되어 있으나, 이 토크나이저의 BOS와 EOS는 <|START|><|END|>입니다. <s></s>는 제어 토큰으로 사용되지 않으면서 HTML의 동일한 태그 문자열과 충돌합니다.

이 때문에 텍스트에 포함된 <s> 태그가 special token으로 인코딩되고, skip_special_tokens=True로 디코딩할 때 해당 문자열이 결과에서 사라집니다. 코드 코퍼스 약 633만 문자에서 <s>는 2회 관측되었습니다. 학습 입력에는 영향이 없으나 디코딩 결과에서 문자열이 손실됩니다.

본 버전에서는 두 토큰을 <|s|><|/s|>로 변경했습니다. token id 1과 2는 그대로 유지되므로 embedding 및 LM head와의 호환성에는 영향이 없으며, merge 역시 변경되지 않습니다. 변경 후 텍스트의 <s> 태그는 일반 문자로 분해되어 round-trip이 보존됩니다.

<pad><unk>는 실제 텍스트와 충돌할 가능성이 낮아 special token으로 유지했습니다.

토큰화 결과

FineWeb2의 중국어 및 일본어 표본을 기준으로 수정 전후의 토큰화를 비교했습니다.

코퍼스 토큰 수 변화 chars/token byte-fallback
중국어 (FineWeb2 cmn) −73.3% 0.42 → 1.56 92.9% → 0.5%
일본어 (FineWeb2 jpn) −55.5% 0.83 → 1.87 67.6% → 0.2%
일본어/중국어 혼합 −53.3% 0.75 → 1.60 67.6% → 0.5%
한국어 / 독일어 / 스페인어 0.0% 변화 없음 변화 없음
코드 / 수학 0.0% 변화 없음 변화 없음

중국어에서는 기존 토큰 수의 약 26.7%, 일본어에서는 약 44.5% 수준으로 감소했습니다. 이는 새 압축 규칙을 별도로 추가한 결과라기보다, 기존 vocab에 이미 존재하던 CJK BPE 구조가 실제로 사용될 수 있도록 복구한 결과입니다.

회귀 검증

CJK 수정이 다른 언어 및 코드 토큰화에 영향을 주지 않는지 별도로 확인했습니다.

  • 한국어, 독일어, 스페인어 문서 각 200개
  • mid-training 데이터 200개
  • Nemotron Synthetic-Code 400개

위 데이터에서는 수정 전후 token id sequence가 모두 동일했습니다.

코드 및 수학 코퍼스 전체 비교에서도 토큰 수가 증가한 문서는 없었습니다. 토큰열이 변경된 문서는 모두 CJK 문자를 포함하고 있었으며, 해당 문서에서는 토큰 수가 감소했습니다.

추가로 코드 및 수학 코퍼스를 포함한 14개 코퍼스 5,200개 문서에 대해 encode → decode round-trip을 검사했습니다. 수정 전후의 실패 건수는 동일했으며, 수정으로 인해 새로 발생한 불일치는 없습니다.

토크나이저 수정만 적용하는 경우 새롭게 할당된 4,960개의 token id는 기존 모델에서 다른 다문자 토큰에 대응하던 embedding을 가지고 있습니다. 따라서 해당 행은 모델 학습 또는 continued pretraining 전에 다시 초기화하는 것이 필요합니다.

util/init\_embeddings.py는 새 단일 한자의 UTF-8 표현에 해당하는 byte token embedding의 평균값으로 해당 행을 초기화합니다.

예를 들어 문자 가 기존 모델에서 다음과 같이 처리되었다면,

我 → <0xE6> <0x88> <0x91>

token의 embedding은 세 byte token embedding의 평균으로 초기화합니다.

E(我) = (E(<0xE6>) + E(<0x88>) + E(<0x91>)) / 3

이는 새 CJK token을 무작위 또는 zero initialization하는 대신, 기존 모델이 해당 문자를 표현할 때 사용하던 embedding을 초기값으로 이용하기 위한 것입니다.

실제 continued training에서는 zero initialization에 비해 초기 embedding gradient 증가가 작고 수렴이 안정적이므로 이 방식을 기본값으로 권장합니다.

포함 파일

  • tokenizer.json
    수정된 tokenizer. vocab 137,216 / merges 225,319.
  • replacement_map.json
    재사용된 token id와 기존 토큰, 새 단일 한자의 대응 관계 4,960건.
  • util/build_tokenizer_surgery.py
    tokenizer 재구성 스크립트.
  • util/init_embeddings.py
    새 CJK token에 대응하는 embedding 행 초기화 스크립트.
  • util/rename_legacy_special.py
    <s>, </s><|s|>, <|/s|>로 변경하는 스크립트.
  • generation_config.json
  • tokenizer_config.json
  • chat_template.jinja

적용 범위

추가한 단일 한자 4,960자는 FineWeb2 중국어 및 일본어 표본 약 630만 문자에서 계산한 문자 빈도를 기준으로 선정했으며, 해당 표본에서 99.735%의 문자 출현을 커버합니다. 다른 언어 분포나 전문 도메인에서는 커버리지가 달라질 수 있습니다.

vocab 크기를 유지하기 위해 기존 다문자 한자 토큰 중 낮은 BPE rank의 4,960개를 제거했습니다. 이 문자열들은 더 이상 단일 token으로 표현되지 않지만, 새 단일 한자와 기존 merge의 조합으로 모두 encoding 및 decoding할 수 있습니다. 따라서 일부 저빈도 문자열에서 token 수가 증가할 수 있으나 문자열 정보 자체가 손실되지는 않습니다.

이번 수정은 한자 tokenization 문제만을 대상으로 합니다. 한글, 일본어 가나, 기호 및 기타 기존에 정상적으로 처리되던 token 영역은 수정하지 않았습니다.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support