Swallowは『雪国』の冒頭をどうトークナイズするのか

日本語に強い大規模言語モデル「Swallow」が[12月19日に公開された](https://zenn.dev/tokyotech_lm/articles/d6cb3a8fdfc907)。私(安岡孝一)にとっても、うれしいクリスマス・プレゼントだ。[東工大ニュース](https://www.titech.ac.jp/news/2023/068089)によれば、以下のような特長があるらしい。

> 研究チームはLlama 2のトークナイザに16,000件の日本語のトークンを追加することで、日本語テキストのトークン長を56.2%に削減した。

すばらしい。[Swallow-7b-hf](https://huggingface.co/tokyotech-llm/Swallow-7b-hf)を、ちょっと試してみよう。

```
>>> from transformers import AutoTokenizer
>>> tkz=AutoTokenizer.from_pretrained("tokyotech-llm/Swallow-7b-hf")
>>> print(tkz.convert_ids_to_tokens(tkz("国境の長いトンネルを抜けると雪国であった。","夜の底が白くなった。")["input_ids"]))
['
', '▁', '国境', 'の', '長い', 'トンネル', 'を', '抜ける', 'と', '雪',　'国', 'で', 'あっ', 'た', '。', '
', '▁', '夜', 'の', '底', 'が', '白く',　'なっ', 'た', '。']
```

国語研短単位より少しだけ短めになっていて、いいセンだ。[2021年12月26日の日記](https://srad.jp/~yasuoka/journal/651709/)にも書いたのだが、下手に「くなった」とかが1トークンになってしまったりすると、非常に扱いに困るので、その点「Swallow」は好感が持てる。では、[常用漢字表2136字](https://www.bunka.go.jp/kokugo_nihongo/sisaku/joho/joho/kijun/naikaku/kanji/)は、どの程度サポートしているのだろう。

```
>>> import urllib.request
>>> with urllib.request.urlopen("https://www.unicode.org/wg2/iso10646/edition6/data/JapaneseCoreKanji.txt") as r:
...   k=[chr(int(t,16)) for t in r.read().decode().strip().split("\n") if not t.startswith("#")]
... 
>>> for i,j in zip(k,tkz(k)["input_ids"]):
...   if len(j)>3:
...     print(i,tkz.convert_ids_to_tokens(j))
...
丙 ['
', '▁', '<0xE4>', '<0xB8>', '<0x99>']
倹 ['
', '▁', '<0xE5>', '<0x80>', '<0xB9>']
儒 ['
', '▁', '<0xE5>', '<0x84>', '<0x92>']
剝 ['
', '▁', '<0xE5>', '<0x89>', '<0x9D>']
劾 ['
', '▁', '<0xE5>', '<0x8A>', '<0xBE>']
勅 ['
', '▁', '<0xE5>', '<0x8B>', '<0x85>']
厘 ['
', '▁', '<0xE5>', '<0x8E>', '<0x98>']
吏 ['
', '▁', '<0xE5>', '<0x90>', '<0x8F>']
嘲 ['
', '▁', '<0xE5>', '<0x98>', '<0xB2>']
塡 ['
', '▁', '<0xE5>', '<0xA1>', '<0xA1>']
墾 ['
', '▁', '<0xE5>', '<0xA2>', '<0xBE>']
婿 ['
', '▁', '<0xE5>', '<0xA9>', '<0xBF>']
嫡 ['
', '▁', '<0xE5>', '<0xAB>', '<0xA1>']
帥 ['
', '▁', '<0xE5>', '<0xB8>', '<0xA5>']
庸 ['
', '▁', '<0xE5>', '<0xBA>', '<0xB8>']
弐 ['
', '▁', '<0xE5>', '<0xBC>', '<0x90>']
恣 ['
', '▁', '<0xE6>', '<0x81>', '<0xA3>']
慄 ['
', '▁', '<0xE6>', '<0x85>', '<0x84>']
憬 ['
', '▁', '<0xE6>', '<0x86>', '<0xAC>']
憾 ['
', '▁', '<0xE6>', '<0x86>', '<0xBE>']
拷 ['
', '▁', '<0xE6>', '<0x8B>', '<0xB7>']
斤 ['
', '▁', '<0xE6>', '<0x96>', '<0xA4>']
斥 ['
', '▁', '<0xE6>', '<0x96>', '<0xA5>']
朕 ['
', '▁', '<0xE6>', '<0x9C>', '<0x95>']
楷 ['
', '▁', '<0xE6>', '<0xA5>', '<0xB7>']
殉 ['
', '▁', '<0xE6>', '<0xAE>', '<0x89>']
沃 ['
', '▁', '<0xE6>', '<0xB2>', '<0x83>']
淫 ['
', '▁', '<0xE6>', '<0xB7>', '<0xAB>']
漸 ['
', '▁', '<0xE6>', '<0xBC>', '<0xB8>']
璽 ['
', '▁', '<0xE7>', '<0x92>', '<0xBD>']
畏 ['
', '▁', '<0xE7>', '<0x95>', '<0x8F>']
痘 ['
', '▁', '<0xE7>', '<0x97>', '<0x98>']
糾 ['
', '▁', '<0xE7>', '<0xB3>', '<0xBE>']
繭 ['
', '▁', '<0xE7>', '<0xB9>', '<0xAD>']
罷 ['
', '▁', '<0xE7>', '<0xBD>', '<0xB7>']
羞 ['
', '▁', '<0xE7>', '<0xBE>', '<0x9E>']
舷 ['
', '▁', '<0xE8>', '<0x88>', '<0xB7>']
虞 ['
', '▁', '<0xE8>', '<0x99>', '<0x9E>']
衷 ['
', '▁', '<0xE8>', '<0xA1>', '<0xB7>']
詔 ['
', '▁', '<0xE8>', '<0xA9>', '<0x94>']
諧 ['
', '▁', '<0xE8>', '<0xAB>', '<0xA7>']
諮 ['
', '▁', '<0xE8>', '<0xAB>', '<0xAE>']
謁 ['
', '▁', '<0xE8>', '<0xAC>', '<0x81>']
賂 ['
', '▁', '<0xE8>', '<0xB3>', '<0x82>']
迭 ['
', '▁', '<0xE8>', '<0xBF>', '<0xAD>']
逓 ['
', '▁', '<0xE9>', '<0x80>', '<0x93>']
錮 ['
', '▁', '<0xE9>', '<0x8C>', '<0xAE>']
陪 ['
', '▁', '<0xE9>', '<0x99>', '<0xAA>']
頒 ['
', '▁', '<0xE9>', '<0xA0>', '<0x92>']
頰 ['
', '▁', '<0xE9>', '<0xA0>', '<0xB0>']
𠮟 ['
', '▁', '<0xF0>', '<0xA0>', '<0xAE>', '<0x9F>']
```

2136字のうち51字が、バイトフォールバックしてしまう。もし、これらの常用漢字が必要なタスクだと、精度が下がる可能性があるので、注意が必要だろう。