说明文档
这是 Sudhanshu Sharma 创建的 bge-reranker-v2-m3 模型量化版本的 ONNX 格式
license: apache-2.0 language:
- 多语言 pipeline_tag: 文本分类 tags:
- transformers
- sentence-transformers
- text-embeddings-inference
重排序器
更多详情请参阅我们的 Github: FlagEmbedding。
与嵌入模型不同,重排序器以问题和文档作为输入,直接输出相似度而非嵌入向量。 您可以通过向重排序器输入查询和段落来获取相关性分数。 该分数可以通过 sigmoid 函数映射到 [0,1] 范围内的浮点值。
模型列表
| 模型 | 基础模型 | 语言 | 逐层 | 特性 |
|---|---|---|---|---|
| BAAI/bge-reranker-base | xlm-roberta-base | 中文和英文 | - | 轻量级重排序模型,易于部署,推理速度快。 |
| BAAI/bge-reranker-large | xlm-roberta-large | 中文和英文 | - | 轻量级重排序模型,易于部署,推理速度快。 |
| BAAI/bge-reranker-v2-m3 | bge-m3 | 多语言 | - | 轻量级重排序模型,具有强大的多语言能力,易于部署,推理速度快。 |
| BAAI/bge-reranker-v2-gemma | gemma-2b | 多语言 | - | 适用于多语言场景,在英文能力和多语言能力方面均表现良好。 |
| BAAI/bge-reranker-v2-minicpm-layerwise | MiniCPM-2B-dpo-bf16 | 多语言 | 8-40 | 适用于多语言场景,在英文和中文能力方面均表现良好,允许自由选择输出层,便于加速推理。 |
您可以根据您的场景和资源选择模型。
-
对于多语言场景,请使用 BAAI/bge-reranker-v2-m3 和 BAAI/bge-reranker-v2-gemma
-
对于中文或英文场景,请使用 BAAI/bge-reranker-v2-m3 和 BAAI/bge-reranker-v2-minicpm-layerwise。
-
对于效率优先场景,请使用 BAAI/bge-reranker-v2-m3 和 BAAI/bge-reranker-v2-minicpm-layerwise 的低层。
-
对于更好的性能,推荐使用 BAAI/bge-reranker-v2-minicpm-layerwise 和 BAAI/bge-reranker-v2-gemma
使用方法
使用 FlagEmbedding
pip install -U FlagEmbedding
对于普通重排序器 (bge-reranker-base / bge-reranker-large / bge-reranker-v2-m3 )
获取相关性分数(分数越高表示相关性越强):
from FlagEmbedding import FlagReranker
reranker = FlagReranker('BAAI/bge-reranker-v2-m3', use_fp16=True) # 将 use_fp16 设置为 True 可以加速计算,但会有轻微的性能下降
score = reranker.compute_score(['query', 'passage'])
print(score) # -5.65234375
# 您可以通过设置 \"normalize=True\" 将分数映射到 0-1 范围,这将对接应用 sigmoid 函数
score = reranker.compute_score(['query', 'passage'], normalize=True)
print(score) # 0.003497010252573502
scores = reranker.compute_score([['what is panda?', 'hi'], ['what is panda?', 'The giant panda (Ailuropoda melanoleuca), sometimes called a panda bear or simply panda, is a bear species endemic to China.']])
print(scores) # [-8.1875, 5.26171875]
# 您可以通过设置 \"normalize=True\" 将分数映射到 0-1 范围,这将对接应用 sigmoid 函数
scores = reranker.compute_score([['what is panda?', 'hi'], ['what is panda?', 'The giant panda (Ailuropoda melanoleuca), sometimes called a panda bear or simply panda, is a bear species endemic to China.']], normalize=True)
print(scores) # [0.00027803096387751553, 0.9948403768236574]
对于基于 LLM 的重排序器
from FlagEmbedding import FlagLLMReranker
reranker = FlagLLMReranker('BAAI/bge-reranker-v2-gemma', use_fp16=True) # 将 use_fp16 设置为 True 可以加速计算,但会有轻微的性能下降
# reranker = FlagLLMReranker('BAAI/bge-reranker-v2-gemma', use_bf16=True) # 您也可以设置 use_bf16=True 来加速计算,但会有轻微的性能下降
score = reranker.compute_score(['query', 'passage'])
print(score)
scores = reranker.compute_score([['what is panda?', 'hi'], ['what is panda?', 'The giant panda (Ailuropoda melanoleuca), sometimes called a panda bear or simply panda, is a bear species endemic to China.']])
print(scores)
对于基于 LLM 的逐层重排序器
from FlagEmbedding import LayerWiseFlagLLMReranker
reranker = LayerWiseFlagLLMReranker('BAAI/bge-reranker-v2-minicpm-layerwise', use_fp16=True) # 将 use_fp16 设置为 True 可以加速计算,但会有轻微的性能下降
# reranker = LayerWiseFlagLLMReranker('BAAI/bge-reranker-v2-minicpm-layerwise', use_bf16=True) # 您也可以设置 use_bf16=True 来加速计算,但会有轻微的性能下降
score = reranker.compute_score(['query', 'passage'], cutoff_layers=[28]) # 调整 'cutoff_layers' 来选择用于计算分数的层。
print(score)
scores = reranker.compute_score([['what is panda?', 'hi'], ['what is panda?', 'The giant panda (Ailuropoda melanoleuca), sometimes called a panda bear or simply panda, is a bear species endemic to China.']], cutoff_layers=[28])
print(scores)
使用 Huggingface transformers
对于普通重排序器 (bge-reranker-base / bge-reranker-large / bge-reranker-v2-m3 )
获取相关性分数(分数越高表示相关性越强):
import torch
from transformers import AutoModelForSequenceClassification, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained('BAAI/bge-reranker-v2-m3')
model = AutoModelForSequenceClassification.from_pretrained('BAAI/bge-reranker-v2-m3')
model.eval()
pairs = [['what is panda?', 'hi'], ['what is panda?', 'The giant panda (Ailuropoda melanoleuca), sometimes called a panda bear or simply panda, is a bear species endemic to China.']]
with torch.no_grad():
inputs = tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512)
scores = model(**inputs, return_dict=True).logits.view(-1, ).float()
print(scores)
对于基于 LLM 的重排序器
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
def get_inputs(pairs, tokenizer, prompt=None, max_length=1024):
if prompt is None:
prompt = "Given a query A and a passage B, determine whether the passage contains an answer to the query by providing a prediction of either 'Yes' or 'No'."
sep = "\n"
prompt_inputs = tokenizer(prompt,
return_tensors=None,
add_special_tokens=False)['input_ids']
sep_inputs = tokenizer(sep,
return_tensors=None,
add_special_tokens=False)['input_ids']
inputs = []
for query, passage in pairs:
query_inputs = tokenizer(f'A: {query}',
return_tensors=None,
add_special_tokens=False,
max_length=max_length * 3 // 4,
truncation=True)
passage_inputs = tokenizer(f'B: {passage}',
return_tensors=None,
add_special_tokens=False,
max_length=max_length,
truncation=True)
item = tokenizer.prepare_for_model(
[tokenizer.bos_token_id] + query_inputs['input_ids'],
sep_inputs + passage_inputs['input_ids'],
truncation='only_second',
max_length=max_length,
padding=False,
return_attention_mask=False,
return_token_type_ids=False,
add_special_tokens=False
)
item['input_ids'] = item['input_ids'] + sep_inputs + prompt_inputs
item['attention_mask'] = [1] * len(item['input_ids'])
inputs.append(item)
return tokenizer.pad(
inputs,
padding=True,
max_length=max_length + len(sep_inputs) + len(prompt_inputs),
pad_to_multiple_of=8,
return_tensors='pt',
)
tokenizer = AutoTokenizer.from_pretrained('BAAI/bge-reranker-v2-gemma')
model = AutoModelForCausalLM.from_pretrained('BAAI/bge-reranker-v2-gemma')
yes_loc = tokenizer('Yes', add_special_tokens=False)['input_ids'][0]
model.eval()
pairs = [['what is panda?', 'hi'], ['what is panda?', 'The giant panda (Ailuropoda melanoleuca), sometimes called a panda bear or simply panda, is a bear species endemic to China.']]
with torch.no_grad():
inputs = get_inputs(pairs, tokenizer)
scores = model(**inputs, return_dict=True).logits[:, -1, yes_loc].view(-1, ).float()
print(scores)
对于基于 LLM 的逐层重排序器
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
def get_inputs(pairs, tokenizer, prompt=None, max_length=1024):
if prompt is None:
prompt = "Given a query A and a passage B, determine whether the passage contains an answer to the query by providing a prediction of either 'Yes' or 'No'."
sep = "\n"
prompt_inputs = tokenizer(prompt,
return_tensors=None,
add_special_tokens=False)['input_ids']
sep_inputs = tokenizer(sep,
return_tensors=None,
add_special_tokens=False)['input_ids']
inputs = []
for query, passage in pairs:
query_inputs = tokenizer(f'A: {query}',
return_tensors=None,
add_special_tokens=False,
max_length=max_length * 3 // 4,
truncation=True)
passage_inputs = tokenizer(f'B: {passage}',
return_tensors=None,
add_special_tokens=False,
max_length=max_length,
truncation=True)
item = tokenizer.prepare_for_model(
[tokenizer.bos_token_id] + query_inputs['input_ids'],
sep_inputs + passage_inputs['input_ids'],
truncation='only_second',
max_length=max_length,
padding=False,
return_attention_mask=False,
return_token_type_ids=False,
add_special_tokens=False
)
item['input_ids'] = item['input_ids'] + sep_inputs + prompt_inputs
item['attention_mask'] = [1] * len(item['input_ids'])
inputs.append(item)
return tokenizer.pad(
inputs,
padding=True,
max_length=max_length + len(sep_inputs) + len(prompt_inputs),
pad_to_multiple_of=8,
return_tensors='pt',
)
tokenizer = AutoTokenizer.from_pretrained('BAAI/bge-reranker-v2-minicpm-layerwise', trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained('BAAI/bge-reranker-v2-minicpm-layerwise', trust_remote_code=True, torch_dtype=torch.bfloat16)
model = model.to('cuda')
model.eval()
pairs = [['what is panda?', 'hi'], ['what is panda?', 'The giant panda (Ailuropoda melanoleuca), sometimes called a panda bear or simply panda, is a bear species endemic to China.']]
with torch.no_grad():
inputs = get_inputs(pairs, tokenizer).to(model.device)
all_scores = model(**inputs, return_dict=True, cutoff_layers=[28])
all_scores = [scores[:, -1].view(-1, ).float() for scores in all_scores[0]]
print(all_scores)
微调
数据格式
训练数据应该是一个 json 文件,每行是一个类似这样的字典:
{"query": str, "pos": List[str], "neg":List[str], "prompt": str}
query 是查询,pos 是正向文本列表,neg 是负向文本列表,prompt 指示查询和文本之间的关系。如果您没有某个查询的负向文本,您可以从整个语料库中随机采样一些作为负样本。
有关示例数据文件,请参见 toy_finetune_data.jsonl。
训练
您可以使用以下代码微调重排序器:
对于基于 llm 的重排序器
torchrun --nproc_per_node {number of gpus} \
-m FlagEmbedding.llm_reranker.finetune_for_instruction.run \
--output_dir {path to save model} \
--model_name_or_path google/gemma-2b \
--train_data ./toy_finetune_data.jsonl \
--learning_rate 2e-4 \
--num_train_epochs 1 \
--per_device_train_batch_size 1 \
--gradient_accumulation_steps 16 \
--dataloader_drop_last True \
--query_max_len 512 \
--passage_max_len 512 \
--train_group_size 16 \
--logging_steps 1 \
--save_steps 2000 \
--save_total_limit 50 \
--ddp_find_unused_parameters False \
--gradient_checkpointing \
--deepspeed stage1.json \
--warmup_ratio 0.1 \
--bf16 \
--use_lora True \
--lora_rank 32 \
--lora_alpha 64 \
--use_flash_attn True \
--target_modules q_proj k_proj v_proj o_proj
对于基于 llm 的逐层重排序器
torchrun --nproc_per_node {number of gpus} \
-m FlagEmbedding.llm_reranker.finetune_for_layerwise.run \
--output_dir {path to save model} \
--model_name_or_path openbmb/MiniCPM-2B-dpo-bf16 \
--train_data ./toy_finetune_data.jsonl \
--learning_rate 2e-4 \
--num_train_epochs 1 \
--per_device_train_batch_size 1 \
--gradient_accumulation_steps 16 \
--dataloader_drop_last True \
--query_max_len 512 \
--passage_max_len 512 \
--train_group_size 16 \
--logging_steps 1 \
--save_steps 2000 \
--save_total_limit 50 \
--ddp_find_unused_parameters False \
--gradient_checkpointing \
--deepspeed stage1.json \
--warmup_ratio 0.1 \
--bf16 \
--use_lora True \
--lora_rank 32 \
--lora_alpha 64 \
--use_flash_attn True \
--target_modules q_proj k_proj v_proj o_proj \
--start_layer 8 \
--head_multi True \
--head_type simple \
--lora_extra_parameters linear_head
我们的重排序器是从 google/gemma-2b(用于基于 llm 的重排序器)和 openbmb/MiniCPM-2B-dpo-bf16(用于基于 llm 的逐层重排序器)初始化的,我们在混合多语言数据集上对其进行训练:
评估
- llama-index.

- BEIR.
对 bge-en-v1.5 large 的前 100 个结果进行重排序。

对 e5 mistral 7b instruct 的前 100 个结果进行重排序。

- CMTEB-retrieval.
对 bge-zh-v1.5 large 的前 100 个结果进行重排序。

- miracl (多语言).
对 bge-m3 的前 100 个结果进行重排序。

引用
如果您觉得这个仓库有用,请考虑点个 star 并引用
@misc{li2023making,
title={Making Large Language Models A Better Foundation For Dense Retrieval},
author={Chaofan Li and Zheng Liu and Shitao Xiao and Yingxia Shao},
year={2023},
eprint={2312.15503},
archivePrefix={arXiv},
primaryClass={cs.CL}
}
@misc{chen2024bge,
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}
}
sudhanshu746/bge-reranker-v2-m3-quant-onnx
作者 sudhanshu746
创建时间: 2024-08-20 12:46:46+00:00
更新时间: 2024-08-20 13:11:53+00:00
在 Hugging Face 上查看