说明文档
BGE-M3 (论文, 代码)
在本项目中,我们介绍了 BGE-M3,其特点在于多功能性(Multi-Functionality)、多语言性(Multi-Linguality)和多粒度性(Multi-Granularity)方面的卓越表现。
- 多功能性:它能够同时执行嵌入模型的三种常见检索功能:稠密检索、多向量检索和稀疏检索。
- 多语言性:它支持超过100种工作语言。
- 多粒度性:它能够处理不同粒度的输入,从短句到最长8192个token的长文档均可处理。
关于RAG检索流程的一些建议
我们推荐使用以下流程:混合检索 + 重排序。
-
混合检索利用各种方法的优势,提供更高的准确性和更强的泛化能力。 一个经典示例:同时使用嵌入检索和BM25算法。 现在,您可以尝试使用BGE-M3,它同时支持嵌入检索和稀疏检索。 这使得您在生成稠密嵌入时,无需任何额外成本即可获得token权重(类似于BM25)。 如需使用混合检索,您可以参考 Vespa 和 Milvus。
-
作为跨编码器模型,重排序器的准确率比双编码器嵌入模型更高。 在检索后使用重排序模型(例如 bge-reranker、bge-reranker-v2)可以进一步过滤选定的文本。
最新消息:
-
2024/7/1:我们更新了BGE-M3的MIRACL评估结果。如需复现新结果,请参考:bge-m3_miracl_2cr。我们也在arXiv上更新了论文。 <details> <summary> 详情 </summary>
之前的测试结果偏低是因为我们错误地从搜索结果中移除了与查询具有相同id的段落。修正此错误后,BGE-M3在MIRACL上的整体性能高于之前的结果,但实验结论保持不变。其他结果不受此错误影响。如需复现之前较低的结果,您需要在使用
pyserini.search.faiss或pyserini.search.lucene搜索段落时添加--remove-query参数。</details>
-
2024/3/20:感谢Milvus团队! 现在您可以在Milvus中使用bge-m3的混合检索:pymilvus/examples/hello_hybrid_sparse_dense.py。
-
2024/3/8:感谢 @Yannael 提供的实验结果。在该基准测试中,BGE-M3在英语和其他语言中均达到了顶级性能,超越了OpenAI等模型。
-
2024/2/1:感谢Vespa提供的优秀工具。 您可以按照此notebook轻松使用BGE-M3的多种模式。
规格参数
- 模型
| 模型名称 | 维度 | 序列长度 | 简介 |
|---|---|---|---|
| BAAI/bge-m3 | 1024 | 8192 | 多语言;从bge-m3-unsupervised统一微调(dense、sparse和colbert) |
| BAAI/bge-m3-unsupervised | 1024 | 8192 | 多语言;从bge-m3-retromae通过对比学习训练 |
| BAAI/bge-m3-retromae | -- | 8192 | 多语言;将xlm-roberta的max_length扩展到8192,并通过retromae进一步预训练 |
| BAAI/bge-large-en-v1.5 | 1024 | 512 | 英文模型 |
| BAAI/bge-base-en-v1.5 | 768 | 512 | 英文模型 |
| BAAI/bge-small-en-v1.5 | 384 | 512 | 英文模型 |
- 数据集
| 数据集 | 简介 |
|---|---|
| MLDR | 文档检索数据集,涵盖13种语言 |
| bge-m3-data | bge-m3使用的微调数据 |
常见问题
1. 不同检索方法简介
- 稠密检索:将文本映射为单一嵌入向量,例如 DPR、BGE-v1.5
- 稀疏检索(词汇匹配):一个与词表大小相同的向量,大部分位置为零,仅为文本中存在的token计算权重。例如 BM25、unicoil 和 splade
- 多向量检索:使用多个向量来表示文本,例如 ColBERT。
2. 如何在其他项目中使用BGE-M3?
对于嵌入检索,您可以使用与BGE相同的方法来使用BGE-M3模型。 唯一的区别是BGE-M3模型不再需要为查询添加指令。
3. 如何微调bge-m3模型?
您可以参考此示例中的通用方法来微调稠密嵌入。
如果您想微调m3的所有嵌入功能(dense、sparse和colbert),可以参考统一微调示例。
使用方法
安装:
git clone https://github.com/FlagOpen/FlagEmbedding.git
cd FlagEmbedding
pip install -e .
或者:
pip install -U FlagEmbedding
为文本生成嵌入
- 稠密嵌入
from FlagEmbedding import BGEM3FlagModel
model = BGEM3FlagModel('BAAI/bge-m3',
use_fp16=True) # 将use_fp16设为True可以加速计算,但会有轻微的性能下降
sentences_1 = ["What is BGE M3?", "Defination of BM25"]
sentences_2 = ["BGE M3 is an embedding model supporting dense retrieval, lexical matching and multi-vector interaction.",
"BM25 is a bag-of-words retrieval function that ranks a set of documents based on the query terms appearing in each document"]
embeddings_1 = model.encode(sentences_1,
batch_size=12,
max_length=8192, # 如果您不需要这么长的长度,可以设置较小的值来加速编码过程
)['dense_vecs']
embeddings_2 = model.encode(sentences_2)['dense_vecs']
similarity = embeddings_1 @ embeddings_2.T
print(similarity)
# [[0.6265, 0.3477], [0.3499, 0.678 ]]
您也可以使用 sentence-transformers 和 huggingface transformers 来生成稠密嵌入。 详情请参考 baai_general_embedding。
- 稀疏嵌入(词汇权重)
from FlagEmbedding import BGEM3FlagModel
model = BGEM3FlagModel('BAAI/bge-m3', use_fp16=True) # 将use_fp16设为True可以加速计算,但会有轻微的性能下降
sentences_1 = ["What is BGE M3?", "Defination of BM25"]
sentences_2 = ["BGE M3 is an embedding model supporting dense retrieval, lexical matching and multi-vector interaction.",
"BM25 is a bag-of-words retrieval function that ranks a set of documents based on the query terms appearing in each document"]
output_1 = model.encode(sentences_1, return_dense=True, return_sparse=True, return_colbert_vecs=False)
output_2 = model.encode(sentences_2, return_dense=True, return_sparse=True, return_colbert_vecs=False)
# 您可以查看每个token的权重:
print(model.convert_id_to_token(output_1['lexical_weights']))
# [{'What': 0.08356, 'is': 0.0814, 'B': 0.1296, 'GE': 0.252, 'M': 0.1702, '3': 0.2695, '?': 0.04092},
# {'De': 0.05005, 'fin': 0.1368, 'ation': 0.04498, 'of': 0.0633, 'BM': 0.2515, '25': 0.3335}]
# 通过词汇匹配计算分数
lexical_scores = model.compute_lexical_matching_score(output_1['lexical_weights'][0], output_2['lexical_weights'][0])
print(lexical_scores)
# 0.19554901123046875
print(model.compute_lexical_matching_score(output_1['lexical_weights'][0], output_1['lexical_weights'][1]))
# 0.0
- 多向量(ColBERT)
from FlagEmbedding import BGEM3FlagModel
model = BGEM3FlagModel('BAAI/bge-m3', use_fp16=True)
sentences_1 = ["What is BGE M3?", "Defination of BM25"]
sentences_2 = ["BGE M3 is an embedding model supporting dense retrieval, lexical matching and multi-vector interaction.",
"BM25 is a bag-of-words retrieval function that ranks a set of documents based on the query terms appearing in each document"]
output_1 = model.encode(sentences_1, return_dense=True, return_sparse=True, return_colbert_vecs=True)
output_2 = model.encode(sentences_2, return_dense=True, return_sparse=True, return_colbert_vecs=True)
print(model.colbert_score(output_1['colbert_vecs'][0], output_2['colbert_vecs'][0]))
print(model.colbert_score(output_1['colbert_vecs'][0], output_2['colbert_vecs'][1]))
# 0.7797
# 0.4620
计算文本对的分数
输入一组文本对,您可以获得由不同方法计算的分数。
from FlagEmbedding import BGEM3FlagModel
model = BGEM3FlagModel('BAAI/bge-m3', use_fp16=True)
sentences_1 = ["What is BGE M3?", "Defination of BM25"]
sentences_2 = ["BGE M3 is an embedding model supporting dense retrieval, lexical matching and multi-vector interaction.",
"BM25 is a bag-of-words retrieval function that ranks a set of documents based on the query terms appearing in each document"]
sentence_pairs = [[i,j] for i in sentences_1 for j in sentences_2]
print(model.compute_score(sentence_pairs,
max_passage_length=128, # 较小的max length会导致更低的延迟
weights_for_different_modes=[0.4, 0.2, 0.4])) # weights_for_different_modes(w) 用于加权求和:w[0]*dense_score + w[1]*sparse_score + w[2]*colbert_score
# {
# 'colbert': [0.7796499729156494, 0.4621465802192688, 0.4523794651031494, 0.7898575067520142],
# 'sparse': [0.195556640625, 0.00879669189453125, 0.0, 0.1802978515625],
# 'dense': [0.6259765625, 0.347412109375, 0.349853515625, 0.67822265625],
# 'sparse+dense': [0.482503205537796, 0.23454029858112335, 0.2332356721162796, 0.5122477412223816],
# 'colbert+sparse+dense': [0.6013619303703308, 0.3255828022956848, 0.32089319825172424, 0.6232916116714478]
# }
评估
开源社区的基准测试
BGE-M3模型在该基准测试中表现最佳(OAI是OpenAI的缩写)。
更多详情请参考文章和GitHub仓库。
我们的结果
- 多语言(MIRACL数据集)

