有道自研RAG引擎QAnything_解析器

令牌数量由提示查询、提示上下文和机器学习模型的答案组成

有道自研RAG引擎QAnything_bc_02

“离线”的Embedding搭配“在线”的Reranker:——BCEmbedding是由网易有道开发的中英双语和跨语种语义表征算法模型库,其中包含 EmbeddingModel和 RerankerModel两类基础模型。EmbeddingModel专门用于生成语义向量,在语义搜索和问答中起着关键作用,而 RerankerModel擅长优化语义搜索结果和语义相关顺序精排。BCEmbedding作为有道的检索增强生成式应用(RAG)的基石,特别是在QAnything [github]中发挥着重要作用。QAnything作为一个网易有道开源项目,在有道许多产品中有很好的应用实践,比如有道速读有道翻译

1、QAnything是网易有道开源的检索增强生成式应用(RAG)项目,包括专门优化的自研的embedding和rerank模型,微调后的LLM,优化后的推理代码,向量数据库,以及一个立即上手可用的前端。所有的算法模型(包括7B大模型+embedding/rerank+OCR)占用显存不超过16G。

2、BCEmbedding是网易有道研发的两阶段检索算法库,作为QAnything的基石发挥着重要作用。作为RAG技术路线中最为重要和基础的一环,二阶段检索器一般由粗召回和精排这个模块组成。检索应该给出尽可能多的相关片段(EmbeddingModel),并且真正有用的片段应该在更靠前的位置(RerankerModel)

有道自研RAG引擎QAnything_有道_03

  • 检索阶段常采用基于向量的密集检索方法,对用户问题和知识库语料进行语义向量提取,然后搜索和用户问题语义相近的若干片段。提取语义向量的Embedding模型一般采用dual-encoder的架构,可以预先(offline)对庞大的知识库语料提取语义向量。用户提问时,模型只需实时提取用户问题的语义向量,就可利用向量数据库进行语义检索了。这个过程中,知识库语料的语义向量提取是一个“静态”的、“离线”的过程,模型在提取用户问题和知识库语料的语义向量时,没有信息交互。该方式的好处是效率可以非常高,但这也限制了语义检索性能的上限。返回的数量 top_k 默认为 100,配置上混合检索后获得的文档数量会更多。
  • 精排阶段为了解决信息交互的问题,采用cross-encoder架构,Reranker模型可以实现用户问题和知识库语料有信息交互,可以识别到更加准确的语义关系,算法性能上限非常高。该方式的缺点是,需要对用户问题和知识库语料进行实时(online)语义关系提取,效率比较低,无法对全量的知识库语料进行实时处理。所以结合检索和精排二者的优势,检索阶段可以快速召回用户问题所需的相关文本片段,精排阶段可以将正确相关片段尽可能排在靠前位置,并过滤掉低质量的片段。二阶段检索可以很好的权衡检索效果和效率,具有巨大应用价值。QAnything 默认检索 100 个文档,使用 Rerank 得分 0.35 进行过滤。
  • BCEmbedding(Bilingual and Crosslingual Embedding, BCEmbedding)算法模型库,包含EmbeddingModel和RerankerModel两种模型。设计一套RAG适配的标签分配方法,给Embedding减负;EmbeddingModel抛弃Instruction设定,不需要费尽心思设计每个任务设计的instruction,就能实现问题与相似问题检索,问题与候选答案检索,短摘要与长文本检索;设计RerankerModel训练loss,使得模型可以输出有意义的语义相关分数,实现低质量片段过滤,而不是仅仅用于排序。
  • 开源的BCEmbedding的两个检索模型bce-embedding-base_v1和bce-reranker-base_v1,最终目的是给RAG社区提供一套强有力的检索基础算法模型,可以拿来直接用,最好不需要finetune。


3、多卡推理:

bash ./run.sh -c local -i 0,1 -b defaul  # 此时的显存使用逻辑为第一张卡部署大模型,第二张卡部署embedding,rerank,和ocr模型,实际意义不大
# 当使用huggingface或vllm后端时支持多卡推理大模型
# 以下示例为两张卡启动,默认embedding,部署在第一张卡上,rerank,ocr模型部署在第二张卡上,两张卡剩余显存均会用于LLM推理
bash ./run.sh -c local -i 0,1 -b default  # 指定0,1号GPU启动,请确认有多张GPU可用,注意设备数量必须是1,2,4,8,16,否则显存无法正常分配

说明:多卡部署是指大模型运行平均分配显存到多张显卡上,但是由于embedding,rerank和ocr模型也需要占用显存(共需4G+显存,启动时占用2G显存,运行后会逐渐上涨至4G左右),目前这三个模型默认会分配到前两个设备上,所以第一张,第二张显卡的显存占用会比其他卡多2G以上,默认启动参数-r(gpu_memory_utilization)=0.81,如果手动设置为0.9以上可能会存在前两张卡显存不足无法启动或启动后运行时显存不足报错的情况

4、pdf(包含表格)解析效果+++

默认使用快速PDF解析器,解析速度快,但是解析效果一般,如果需要更好的解析效果,可以使用以下方式手动开启强力解析器: 典型耗时对比: 环境:Mac M1Pro 16GB, 单页PDF解析耗时:快速解析器耗时约1/30s,强力解析器耗时约1s 原理:快速解析器主要依赖PyMuPDF,强力解析器则使用了表格解析模型和版面分析模型,并做了后处理优化。QAnything 使用 PyMuPDF 提供的 get_pixmap 将原始的 pdf 转换为图像,并调用 OCR 服务提取内容,简单粗暴。优势是处理简单,不需要区分文字文档,还是图像文档,处理统一。

5、实际请求大模型时,最终默认使用的 prompt 模板如下所示:

"""参考信息:
{context}
---
我的问题或指令:
{question}
---
请根据上述参考信息回答我的问题或回复我的指令。前面的参考信息可能有用,也可能没用,你需要从我给出的参考信息中选出与我的问题最相关的那些,来为你的回答提供依据。回答一定要忠于原文,简洁但不丢信息,不要胡乱编造。我的问题或指令是什么语种,你就用什么语种回复,
你的回复:"""

其中 context 对应的就是检索的文档的内容。

6、考虑到模型能力和实际模型推理效率,QAnything选用Base规模的模型,而不是instrcution。INSTRUCTOR将instruction引入到语义向量表征中,对各个任务、各个数据集设计不同的instruction,可以使模型产生类似LLM指令跟随的能力。当遇到新场景、新数据集时,利用instruction可以实现zero-shot的语义表征能力。类似prompt的作用,设计instruction可以对不同的任务、不同的数据集进行子空间划分,缓解不同任务不同数据集之间数据分布和模式的冲突,激发出模型在预先定义的子空间的语义表征能力.更深一步,instruction也可以看成是标签分配的问题。