跳转至

Embedding 模型选型与微调 · 运维手册

适用场景:为 RAG 知识库、语义搜索、相似度匹配场景选择合适的 Embedding 模型。


1. Embedding 模型概览

1.1 什么是 Embedding

Embedding 是将文本转化为固定长度的向量(数组),语义相近的文本向量距离也近。

"Kubernetes 部署失败" → [0.12, -0.45, 0.78, ...]  # 1024 维
"Docker 容器启动错误" → [0.15, -0.42, 0.75, ...]  # 相似度高

1.2 核心指标

指标 说明 典型值
维度 向量长度 384-1024
最大 token 单次输入长度 512-8192
MTEB 分数 基准测试质量 60-85
推理速度 每秒处理 token 数 1000-10000
显存占用 模型加载所需显存 1-3 GB

2. 主流模型对比

2.1 国内主流模型

模型 厂商 维度 最大 token 中文支持 部署方式
bge-m3 阿里 1024 8192 ⭐⭐⭐ 本地/API
text2vec-large 上海 AI Lab 1024 512 ⭐⭐⭐ 本地
mxbai-embed-large Mixedbread 1024 512 ⭐⭐ 本地
GTE-Qwen2 阿里 1536 8192 ⭐⭐⭐ 本地

2.2 国际主流模型

模型 厂商 维度 最大 token 中文支持 成本
text-embedding-3-small OpenAI 1536/512/256 8191 ⭐⭐⭐ 付费
text-embedding-3-large OpenAI 3072 8191 ⭐⭐⭐ 付费
embed-english-v3 Voyage AI 1024 4000 ⭐⭐ 付费
nomic-embed-text Nomic 768 8192 ⭐⭐ 免费

2.3 选型决策树

需要私有化部署?
├─ 是 → 用 bge-m3(综合最强)
└─ 否 → 需要高并发?
    ├─ 是 → text-embedding-3-small(快速便宜)
    └─ 否 → 追求精度?
        ├─ 是 → text-embedding-3-large
        └─ 否 → bge-m3(免费且好用)

3. 本地部署

3.1 Ollama 部署 bge-m3

# 拉取模型
ollama pull bge-m3

# 测试生成
curl http://localhost:11434/api/embeddings -d '{
  "model": "bge-m3",
  "prompt": "Kubernetes Pod 处于 Pending 状态"
}'

3.2 Python 调用

from langchain_community.embeddings import OllamaEmbeddings

embeddings = OllamaEmbeddings(
    model="bge-m3",
    base_url="http://localhost:11434"
)

# 生成向量
vec = embeddings.embed_query("Nginx 502 错误")
print(f"向量维度: {len(vec)}")
print(f"向量前 5 维: {vec[:5]}")

3.3 批量生成优化

from concurrent.futures import ThreadPoolExecutor

def batch_embed(texts: list[str], batch_size: int = 32) -> list[list[float]]:
    """批量生成 Embedding"""
    results = []
    for i in range(0, len(texts), batch_size):
        batch = texts[i:i+batch_size]
        vecs = embeddings.embed_documents(batch)
        results.extend(vecs)
    return results

4. 检索优化

4.1 向量相似度计算

import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

def similarity_score(v1: list[float], v2: list[float]) -> float:
    """余弦相似度"""
    a = np.array([v1])
    b = np.array([v2])
    return cosine_similarity(a, b)[0][0]

# 阈值判断
THRESHOLD = 0.75
if similarity_score(query_vec, doc_vec) > THRESHOLD:
    print("语义高度相关")

4.2 混合检索策略

from langchain.retrievers import EnsembleRetriever
from langchain.vectorstores import Chroma
from langchain.retrievers import BM25Retriever

# 向量检索
vector_retriever = Chroma(...).as_retriever()

# 关键词检索
bm25_retriever = BM25Retriever.from_documents(documents)

# 混合检索
ensemble = EnsembleRetriever(
    retrievers=[vector_retriever, bm25_retriever],
    weights=[0.7, 0.3]  # 向量 70% + 关键词 30%
)

5. 模型微调

5.1 何时需要微调

场景 是否需要微调 理由
通用知识库 ❌ 不需要 预训练模型已足够
垂直领域(医疗/法律) ✅ 建议微调 领域术语和表达特殊
多语言混合 ✅ 建议微调 提升低资源语言表现
极高精度要求 ✅ 需要微调 特定场景优化

5.2 微调流程

from sentence_transformers import SentenceTransformer, InputExample, losses
from torch.utils.data import DataLoader

# 加载预训练模型
model = SentenceTransformer('BAAI/bge-m3')

# 准备训练数据
train_examples = [
    InputExample(texts=["查询文本", "相关文档"]),
    InputExample(texts=["查询文本", "不相关文档"]),
]

# 训练
train_dataloader = DataLoader(train_examples, shuffle=True, batch_size=16)
train_loss = losses.CosineSimilarityLoss(model)

model.fit(
    train_objectives=[(train_dataloader, train_loss)],
    epochs=3,
    warmup_steps=100
)

# 保存
model.save("my-embedding-model")

5.3 微调效果评估

# 测试集评估
from sentence_transformers.evaluation import SemanticSearchEvaluator

eval_dataset = [...]  # 测试数据
evaluator = SemanticSearchEvaluator(
    queries=test_queries,
    corpus=test_corpus,
    relevant_docs=test_relevant
)

score = evaluator(model)
print(f"MRR: {score['mrr']}")  # 平均倒数排名
print(f"HitRate: {score['hit_rate']}")  # 命中率

6. 性能调优

6.1 向量库索引优化

# ChromaDB HNSW 索引
collection = client.get_or_create_collection(
    name="ops-knowledge",
    metadata={
        "hnsw:space": "cosine",
        "hnsw:M": 16,           # 连接度
        "hnsw:ef_construction": 200  # 构建效率
    }
)

6.2 量化加速

# FP16 量化(显存减半,精度损失小)
model = SentenceTransformer(
    'BAAI/bge-m3',
    model_kwargs={"torch_dtype": torch.float16}
)

# INT8 量化(显存减 4 倍)
from optimum.quanto import quantize

quantize(model, bits=8)

7. 常见问题排查

问题 1:检索结果不相关

原因:Embedding 质量差或 chunk 切分不当

解决: - 换更好的模型(bge-m3 → text-embedding-3-large) - 优化 chunk_size(512 → 1024) - 调整相似度阈值(0.75 → 0.6)


问题 2:检索速度慢

解决: - 启用 HNSW 索引 - 减小向量维度(1024 → 768) - 使用 GPU 加速推理


问题 3:长文本截断

解决: - 用支持长文本的模型(bge-m3 支持 8192 token) - 提前切分长文档 - 用 sliding window 滑动切片


8. 延伸阅读


FAQ

bge-m3 和 text-embedding-3 怎么选? bge-m3 支持多语言(中英日等)、长文本(8192 token)、本地部署免费;text-embedding-3 是 OpenAI 官方,质量好但需付费 API。预算充足选 OpenAI,私有化部署选 bge-m3。

Embedding 维度如何影响性能? 维度越高精度越好但检索越慢、显存越大。常用维度:384(快)、768(平衡)、1024(高精度)。向量库选择 HNSW 索引可加速高维检索。

如何评估 Embedding 模型效果? 用 MTEB 基准测试(语义相似度、分类、聚类)。生产环境自建评估集:100 条问答对,计算检索召回率和排序准确率。

Embedding 模型需要微调吗? 通用场景不用微调,直接用预训练模型。垂直领域(如医疗、法律)建议微调,用领域数据 LoRA 适配。