2026年ベクトル埋め込みモデル比較・選択完全ガイド

AI与大数据

なぜ2026年の埋め込みモデル選択がRAGシステムの上限を決めるのか

2026年になっても2023年の埋め込みモデルでRAGを構築しているなら、それはPentium IIIで大規模モデルを動かすようなもの——動かないわけではないが、あまりにもったいない。埋め込みモデルはRAGパイプライン全体の起点であり、ドキュメントが「理解」される深さを決め、検索リコールの品質上限を設定する。どれほど優れたLLMでも、間違ったチャンクを入力すればゴミが出力される。

過去1年間、埋め込みモデルの進化速度は予想を遥かに超えた。OpenAIのtext-embedding-3シリーズは安定し、オープンソース陣営のbge、E5、GTEも継続的に進化、CohereとJinaは多言語と長文脈の2つの次元から攻勢をかけた。どれを選ぶべきか?どう選ぶべきか?このガイドが完全な答えを提供する。

2026年主流埋め込みモデル一覧

モデル 次元 最大Token 中国語対応 オープンソース MTEB平均 推論遅延(ms/1k tokens)
text-embedding-3-small 1536 8191 ★★★★ 64.2 18
text-embedding-3-large 3072 8191 ★★★★★ 68.7 32
bge-large-zh-v1.5 1024 512 ★★★★★ 65.8 12
bge-m3 1024 8192 ★★★★★ 67.3 22
E5-large-v2 1024 512 ★★★ 63.5 14
GTE-large 1024 512 ★★★ 64.1 13
Cohere embed-v3 1024 512 ★★★★★ 67.9 25
Jina-embeddings-v2 1024 8192 ★★★★ 62.8 20
multilingual-e5-large 1024 512 ★★★★★ 63.2 16
mxbai-embed-large 1024 8192 ★★★★ 66.5 15

データは2026年5月時点のMTEBおよびC-MTEBベンチマークに基づく。推論遅延はA100単一GPUでの測定結果。参考値として扱うこと。


モデル別詳細比較

OpenAI text-embedding-3-small / large

OpenAIが2024年初頭にリリースした第3世代埋め込みモデルで、現在もAPI呼び出しの首选。small版はコストパフォーマンスに優れ、1536次元でほとんどのユースケースに十分;large版は3072次元で、次元削減(256次元まで削減してストレージ節約)をサポートし、高精度が求められる場面で優位性が顕著。

強み:安定したAPI、デプロイ不要、多言語バランス良好、柔軟な次元削減 弱み:データ越境制限、長期コスト高、中国語ではbge-m3に劣る

bge-large-zh-v1.5 / bge-m3

BAAIのbgeシリーズは中国語シナリオの王者。bge-large-zh-v1.5は中国語専用最適化でC-MTEBで長期トップ。bge-m3は2025年の新フラッグシップで8192トークン長文対応、同時に密+疎+ColBERTの3種ベクトルを生成し、検索リコール率が極めて高い。

強み:中国語トップクラス、オープンソースでプライベートデプロイ可能、bge-m3多粒度検索 弱み:bge-large-zhは最大512トークン、デプロイにGPUリソースが必要

E5-large-v2

MicrosoftのE5シリーズは「テキストプレフィックス」戦略で知られる——クエリに"query:"プレフィックス、ドキュメントに"passage:"プレフィックスを付加。v2は英語で優秀だが、中国語対応は中程度。

強み:英語で優秀、シンプルで効果的なプレフィックス戦略、オープンソース 弱み:中国語は中程度、512トークン制限、プレフィックスの正しい使用が必須

GTE-large

Alibaba DAMOのGTEモデルは英語MTEBで好成績、中国語も基礎がしっかり。訓練データ品質が高く、モデル安定性が良い。

強み:中国語・英語バランス良好、高品質訓練データ、オープンソース 弱み:中国語ではbgeに劣る、512トークン制限

Cohere embed-v3

Cohereの第3世代埋め込みモデルの最大の特徴は「入力タイプ」パラメータ対応——モデルにsearch_documentかsearch_queryかを伝えると、モデルが最適化して処理。多言語対応も優秀。

