対日本語でのOpenAIEmbeddingsとHuggingFaceEmbeddingsの比較

# はじめに
OpenAiのEmbeddingsAPIだとそこそこなコストが発生するので、それを少しでも減らしたいというところから色々探していたら見つけました。

# 環境
- google colab
(GPUは使わず、CPUで処理しています。)

# 事前準備

## ApiKeyの設定
```
openai_key = YOUR_OPENAI_APIKEY #@param {type:"string"}
```

## ライブラリインストール
```
%%writefile requirements.txt
openai
chromadb
langchain
tiktoken
sentence_transformers
unstructured

%pip install -r requirements.txt
```

## インポート
```
import os
import platform

import openai

from langchain.embeddings import HuggingFaceEmbeddings, OpenAIEmbeddings
from langchain.document_loaders import UnstructuredHTMLLoader
from langchain.vectorstores import Chroma
from langchain.text_splitter import CharacterTextSplitter
```

## 関数と変数の準備
```
os.environ["OPENAI_API_KEY"] = openai_key
openai.api_key = os.getenv("OPENAI_API_KEY")

model_name = "oshizo/sbert-jsnli-luke-japanese-base-lite"
huggingface_embeddings = HuggingFaceEmbeddings(model_name=model_name)

doc_path = "/content/ぼっち・ざ・ろっく! - Wikipedia.html"
loader = UnstructuredHTMLLoader(doc_path)
docs = loader.load()
```

ぼっち・ざ・ろっく! - Wikipedia.htmlに関しては直接WikipediaからHTMLを取得して、content以下に移動しています。

```
def split(docs, vectordb_path, embeddings=OpenAIEmbeddings() ,chunk_size=1000, ):
  text_splitter = CharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=0)
  texts = text_splitter.split_documents(docs)
  chroma_index = Chroma.from_documents(texts, embedding=embeddings, persist_directory=vectordb_path)
  chroma_index.persist()

  return chroma_index

def similarity_search(query, vectordb):
  res = vectordb.similarity_search(query, k=5)
  contents = [f"doc {i+1}:\n {res[i].page_content}" for i in range(len(res))]
  join_contents = "\n\n".join(contents)
  print(join_contents)
```


# Embbedingの比較

## HuggingFace
```
hf_vector = split(docs, "vectors/hf_test", embeddings=huggingface_embeddings, chunk_size=150)
query = "ぼっちちゃんは何歳？"
similarity_search(query, hf_vector)
```

出力
```
doc 1:
 本作の主人公[4]。リードギター・作詞担当。秀華高校1年→2年。ニックネームはリョウが名前から付けた「ぼっち（ちゃん）[注 7][25]」。金沢八景付近に在住[注 8]。髪型はピンク色のロングヘアーで、右側に水色と黄色の2つの立方体型の髪留めを付けている。服装は常にジャージ[注 9]、家では暗い押し入れでギターばかり弾いている、いわゆる陰キャ少女。休みもどこかへ出かけることはなく、ずっと家に引きこもるなどインドア派[注 10]。

doc 2:
 ^ “ぼっち・ざ・ろっく！”. 芳文社. 2022年11月26日閲覧。

doc 3:
 声 - 和多田美咲[114]

誕生日：7月7日 /血液型：A型

ひとりの妹。5歳[注 29][115]。性格は姉とは正反対で初対面の相手にも物怖じしない。無邪気に相手の心を抉るようなことを言って、（特にひとりに）精神的ダメージを与えることが多い。

声 - 小岩井ことり[116]

doc 4:
 ^ “次にくるマンガ大賞2019”. 2021年3月26日閲覧。

^ 山内貴範 (2022年12月31日). “『ぼっち・ざ・ろっく！』作者・はまじあきインタビュー「 ぼっちちゃんの性格は、私自身の投影です（笑）」”. REAL SOUND. 2022年12月31日閲覧。

doc 5:
 ^ a b 草野虹 (2022年12月4日). “なぜ『ぼっち・ざ・ろっく！』は心を捉えて離さないのか？ロックにアニメにマンガにと綴る10,000字レビュー”.   イード. 2022年12月26日閲覧。
```

## OpenAi
```
oa_vector = split(docs, "vectors/oa_test", chunk_size=150)
query = "ぼっちちゃんは何歳？"
similarity_search(query, oa_vector)
```

出力
```
doc 1:
 ^ “ぼっち・ざ・ろっく！”. 芳文社. 2022年11月26日閲覧。

doc 2:
 はまじあき『ぼっち・ざ・ろっく！』 1巻、芳文社〈まんがタイムKRコミックス〉、2019年2月27日。ISBN 978-4-8322-7072-5。

はまじあき『ぼっち・ざ・ろっく！』 2巻、芳文社〈まんがタイムKRコミックス〉、2020年2月27日。ISBN 978-4-8322-7170-8。

doc 3:
 はまじあき『ぼっち・ざ・ろっく！』 3巻、芳文社〈まんがタイムKRコミックス〉、2021年2月25日。ISBN 978-4-8322-7252-1。

はまじあき『ぼっち・ざ・ろっく！』 4巻、芳文社〈まんがタイムKRコミックス〉、2022年8月26日。ISBN 978-4-8322-7388-7。

doc 4:
 ^ “「ぼっち・ざ・ろっく！」TVアニメ化、コミュ力低すぎ少女のバンド4コマ”. コミックナタリー (ナターシャ). https://natalie.mu/comic/news/416922 2021年2月24日閲覧。

doc 5:
 はまじあき『ぼっち・ざ・ろっく！』 5巻、芳文社〈まんがタイムKRコミックス〉、2022年11月26日。ISBN 978-4-8322-7419-8。

外部リンク[編集]

ぼっち・ざ・ろっく！ - 芳文社

ぼっち・ざ・ろっく！ - きららベース（ニコニコ静画）

隠す

表

話

編

歴
```

# まとめ
chunk_sizeは150,200,500,1000でドキュメントを生成し、150が一番正確な情報を得られたので150を使用しています。
このことから適したchunk_sizeを指定しないと精度が悪くなるということがわかりました。

また、日本語のドキュメントに関してはOpenAiのEmbeddingsApiを使うより日本語向けのモデルを使った方が精度が良いのかも？

ちなみに生成されたドキュメント+質問をGpt-3.5に投げたところ、あまり正確な返答が得られませんでした。
ここに関してはより適したプロンプトの生成方法を色々試していきたい思います。


# 参考
https://note.com/npaka/n/n95d9b6b33309

https://huggingface.co/oshizo/sbert-jsnli-luke-japanese-base-lite

[ぼっち・ざ・ろっく! - Wikipedia](https://ja.wikipedia.org/wiki/%E3%81%BC%E3%81%A3%E3%81%A1%E3%83%BB%E3%81%96%E3%83%BB%E3%82%8D%E3%81%A3%E3%81%8F!)