RAG 基础(一):bge-m3 如何把文本变成可检索的向量
在 RAG 系统中,我们经常看到一句话:
把文档切分后生成 Embedding,再写入向量数据库。但如果不知道 Embedding 模型在做什么,就很容易把 bge-m3、Qdrant 和 DeepSeek 混为一谈。
这篇先只解决一个问题:bge-m3 为什么能让系统根据语义检索文本?
1. bge-m3 不是聊天模型
DeepSeek 这类聊天模型接收文本并生成文本:
问题 → DeepSeek → 回答bge-m3 的输出不是一段回答,而是一组数字:
文本 → bge-m3 → [0.021, -0.034, 0.008, ...]这组数字叫作 Embedding,也叫语义向量。
在 AgentShop 当前使用的 bge-m3 配置中,每段文本会得到一个 1024 维稠密向量。所谓 1024 维,就是数组中有 1024 个浮点数,而不是“模型理解了 1024 个关键词”。单个维度通常没有可以直接解释的人类含义,真正有意义的是向量整体在空间中的位置。
2. 为什么向量可以表示语义
Embedding 模型在训练过程中学习把语义相关的文本放到相近的位置。
例如:
文本 A:商品签收后七天内可以申请退货文本 B:收到商品后怎么办理退货文本 C:积分可以兑换哪些优惠券虽然 A 和 B 没有使用完全相同的词,但含义接近,因此向量距离应该更近。C 讨论积分,与它们的距离通常更远。
RAG 检索比较的不是字符串是否相等,而是:
queryVector 与 documentVector 的相似程度这也是语义检索能处理近义表达的原因。
3. Cosine 相似度是什么
AgentShop 的 Qdrant Collection 使用 Cosine 距离。
余弦相似度关注两个向量方向是否接近,而不是单纯比较长度:
cosine(A, B) = (A · B) / (|A| × |B|)不必手算 1024 个数字。只需要理解:向量方向越接近,通常表示语义越相似。
在应用层还需要设置最低相关度。例如当前知识检索配置为:
min-score: 0.70它不是永远正确的标准答案。文档切分方式、模型版本和业务语料都会影响分数分布,应该使用真实问答集进行调优。
4. bge-m3 的三个 M
bge-m3 中的 M3 对应三种能力。
Multi-Linguality:多语言
官方模型资料说明它支持 100 多种工作语言,适合中文、英文以及跨语言检索场景。
对商城知识库而言,这意味着“退换货规则”“return policy”等内容可以进入相同的语义检索体系。不过支持多语言不等于每种业务语料都天然准确,仍然需要评测。
Multi-Functionality:多种检索方式
bge-m3 可以支持:
- Dense Retrieval:一段文本对应一个稠密向量;
- Sparse Retrieval:保留更强的词项匹配信号;
- Multi-Vector Retrieval:用多个向量表示文本并进行细粒度交互。
AgentShop 第一版只使用 Dense Retrieval。
这点很重要:模型支持混合检索,不代表接入模型后系统就自动启用了混合检索。 如果想同时利用稀疏向量或多向量,还需要存储结构、查询逻辑和融合排序共同支持。
Multi-Granularity:多粒度
官方资料给出的最大输入长度为 8192 Token,可以处理短句和较长文档。
但这不意味着应该把整个商城帮助中心作为一个向量。RAG 仍然需要合理切分:块太大时主题混杂,块太小时上下文不足。
5. Query 和 Document 必须使用同一套向量空间
知识入库时:
商城规则片段 → bge-m3 → documentVector用户查询时:
用户问题 → bge-m3 → queryVector两边必须使用兼容的模型、维度和预处理方式。否则向量虽然都是数字,却不位于同一个语义空间,比较结果没有意义。
因此更换 Embedding 模型通常意味着:
- 创建新版本 Collection;
- 重新切分或读取全部文档;
- 用新模型重新生成向量;
- 重新评测召回质量;
- 切换线上检索流量。
不能只改配置里的模型名,然后继续复用旧向量。
6. 为什么 AgentShop 通过 Ollama 运行 bge-m3
当前项目选择:
Java / LangChain4j ↓ HTTPOllama bge-m3 ↓1024 维向量这样做的优点是模型可以在本地运行,知识文本不必为了生成 Embedding 发给外部 API,同时 Java 项目不需要直接管理 Python 推理环境。
先准备模型:
ollama pull bge-m3配置如下:
mall: ai: embedding: base-url: ${OLLAMA_BASE_URL:http://localhost:11434} model-name: ${EMBEDDING_MODEL_NAME:bge-m3} dimension: ${EMBEDDING_DIMENSION:1024}LangChain4j 配置:
@Beanpublic EmbeddingModel knowledgeEmbeddingModel( MallAiEmbeddingProperties properties) { return OllamaEmbeddingModel.builder() .baseUrl(properties.getBaseUrl()) .modelName(properties.getModelName()) .dimensions(properties.getDimension()) .build();}dimension 必须与 Qdrant Collection 的向量维度一致。
7. 一次向量化发生了什么
以文档片段为例:
商品签收后 7 天内,在符合退货条件时可提交售后申请。应用调用:
Embedding embedding = embeddingModel.embed(textSegment).content();得到向量后,向量本身不能直接回答问题,它需要和原文一起进入 Qdrant:
Vector → 用于相似度检索Text → 检索命中后交给 DeepSeek 阅读Metadata → 标题、来源、文档 Key、分块编号如果只保存向量而不保存原文,找到相似 Point 后也没有知识内容可以交给模型。
8. 文档切分会直接影响 Embedding 质量
Embedding 模型不是把一篇长文“压缩成完整知识”。当一个块同时包含退货、物流、积分和优惠券时,单个向量需要表达多个主题,检索结果会变得模糊。
常见切分策略包括:
- 按 Markdown 标题划分主题;
- 按段落和句子继续细分;
- 控制块的最大长度;
- 保留少量重叠,避免关键信息被边界切断;
- 把标题附加到正文,给短片段补充主题。
因此检索效果不好时,不应该第一反应就更换模型。先检查:
原始文档质量→ 切分粒度→ Metadata→ TopK 和阈值→ 最后才是模型选择9. 如何评测 Embedding
不能只用“看起来找到了”判断效果。至少准备一组真实问题及预期文档:
| 用户问题 | 应命中文档 |
|---|---|
| 签收后怎么退货 | 退换货政策、售后申请流程 |
| 优惠券过期还能恢复吗 | 优惠券规则 |
| 节假日什么时候发货 | 配送规则 |
关注这些指标:
- Recall@K:正确片段是否出现在前 K 个结果中;
- MRR:第一个正确结果排得是否足够靠前;
- 无答案问题:不相关内容是否也被高分召回;
- 延迟:单次与批量 Embedding 需要多久;
- 资源:模型运行占用的内存和计算资源。
生成模型回答得不好,不一定是 DeepSeek 的问题,也可能是 bge-m3 根本没有召回正确知识。
10. 常见误区
bge-m3 会生成答案
不会。它生成向量,答案由 DeepSeek 等生成模型完成。
维度越大效果一定越好
不一定。维度会影响存储和计算成本,模型训练质量与业务适配更重要。
支持 8192 Token 就不需要切分
错误。最大输入长度解决“能否输入”,不等于整个长文只生成一个向量就最适合检索。
bge-m3 支持稀疏检索,所以当前项目已经是混合检索
错误。AgentShop 当前只把 1024 维 Dense Vector 写入 Qdrant。
换模型只需要修改 model-name
错误。旧向量必须重新生成,维度不一致时还要创建新 Collection。
11. 本文总结
bge-m3 在 RAG 中承担的是语义编码:
文档片段 ─┐ ├→ bge-m3 → 同一个 1024 维语义空间用户问题 ─┘真正需要记住的是:
- Embedding 是语义表示,不是答案;
- 文档和问题必须使用同一套模型与向量空间;
- 模型能力、项目实际启用的检索方式要分开描述;
- 切分、阈值和评测往往和选模型同样重要。
下一篇继续介绍负责保存这些向量并完成相似度检索的 Qdrant。
参考资料
If this article helped you, please share it with others!
Some information may be outdated