強み:入力タイプ認識、多言語優秀、安定したAPI 弱み:クローズドソース、価格高め、外部API依存

Jina-embeddings-v2

Jinaの長文脈埋め込みモデルで、8192トークン対応が長ドキュメントシナリオで唯一無二。チャンキングを最小限にしたい場合、Jinaは長ドキュメントを直接処理できる数少ない選択肢。

強み:8192トークン長文脈、オープンソース、カスタムファインチューニング対応 弱み:短文精度はbgeに劣る、推論速度は中程度

multilingual-e5-large

Microsoftの多言語E5は100+言語をカバーし、言語間検索で優秀。データセットに複数言語が含まれる場合、最も安全な選択。

強み:100+言語カバー、言語間検索が強力、オープンソース 弱み:単一言語精度は専用モデルに劣る、モデルサイズ大

mxbai-embed-large

Mixed Bread AIの埋め込みモデルは2025年に台頭——8192トークン + オープンソース + 軽量推論でコストパフォーマンス抜群。MTEBスコアはクローズドソースモデルに迫る。

強み:長文脈 + オープンソース + 軽量、高MTEBスコア、高速推論 弱み:bgeほどコミュニティが成熟していない、中国語ファインチューニングリソースが少ない


ベンチマーク結果

中国語データセット(C-MTEB)

モデル 分類 クラスタリング ペア分類 リランキング 検索 意味類似度 平均
bge-m3 68.2 44.7 76.3 62.1 72.8 81.5 67.6
bge-large-zh-v1.5 67.8 43.9 75.8 61.5 71.2 80.9 66.9
text-embedding-3-large 66.5 42.3 74.2 60.8 69.5 79.8 65.5
Cohere embed-v3 65.9 41.8 73.6 59.7 68.8 79.2 64.8
mxbai-embed-large 64.7 40.5 72.1 58.3 67.2 78.1 63.5
multilingual-e5-large 63.8 39.7 71.5 57.6 66.4 77.5 62.8
GTE-large 62.4 38.9 70.8 56.2 65.1 76.8 61.7
E5-large-v2 61.2 37.5 69.4 55.1 63.8 75.6 60.4

英語データセット(MTEB)

モデル 分類 クラスタリング ペア分類 リランキング 検索 意味類似度 平均
text-embedding-3-large 72.4 48.6 82.1 65.3 74.2 84.7 71.2
Cohere embed-v3 71.8 47.9 81.5 64.8 73.5 83.9 70.6
mxbai-embed-large 70.5 46.2 80.3 63.1 72.1 82.8 69.2
bge-m3 69.8 45.7 79.6 62.4 71.3 82.1 68.5
GTE-large 68.9 44.8 78.7 61.5 70.2 81.3 67.6
E5-large-v2 68.2 44.1 78.1 60.8 69.5 80.7 66.9
text-embedding-3-small 67.5 43.3 77.4 59.6 68.8 79.9 66.1
Jina-embeddings-v2 65.8 41.7 75.6 57.9 66.4 78.2 64.3

完全評価コード

以下のPythonコードは、独自データセットで異なる埋め込みモデルの効果を評価するのに役立つ:

import numpy as np
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
from typing import List, Dict, Tuple
import time
import json

MODEL_NAMES = [
    "BAAI/bge-large-zh-v1.5",
    "BAAI/bge-m3",
    "intfloat/e5-large-v2",
    "Alibaba-NLP/gte-large",
    "mixedbread-ai/mxbai-embed-large-v1",
    "jinaai/jina-embeddings-v2-base-zh",
    "intfloat/multilingual-e5-large",
]

def load_test_data(path: str) -> List[Dict]:
    with open(path, "r", encoding="utf-8") as f:
        return json.load(f)

def encode_texts(
    model: SentenceTransformer,
    texts: List[str],
    prefix: str = "",
    batch_size: int = 64,
) -> np.ndarray:
    if prefix:
        texts = [f"{prefix}{t}" for t in texts]
    embeddings = model.encode(
        texts,
        batch_size=batch_size,
        show_progress_bar=True,
        normalize_embeddings=True,
    )
    return embeddings

