Snowflake のベクトル化は何を使えばいいのか? (Cortex LLM Embedding)
はじめに
ドキュメントや画像などの非構造化データの類似性を調べたり、曖昧検索などにおいてベクトル化 (Embedding) の技術は非常に重要であり、これからもその重要性は更に増えてくると考えられます。Snowflake は標準でベクトルデータ型に対応しており、ベクトル化を行う Cortex LLM の Embedding 関数やベクトル類似度を算出する関数などベクトルデータの取り扱いがしやすい環境を提供しています。
直近では2024/8/29に Embedding 関数のモデル multilingual-e5-large
が、2024/9/12に同じく Embedding 関数のモデルである voyage-multilingual-2
が、その後2024/12には arctic-embed-v1.5
と snowflake-arctic-embed-l-v2.0
が怒涛の勢いでリリースされました。
ただ、Embedding 関数は現時点で7モデル、ベクトル類似度関数は現時点で4種類と選択肢が多いため何を使えばいいのか悩んでしまうケースがあるかもしれません。そこで今回は Snowflake の仕組みを使って日本語利用時における各 Embedding モデルとベクトル類似度関数の性能比較をしてみたいと思います。
先に結論
日本語環境下においては、
Embedding モデル: voyage-multilingual-2
ベクトル類似度関数: コサイン類似度 or 内積
の組み合わせが良さそうです。
ただし multilingual-e5-large も voyage-multilingual-2 に準ずる高い性能を示しており、かつ単価が安いため、multilingual-e5-large も状況次第で十分に選択できると思います。
では検証の流れをご紹介します。
(参考) Embedding モデルの単価
2024/12/16 時点の価格テーブル
(参考) 各モデルのコンテキストウィンドウについて
2024/12/16 時点の各モデルのベクトル次元、コンテキストウィンドウ、対応言語
各モデル基本的には 512
ですが、voyage-multilingual-2
だけ 32,000
と巨大なインプットトークンに対応しています。これまでは小さめにチャンクを切ってからベクトル化する必要がありましたが、voyage-multilingual-2
であればページ丸ごとベクトル化するなどもできそうですね。(それで精度が出るかは検証が必要ですが、、、)
前提条件
- Snowflake アカウント
- Cortex LLM が利用できる Snowflake アカウント (クロスリージョン推論のリリースによりクラウドやリージョンの制約がほぼ無くなりました)
注意事項
- 特定の検証用データを用いた場合の結果となりますので、本番利用の際には十分に検証することを推奨します
- 日本語データを用いた検証結果となりますので、英語など他の言語の場合には違った結果となりますのでご留意願います
基本の確認
Cortex LLM Embedding 関数の使い方
基本事項を確認していきます。まずは Embedding 関数の使い方ですが、Snowsight のワークシートから以下 SQL クエリを実行するだけです。
SELECT SNOWFLAKE.CORTEX.EMBED_TEXT_1024('voyage-multilingual-2', 'こんにちは');
出力結果
1024次元のベクトル化関数なので、こんにちは
という文字列に対して1024個の数字に変換されていることが分かると思います。
ベクトル類似度関数の使い方 (≒ベクトル検索のやり方)
次にベクトル類似度検索を用いて2つのベクトルデータの類似度を算出してみます。まずは前述の Embedding 関数を駆使してテーブルを作成します。
CREATE TABLE vector_table_test (
text1 varchar,
text1_vector VECTOR(FLOAT, 1024),
text2 varchar,
text2_vector VECTOR(FLOAT, 1024));
INSERT INTO vector_table_test
SELECT
'おはよう',
SNOWFLAKE.CORTEX.EMBED_TEXT_1024('voyage-multilingual-2', 'おはよう'),
'こんにちは',
SNOWFLAKE.CORTEX.EMBED_TEXT_1024('voyage-multilingual-2', 'こんにちは');
SELECT * FROM vector_table_test;
出力結果
おはよう
と こんにちは
のベクトルデータが生成されましたので、ここに対してベクトル類似度関数を使ってみます。
SELECT VECTOR_COSINE_SIMILARITY(text1_vector, text2_vector) AS similarity
FROM vector_table_test;
出力結果
このように、おはよう
と こんにちは
の類似度は約 0.7
ぐらいの類似度であるということが分かります。この数字が 1
に近いほど類似度が高いと判断できます。
検証
使用するデータ
AI などの日本語能力を検証するために広く使われている JGLUE の JSTS データセットを利用させていただきます。
JSTS データをテーブルにアップロード
データサイズもそこまで大きくないため、JSON データとしてそのままダウンロードし、Snowsight から直接 Snowflake のテーブルとしてアップロードしちゃいます。
Snowsight > データ > データベースから使用するデータベースとスキーマを選択し、画面右上の作成ボタン > テーブル > ファイルからを選択します。
先ほどダウンロードした JSTS の JSON ファイルをドラッグ&ドロップし、テーブル名を JSTS_V1_1
と入力して次へをクリックします。
デフォルトのままロードボタンを押します。
これで JSTS_V1_1
テーブルに JSTS データが格納されました。
性能比較
準備が整いましたので後は性能比較を実施します。かなり雑なクエリですが以下をワークシートで実行してみましょう。
-- JSTS_V1_1テーブルのあるスキーマを指定
USE WAREHOUSE <使用するウェアハウス>;
USE DATABASE <JSTS_V1_1テーブルがあるDB名>;
USE SCHEMA <JSTS_V1_1テーブルがあるスキーマ名>;
-- 各種Embeddingモデルとベクトル類似度関数の性能比較
WITH embeddings AS (
SELECT
SENTENCE_PAIR_ID,
LABEL,
SNOWFLAKE.CORTEX.EMBED_TEXT_768('snowflake-arctic-embed-m', SENTENCE1) AS arctic_embed_1,
SNOWFLAKE.CORTEX.EMBED_TEXT_768('snowflake-arctic-embed-m', SENTENCE2) AS arctic_embed_2,
SNOWFLAKE.CORTEX.EMBED_TEXT_768('e5-base-v2', SENTENCE1) AS e5_base_1,
SNOWFLAKE.CORTEX.EMBED_TEXT_768('e5-base-v2', SENTENCE2) AS e5_base_2,
SNOWFLAKE.CORTEX.EMBED_TEXT_768('snowflake-arctic-embed-m-v1.5', SENTENCE1) AS arctic_embed_v15_1,
SNOWFLAKE.CORTEX.EMBED_TEXT_768('snowflake-arctic-embed-m-v1.5', SENTENCE2) AS arctic_embed_v15_2,
SNOWFLAKE.CORTEX.EMBED_TEXT_1024('nv-embed-qa-4', SENTENCE1) AS nv_embed_1,
SNOWFLAKE.CORTEX.EMBED_TEXT_1024('nv-embed-qa-4', SENTENCE2) AS nv_embed_2,
SNOWFLAKE.CORTEX.EMBED_TEXT_1024('multilingual-e5-large', SENTENCE1) AS multi_e5_1,
SNOWFLAKE.CORTEX.EMBED_TEXT_1024('multilingual-e5-large', SENTENCE2) AS multi_e5_2,
SNOWFLAKE.CORTEX.EMBED_TEXT_1024('voyage-multilingual-2', SENTENCE1) AS voyage_1,
SNOWFLAKE.CORTEX.EMBED_TEXT_1024('voyage-multilingual-2', SENTENCE2) AS voyage_2,
SNOWFLAKE.CORTEX.EMBED_TEXT_1024('snowflake-arctic-embed-l-v2.0', SENTENCE1) AS arctic_embed_v20_1,
SNOWFLAKE.CORTEX.EMBED_TEXT_1024('snowflake-arctic-embed-l-v2.0', SENTENCE2) AS arctic_embed_v20_2
FROM JSTS_V1_1
)
SELECT
'arctic-embed' AS model,
'inner_product' AS similarity_function,
CORR(LABEL, VECTOR_INNER_PRODUCT(arctic_embed_1, arctic_embed_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'arctic-embed' AS model,
'l1_distance' AS similarity_function,
CORR(LABEL, -VECTOR_L1_DISTANCE(arctic_embed_1, arctic_embed_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'arctic-embed' AS model,
'l2_distance' AS similarity_function,
CORR(LABEL, -VECTOR_L2_DISTANCE(arctic_embed_1, arctic_embed_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'arctic-embed' AS model,
'cosine_similarity' AS similarity_function,
CORR(LABEL, VECTOR_COSINE_SIMILARITY(arctic_embed_1, arctic_embed_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'arctic-embed-v1.5' AS model,
'inner_product' AS similarity_function,
CORR(LABEL, VECTOR_INNER_PRODUCT(arctic_embed_v15_1, arctic_embed_v15_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'arctic-embed-v1.5' AS model,
'l1_distance' AS similarity_function,
CORR(LABEL, -VECTOR_L1_DISTANCE(arctic_embed_v15_1, arctic_embed_v15_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'arctic-embed-v1.5' AS model,
'l2_distance' AS similarity_function,
CORR(LABEL, -VECTOR_L2_DISTANCE(arctic_embed_v15_1, arctic_embed_v15_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'arctic-embed-v1.5' AS model,
'cosine_similarity' AS similarity_function,
CORR(LABEL, VECTOR_COSINE_SIMILARITY(arctic_embed_v15_1, arctic_embed_v15_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'e5-base-v2' AS model,
'inner_product' AS similarity_function,
CORR(LABEL, VECTOR_INNER_PRODUCT(e5_base_1, e5_base_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'e5-base-v2' AS model,
'l1_distance' AS similarity_function,
CORR(LABEL, -VECTOR_L1_DISTANCE(e5_base_1, e5_base_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'e5-base-v2' AS model,
'l2_distance' AS similarity_function,
CORR(LABEL, -VECTOR_L2_DISTANCE(e5_base_1, e5_base_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'e5-base-v2' AS model,
'cosine_similarity' AS similarity_function,
CORR(LABEL, VECTOR_COSINE_SIMILARITY(e5_base_1, e5_base_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'nv-embed-qa-4' AS model,
'inner_product' AS similarity_function,
CORR(LABEL, VECTOR_INNER_PRODUCT(nv_embed_1, nv_embed_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'nv-embed-qa-4' AS model,
'l1_distance' AS similarity_function,
CORR(LABEL, -VECTOR_L1_DISTANCE(nv_embed_1, nv_embed_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'nv-embed-qa-4' AS model,
'l2_distance' AS similarity_function,
CORR(LABEL, -VECTOR_L2_DISTANCE(nv_embed_1, nv_embed_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'nv-embed-qa-4' AS model,
'cosine_similarity' AS similarity_function,
CORR(LABEL, VECTOR_COSINE_SIMILARITY(nv_embed_1, nv_embed_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'multilingual-e5-large' AS model,
'inner_product' AS similarity_function,
CORR(LABEL, VECTOR_INNER_PRODUCT(multi_e5_1, multi_e5_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'multilingual-e5-large' AS model,
'l1_distance' AS similarity_function,
CORR(LABEL, -VECTOR_L1_DISTANCE(multi_e5_1, multi_e5_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'multilingual-e5-large' AS model,
'l2_distance' AS similarity_function,
CORR(LABEL, -VECTOR_L2_DISTANCE(multi_e5_1, multi_e5_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'multilingual-e5-large' AS model,
'cosine_similarity' AS similarity_function,
CORR(LABEL, VECTOR_COSINE_SIMILARITY(multi_e5_1, multi_e5_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'voyage-multilingual-2' AS model,
'inner_product' AS similarity_function,
CORR(LABEL, VECTOR_INNER_PRODUCT(voyage_1, voyage_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'voyage-multilingual-2' AS model,
'l1_distance' AS similarity_function,
CORR(LABEL, -VECTOR_L1_DISTANCE(voyage_1, voyage_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'voyage-multilingual-2' AS model,
'l2_distance' AS similarity_function,
CORR(LABEL, -VECTOR_L2_DISTANCE(voyage_1, voyage_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'voyage-multilingual-2' AS model,
'cosine_similarity' AS similarity_function,
CORR(LABEL, VECTOR_COSINE_SIMILARITY(voyage_1, voyage_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'snowflake-arctic-embed-l-v2.0' AS model,
'inner_product' AS similarity_function,
CORR(LABEL, VECTOR_INNER_PRODUCT(arctic_embed_v20_1, arctic_embed_v20_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'snowflake-arctic-embed-l-v2.0' AS model,
'l1_distance' AS similarity_function,
CORR(LABEL, -VECTOR_L1_DISTANCE(arctic_embed_v20_1, arctic_embed_v20_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'snowflake-arctic-embed-l-v2.0' AS model,
'l2_distance' AS similarity_function,
CORR(LABEL, -VECTOR_L2_DISTANCE(arctic_embed_v20_1, arctic_embed_v20_2)) AS correlation
FROM embeddings
UNION ALL
SELECT
'snowflake-arctic-embed-l-v2.0' AS model,
'cosine_similarity' AS similarity_function,
CORR(LABEL, VECTOR_COSINE_SIMILARITY(arctic_embed_v20_1, arctic_embed_v20_2)) AS correlation
FROM embeddings
ORDER BY correlation DESC;
検証結果
検証結果は以下の通りです。
JSTS の正解ラベルとの相関係数で並べ替えております。(つまり正しい類似度を算出すると 1
に近づいていきます)
Embedding モデル | ベクトル類似度関数 | 正解ラベルとの相関係数 |
---|---|---|
voyage-multilingual-2 | cosine_similarity | 0.8669603068 |
voyage-multilingual-2 | inner_product | 0.8667315701 |
voyage-multilingual-2 | l1_distance | 0.8531674528 |
voyage-multilingual-2 | l2_distance | 0.8530933051 |
multilingual-e5-large | inner_product | 0.8502651471 |
multilingual-e5-large | cosine_similarity | 0.8502651416 |
multilingual-e5-large | l2_distance | 0.8252620835 |
multilingual-e5-large | l1_distance | 0.8245783391 |
snowflake-arctic-embed-l-v2.0 | inner_product | 0.8212467042 |
snowflake-arctic-embed-l-v2.0 | cosine_similarity | 0.8212466973 |
snowflake-arctic-embed-l-v2.0 | l2_distance | 0.8004408183 |
snowflake-arctic-embed-l-v2.0 | l1_distance | 0.7991156231 |
e5-base-v2 | inner_product | 0.6159605484 |
e5-base-v2 | cosine_similarity | 0.6159605425 |
e5-base-v2 | l2_distance | 0.5855630207 |
e5-base-v2 | l1_distance | 0.5834929858 |
nv-embed-qa-4 | cosine_similarity | 0.5387621265 |
nv-embed-qa-4 | inner_product | 0.5387621213 |
nv-embed-qa-4 | l1_distance | 0.5145131639 |
nv-embed-qa-4 | l2_distance | 0.5135808932 |
arctic-embed | l1_distance | 0.4576172035 |
arctic-embed | l2_distance | 0.4572275601 |
arctic-embed | inner_product | 0.4393895588 |
arctic-embed | cosine_similarity | 0.4393895067 |
arctic-embed-v1.5 | l2_distance | 0.4194332344 |
arctic-embed-v1.5 | l1_distance | 0.4193826698 |
arctic-embed-v1.5 | inner_product | 0.4130231283 |
arctic-embed-v1.5 | cosine_similarity | 0.4130231056 |
voyage-multilingual-2
がどのベクトル類似度関数を使った場合でも高い水準の結果を示しており、実際に RAG で用いた際にも安定して高い精度の出力結果を示していました。
arctic-embed-v1.5
、e5-base-v2
、nv-embed-qa-4
、arctic-embed
についてはドキュメントにも記載がある通り英語専用の Embedding モデルとなるため日本語環境下においては限定的な能力しか発揮しなさそうです。
上記より日本語環境下においては voyage-multilingual-2
、multilingual-e5-large
のどちらかを使い、精度重視の場合には voyage-multilingual-2
を、コスパ重視の場合には multilingual-e5-large
を選んでいただくのが良さそうです。
ベクトル類似度関数についてはそこまで大きな差には繋がらない可能性が高いですが、Embedding モデルやテキストデータとの相性もあるため最後の微調整として試してみていただくのが良いのかなと思いました。
最後に
いかがでしたでしょうか?ベクトル化は難しい印象をお持ちの方が多いのではないかと思いますが、実際に触ってみると「なるほど」と思っていただけるのではないかと考えます。特に Snowflake はベクトルデータを扱いやすい環境ですので、身近なドキュメントなどから RAG や検索の仕組みを試しやすいのではないかと思います。ぜひ皆様も本記事を参考に試してみてください!
宣伝
生成AI Conf 様の Webinar で登壇しました!
『生成AI時代を支えるプラットフォーム』というテーマの Webinar で NVIDIA 様、古巣の AWS 様と共に Snowflake 社員としてデータ*AI をテーマに LTをしました!以下が動画アーカイブとなりますので是非ご視聴いただければ幸いです!
SNOWFLAKE WORLD TOUR TOKYO のオンデマンド配信中!
Snowflake の最新情報を知ることができる大規模イベント『SNOWFLAKE WORLD TOUR TOKYO』が2024/9/11-12@ANAインターコンチネンタル東京で開催されました。
現在オンデマンド配信中ですので数々の最新のデータ活用事例をご覧ください。
また私が登壇させていただいた『今から知ろう!Snowflakeの基本概要』では、Snowflakeのコアの部分を30分で押さえられますので、Snowflake をイチから知りたい方、最新の Snowflake の特徴を知りたい方は是非ご視聴いただければ嬉しいですmm
X で Snowflake の What's new の配信してます
X で Snowflake の What's new の更新情報を配信しておりますので、是非お気軽にフォローしていただければ嬉しいです。
日本語版
Snowflake の What's New Bot (日本語版)
English Version
Snowflake What's New Bot (English Version)
変更履歴
(20240914) 新規投稿
(20240926) 宣伝欄の修正
(20241216) Embedding 関数のモデル arctic-embed-v1.5
と snowflake-arctic-embed-l-v2.0
、ベクトル類似度関数 VECTOR_L1_DISTANCE
の追加に伴い記事を大幅にアップデート。宣伝欄のアップデート
Discussion