https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https://seen-point-bd9.notion.site/Tokenizer-Expansion-ecb6d78211a54ba6b3cf8ebc0ec1d105&count_bg=#79C83D&title_bg=#FF9DDD&icon=iconify.svg&icon_color=#E7E7E7&title=hits&edge_flat=false

1. Why Tokenizer Expansion?

2. What is Tokenizer Expansion?

3. How to Tokenizer Expansion?

Appendix A. Tokenizer structure

Untitled

Appendix B. tokenizer.json

#### original tokenizer (llama_tokenizer)

```jsonc
{ ... // Some configurations
  "model": {
    "type": "BPE",
    "dropout": null,
    "unk_token": "<unk>",
    "continuing_subword_prefix": null,
    "end_of_word_suffix": null,
    "fuse_unk": true,
    "byte_fallback": true,
    "vocab": {
      "<unk>": 0,
      "<s>": 1,
      "</s>": 2,
      "<0x00>": 3,
      "<0x01>": 4,
      "<0x02>": 5,
      "<0x03>": 6,
      "<0x04>": 7,
      "<0x05>": 8,
      "<0x06>": 9,
      "<0x07>": 10,
      "<0x08>": 11,
      "<0x09>": 12,
      "<0x0A>": 13,
      "<0x0B>": 14,
      "<0x0C>": 15,
      "<0x0D>": 16,
      "<0x0E>": 17,
      "<0x0F>": 18,
      "<0x10>": 19,
      "<0x11>": 20,
      "<0x12>": 21,
      "<0x13>": 22,
      "<0x14>": 23,
      "<0x15>": 24,
      "<0x16>": 25,
      "<0x17>": 26,
      "<0x18>": 27,
      "<0x19>": 28,
      ... // all byte-pairs' input ids
      "<0xFC>": 255,
      "<0xFD>": 256,
      "<0xFE>": 257,
      "<0xFF>": 258,
      "▁▁": 259,
      "▁▁": 259,
      "▁t": 260,
      "er": 261,
      "in": 262,
      "▁a": 263,
      "en": 264,
      "on": 265,
      "▁th": 266,
      "es": 267,
      "▁▁▁▁": 268,
      "▁s": 269,
      "▁d": 270,
      "at": 271,
      "or": 272,
      "an": 273,
      "▁c": 274,
      "is": 275,
      "re": 276,
      "it": 277,
      "▁the": 278,
      "ar": 279,
      ... // all characters' (except unigram) input ids <-- are only tokens made of other 2 tokens
      "▁nev": 29865,
      "Daniel": 29866,
      "▁tends": 29867,
      "▁compagnie": 29868,
      "▁livres": 29869,
      "lub": 29870,
      "▁": 29871,
      "e": 29872,
      "t": 29873,
      "a": 29874,
      ... //all unigram characters' input ids
      "边": 31993,
      "还": 31994,
      "黃": 31995,
      "왕": 31996,
      "收": 31997,
      "弘": 31998,
      "给": 31999
    },
    "merges": [
      "▁ t",
      "e r",
      "i n",
      "▁ a",
      "e n",
      "o n",
      "▁t h",
      "▁ th",
      "e s",
      "▁ s",
      "▁ d",
      "a t",
      "o r",
      "a n",
      "▁ c",
      "i s",
      "r e",
      "i t",
      "▁t he",
      "▁th e",
      "▁ the",
      "a r",
      ... // all merge rules of input_ids(c.f. [..., "▁techn ical", "▁techni cal", ...])
      "lu b",
      "l ub",
      "▁ ▁",
      "▁▁ ▁▁",
      "▁▁▁ ▁",
      "▁ ▁▁▁",
      ... // all merge rules of normalizers
      "▁▁▁▁▁▁▁▁▁ ▁▁▁▁▁▁",
      "▁▁▁▁▁▁▁ ▁▁▁▁▁▁▁▁",
      "▁▁▁▁▁▁▁▁▁▁▁ ▁▁▁▁",
      "▁ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁"
    ]
  }
}


```json
#### reference tokenizer (beomi_tokenizer)