def evaluate_retrieval(
    queries: List[str],
    documents: List[str],
    relevance: List[List[int]],
    model_name: str,
) -> Dict[str, float]:
    model = SentenceTransformer(model_name)
    prefix_q = "query: " if "e5" in model_name.lower() else ""
    prefix_d = "passage: " if "e5" in model_name.lower() else ""

    start = time.time()
    q_emb = encode_texts(model, queries, prefix=prefix_q)
    d_emb = encode_texts(model, documents, prefix=prefix_d)
    latency = time.time() - start

    sim_matrix = cosine_similarity(q_emb, d_emb)

    hits_at_1 = 0
    hits_at_5 = 0
    hits_at_10 = 0
    mrr_total = 0.0

    for i in range(len(queries)):
        ranked = np.argsort(-sim_matrix[i])
        rel_set = set(relevance[i])
        if ranked[0] in rel_set:
            hits_at_1 += 1
        if any(r in rel_set for r in ranked[:5]):
            hits_at_5 += 1
        if any(r in rel_set for r in ranked[:10]):
            hits_at_10 += 1
        for rank_idx, doc_idx in enumerate(ranked):
            if doc_idx in rel_set:
                mrr_total += 1.0 / (rank_idx + 1)
                break

    n = len(queries)
    return {
        "model": model_name,
        "hit@1": round(hits_at_1 / n, 4),
        "hit@5": round(hits_at_5 / n, 4),
        "hit@10": round(hits_at_10 / n, 4),
        "mrr": round(mrr_total / n, 4),
        "latency_s": round(latency, 2),
    }

def run_benchmark(data_path: str) -> None:
    data = load_test_data(data_path)
    queries = [item["query"] for item in data]
    documents = list({d for item in data for d in item["documents"]})
    doc_index = {d: i for i, d in enumerate(documents)}
    relevance = [
        [doc_index[d] for d in item["relevant_docs"] if d in doc_index]
        for item in data
    ]

    results = []
    for model_name in MODEL_NAMES:
        print(f"Evaluating {model_name}...")
        result = evaluate_retrieval(queries, documents, relevance, model_name)
        results.append(result)
        print(f"  Hit@1={result['hit@1']}, MRR={result['mrr']}")

    print("\n=== Benchmark Results ===")
    for r in results:
        print(f"{r['model']}: Hit@1={r['hit@1']}, Hit@5={r['hit@5']}, "
              f"Hit@10={r['hit@10']}, MRR={r['mrr']}, Latency={r['latency_s']}s")

if __name__ == "__main__":
    run_benchmark("test_data.json")

よくある5つの落とし穴

1. E5にプレフィックスなしで使用

E5モデルはクエリにquery:プレフィックス、ドキュメントにpassage:プレフィックスが必須。プレフィックスなしでは性能が15-25%低下する。これは推奨ではなく必須要件。

2. 最大Token制限の無視

bge-large-zh-v1.5とE5-large-v2の最大トークンは512のみ。チャンクがこの長さを超えると、超過分は黙って切り捨てられ、意味情報が大きく失われる。チャンクサイズを制御するか、bge-m3/Jinaなどの長文脈モデルを選ぶこと。

3. 異なるモデル間でベクトル混用

各モデルのベクトル空間は独立している。bgeでクエリをエンコードし、E5でドキュメントをエンコードして類似度を計算することはできない。ベクトルは同じモデル下で生成しなければ意味がない。

4. ベクトルの正規化忘れ

コサイン類似度の計算時、ベクトルが正規化されていないと不正確な結果になる。エンコード時にnormalize_embeddings=Trueを設定するか、手動で正規化する:

embeddings = embeddings / np.linalg.norm(embeddings, axis=1, keepdims=True)

5. ユークリッド距離をコサイン類似度の代わりに使用

正規化済みベクトルではユークリッド距離とコサイン類似度は等価。しかし未正規化では全く異なるランキング結果になる。ベクトルデータベースでコサイン類似度メトリックを使用していることを必ず確認すること。


10のエラートラブルシューティング

