从“精排”到“粗排+精排”的两阶段检索
2026/5/14 18:36:14 网站建设 项目流程

优化整体流程

在代码和系统架构层面,可以配合多种策略来进一步提升效率。

  1. 从“精排”到“粗排+精排”的两阶段检索:这是最重要的一步。先让SimilarityPostprocessor开闸,调大VectorIndexRetrieverBM25Retrieverretrieval_top_k,让引擎召回足够多的候选(比如20-50个),再让SentenceTransformerRerank只对其中的top_n(比如5-10个)进行精排。这能让重排的计算量减少50%以上,同时保证高质量的召回。

    参数对照:

    • retrieval_top_k: 粗排召回量 → 增加 20-50

    • rerank_top_k: 精排输出量 → 减少 3-5

  2. 异步非阻塞重排:重排序的过程可以不阻塞用户。当RAG处理请求时,可以先返回一个基于纯检索的“快速答案”,同时在后台启动重排任务,任务完成后通知前端更新。这样能提升界面响应的流畅度。

  3. 差异化的条件触发:并非所有查询都需要重排。你可以通过简单的规则(如查询长度<3个词)或一个轻量级分类器来判断查询的复杂度,仅在处理“难”问题时才启用重排步骤,从而节省宝贵的计算资源

    维度BGE-Reranker-v2-M3Jina-Reranker-v3BGE-Reranker-Base
    中文精度⭐⭐⭐⭐⭐ (最强)⭐⭐⭐⭐⭐⭐⭐⭐
    CPU推理速度中等 (建议开启Batch)快 (架构优势)极快
    内存占用低 (~2GB)低 (~2GB)极低 (~1.5GB)
    适用场景追求高精度、纯中文环境追求速度、中英混合环境实时性要求极高、配置较低
    推荐指数第一选择第二选择备选方案
pip install FlagEmbedding optimum

1、下载模型 cmd下

pip show huggingface_hub Name: huggingface_hub Version: 0.36.2 set HF_ENDPOINT=https://hf-mirror.com
huggingface-cli download BAAI/bge-reranker-v2-m3 --local-dir bge-reranker-v2-m3 --local-dir-use-symlinks False huggingface-cli download BAAI/bge-reranker-base --local-dir ./bge-reranker-base --local-dir-use-symlinks False
  • 融合排序 vs 重排

    • 查询融合(QueryFusionRetriever)是一种检索阶段的分数合并方法(例如倒数排名融合、平均分数等),它在多个检索器之间做第一次排序。

    • 重排(Cross-Encoder Rerank)是后处理阶段的独立步骤,它对检索器已经输出的节点列表进行重新打分和排序,通常可以弥补向量/BM25召回的不足。

---------------------------------------------------------------------------------------------------------

对模型进行量化

使用optimum-cli将模型导出为 ONNX 格式并进行 INT8 量化,然后让FlagReranker自动加载 ONNX 模型(因为 FlagEmbedding 新版支持从 ONNX 目录加载)。

下面给出具体操作步骤:

步骤 1:导出量化模型

打开命令行,进入到你的模型目录(或任意目录),执行以下脚本:

方案一