```jsonc
{ ... // Some configurations
  "model": {
    "type": "BPE",
    "dropout": null,
    "unk_token": "<unk>",
    "continuing_subword_prefix": null,
    "end_of_word_suffix": null,
    "fuse_unk": true,
    "byte_fallback": true,
    "vocab": {
      "<unk>": 0,
      "<s>": 1,
      "</s>": 2,
      "<0x00>": 3,
      "<0x01>": 4,
      "<0x02>": 5,
      "<0x03>": 6,
      "<0x04>": 7,
      "<0x05>": 8,
      "<0x06>": 9,
      "<0x07>": 10,
      "<0x08>": 11,
      "<0x09>": 12,
      "<0x0A>": 13,
      "<0x0B>": 14,
      "<0x0C>": 15,
      "<0x0D>": 16,
      "<0x0E>": 17,
      "<0x0F>": 18,
      "<0x10>": 19,
      "<0x11>": 20,
      "<0x12>": 21,
      "<0x13>": 22,
      "<0x14>": 23,
      "<0x15>": 24,
      "<0x16>": 25,
      "<0x17>": 26,
      "<0x18>": 27,
      "<0x19>": 28,
      ... // same as llama till 32000
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			.
			... // same as llama till 32000
      "收": 31997,
      "弘": 31998,
      "给": 31999,
      "<pad>": 32000,
      "▁이": 32001,
      "▁대": 32002,
      "▁사": 32003,
      "▁그": 32004,
      "▁있": 32005,
      "으로": 32006,
      "▁지": 32007,
      "▁아": 32008,
      ... // added <pad>(but unused), korean token (except unigram)
      "▁가이드": 44808,
      "▁지수는": 44809,
      "▁내수": 44810,
      "▁언론의": 44811,
      "▁어느나라": 44812,
      "으": 44813,
      "게": 44814,
      "있": 44815,
      ... // added unigram korean token
      "앎": 46327,
      "챘": 46328,
      "컹": 46329,
      "묽": 46330,
      "<|sep|>": 46331,
      "<|endoftext|>": 46332,
      "<|acc|>": 46333,
      "<|rrn|>": 46334,
      "<|tel|>": 46335
  },
  "merges": [
    "▁ t",
    "e r",
    "i n",
    "▁ a",
    "e n",
    "o n",
    "▁t h",
    "▁ th",
    ... // same as llama till normalizers
    "▁▁▁▁▁▁▁▁▁ ▁▁▁▁▁▁",
    "▁▁▁▁▁▁▁ ▁▁▁▁▁▁▁▁",
    "▁▁▁▁▁▁▁▁▁▁▁ ▁▁▁▁",
    "▁ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁"
    "▁ 이",
    "▁ 대",
    "▁ 사",
    "▁ 그",
    "▁ 있",
    "으 로",
    "▁ 지",
    "▁ 아",
    "니 다",
    "▁ 정",
    "▁ 하",
    "에 서",
    "▁ 기",
    "▁ 전",
    "▁ 가",
    "▁ 한",
    "▁ 수",
    "했 다",
    "▁ 나",
    ... // all merge rules of korean input_ids
    "▁리 모델링",
    "▁가 이드",
    "▁지 수는",
    "▁지수 는",
    "▁ 지수는",
    "▁내 수",
    "▁언론 의",
    "▁어느 나라"
    ]
  }
}


- 실제 토큰과 그에 해당하는 `input_ids` 는 `vocab`에, `BPE merge rule`은  `merges`에 저장하는 구조이므로, 아래와 같은 작업을 할 수 있음
- 새로 학습한 tokenizer의 vocab을 순회,
    - if 기존 tokenizer의 vocab에 없는 토큰을 발견,
        - 기존 tokenizer의 vocab에 이어서 토큰을 추가
        - 기존 tokenizer의 merges에 이 토큰에 해당하는 merge rule을 찾아서 extend

### 3-0. TL; DR

```markdown
1. 기준이 될 Tokenizer(Ex. `llama_tokenizer`)의 `토큰 정보`(tokenizer.json)를 load 
2. 추가할 토큰을 학습한 Tokenizer(Ex. `new_tokenizer`)의 `토큰 정보`(tokenizer.json)를 load
3. 2번의 토큰들을 하나씩 iterate하면서, if 해당 토큰이 1번에 없다면, 토큰 추가