# 症状 推定原因 解決策
1 検索結果が完全に無関係 モデルプレフィックス未追加 E5/multilingual-e5にはquery:/passage:プレフィックスが必須
2 中国語検索の品質が低い 英語専用モデルを使用 bge-large-zh-v1.5またはbge-m3に切り替え
3 ベクトル次元の不一致 DBとモデルの次元が不整合 ベクトルDBの次元設定がモデル出力と一致するか確認
4 長ドキュメントのリコールが低い ドキュメントが切り捨てられた 8192トークンモデルを使用またはチャンキング戦略を最適化
5 推論が遅すぎる モデルが大きすぎるかバッチ処理なし small版を使用、batch_sizeを増加、GPUを有効化
6 言語間検索が失敗 単一言語モデル multilingual-e5またはCohere embed-v3を使用
7 メモリ不足 一度に多すぎるテキストをエンコード 64-128件ずつバッチでエンコード
8 類似度がすべて1または-1 ベクトルがすべてゼロまたはNaN 入力が空でないか、モデルが正しくロードされているか確認
9 ファインチューニング後の性能低下 過学習または学習率が大きすぎる 学習率を下げる、データを増やす、early stoppingを使用
10 API呼び出しタイムアウト ネットワーク問題またはリクエスト過大 バッチサイズを減らす、timeoutを増加、ローカルデプロイを使用

モデルファインチューニングのコツ

埋め込みモデルのファインチューニングは、特定ドメインでの検索性能を大幅に向上できる。以下が主要ステップ:

データ準備

from sentence_transformers import InputExample
from torch.utils.data import DataLoader

train_examples = []
for item in training_data:
    train_examples.append(InputExample(
        texts=[item["query"], item["positive_doc"]],
        label=1.0
    ))
    if item.get("negative_doc"):
        train_examples.append(InputExample(
            texts=[item["query"], item["negative_doc"]],
            label=0.0
        ))

train_dataloader = DataLoader(train_examples, shuffle=True, batch_size=32)

訓練設定

from sentence_transformers import losses, SentenceTransformer

model = SentenceTransformer("BAAI/bge-large-zh-v1.5")
train_loss = losses.ContrastiveLoss(model)

model.fit(
    train_objectives=[(train_dataloader, train_loss)],
    epochs=3,
    warmup_steps=int(0.1 * len(train_dataloader)),
    output_path="./fine_tuned_bge",
    show_progress_bar=True,
)

ファインチューニングの核心アドバイス

  1. データ品質 > データ量:1000件の高品質アノテーションが10000件のノイズデータに勝る
  2. Hard Negativeは不可欠:ランダムなネガティブは簡単すぎてモデルが識別力を学べない。BM25の検索結果から上位だが無関係なドキュメントをhard negativeとして使用
  3. 学習率は2e-5から開始:埋め込みモデルは学習率に非常に敏感、大きすぎると事前学習知識が破壊される
  4. 検証セットの監視:各エポック後に検証セットでMRRを評価、低下したら即座に停止
  5. ドメイン語彙の注入:訓練データにドメイン固有用語の定義ペアを追加し、専門用語の理解を助ける

おすすめツール

埋め込みモデル関連データの処理に役立つツール:

  • JSONフォーマッター — 埋め込みモデルのAPIレスポンスは通常JSON形式、このツールでベクトルデータ構造を素早くフォーマット・検査
  • Base64エンコーダー — ベクトルデータの転送時にBase64エンコーディングが頻繁に必要、このツールでエンコード/デコードを瞬時に完了
  • ハッシュ計算ツール — ドキュメント内容のハッシュ値を計算し、重複排除とバージョン管理に使用、埋め込みキャッシュの有効性を確保

まとめ:2026年の埋め込みモデル選択——中国語シナリオならbge-m3(長文脈+多粒度検索)、英語ならtext-embedding-3-large(最高精度)、言語間検索ならmultilingual-e5-large、予算制限ならmxbai-embed-large。万能モデルは存在しない、あなたのシナリオに最適なモデルだけがある。まず評価し、それからデプロイし、本番トラフィックで実験してはいけない。

ブラウザローカルツールを無料で試す →

#向量嵌入#embedding#语义搜索#文本向量化#RAG#2026