import torch import os import json from transformers import AutoTokenizer, AutoConfig, AutoModelForSequenceClassification # --- 配置区域 --- ORIGINAL_MODEL_PATH = r"D:\project\llama\python_knowlage_rag_api\models\bge-reranker-v2-m3" QUANTIZED_MODEL_PATH = r"D:\project\llama\python_knowlage_rag_api\models\bge-reranker-v2-m3-int8-cpu" print("🚀 开始 CPU 量化 (PyTorch 原生方案)...") # 1. 检查源路径是否存在 if not os.path.exists(ORIGINAL_MODEL_PATH): print(f"❌ 错误:找不到源模型目录 {ORIGINAL_MODEL_PATH}") exit() # 2. 创建输出目录 os.makedirs(QUANTIZED_MODEL_PATH, exist_ok=True) # 3. 加载 Tokenizer 和 Config print("⬇️ 加载分词器和配置...") try: tokenizer = AutoTokenizer.from_pretrained(ORIGINAL_MODEL_PATH, trust_remote_code=True) config = AutoConfig.from_pretrained(ORIGINAL_MODEL_PATH, trust_remote_code=True) # 保存基础文件 tokenizer.save_pretrained(QUANTIZED_MODEL_PATH) config.save_pretrained(QUANTIZED_MODEL_PATH) except Exception as e: print(f"❌ 加载配置失败: {e}") exit() # 4. 智能加载模型权重 print("⚙️ 正在加载原始模型权重...") model_file_path = None # 优先查找 model.safetensors (新标准),其次找 pytorch_model.bin (旧标准) candidates = ["model.safetensors", "pytorch_model.bin"] for candidate in candidates: path = os.path.join(ORIGINAL_MODEL_PATH, candidate) if os.path.exists(path): model_file_path = path print(f" 发现权重文件: {candidate}") break if not model_file_path: print(f"❌ 错误:在目录中未找到 'model.safetensors' 或 'pytorch_model.bin'") print(f" 请检查目录: {ORIGINAL_MODEL_PATH}") exit() # 5. 执行动态量化 # 注意:必须用 AutoModel... 来加载 safetensors,不能直接用 torch.load print("⚙️ 正在进行 INT8 动态量化 (这可能需要几分钟)...") try: # 使用 from_pretrained 可以自动处理 safetensors 和 bin 的加载 model = AutoModelForSequenceClassification.from_pretrained( ORIGINAL_MODEL_PATH, trust_remote_code=True, torch_dtype=torch.float32, # 确保以 float32 加载以便量化 device_map="cpu" ) # 执行量化 quantized_model = torch.quantization.quantize_dynamic( model, {torch.nn.Linear}, dtype=torch.qint8 ) # 6. 手动保存权重 print("💾 正在保存量化后的模型...") # 无论原文件是什么,我们都保存为 pytorch_model.bin 以保持兼容 output_bin_path = os.path.join(QUANTIZED_MODEL_PATH, "pytorch_model.bin") torch.save(quantized_model.state_dict(), output_bin_path) print("✅ 量化完成!") print(f"✨ 模型已保存至: {QUANTIZED_MODEL_PATH}") except Exception as e: print(f"❌ 量化过程出错: {e}") import traceback traceback.print_exc()

方案二

先导出 ONNX,再进行量化

第一步:先导出标准 ONNX 模型

请运行以下命令,这一步只负责把 PyTorch 模型转换成 ONNX 格式(不量化):

optimum-cli export onnx -m "D:\project\llama\python_knowlage_rag_api\models\bge-reranker-v2-m3" --task text-classification --opset 17 --no-post-process "D:\project\llama\python_knowlage_rag_api\models\bge-reranker-v2-m3-onnx"

第二步:对 ONNX 模型进行 INT8 量化

import os import time import threading from optimum.onnxruntime import ORTQuantizer from optimum.onnxruntime.configuration import AutoQuantizationConfig # --- 配置路径 --- ONNX_MODEL_PATH = r"D:\project\llama\python_knowlage_rag_api\models\bge-reranker-v2-m3-onnx" QUANTIZED_MODEL_PATH = r"D:\project\llama\python_knowlage_rag_api\models\bge-reranker-v2-m3-int8-onnx" def monitor_progress(target_dir): """后台监控函数:显示心跳和文件大小变化""" last_size = 0 counter = 0 while True: time.sleep(2) # 每2秒检查一次 counter += 1 # 简单的“心跳”动画 print(f"\r💓 正在处理中... {'. ' * (counter % 5)}", end="", flush=True) if os.path.exists(target_dir): # 计算目录下所有文件总大小 (MB) total_size = sum(os.path.getsize(os.path.join(dp, f)) for dp, dn, filenames in os.walk(target_dir) for f in [os.path.join(dp, fn) for fn in filenames]) / (1024 * 1024) if total_size > last_size: print(f"\r📊 当前输出体积: {total_size:.1f} MB (写入中...)", flush=True) last_size = total_size def main(): print("🚀 开始 ONNX INT8 量化...") # 1. 创建配置 qconfig = AutoQuantizationConfig.avx2(is_static=False, per_channel=False) # 2. 启动监控线程 monitor_thread = threading.Thread(target=monitor_progress, args=(QUANTIZED_MODEL_PATH,), daemon=True) monitor_thread.start() try: # 3. 加载量化器 print(f"🔧 正在从 {ONNX_MODEL_PATH} 加载模型...") quantizer = ORTQuantizer.from_pretrained(ONNX_MODEL_PATH) # 4. 执行量化 (这里会阻塞一段时间) print("⚙️ 开始量化计算 (CPU满载是正常的)...") quantizer.quantize( quantization_config=qconfig, save_dir=QUANTIZED_MODEL_PATH ) print("\n✅ 量化成功!") print(f"💾 模型已保存至: {QUANTIZED_MODEL_PATH}") except Exception as e: print(f"\n❌ 量化失败: {e}") if __name__ == "__main__": main()

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询