❄️

Snowflake のベクトル化は何を使えばいいのか? (Cortex LLM Embedding)

に公開

SNOWFLAKE WORLD TOUR TOKYO 2025

2025/9/11 - 12の2日間、Snowflake の国内最大のイベント『SNOWFLAKE WORLD TOUR TOKYO 2025』が開催されます!データ活用の最前線を是非体感しに来てください!私は『Snowflake Cortex AISQL を用いた高度な分析手法』というセッションで登壇させていただきます。AISQL の基本から応用までキャッチアップできますので是非ご登録いただければ嬉しいですー!(9/12の方がまだ空席がございます)

はじめに

ドキュメントや画像などの非構造化データの類似性を調べたり、曖昧検索などにおいてベクトル化 (Embedding) の技術は非常に重要であり、これからもその重要性は更に増えてくると考えられます。Snowflake は標準でベクトルデータ型に対応しており、ベクトル化を行う Cortex LLM の Embedding 関数ベクトル類似度を算出する関数などベクトルデータの取り扱いがしやすい環境を提供しています。

直近では2024/8/29に Embedding 関数のモデル multilingual-e5-large が、2024/9/12に同じく Embedding 関数のモデルである voyage-multilingual-2 が、その後2024/12には arctic-embed-v1.5snowflake-arctic-embed-l-v2.0 が怒涛の勢いでリリースされました。

ただ、Embedding 関数は現時点で7モデル、ベクトル類似度関数は現時点で4種類と選択肢が多いため何を使えばいいのか悩んでしまうケースがあるかもしれません。そこで今回は Snowflake の仕組みを使って日本語利用時における各 Embedding モデルとベクトル類似度関数の性能比較をしてみたいと思います。

(2025/7/17追記) 後発の関数として AI_EMBED 関数がリリースされました。AI_EMBED 関数の使い方については「Snowflake AI_EMBED 関数で実現するマルチモーダルベクトル検索」にて解説しておりますので合わせてご確認ください。

https://zenn.dev/tsubasa_tech/articles/e7683605e7d7aa

先に結論

日本語環境下においては、
Embedding モデル: voyage-multilingual-2
ベクトル類似度関数: コサイン類似度 or 内積
の組み合わせが良さそうです。

ただし multilingual-e5-largevoyage-multilingual-2 に準ずる高い性能を示しており、かつ単価が安いため、multilingual-e5-large も状況次第で十分に選択できると思います。

では検証の流れをご紹介します。

(参考) Embedding モデルの単価

Credit Consumption Table


2024/12/16 時点の価格テーブル

(参考) 各モデルのコンテキストウィンドウについて

Text embedding models


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 などの日本語能力を検証するために広く使われている JGLUEJSTS データセットを利用させていただきます。

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.5e5-base-v2nv-embed-qa-4arctic-embed についてはドキュメントにも記載がある通り英語専用の Embedding モデルとなるため日本語環境下においては限定的な能力しか発揮しなさそうです。

上記より日本語環境下においては voyage-multilingual-2multilingual-e5-large のどちらかを使い、精度重視の場合には voyage-multilingual-2 を、コスパ重視の場合には multilingual-e5-large を選んでいただくのが良さそうです。

ベクトル類似度関数についてはそこまで大きな差には繋がらない可能性が高いですが、Embedding モデルやテキストデータとの相性もあるため最後の微調整として試してみていただくのが良いのかなと思いました。

最後に

いかがでしたでしょうか?ベクトル化は難しい印象をお持ちの方が多いのではないかと思いますが、実際に触ってみると「なるほど」と思っていただけるのではないかと考えます。特に Snowflake はベクトルデータを扱いやすい環境ですので、身近なドキュメントなどから RAG や検索の仕組みを試しやすいのではないかと思います。ぜひ皆様も本記事を参考に試してみてください!

宣伝

SNOWFLAKE DISCOVER (第2弾) 開催決定!

2025/7/8-9の2日間「Snowflake Discover (第2弾)」が開催されます!Snowflake Summit の振り返りからハンズオンまで凝縮したコンテンツを Webinar 形式でお届けしますので是非ご視聴ください!私は2日目のハンズオン「Snowflake Cortex AI で実現する次世代の VoC (顧客の声) 分析」をデリバリします。最新の Cortex AISQL 関数を用いた実践的な顧客の声分析の手法を体得することができますので是非お気軽にご登録ください!

開催日時: 2025/7/8-9
形式: Webinar (オンライン)
参加費: 無料

https://www.snowflake.com/about/webinars/snowflake-discover-ja/?utm_source=aesdr

SNOWFLAKE DISCOVER で登壇しました!

2025/4/24-25に開催されました Snowflake のエンジニア向け大規模ウェビナー『SNOWFLAKE DISCOVER』において『ゼロから始めるSnowflake:モダンなデータ&AIプラットフォームの構築』という一番最初のセッションで登壇しました。Snowflake の概要から最新状況まで可能な限り分かりやすく説明しておりますので是非キャッチアップにご活用いただければ嬉しいです!

以下リンクでご登録いただけるとオンデマンドですぐにご視聴いただくことが可能です。

生成AI Conf 様の Webinar で登壇しました!

『生成AI時代を支えるプラットフォーム』というテーマの Webinar で NVIDIA 様、古巣の AWS 様と共に Snowflake 社員としてデータ*AI をテーマに LTをしました!以下が動画アーカイブとなりますので是非ご視聴いただければ幸いです!

https://www.youtube.com/live/no9WYeLFNaI?si=2r0TVWLkv1F5d4Gs

X で Snowflake の What's new の配信してます

X で Snowflake の What's new の更新情報を配信しておりますので、是非お気軽にフォローしていただければ嬉しいです。

日本語版

Snowflake の What's New Bot (日本語版)
https://x.com/snow_new_jp

English Version

Snowflake What's New Bot (English Version)
https://x.com/snow_new_en

変更履歴

(20240914) 新規投稿
(20240926) 宣伝欄の修正
(20241216) Embedding 関数のモデル arctic-embed-v1.5snowflake-arctic-embed-l-v2.0、ベクトル類似度関数 VECTOR_L1_DISTANCE の追加に伴い記事を大幅にアップデート。宣伝欄のアップデート
(20250508) 宣伝欄の修正
(20250629) 宣伝欄の修正
(20250717) 「Snowflake AI_EMBED 関数で実現するマルチモーダルベクトル検索」へのリンクを追記

Discussion