Bedrock Cohere Embed の日本語性能を Titan Embeddings と比較する - Amazon Titan Embeddingsでベクトル入門⑤

Cohere EmbedなるEmbeddingモデルが使用可能になったので、Amazon Titan Embeddingsと比較してみます。

比較対象は以下

https://qiita.com/cyberBOSE/items/fb96dcfcae78d5d788e9

# 作ったもの
まずはガワを作って比較してみます。~~2023/11/14現在、LangChainのBedrockEmbeddingsでは上手く動かなかった（パラメータとレスポンスがTitan Embeddings用になってる？）のでboto3で書いてます。~~

:::note
~~よく考えると'texts'に1も2も入れてまとめてEmbedding出来る気がしますがまあこのまま…~~
:::

:::note
バージョン`0.0.336`でlangChainがBedrockのCohere Embedに対応したのでLangChain版に変更しました。
:::

```Python:cos2_cohere_embed.py
from langchain.embeddings import BedrockEmbeddings
from sklearn.metrics.pairwise import cosine_similarity
import streamlit as st

st.title("コサイン類似度 測ルンです  \n（Cohere Embed）")
input_text_1 = st.text_area("文章1")
input_text_2 = st.text_area("文章2")
send_button = st.button("送信")

if send_button:

    # 文章1,2のEmbedding
    embeddings = BedrockEmbeddings(model_id="cohere.embed-multilingual-v3")
    vector_1 = embeddings.embed_documents([input_text_1])
    vector_2 = embeddings.embed_documents([input_text_2])

    # コサイン類似度の計算
    similarities = cosine_similarity(vector_1, vector_2).tolist()[0][0]
    st.write("コサイン類似度: " + str(similarities))    

    st.text("文章1のVector: ")
    st.write(vector_1)    
    st.text("文章2のVector: ")
    st.write(vector_2)   
```

# 実行
```
python -m streamlit run cos2_cohere_embed.py
```
文章1に入力されたものと文章2に入力されたもののコサイン類似度を出力するプログラムです。

以下のデータセット（JGLUE:日本語言語理解ベンチマークのJSTSデータセット）から幾つかピックアップして、sentence1とsentence2のコサイン類似度を見てみます。

https://github.com/yahoojapan/JGLUE/blob/main/datasets/jsts-v1.1/valid-v1.1.json

`label`が0.0のものを幾つか試します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/2a043259-b245-156d-56c7-4911eeb5faea.png)
コサイン類似度: 0.5316826458985118

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/118e1b53-7cd8-cd6b-a415-ae9fbc743ed2.png)
コサイン類似度: 0.41077689352293467

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/e4a6fa81-3a78-ed71-f0f7-0ffa838badda.png)
コサイン類似度: 0.561588540325247

こちらも関係なさそうな文章のコサイン類似度は0.5程度になりました。
今度は`label`が4.xのものを幾つか試します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/aee7234f-f4e8-01aa-acc8-d37f3eed9e45.png)
コサイン類似度: 0.7746420939787051

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/98b45e85-2276-7d36-acd6-010ac45fe5fc.png)
コサイン類似度: 0.9753954063523695

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/b5ab4403-56df-f5b1-b12a-ce952d990a9d.png)
コサイン類似度: 0.8917781565650358

こちらも明らかに高い値になりました。Titan Embeddingsと似たような値になりますね。
最後に`label`が3.0のものを試してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/28f8f586-35ce-f188-325b-fb241c8ed7be.png)
コサイン類似度: 0.8770156997178417

これもTitan Embeddingsと同じ傾向で、上記の`label`が4.xのものの間に挟まってますが（スケートボーダーのものよりも類似していると判定している）、私はそんなに違和感を感じませんでした。

ちなみに画面下部にはCohere Embedの1024次元のベクトルを表示しています。
Titan Embeddingsは1536次元だったのでCohere Embedの方が次元の数は少ないですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/4399ffe9-cadd-82f9-7be6-908f33a3b33f.png)

# データセット全量に対するスピアマン順位相関係数を求める

ここまでのところ、Titan Embeddingsと大きな違いはありませんでした。
上述のデータセットの1457件のデータに対して、テストプログラムを作ってCohere Embedのコサイン類似度とデータセットのラベルについて相関係数を求めてみます。

# 実行

上述のデータセットをカレントディレクトリに保存し、以下を実行します。

```Python:spearmanr_cohere.py
from langchain.embeddings import BedrockEmbeddings
from sklearn.metrics.pairwise import cosine_similarity
import json
from scipy.stats import spearmanr

cosine_ary = []
label_ary = []
with open("valid-v1.1.json", encoding="utf-8") as f:
    for line in f:
        line = json.loads(line)

        # 文章1,2のEmbedding
        embeddings = BedrockEmbeddings(model_id="cohere.embed-multilingual-v3")
        vector_1 = embeddings.embed_documents([line["sentence1"]])
        vector_2 = embeddings.embed_documents([line["sentence2"]])

        # コサイン類似度の計算
        similarities = cosine_similarity(vector_1, vector_2).tolist()[0][0]

        # 配列に追加
        cosine_ary.append(similarities)
        label = line["label"]
        label_ary.append(label)
        
# スピアマン順位相関係数
correlation, pvalue = spearmanr(cosine_ary,label_ary)
print(correlation)
```
```:実行結果
0.8143659029911076
```
Cohere Embedのスピアマン順位相関係数は`0.814`となりました。
Titan Embeddingsは`0.729`だったので、Cohere Embedの方が（使用したデータセットに対しては）優れてそうです。

他の方も比較結果を見てみても、

Cohere Embed ＞ OpenAI Embeddings ＞ Amazon Titan Embeddings

となっていたので、AWSのBedrock環境でも日本語のEmbeddingsに関してはOpenAIよりも優れている環境が手に入った…と言いたいところですが、Cohere Embedの入力可能トークン数は`512`のようなので、チャンクの大きさが512トークンで収まるようなユースケースで使用するのが良さそうです。
ちなみに実行速度はTitan Embeddingsと比べると少し速いですね。

日本語でRAGを実装する場合、チャンクの大きさはどれぐらいが適切なんでしょうね。
ドキュメントと検索の仕方によって変わりそうですが。

# Cohere Embedのトークン数

1トークン ＞ 1文字のような感じです。

`ベッドとソファの置かれた部屋です。`(17文字)
"inputTokenCount": 11

`カラフルなベッドとソファーが並べて置いてあります。`(25文字)
"inputTokenCount": 15

`花柄のベッドの上に二匹の猫が座っています。`(21文字)
"inputTokenCount": 15

`ベッドの布団の上に二匹の猫がいます。`(18文字)
"inputTokenCount": 14

`階段の手すりでスケートボードをする男性がいます。`(24文字)
"inputTokenCount": 16

https://qiita.com/cyberBOSE/items/fe66c2049aaa04568d61