Amazon Titan EmbeddingsとCohere Embed Multilingualのトークン数を日本語と英語で比較

Amazon BedrockでCohere Embedが使えるようになりました。🎉🎉🎉

使い方は他のモデルと同様です。

```python
import json
import boto3

bedrock = boto3.client('bedrock-runtime')

params = {
  "modelId": "cohere.embed-multilingual-v3",
  "contentType": "application/json",
  "accept": "*/*",
  "body": json.dumps({
    "texts": ["hello", "goodbye"],
    "input_type": "search_document"
  })
}

response = bedrock.invoke_model(**params)

body = response['body'].read().decode('utf-8')
json_body = json.loads(body)
print(json_body)
```

ところで、トークン数ってどれくらいなんでしょう？

---
トークン数の調べ方
---

[こちら](https://huggingface.co/Cohere/multilingual-22-12)にトークンカウントの方法が載ってました。Bedrockで利用できるのは[embed-multilingual-v3.0](https://huggingface.co/Cohere/Cohere-embed-multilingual-v3.0)なので、ちょこっと改変して使ってみます。

```shell
pip install -Uq 'transformers[torch]'
```

```python
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("Cohere/Cohere-embed-multilingual-v3.0")
text = "Hellö World, this is my input string!"
enc = tokenizer(text)
print("Encoded input:")
print(enc)

inv_vocab = {v: k for k, v in tokenizer.vocab.items()}
tokens = [inv_vocab[token_id] for token_id in enc['input_ids']]
print("Tokens:")
print(tokens)

number_of_tokens = len(enc['input_ids'])
print("Number of tokens:", number_of_tokens)
```
```
Encoded input:
{'input_ids': [0, 10440, 18540, 6661, 4, 903, 83, 759, 107730, 79315, 38, 2], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}
Tokens:
['
', '▁Hel', 'lö', '▁World', ',', '▁this', '▁is', '▁my', '▁input', '▁string', '!', '
']
Number of tokens: 12
```

:::note 
`transformers`を使わずに`tokenizers`を使う場合はこんな感じ？

```shell
pip install -U tokenizers
```
```python
from tokenizers import Tokenizer

tokenizer = Tokenizer.from_pretrained("Cohere/Cohere-embed-multilingual-v3.0")
text = "Hellö World, this is my input string!"
enc = tokenizer.encode(text)
print("Encoded input:")
print(enc.ids)
print(enc.attention_mask)

print("Tokens:")
print(enc.tokens)
print("Number of tokens:", len(enc))
```
```
Encoded input:
[0, 10440, 18540, 6661, 4, 903, 83, 759, 107730, 79315, 38, 2]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
Tokens:
['
', '▁Hel', 'lö', '▁World', ',', '▁this', '▁is', '▁my', '▁input', '▁string', '!', '
']
Number of tokens: 12
```
:::

---
検証
---

[ここ](https://www.nikkei.com/article/DGXZZO35455660Y1A001C1000000/)にスティーブ・ジョブズさんのスピーチの原文と日本語訳があります。それぞれのトークン数を見てみましょう。

https://www.nikkei.com/article/DGXZZO35455660Y1A001C1000000/

| 言語 | 文字数 | トークン数 |
| --- | --: | --: |
| 日本語 | 5297文字 | 2901トークン |
| 英語 | 11860文字 | 2882トークン |

意外と変わらないですね

ちなみにトークン分割した文字列はこんな感じです。（先頭のみ）一文字1トークンのようで、そうでもないようで。

> '\
', '▁', '世界', 'で', 'もっと', 'も', '優秀', 'な', '大学', 'の', '卒業', '式', 'に', '同', '席', 'できて', '光', '栄', 'です', '。', '私は', '大学', 'を', '卒業', 'したこと', 'がありません', '。', '実', 'の', 'ところ', '、', 'き', 'ょう', 'が', '人生', 'で', 'もっと', 'も', '大学', '卒業', 'に', '近', 'づ', 'いた', '日', 'です', '。', '本', '日は', '自分が', '生き', 'てきた', '経験', 'から', '、3', 'つの', '話を', 'させて', 'ください', '。', 'たい', 'したこと', 'ではない', '。', 'たった', '3', 'つ', 'です', '。',


**同じ情報量の場合、文字数は日本語のほうが多いけど、トークン数はほぼ同じ** ということがわかりました。

---
Amazon Titan Embeddingsのトークン数
---

Titan Embeddingsのトークン数の取得は`invoke`APIの呼び出し結果で取得できます。

```python
params = {
  "modelId": "amazon.titan-embed-text-v1",
  "contentType": "application/json",
  "accept": "*/*",
  "body": json.dumps({
    "inputText": "this is where you place your input text"
  })
}

response = bedrock.invoke_model(**params)

body = response['body'].read().decode('utf-8')
json_body = json.loads(body)
print("Number of tokens:", json_body['inputTextTokenCount'])
```
```
Number of tokens: 8
```

Cohereよりトークン数が少ないようです。

* CohereとTitan Embeddingsの比較

| 言語 | トークン数（Cohere） | トークン数（Titan Embeddings） |
| --- | --: | --: |
| 日本語 | 2901トークン | 2821トークン |
| 英語 | 2882トークン | 2716トークン |

Amazon Titan EmbeddingsもCohere Embed – Multilingualもどちらも`$0.0001/1oooトークン`と同じ価格なので微妙にTitan Embeddingsが安いようです。