篇三:Embedding 与向量检索——选错模型,后面全白跑

第三篇:Embedding 与向量检索

前两篇聊了文档解析和切片,地基打好了,接下来进入核心环节:怎么把文本变成向量,怎么在百万级数据里快速找到最相关的那几条。

先说结论

  1. Embedding 模型选型比向量库选型重要得多。 模型不行,换什么库都救不回来。
  2. 中文场景首选 BGE / M3E,英文场景首选 OpenAI / Cohere。
  3. 向量库选型看数据量和运维能力: 小规模用 PGVector,中大规模用 Milvus / Qdrant,已有 ES 集群可以用 Elasticsearch 做混合检索。
  4. 纯向量检索不够用,必须搭配 BM25 做混合检索。 这一点下一篇细讲,这篇先铺垫。

一个实际案例

某企业内部知识库,上线后用户反馈"搜不到东西"。排查发现:

  • 文档解析和切片没问题
  • 向量库是 Milvus,性能也没问题
  • 问题出在 Embedding 模型 :用的是 text-embedding-ada-002,但用户提问和文档都是中文, ada-002 对中文语义的理解明显弱于中文专用模型

换成 bge-large-zh-v1.5 后,检索命中率从 62% 提升到 87%。换模型比调参数有效 10 倍。


一、Embedding 模型怎么选?

Embedding 的作用是把文本映射到一个高维向量空间,语义相近的文本,向量距离也近。所以模型的质量直接决定检索的上限。

主流模型对比

模型 维度 语言 特点 适用场景
bge-large-zh-v1.5 1024 中文 中文检索 SOTA,开源免费 中文知识库首选
bge-m3 1024 多语言 支持稠密+稀疏+多向量,一模型多用 多语言混合场景
m3e-base / m3e-large 768 / 1024 中文 中文语义匹配效果好 中文问答/搜索
text-embedding-3-large 3072 多语言 OpenAI 最新,效果强但收费 预算充足的英文/多语言项目
text-embedding-ada-002 1536 多语言 上一代,中文偏弱 不推荐新项目中英文场景
Cohere embed-multilingual-v3.0 1024 多语言 多语言效果好,支持自定义维度 国际化项目

选型建议

  • 纯中文项目 → bge-large-zh-v1.5(效果最好)或 m3e-large
  • 中英混合 → bge-m3(一个模型搞定)
  • 纯英文项目 → text-embedding-3-large 或 Cohere embed-multilingual-v3.0
  • 不想自托管 → OpenAI / Cohere API
  • 必须本地部署 → HuggingFace 下载 BGE / M3E 权重,用 Sentence-Transformers 加载

代码示例

ini 复制代码
# 方案 1:Sentence-Transformers(本地部署 BGE)
from sentence_transformers import SentenceTransformer

model = SentenceTransformer("BAAI/bge-large-zh-v1.5")
vectors = model.encode(["公司报销流程是什么", "员工手册第12页"])
print(vectors.shape)  # (2, 1024)
ini 复制代码
# 方案 2:OpenAI API
from openai import OpenAI

client = OpenAI(api_key="sk-xxx")
response = client.embeddings.create(
    model="text-embedding-3-large",
    input=["公司报销流程是什么", "员工手册第12页"]
)
vectors = [item.embedding for item in response.data]
ini 复制代码
# 方案 3:FlagEmbedding(BGE 官方库,支持更多功能)
from FlagEmbedding import BGEM3FlagModel

model = BGEM3FlagModel('BAAI/bge-m3', use_fp16=True)
# 同时输出稠密向量、稀疏向量、多向量
output = model.encode(["公司报销流程"], return_dense=True, return_sparse=True, return_colbert_vecs=True)

二、向量库怎么选?

向量库的核心职责:存向量 + 快速检索。选型看三个维度:数据量、查询延迟、运维复杂度。

主流向量库对比

向量库 类型 数据规模 运维难度 特点
PGVector PostgreSQL 插件 < 1000 万 低(已有 PG 就能用) 适合小规模,SQL + 向量一体化
Milvus 专用向量数据库 亿级 中(需单独部署) 功能最全,社区活跃,中文文档好
Qdrant 专用向量数据库 亿级 中 Rust 编写,性能高,API 友好
Chroma 轻量向量库 < 1000 万 低 开发友好,适合快速原型
Elasticsearch 搜索引擎 亿级 中(已有 ES 就能用) 支持 BM25 + 向量混合检索,天然优势
Faiss 向量检索库 亿级 高(需自己封装服务) Facebook 开源,性能最强但无服务化

选型建议

  • 已有 PostgreSQL → 直接装 PGVector 插件,零额外运维
  • 已有 Elasticsearch → 用 ES 的 dense_vector 类型,天然支持混合检索
  • 从零开始、数据量大 → Milvus(中文社区好)或 Qdrant(性能高)
  • 快速原型 / 小规模 → Chroma
  • 追求极致性能、有工程能力 → Faiss 自己封装

三、检索方式:不只是"相似度搜索"

3.1 相似度搜索(最基础)

ini 复制代码
# Milvus 示例
from pymilvus import Collection

collection = Collection("knowledge_base")
collection.load()

