2026年向量嵌入模型對比與選擇完全指南
為什麼2026年嵌入模型的選擇決定了RAG系統的上限
如果你在2026年還在用2023年的嵌入模型做RAG,那就像用奔騰III跑大模型——不是不行,是太虧了。嵌入模型是整個RAG鏈路的起點,它決定了你的文件被「理解」的深度,也決定了檢索召回的品質上限。再好的LLM,餵進去的chunk不對,輸出也是垃圾。
過去一年,嵌入模型的迭代速度遠超預期。OpenAI的text-embedding-3系列已經穩定,開源陣營的bge、E5、GTE也在持續進化,Cohere和Jina則從多語言和長文本兩個維度發起了衝擊。選哪個?怎麼選?這篇文章給你一個完整的答案。
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單卡測試結果,僅供參考。
逐模型深度對比
OpenAI text-embedding-3-small / large
OpenAI在2024年初推出的第三代嵌入模型,至今仍是API呼叫的首選。small版本性價比極高,1536維在大多數場景下夠用;large版本3072維,支援維度截斷(可以降到256維節省儲存),在精度要求高的場景下優勢明顯。
優勢:API穩定、無需部署、多語言表現均衡、維度截斷靈活 劣勢:資料不出境受限、長期成本高、中文場景不如bge-m3
bge-large-zh-v1.5 / bge-m3
智源研究院的bge系列是中文場景的王者。bge-large-zh-v1.5專門針對中文最佳化,在C-MTEB上長期霸榜。bge-m3是2025年的新旗艦,支援8192 token長文本,同時生成稠密+稀疏+ColBERT三種向量,檢索召回率極高。
優勢:中文效果頂級、開源可私有化部署、bge-m3多粒度檢索 劣勢:bge-large-zh最大token僅512、部署需要GPU資源
E5-large-v2
微軟的E5系列以「文字前綴」策略著稱——查詢加"query:"前綴,文件加"passage:"前綴。v2版本在英文場景表現優異,但中文支援一般。
優勢:英文效果出色、前綴策略簡單有效、開源 劣勢:中文效果中等、512 token限制、需要正確使用前綴
GTE-large
阿里巴巴達摩院的GTE模型,在英文MTEB上表現亮眼,中文也有不錯的基礎。訓練資料品質高,模型穩定性好。
優勢:中英文均衡、訓練資料品質高、開源 劣勢:中文場景不如bge、512 token限制
Cohere embed-v3
Cohere的第三代嵌入模型,最大亮點是支援「輸入類型」參數——你可以告訴模型當前是search_document還是search_query,模型會針對性最佳化。多語言支援出色。
優勢:輸入類型感知、多語言優秀、API穩定 劣勢:閉源、價格較高、依賴外部API
Jina-embeddings-v2
Jina的長文本嵌入模型,8192 token的支援讓它在長文件場景下獨樹一幟。如果你不想做chunking,Jina是少數能直接處理長文件的選擇。
優勢:8192 token長文本、開源、支援自訂微調 劣勢:短文本精度不如bge、推理速度中等
multilingual-e5-large
微軟的多語言E5,覆蓋100+語言,在跨語言檢索場景下表現優異。如果你的資料集包含多種語言,這是最穩妥的選擇。
優勢:100+語言覆蓋、跨語言檢索強、開源 劣勢:單語言精度不如專用模型、模型體積大
mxbai-embed-large
Mixed Bread AI的嵌入模型,2025年異軍突起,8192 token + 開源 + 輕量級推理,性價比極高。在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的最大token只有512。如果你的文件chunk超過這個長度,超出部分會被直接截斷,語義資訊丟失嚴重。要麼控制chunk大小,要麼選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 | 向量維度不匹配 | 資料庫與模型維度不一致 | 確認向量資料庫的維度設定與模型輸出一致 |
| 4 | 長文件檢索召回低 | 文件被截斷 | 使用8192 token模型或最佳化chunk策略 |
| 5 | 推理速度太慢 | 模型太大或未批次處理 | 使用small版本、增加batch_size、啟用GPU |
| 6 | 跨語言檢索失敗 | 單語言模型不支援 | 使用multilingual-e5或Cohere embed-v3 |
| 7 | 記憶體溢位 | 一次性編碼過多文字 | 分批編碼,每批64-128條 |
| 8 | 相似度全是1或-1 | 向量全為零或NaN | 檢查輸入是否為空、模型是否載入正確 |
| 9 | 微調後效果變差 | 過擬合或學習率過大 | 降低學習率、增加資料量、使用early stopping |
| 10 | API呼叫超時 | 網路問題或請求過大 | 減小batch、增加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,
)
微調核心建議
- 資料品質 > 資料數量:1000條高品質標註勝過10000條雜訊資料
- Hard Negative必不可少:隨機負樣本太簡單,模型學不到區分能力。從BM25檢索結果中取排名靠前但不相關的文件作為hard negative
- 學習率從2e-5開始:嵌入模型對學習率非常敏感,過大會破壞預訓練知識
- 驗證集監控:每個epoch後在驗證集上評估MRR,出現下降立即停止
- 領域詞典注入:在訓練資料中加入領域專有名詞的釋義對,幫助模型理解專業術語
工具推薦
在處理嵌入模型相關的資料時,以下工具可以提升你的效率:
- JSON格式化工具 — 嵌入模型的API回傳值通常是JSON格式,用這個工具快速格式化和檢查回傳的向量資料結構
- Base64編碼工具 — 向量資料在傳輸時經常需要Base64編碼,這個工具可以快速完成編解碼
- 雜湊計算工具 — 對文件內容計算雜湊值,用於去重和版本管理,確保嵌入快取的有效性
總結:2026年選嵌入模型,中文場景首選bge-m3(長文本+多粒度檢索),英文場景首選text-embedding-3-large(精度最高),跨語言場景選multilingual-e5-large,預算有限選mxbai-embed-large。沒有萬能模型,只有最適合你場景的模型。先評估,再上線,別拿線上流量做實驗。
本站提供瀏覽器本地工具,免註冊即可試用 →