BCEmbedding: 用于RAG的双语和跨语言嵌入
<a href="https://twitter.com/YDopensource">
<img src="https://img.shields.io/badge/follow-%40YDOpenSource-1DA1F2?logo=twitter&style={style}">
</a>
English | 简体中文
点击展开目录
Bilingual and Crosslingual Embedding(BCEmbedding
)是由网易有道开发的英语和中文双语和跨语言嵌入,包括EmbeddingModel
和RerankerModel
。EmbeddingModel
专门用于生成语义向量,在语义搜索和问答中发挥关键作用,而RerankerModel
则擅长优化搜索结果和排序任务。
BCEmbedding
是有道检索增强生成(RAG)实现的基石,特别是QAnything [github],这是一个开源实现,广泛集成在各种有道产品中,如有道速读和有道翻译。
以其双语和跨语言能力而著称,BCEmbedding
擅长弥合中英文语言差距,实现了
- 在MTEB中的语义表示评估中表现出色;
- 在LlamaIndex中的RAG评估领域创造了新的基准。
我们的目标
为RAG社区提供一个无需微调即可直接使用的双语和跨语言两阶段检索模型仓库,包括EmbeddingModel
和RerankerModel
:
- 一个模型:
EmbeddingModel
处理英语和中文的双语和跨语言检索任务。RerankerModel
支持英语、中文、日语和韩语。 - 一个模型:覆盖常见的RAG优化业务应用场景。例如教育、医疗场景、法律、金融、文学、FAQ、教科书、维基百科、通用对话。
- 易于集成:我们在
BCEmbedding
中提供API,可与LlamaIndex和LangChain集成。 - 其他要点:
RerankerModel
支持长文本(超过512个token,少于32k个token)重排;RerankerModel
提供有意义的相关性得分,有助于移除低质量段落。EmbeddingModel
不需要特定指令。
第三方示例
- RAG应用:QAnything、HuixiangDou、ChatPDF。
- 高效推理:ChatLLM.cpp、Xinference、mindnlp(华为GPU)。
🌐 双语和跨语言优势
现有的嵌入模型在双语和跨语言场景中经常遇到性能挑战,特别是在中文、英文及其跨语言任务中。BCEmbedding
利用有道翻译引擎的优势,在单语、双语和跨语言环境中都能提供卓越的性能。
EmbeddingModel
支持中文(ch)和英文(en)(更多语言支持即将推出),而RerankerModel
支持中文(ch)、英文(en)、日文(ja)和韩文(ko)。
💡 主要特点
- 双语和跨语言能力:由有道翻译引擎驱动,在中文、英文及其跨语言检索任务中表现出色,即将支持更多语言。
- RAG优化:为各种RAG任务量身定制,包括翻译、摘要和问答,确保准确的查询理解。参见LlamaIndex中的RAG评估。
- 高效精确检索:第一阶段使用
EmbeddingModel
的双编码器实现高效检索,第二阶段使用RerankerModel
的交叉编码器进行更深入的语义分析,提高精确度。 - 广泛领域适应性:在多样化数据集上训练,在各个领域都能表现出色。
- 用户友好设计:无需指令,可用于多种任务,无需为每个任务指定查询指令。
- 有意义的重排得分:
RerankerModel
提供相关性得分,以提高结果质量并优化大语言模型性能。 - 生产环境验证:在有道产品中成功实施和验证。
🚀 最新更新
- 2024-02-04:技术博客 - 请参阅为RAG而生-BCEmbedding技术报告。
- 2024-01-16:LangChain和LlamaIndex集成 - 请参阅更多。
- 2024-01-03:模型发布 - bce-embedding-base_v1和bce-reranker-base_v1现已可用。
- 2024-01-03:评估数据集 [CrosslingualMultiDomainsDataset] - 使用LlamaIndex评估RAG性能。
- 2024-01-03:评估数据集 [详情] - 使用MTEB评估跨语言语义表示性能。
🍎 模型列表
模型名称 | 模型类型 | 语言 | 参数量 | 权重 |
---|---|---|---|---|
bce-embedding-base_v1 | EmbeddingModel | 中文, 英文 | 279M | Huggingface, 国内通道 |
bce-reranker-base_v1 | RerankerModel | 中文, 英文, 日文, 韩文 | 279M | Huggingface, 国内通道 |
📖 使用手册
安装
首先,创建一个conda环境并激活它。
conda create --name bce python=3.10 -y
conda activate bce
然后安装BCEmbedding
以进行最小安装(为避免cuda版本冲突,您应该首先手动安装与您系统cuda版本兼容的torch
):
pip install BCEmbedding==0.1.5
或从源代码安装(推荐):
git clone git@github.com:netease-youdao/BCEmbedding.git
cd BCEmbedding
pip install -v -e .
快速开始
1. 基于BCEmbedding
使用EmbeddingModel
,默认使用cls
pooler。
from BCEmbedding import EmbeddingModel
# 句子列表
sentences = ['sentence_0', 'sentence_1']
# 初始化嵌入模型
model = EmbeddingModel(model_name_or_path="maidalun1020/bce-embedding-base_v1")
# 提取嵌入
embeddings = model.encode(sentences)
使用RerankerModel
计算相关性得分并重新排序:
from BCEmbedding import RerankerModel
# 您的查询和对应的段落
query = 'input_query'
passages = ['passage_0', 'passage_1']
# 构建句子对
sentence_pairs = [[query, passage] for passage in passages]
# 初始化重排序模型
model = RerankerModel(model_name_or_path="maidalun1020/bce-reranker-base_v1")
# 方法0:计算句子对的得分
scores = model.compute_score(sentence_pairs)
# 方法1:重新排序段落
rerank_results = model.rerank(query, passages)
注意:
- 在
RerankerModel.rerank
方法中,我们提供了一个高级预处理,当"passages"非常长时,我们在生产中使用它来构建sentence_pairs
。
2. 基于transformers
对于EmbeddingModel
:
from transformers import AutoModel, AutoTokenizer
# 句子列表
sentences = ['sentence_0', 'sentence_1']
# 初始化模型和分词器
tokenizer = AutoTokenizer.from_pretrained('maidalun1020/bce-embedding-base_v1')
model = AutoModel.from_pretrained('maidalun1020/bce-embedding-base_v1')
device = 'cuda' # 如果没有GPU,设置为"cpu"
model.to(device)
# 获取输入
inputs = tokenizer(sentences, padding=True, truncation=True, max_length=512, return_tensors="pt")
inputs_on_device = {k: v.to(device) for k, v in inputs.items()}
# 获取嵌入
outputs = model(**inputs_on_device, return_dict=True)
embeddings = outputs.last_hidden_state[:, 0] # cls pooler
embeddings = embeddings / embeddings.norm(dim=1, keepdim=True) # 归一化
对于RerankerModel
:
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification
# 初始化模型和分词器
tokenizer = AutoTokenizer.from_pretrained('maidalun1020/bce-reranker-base_v1')
model = AutoModelForSequenceClassification.from_pretrained('maidalun1020/bce-reranker-base_v1')
device = 'cuda' # 如果没有GPU,设置为"cpu"
model.to(device)
# 获取输入
inputs = tokenizer(sentence_pairs, padding=True, truncation=True, max_length=512, return_tensors="pt")
inputs_on_device = {k: v.to(device) for k, v in inputs.items()}
# 计算得分
scores = model(**inputs_on_device, return_dict=True).logits.view(-1,).float()
scores = torch.sigmoid(scores)
3. 基于sentence_transformers
对于EmbeddingModel
:
from sentence_transformers import SentenceTransformer
# 句子列表
sentences = ['sentence_0', 'sentence_1', ...]
# 初始化嵌入模型
## sentence-transformers的新更新。因此,请先清理您的"`SENTENCE_TRANSFORMERS_HOME`/maidalun1020_bce-embedding-base_v1"或"~/.cache/torch/sentence_transformers/maidalun1020_bce-embedding-base_v1",以下载新版本。
model = SentenceTransformer("maidalun1020/bce-embedding-base_v1")
# 提取嵌入
embeddings = model.encode(sentences, normalize_embeddings=True)
对于RerankerModel
:
from sentence_transformers import CrossEncoder
# 初始化重排序模型
model = CrossEncoder('maidalun1020/bce-reranker-base_v1', max_length=512)
# 计算句子对的得分
scores = model.predict(sentence_pairs)
RAG框架的嵌入和重排序集成
1. 在langchain
中使用
我们在BCEmbedding.tools.langchain
中提供了BCERerank
,它继承了RerankerModel
的高级预处理分词功能。
- 首先安装langchain
pip install langchain==0.1.0
pip install langchain-community==0.0.9
pip install langchain-core==0.1.7
pip install langsmith==0.0.77
- 示例
# 我们为重排序提供了高级预处理分词功能。
from BCEmbedding.tools.langchain import BCERerank
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import PyPDFLoader
from langchain_community.vectorstores import FAISS
from langchain.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores.utils import DistanceStrategy
from langchain.retrievers import ContextualCompressionRetriever
# 初始化嵌入模型
嵌入模型名称 = 'maidalun1020/bce-embedding-base_v1'
嵌入模型参数 = {'device': 'cuda:0'}
嵌入编码参数 = {'batch_size': 32, 'normalize_embeddings': True, 'show_progress_bar': False}
嵌入模型 = HuggingFaceEmbeddings(
model_name=嵌入模型名称,
model_kwargs=嵌入模型参数,
encode_kwargs=嵌入编码参数
)
重排序器参数 = {'model': 'maidalun1020/bce-reranker-base_v1', 'top_n': 5, 'device': 'cuda:1'}
重排序器 = BCERerank(**重排序器参数)
# 初始化文档
文档 = PyPDFLoader("BCEmbedding/tools/eval_rag/eval_pdfs/Comp_en_llama2.pdf").load()
文本分割器 = RecursiveCharacterTextSplitter(chunk_size=1500, chunk_overlap=200)
文本 = 文本分割器.split_documents(文档)
# 示例1. 使用嵌入和重排序器进行检索
检索器 = FAISS.from_documents(文本, 嵌入模型, distance_strategy=DistanceStrategy.MAX_INNER_PRODUCT).as_retriever(search_type="similarity", search_kwargs={"score_threshold": 0.3, "k": 10})
压缩检索器 = ContextualCompressionRetriever(
base_compressor=重排序器, base_retriever=检索器
)
响应 = 压缩检索器.get_relevant_documents("什么是 Llama 2?")
2. 在llama_index
中使用
我们在BCEmbedding.tools.llama_index
中提供了BCERerank
,它继承了RerankerModel
的高级预处理分词功能。
- 首先安装 llama_index
pip install llama-index==0.9.42.post2
- 示例
# 我们为重排序提供了高级预处理分词功能。
from BCEmbedding.tools.llama_index import BCERerank
import os
from llama_index.embeddings import HuggingFaceEmbedding
from llama_index import VectorStoreIndex, ServiceContext, SimpleDirectoryReader
from llama_index.node_parser import SimpleNodeParser
from llama_index.llms import OpenAI
from llama_index.retrievers import VectorIndexRetriever
# 初始化嵌入模型和重排序模型
嵌入参数 = {'model_name': 'maidalun1020/bce-embedding-base_v1', 'max_length': 512, 'embed_batch_size': 32, 'device': 'cuda:0'}
嵌入模型 = HuggingFaceEmbedding(**嵌入参数)
重排序器参数 = {'model': 'maidalun1020/bce-reranker-base_v1', 'top_n': 5, 'device': 'cuda:1'}
重排序模型 = BCERerank(**重排序器参数)
# 示例 #1. 提取嵌入
查询 = '苹果'
段落 = [
'我喜欢苹果',
'我喜欢橙子',
'苹果和橙子都是水果'
]
查询嵌入 = 嵌入模型.get_query_embedding(查询)
段落嵌入 = 嵌入模型.get_text_embedding_batch(段落)
# 示例 #2. RAG 示例
llm = OpenAI(model='gpt-3.5-turbo-0613', api_key=os.environ.get('OPENAI_API_KEY'), api_base=os.environ.get('OPENAI_BASE_URL'))
服务上下文 = ServiceContext.from_defaults(llm=llm, embed_model=嵌入模型)
文档 = SimpleDirectoryReader(input_files=["BCEmbedding/tools/eval_rag/eval_pdfs/Comp_en_llama2.pdf"]).load_data()
节点解析器 = SimpleNodeParser.from_defaults(chunk_size=400, chunk_overlap=80)
节点 = 节点解析器.get_nodes_from_documents(文档[0:36])
索引 = VectorStoreIndex(节点, service_context=服务上下文)
查询 = "什么是 Llama 2?"
# 示例 #2.1. 使用嵌入模型和重排序模型进行检索
向量检索器 = VectorIndexRetriever(index=索引, similarity_top_k=10, service_context=服务上下文)
嵌入检索结果 = 向量检索器.retrieve(查询)
重排序检索结果 = 重排序模型.postprocess_nodes(嵌入检索结果, query_str=查询)
# 示例 #2.2. 使用嵌入模型和重排序模型进行查询
查询引擎 = 索引.as_query_engine(node_postprocessors=[重排序模型])
查询响应 = 查询引擎.query(查询)
⚙️ 评估
使用 MTEB 评估语义表示
我们提供了基于 MTEB 和 C_MTEB 的嵌入
和重排序
模型评估工具。
首先,安装 MTEB
:
pip install mteb==1.1.1
1. 嵌入模型
只需运行以下命令,即可在双语和跨语言设置(例如 ["en", "zh", "en-zh", "zh-en"]
)中评估 your_embedding_model
(例如 maidalun1020/bce-embedding-base_v1
)。
python BCEmbedding/tools/eval_mteb/eval_embedding_mteb.py --model_name_or_path maidalun1020/bce-embedding-base_v1 --pooler cls
总评估任务包含 114 个数据集,涵盖**"检索"、"语义文本相似度"、"对分类"、"分类"、"重排序"和"聚类"**。
注意:
- 所有模型都使用其推荐的池化方法(
pooler
)进行评估。mean
池化:"jina-embeddings-v2-base-en"、"m3e-base"、"m3e-large"、"e5-large-v2"、"multilingual-e5-base"、"multilingual-e5-large" 和 "gte-large"。cls
池化:其他模型。
- "jina-embeddings-v2-base-en" 模型应该使用
trust_remote_code
加载。
python BCEmbedding/tools/eval_mteb/eval_embedding_mteb.py --model_name_or_path {mean_pooler_models} --pooler mean
python BCEmbedding/tools/eval_mteb/eval_embedding_mteb.py --model_name_or_path jinaai/jina-embeddings-v2-base-en --pooler mean --trust_remote_code
2. 重排序模型
运行以下命令,在双语和跨语言设置(例如 ["en", "zh", "en-zh", "zh-en"]
)中评估 your_reranker_model
(例如 "maidalun1020/bce-reranker-base_v1")。
python BCEmbedding/tools/eval_mteb/eval_reranker_mteb.py --model_name_or_path maidalun1020/bce-reranker-base_v1
评估任务包含 12 个数据集,涵盖**"重排序"**。
3. 指标可视化工具
我们提供了一键式脚本,用于总结嵌入
和重排序
模型的评估结果,生成 嵌入模型评估摘要 和 重排序模型评估摘要。
python BCEmbedding/tools/eval_mteb/summarize_eval_results.py --results_dir {your_embedding_results_dir | your_reranker_results_dir}
使用 LlamaIndex 评估 RAG
LlamaIndex 是一个著名的基于 LLM 的应用数据框架,特别是在 RAG 中。最近,一篇 LlamaIndex 博客 评估了 RAG 流程中流行的嵌入和重排序模型,引起了广泛关注。现在,我们按照其流程评估我们的 BCEmbedding
。
首先,安装 LlamaIndex,并将 transformers
升级到 4.36.0:
pip install transformers==4.36.0
pip install llama-index==0.9.22
将您的 "openai" 和 "cohere" 应用密钥以及 openai 基础 URL(例如 "https://api.openai.com/v1")导出到环境变量:
export OPENAI_BASE_URL={openai_base_url} # https://api.openai.com/v1
export OPENAI_API_KEY={your_openai_api_key}
export COHERE_APPKEY={your_cohere_api_key}
1. 指标定义
-
命中率:
命中率计算在前k个检索文档中找到正确答案的查询比例。简单来说,就是我们的系统在前几次猜测中正确的频率。越大越好。
-
平均倒数排名(MRR):
对于每个查询,MRR通过查看最高排名的相关文档的位置来评估系统的准确性。具体而言,它是所有查询中这些排名的倒数的平均值。因此,如果第一个相关文档是最佳结果,倒数排名为1;如果是第二个,倒数排名为1/2,以此类推。越大越好。
2. 复现LlamaIndex博客
为了公平地将我们的BCEmbedding
与其他嵌入和重排序模型进行比较,我们提供了一键式脚本来复现LlamaIndex博客的结果,包括我们的BCEmbedding
:
# 至少需要两个可用的GPU。
CUDA_VISIBLE_DEVICES=0,1 python BCEmbedding/tools/eval_rag/eval_llamaindex_reproduce.py
然后,通过以下命令汇总评估结果:
python BCEmbedding/tools/eval_rag/summarize_eval_results.py --results_dir BCEmbedding/results/rag_reproduce_results
从LlamaIndex博客复现的结果可以在***RAG评估复现总结中查看,得出一些明显的结论***:
- 在
WithoutReranker
设置中,我们的bce-embedding-base_v1
优于所有其他嵌入模型。 - 在固定嵌入模型的情况下,我们的
bce-reranker-base_v1
取得了最佳性能。 bce-embedding-base_v1
和bce-reranker-base_v1
的组合是最先进的。
3. 广泛领域适应性
LlamaIndex博客的评估是单语言、小数据量、特定领域的(仅包括"llama2"论文)。为了评估广泛领域适应性、双语和跨语言能力,我们参照该博客构建了一个多领域评估数据集(包括"计算机科学"、"物理"、"生物学"、"经济学"、"数学"和"定量金融"。详情),命名为CrosslingualMultiDomainsDataset:
- 为防止测试数据泄露,英文评估数据选自截至2023年12月30日ArXiv上各领域最新的英文文章。中文评估数据选自Semantic Scholar上对应领域尽可能新的高质量中文文章。
- 使用OpenAI的
gpt-4-1106-preview
生成高质量的评估数据。
首先,运行以下命令评估最流行和强大的嵌入和重排序模型:
# 至少需要两个可用的GPU。
CUDA_VISIBLE_DEVICES=0,1 python BCEmbedding/tools/eval_rag/eval_llamaindex_multiple_domains.py
然后,运行以下脚本汇总评估结果:
python BCEmbedding/tools/eval_rag/summarize_eval_results.py --results_dir BCEmbedding/results/rag_results
多领域评估的总结可以在多领域场景中查看。
📈 排行榜
MTEB中的语义表示评估
1. 嵌入模型
模型 | 维度 | 池化方式 | 指令 | 检索 (47) | 语义文本相似度 (19) | 配对分类 (5) | 分类 (21) | 重排序 (12) | 聚类 (15) | 平均 (119) |
---|---|---|---|---|---|---|---|---|---|---|
bge-base-en-v1.5 | 768 | cls | 需要 | 37.14 | 55.06 | 75.45 | 59.73 | 43.00 | 37.74 | 47.19 |
bge-base-zh-v1.5 | 768 | cls | 需要 | 47.63 | 63.72 | 77.40 | 63.38 | 54.95 | 32.56 | 53.62 |
bge-large-en-v1.5 | 1024 | cls | 需要 | 37.18 | 54.09 | 75.00 | 59.24 | 42.47 | 37.32 | 46.80 |
bge-large-zh-v1.5 | 1024 | cls | 需要 | 47.58 | 64.73 | 79.14 | 64.19 | 55.98 | 33.26 | 54.23 |
gte-large | 1024 | mean | 免费 | 36.68 | 55.22 | 74.29 | 57.73 | 42.44 | 38.51 | 46.67 |
gte-large-zh | 1024 | cls | 免费 | 41.15 | 64.62 | 77.58 | 62.04 | 55.62 | 33.03 | 51.51 |
jina-embeddings-v2-base-en | 768 | mean | 免费 | 31.58 | 54.28 | 74.84 | 58.42 | 41.16 | 34.67 | 44.29 |
m3e-base | 768 | mean | 免费 | 46.29 | 63.93 | 71.84 | 64.08 | 52.38 | 37.84 | 53.54 |
m3e-large | 1024 | mean | 免费 | 34.85 | 59.74 | 67.69 | 60.07 | 48.99 | 31.62 | 46.78 |
e5-large-v2 | 1024 | mean | 需要 | 35.98 | 55.23 | 75.28 | 59.53 | 42.12 | 36.51 | 46.52 |
multilingual-e5-base | 768 | mean | 需要 | 54.73 | 65.49 | 76.97 | 69.72 | 55.01 | 38.44 | 58.34 |
multilingual-e5-large | 1024 | mean | 需要 | 56.76 | 66.79 | 78.80 | 71.61 | 56.49 | 43.09 | 60.50 |
bce-embedding-base_v1 | 768 | cls | 免费 | 57.60 | 65.73 | 74.96 | 69.00 | 57.29 | 38.95 | 59.43 |
注意:
- 我们的 bce-embedding-base_v1 在同等模型规模下优于其他开源嵌入模型。
- 114个数据集包括119个评估结果(一些数据集包含多种语言)涵盖了"检索"、"语义文本相似度"、"配对分类"、"分类"、"重排序"和"聚类"在
["en", "zh", "en-zh", "zh-en"]
设置下,包括 MTEB 和 CMTEB。 - 我们发布的跨语言评估数据集属于
检索
任务。 - 更多评估细节请查看嵌入模型评估。
2. 重排序模型
模型 | 重排序 (12) | 平均 (12) |
---|---|---|
bge-reranker-base | 59.04 | 59.04 |
bge-reranker-large | 60.86 | 60.86 |
bce-reranker-base_v1 | 61.29 | 61.29 |
注意:
- 我们的 bce-reranker-base_v1 优于其他开源重排序模型。
- 12个数据集 涵盖了"重排序"在
["en", "zh", "en-zh", "zh-en"]
设置下。 - 更多评估细节请查看重排序模型评估。
LlamaIndex 中的 RAG 评估
1. 多领域场景
注意:
- 数据质量:
- 为防止测试数据泄露,英文评估数据从 ArXiv 上截至 2023 年 12 月 30 日的各领域最新英文文章中选取。中文评估数据从 Semantic Scholar 上相应领域的高质量、尽可能最新的中文文章中选取。
- 使用 OpenAI
gpt-4-1106-preview
生成高质量的评估数据。
- 在
["en", "zh", "en-zh", "zh-en"]
设置下 进行评估。如果您对单语设置感兴趣,请查看中文 RAG 评估(["zh"] 设置)和英文 RAG 评估(["en"] 设置)。 - 与我们的 复现结果 一致,参考 LlamaIndex 博客。
- 在
不使用重排序
设置下,我们的bce-embedding-base_v1
优于所有其他嵌入模型。 - 在固定嵌入模型的情况下,我们的
bce-reranker-base_v1
取得最佳性能。 bce-embedding-base_v1
和bce-reranker-base_v1
的组合是当前最优的。
🛠 有道的 BCEmbedding API
对于那些偏好无需在自己系统上下载和配置模型的便捷体验的用户,BCEmbedding
可通过有道的API轻松获取。这一选项提供了一种简化高效的方式,让您能够将BCEmbedding集成到您的项目中,绕过了手动设置和维护的复杂性。详细说明和全面的API文档可在有道BCEmbedding API获取。在这里,您将找到所有必要的指导,以便在各种使用场景中轻松实施BCEmbedding
,确保顺利有效的集成以获得最佳结果。
🧲 微信群
欢迎扫描下方二维码加入微信群。
✏️ 引用
如果您在研究或项目中使用了BCEmbedding
,请随意引用并为其点星:
@misc{youdao_bcembedding_2023,
title={BCEmbedding: Bilingual and Crosslingual Embedding for RAG},
author={NetEase Youdao, Inc.},
year={2023},
howpublished={\url{https://github.com/netease-youdao/BCEmbedding}}
}
🔐 许可证
BCEmbedding
采用Apache 2.0许可证