results = collection.search(
    data=[query_vector],        # 查询向量
    anns_field="embedding",     # 向量字段
    param={"metric_type": "COSINE", "params": {"nprobe": 10}},
    limit=10,                   # 返回 Top-10
    output_fields=["text", "source"]
)

相似度度量方式:

  • COSINE(余弦相似度) :最常用,不受向量长度影响
  • L2(欧氏距离) :归一化后等价于余弦
  • IP(内积) :向量归一化后等价于余弦

3.2 过滤检索(Metadata Filter)

用户问"销售部的报销流程",可以在检索时加过滤条件,只搜销售部的文档:

ini 复制代码
from pymilvus import AnnSearchRequest, RRFRanker

# 元数据过滤
expr = "department == 'sales'"
results = collection.search(
    data=[query_vector],
    anns_field="embedding",
    param={"metric_type": "COSINE", "params": {"nprobe": 10}},
    limit=10,
    expr=expr,  # 过滤表达式
    output_fields=["text", "source"]
)

关键点: 切片时把章节、部门、日期等信息写入 metadata,检索时就能做精准过滤。这也是为什么第二篇强调要保留标题层级。

3.3 多路召回(下一篇重点)

同时用向量检索 + BM25 关键词检索,结果合并后再重排序。这是当前生产环境的标配,下一篇详细展开。


四、多语言场景怎么处理?

如果文档和提问混合了中英文,有两种方案:

方案 A:用多语言 Embedding 模型

bge-m3、Cohere embed-multilingual-v3.0、text-embedding-3-large 都天然支持多语言,中英文文本可以直接放在同一个向量空间里检索。

方案 B:查询翻译

用户用中文提问,先把问题翻译成英文,再用英文向量检索英文文档。适合文档以英文为主、用户以中文为主的场景。

ini 复制代码
# 查询翻译示例
from openai import OpenAI

client = OpenAI()
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "system", "content": "将用户问题翻译成英文,只输出翻译结果"},
        {"role": "user", "content": "公司报销流程是什么"}
    ]
)
translated_query = response.choices[0].message.content
# "What is the company reimbursement process?"

建议: 优先用方案 A,简单可靠。方案 B 多一次 LLM 调用,增加延迟和成本,除非多语言模型效果确实不够好再用。


五、性能优化:百万级数据怎么保证低延迟

优化手段 说明 效果
HNSW 索引 近似最近邻算法,检索速度比暴力搜索快 10-100 倍 Milvus / Qdrant / PGVector 默认支持
IVF 索引 倒排文件索引,适合大规模数据 Milvus 支持,需调 nlist 和 nprobe
量化(FP16 / INT8) 降低向量精度,减少内存占用 内存减半,精度损失 < 1%
缓存热门查询 相同 query 直接返回缓存结果 高重复查询场景效果显著
预计算 Embedding 文档入库时提前算好向量,不要在线算 必须做

经验值: 100 万条向量、HNSW 索引、COSINE 度量,Top-10 检索延迟通常在 10-50ms 之间。瓶颈往往不在向量检索,而在 LLM 生成。


六、避坑清单

  1. 中文项目用 ada-002 → 中文语义理解弱,换 BGE 立竿见影
  2. 向量不做归一化就比内积 → 结果不准,统一用 COSINE 或先归一化
  3. 不建索引就直接搜 → 暴力搜索,数据量大时延迟爆炸
  4. metadata 不存章节/来源信息 → 无法做过滤检索,也无法追溯答案来源
  5. 在线计算 Embedding → 每次请求都调一次模型,延迟翻倍,务必预计算
  6. 忽略多语言问题 → 中英文混用同一个模型,效果可能很差

总结

Embedding 和向量检索是 RAG 的"搜索引擎",模型选对了、库选对了,后面才能谈优化。记住一个原则:先保证召回质量,再追求检索速度。

相关推荐
枫叶丹42 小时前
从一次推理请求出发:模型、显存、网络与服务系统如何共同决定性能
网络·人工智能·chatgpt·开源·agent·codex
deepseek233 小时前
硬预算帽默认值拆解:AWS 九月上线支出上限、GCP 七月跟进,Agent 时代按量付费必须默认断供
人工智能·llm·云计算·agent·aws
FanetheDivine4 小时前
学习Agent开发 10.延迟工具 deferred tools
agent·ai编程
为你学会写情书5 小时前
Agent 开发框架深度对比——LangGraph、AutoGen、CrewAI 与 Microsoft Agent Framework 该选谁
agent
染指11105 小时前
135.Agent-多Agent框架-LangChain多智能体(SubAgents子代理)
数据库·人工智能·设计模式·langchain·agent·agents
为你学会写情书5 小时前
Agent 能力评测——2026 年基准测试全景与模型真实能力画像
agent
lucas_AI5 小时前
别等上下文爆了才压缩:AutoCompact 教编码智能体主动「断舍离」
llm·agent
用户3134672143545 小时前
Agent相关 - agent_scratchpad 到底该放哪?一个隐蔽的顺序坑
langchain·llm·agent
七夜zippoe6 小时前
多 Agent 协作架构:Pipeline 模式——串行流水线设计与实战
ai·架构·pipeline·agent·串行流水线