- 跨语言(MKQA数据集)

-
长文档检索
-
MLDR:
请注意,MLDR是我们通过LLM构建的文档检索数据集,
涵盖13种语言,包括测试集、验证集和训练集。
我们使用MLDR的训练集来增强模型的长文档检索能力。
因此,将基线与Dense w.o.long(不使用长文档数据集微调)进行比较更为公平。 此外,该长文档检索数据集将开源,以解决目前开源多语言长文本检索数据集的缺乏。 我们相信这些数据将对开源社区训练文档检索模型有所帮助。 -
NarrativeQA:

-
-
与BM25的比较
我们使用Pyserini实现BM25,测试结果可以通过此脚本复现。 我们使用两种不同的分词器测试BM25: 一种使用Lucene Analyzer,另一种使用与M3相同的分词器(即xlm-roberta的分词器)。 结果表明,BM25仍然是一个具有竞争力的基线,特别是在长文档检索中。

训练
- 自知识蒸馏:结合来自不同检索模式的多个输出作为奖励信号,以增强单模式的性能(尤其是稀疏检索和多向量检索)
- 高效批处理:提高长文本微调时的效率。小批量策略简单但有效,也可用于微调大型嵌入模型。
- MCLS:一种无需微调即可提高长文本性能的方法。 如果您没有足够的资源来用长文本微调模型,该方法会很有用。
更多详情请参阅我们的报告。
致谢
感谢开源数据集的作者,包括Miracl、MKQA、NarrativeQA等。 感谢Tevatron、Pyserini等开源库。
引用
如果您觉得这个仓库有用,请考虑给个星标:star:并引用。
@misc{bge-m3,
title={BGE M3-Embedding: Multi-Lingual, Multi-Functionality, Multi-Granularity Text Embeddings Through Self-Knowledge Distillation},
author={Jianlv Chen and Shitao Xiao and Peitian Zhang and Kun Luo and Defu Lian and Zheng Liu},
year={2024},
eprint={2402.03216},
archivePrefix={arXiv},
primaryClass={cs.CL}
}
BAAI/bge-m3
作者 BAAI
创建时间: 2024-01-27 17:07:29+00:00
更新时间: 2024-07-03 14:50:10+00:00
在 Hugging Face 上查看