はじめに
スケルツォ見てスッキリ。nikkieです。
OpenAIから2024年1月のアップデートが来ましたね。
その中の目玉と思われるembedding新モデルのAPIで少しだけ手を動かしました
目次
OpenAI embedding新モデルのAPI
「New embedding models with lower pricing」参照。
embeddingの新しいモデル2つが登場しています。
- text-embedding-3-small
- text-embedding-3-large
embeddingの既存APIにtext-embedding-ada-002がありましたが、新モデルのどちらも精度向上しています。
多言語における検索のベンチマークMIRACLと英語タスクのベンチマークMTEB1でembeddingを評価した表を引用。
Eval benchmark ada v2 text-embedding-3-small text-embedding-3-large MIRACL average 31.4 44.0 54.9 MTEB average 61.0 62.3 64.6
なおOpenAIとしては、text-embedding-ada-002のdeprecation(廃止)は今は考えていないようです。
ですが、新モデルのほうが精度が高く低コストなので、乗り換える方向に進みそうです。
embeddingはテキストの意味を表すベクトルですが、精度向上しただけでなく、ベクトルの長さ(dimensions)を指定できるようになったとのこと!
For example, on the MTEB benchmark, a text-embedding-3-large embedding can be shortened to a size of 256 while still outperforming an unshortened text-embedding-ada-002 embedding with a size of 1536.
なんでも、text-embedding-3-largeのembeddingは、デフォルトの3072次元でtext-embedding-ada-002をMTEBのスコアで上回る(64.6 > 61.0)のは先に見たとおりですが、256次元に短縮してもtext-embedding-ada-002を上回る(62.0 > 61.0)そうです
既存のAPIと比べて安くうまくなったわけで、これは素振りしたくなりますね。
APIでembeddingを得て、テキストの類似度計算
以前sentence-transformersで手を動かしたのをなぞって、APIでembedidngを得てから類似度を求めます。
今回はAPI呼び出しだけで済んじゃうんですね!
なおお金は少額ですがかかります(ただし1ドルもいきません)
ライブラリのバージョン
annotated-types==0.6.0 anyio==4.2.0 certifi==2023.11.17 distro==1.9.0 h11==0.14.0 httpcore==1.0.2 httpx==0.26.0 idna==3.6 numpy==1.26.3 openai==1.10.0 pydantic==2.5.3 pydantic_core==2.14.6 sniffio==1.3.0 tqdm==4.66.1 typing_extensions==4.9.0
英語の例(text-embedding-3-small)
以下を参考にして、APIを介してembeddingを得るスクリプトを書きました。
OpenAIのAPIから返るembedding(ベクトル)は、長さが1になるように正規化されている2ので、embeddingどうしの内積(dot product)がコサイン類似度となります
>>> np.dot(embeddings[0], embeddings[0]) # 1文目自身は1文目と類似度1 1.0000001104418899 >>> np.dot(embeddings[0], embeddings[1]) 0.363144529288284 >>> np.dot(embeddings[0], embeddings[2]) # 1文目と3文目は類似度が小さいです(最小は-1ですが) 0.029553639372359004
日本語の例(text-embedding-3-small)
文: 今日は雨降らなくてよかった 類似文: 今日は良いお天気ですね 類似度: [0.15914484 0.16386892 0.24410782 0.65602571 0.30940887]
文: ハンバーガーは好きですか? 類似文: 好きな食べ物は何ですか? 類似度: [0.42248486 0.16168734 0.05642641 0.15871578 0.08902706]
sentence-transformersの素振り記事で試したモデルと比べると、どちらの例も1つだけスコアが高くなっていてすごいなと思います。
誤回答の余地がないので、embeddingがよくできていると感じました。
text-embedding-3-large(日本語)
モデルの指定を変更します。
- model_name = "text-embedding-3-small" + model_name = "text-embedding-3-large"
文: 今日は雨降らなくてよかった 類似文: 今日は良いお天気ですね 類似度: [0.11441737 0.13935541 0.21728123 0.62243932 0.26052769]
文: ハンバーガーは好きですか? 類似文: 好きな食べ物は何ですか? 類似度: [0.55978838 0.23029284 0.13640034 0.19007486 0.17140786]
text-embedding-3-large(日本語)でdimensionsを指定する
API呼び出しにdimensions引数の指定を追加します。
def get_embedding(text, model): - response = client.embeddings.create(input=text, model=model) + response = client.embeddings.create(input=text, model=model, dimensions=256)
文: 今日は雨降らなくてよかった 類似文: 今日は良いお天気ですね 類似度: [0.05933593 0.15390326 0.31828702 0.63382458 0.26526732]
文: ハンバーガーは好きですか? 類似文: 好きな食べ物は何ですか? 類似度: [0.65567454 0.25886909 0.12645944 0.21691509 0.17720161]
3072次元から256次元までベクトルを小さくした(表現できる情報を絞った)のに、全然変わらないように映ります。すごい!
積ん読資料たち
(1) Embeddings Guide
https://platform.openai.com/docs/guides/embeddings
Cookbookへのリンクもあり、コード込みでユースケースが掴めそうです。
気になるところ
- Classification using the embedding features
- Zero-shot classification
(2) 日本語のベンチマークで評価した例
OpenAIの新しい埋め込みモデルtext-embedding-3の日本語データでの評価をリポジトリに追加しました。
— oshizo (@_oshizo_) 2024年1月26日
STSも検索タスクもada-002よりかなり良さそうです。https://t.co/SLarHo6E5b pic.twitter.com/V0O2LoBmcL
終わりに
OpenAIからembeddingの新モデルのAPIがリリースされました。
過去にsentence-transformersで素振りしたときと同じトイデータで触った範囲では、たしかに性能が良さそうなembeddingです。
たくさんのテキストをembeddingにするときは、openaiライブラリがサポートしている並行処理によるリクエストが有効だと思います(今後の素振り材料)
- StudyCoさんの勉強会で聞いたやつだ〜! ↩
- 「OpenAI embeddings are normalized to length 1」ref: https://platform.openai.com/docs/guides/embeddings/which-distance-function-should-i-use↩