Elasticsearchに日本語のNLPモデルをアップロードする

# Elastic + eland v8.7.0 での日本語モデルアップロードの問題

ElasticではHugging Faceで公開されているNLPモデルをElasticsearchにアップロードして、Ingestion Pipelineなどでテキストの加工・分析等に利用することができます。この時に利用するのが[Pythonで実装されたelandおよびそれにバンドルされるコマンドラインツールeland_import_hub_model](https://www.elastic.co/guide/en/elasticsearch/client/eland/current/machine-learning.html#ml-nlp-pytorch)です。


Elastic Stack v8.7.0のリリースに合わせてelandもv8.7.0がリリースされたので東北大学が公開している[cl-tohoku/bert-base-japanese-v2](https://huggingface.co/cl-tohoku/bert-base-japanese-v2)を使って試してみました。コマンドは以下のような感じ。Colabを利用しています。

```
!eland_import_hub_model \
--url https://user:password@myess:9243 \
--hub-model-id cl-tohoku/bert-base-japanese-v2 \
--task-type text_embedding \
--start
```

しかし、（実際にいつから発生している問題かはわかりませんが）以下の様なエラーが発生しました。

```
TypeError: Tokenizer type BertJapaneseTokenizer(name_or_path='cl-tohoku/bert-base-japanese-v2', vocab_size=32768, model_max_length=1000000000000000019884624838656, is_fast=False, padding_side='right', truncation_side='right', special_tokens={'unk_token': '[UNK]', 'sep_token': '[SEP]', 'pad_token': '[PAD]', 'cls_token': '[CLS]', 'mask_token': '[MASK]'}, clean_up_tokenization_spaces=True) not supported, must be one of: <class 'transformers.models.bart.tokenization_bart.BartTokenizer'>, <class 'transformers.models.bert.tokenization_bert.BertTokenizer'>, <class 'transformers.models.distilbert.tokenization_distilbert.DistilBertTokenizer'>, <class 'transformers.models.dpr.tokenization_dpr.DPRContextEncoderTokenizer'>, <class 'transformers.models.dpr.tokenization_dpr.DPRQuestionEncoderTokenizer'>, <class 'transformers.models.electra.tokenization_electra.ElectraTokenizer'>, <class 'transformers.models.mobilebert.tokenization_mobilebert.MobileBertTokenizer'>, <class 'transformers.models.mpnet.tokenization_mpnet.MPNetTokenizer'>, <class 'transformers.models.retribert.tokenization_retribert.RetriBertTokenizer'>, <class 'transformers.models.roberta.tokenization_roberta.RobertaTokenizer'>, <class 'transformers.models.squeezebert.tokenization_squeezebert.SqueezeBertTokenizer'>
```

BertJapaneseTokenizerがサポートされていないと言っています。私の記憶では以前（モデルは違ったと思いますが）同様にBertJapaneseTokenizerを利用しているモデルを問題なくアップロードできていたので、何らかのバリデーションが追加されたのかもしれません。

# 対応方法

このままだとモデルのアップロードの時点でつまずくので、とりあえずelandからのアップロードだけでも通るようにパッチを書いてプルリクを投げました。

- [Add BertJapaneseTokenizer support](https://github.com/elastic/eland/pull/529)

少なくとも記事執筆時点では取り込まれていないので、もしも最新版のelandからBertJapaneseTokenizerを使ったモデルをアップロードしたい場合は、以下のように私のリポジトリからelandを取得してインストールしてください。

```
git clone -b add_BertJapaneseTokenizer_support https://github.com/daixque/eland.git
cd eland
pip install .
```

pip installしないで直接実行する方法については[別記事](https://qiita.com/daixque/items/742951964e47bf6c802d)を書きました。


# 現在の日本語対応状況

プルリクの中でも記載しているのですが、この対応をしたとしても今時点で以下の様な状況になっています。

- 学習時にはBertJapaneseTokenizerを使ってトークナイズしており、pre-tokenizeにはMeCabによる形態素解析を利用している
- Elasticsearch側ではBertJapaneseTokenizerに対応する（Bertの）Tokenizerは現状実装されておらず、pre-tokenizeはWhitespaceTokenizerが利用されている

学習と利用でトークナイズ方式が異なるため、Elasticsearchで利用する際にBertが利用しているボキャブラリとマッチしない問題が起きます。この辺りの事については @ijokarumawak@github さんの [こちらの記事](https://qiita.com/ijokarumawak@github/items/6cc714060090160cf2d5)でもう少し詳しく説明されています。

今後、ElasticのNLP周りでも日本語対応が充実するように貢献できればと思っています。

# 2023/11/04 追記

その後Elasticsearch側のトークナイズ処理も含めて修正するプルリクを送って、Elasticsearch 8.9で取り込まれました。以下参考にして下さい。

Elastic公式ブログ

https://www.elastic.co/jp/blog/elasticsearch-nlp-ja

ウェビナー

https://www.elastic.co/jp/virtual-events/introduction-to-nlp-models-and-vector-search

Qiita

https://qiita.com/daixque/items/931b8be343075b835097