在前面一篇文章RAG 高效应用指南:01中,笔者介绍了文档解析和文本分块,不少读者发来私信或者留言,想进一步了解 PDF 解析和表格内容识别等方面的优化方案,这块确实是文档治理中比较麻烦的一块。
关于文档智能解析,笔者后续也会再进一步更新,请读者朋友持续关注。
在本篇文章中,笔者将讨论以下几个问题:
• 向量模型在 RAG 系统中的作用
万物皆可 Embedding。在推荐系统、自然语言处理和计算机视觉等领域,Embedding 是一个非常重要的概念。Embedding 的本质是一种将高维稀疏数据转换为低维稠密向量的技术,通过这种转换,能够捕捉数据中的语义或特征关系。具体来说,Embedding 用一个多维稠密向量来表示事物的多维特征,从而在一个连续的向量空间中刻画事物之间的相似性和差异性。这种表示方式不仅提高了计算效率,还增强了模型对数据内在结构和关系的理解能力。比如,在处理文字时,我们可以把每个单词表示成一个向量(一个有方向和大小的数值列表),这种表示方法就叫做 word embedding。
大多数数据,特别是文本数据,都是高维且稀疏的。高维意味着数据量庞大,稀疏意味着大多数数据的值都是零。这样的数据在计算机中处理起来非常复杂且低效。通过 embedding 技术,我们可以将高维离散数据转换成低维稠密向量,这样可以显著提高计算效率。
此外,Embedding 还能捕捉到数据中的潜在关系。比如,在文本处理中,经过训练的 word embedding 可以让相似的单词(如『猫』和『狗』)在低维空间中靠得更近,而不相似的单词(如『猫』和『汽车』)则会离得更远。这种语义上的相似性对很多 NLP 任务非常重要。
很多文本处理任务可以在文本相似性的基础上进行构建,比如:
如图所示,使用 bge-m3 模型计算一个句子与其他句子(含英文句子)的相似度,可以看到,bge-m3 模型比较准确地度量了不同句子间的语义相似度。
拓展阅读
Embedding 是文本的固定长度数值表示,这使得计算机能够轻松地测量文本之间的语义相关性。它们是一些重要自然语言处理任务的核心,比如文本相似性、语义搜索、信息检索和重新排序、聚类、下游任务的特征提取等。
Embedding 在 RAG 系统中扮演着至关重要的角色:如果 Embedding 模型在对私域知识进行向量化表示的过程中表现不佳,那么即使 RAG 系统在其他方面设计得当,最终效果也难以达到预期水平 。
为了让私域知识能在问答中被检索到,我们可以基于倒排和基于向量的方式构建知识库索引。倒排索引是一种基于关键词的精确性检索,但语义理解能力弱,而向量索引是基于文本向量的语义检索,可以捕捉文本的语义信息。一般情况下,我们会同时使用这两种检索方式。
在 RAG 系统中,向量模型主要有以下几个方面的作用:
1. 对 query 和 私域知识 进行向量化表示
在 RAG 系统中,用户的 query 和知识库中的文档需要被表示为向量。向量模型不仅支持文本、也支持图像和视频等多模态数据。通过使用预训练的语言模型(如 BERT、DPR 等),我们可以将 query 和分块文本转换为向量。这些向量捕捉了文本中的语义信息,使得相似的 query 和分块文本在向量空间中彼此接近,从而便于后续的 ANN 检索操作。
2. 动态更新知识库
在 RAG 系统中,随着新数据的不断加入,知识库需要动态更新。向量模型在此过程中也发挥了重要作用。新文档经过处理之后会被实时转换为向量并添加到向量数据库中,这保证了知识库的实时性和扩展性。向量模型的高效性使得这一过程能够迅速完成,不会对系统性能造成显著影响。
3. 数据隐私和安全
向量模型通过将私域知识转换为向量表示,实现了数据的匿名化。原始文本经过向量化处理后,其具体内容难以直接还原,从而保护了敏感信息。即使攻击者获得了向量表示,也难以重建原始信息。比如在金融领域,向量模型将敏感的金融交易记录转化为向量表示,RAG 系统可以在保护客户隐私的同时,进行高效的信息检索和生成,从而支持金融决策和客户服务。
拓展阅读
RAG 系统需要高性能向量模型,现有开源/闭源的向量模型比较多,这里笔者推荐几个性能不错的向量模型。
OpenAI 的最新 embedding 模型如text-embedding-ada-002
,在长文本搜索、文本相似性和代码搜索等任务上表现出色,它支持 8K(8191)tokens 的输入长度。不过,OpenAI Embedding 并不是免费的,而是根据 token 数量来收费,这可能会增加一定的使用成本。
目前大部分开源向量模型仅支持 512 tokens 或者 1024 tokens 的输入长度,支持 8K tokens 的开源向量模型不多,Jina AI 发布的 jina-embeddings-v2 是其中一个。一般而言,如果文本的输入长度大于向量模型支持的最大 tokens 长度,则文本被会截断,从而破坏了文本的完整性,这样会直接影响下游任务的效果。
北京智源人工智能研究院(BAAI)开源了 BGE 系列 Embedding 模型,在多个评测任务排名靠前,还支持免费商用授权,可以满足不少业务场景的需求。其中,bge-m3 模型在多语言性(Multi-Linguality)、多功能性(Multi-Functionality)和多粒度性(Multi-Granularity)方面表现出色。bge-m3 支持超过 100 种语言,支持 8K 长度的输入文本,同时支持密集检索(Dense Retrieval)、多向量检索(Multi-Vector Retrieval)和稀疏检索(Sparse Retrieval)。
除此之外,还有包括 sentense-bert 系列,text2vec,m3e 等向量模型。
面对这么多向量模型,我们如何衡量一种 Embedding 模型相对于其他模型的有效性呢?Hugging Face 推出了 MTEB(Massive Text Embedding Benchmark 大规模文本嵌入基准)测试框架,旨在评估文本 Embedding 模型在多种任务上的性能。它覆盖了 8 类任务和 58 个数据集,涉及 112 种语言,是目前最全面的文本嵌入评估基准之一。MTEB 提供了一个公开的排行榜,用于展示各个模型在不同任务上的表现。
MTEB 排行榜:https://huggingface.co/spaces/mteb/leaderboard
如图所示,是 MTEB 的测试框架。
MTEB 包含以下任务类别,每个类别对应不同的评估指标和数据集:
虽然我们可以通过 MTEB 排行榜对比不同向量模型的差异,但也只能作为一个参考,这些模型在公开数据集上的 benchmark 在垂直领域、企业自身的业务领域不一定成立,具体选择哪个向量模型还需结合业务特点进行综合比较、权衡。
拓展阅读
• https://zhuanlan.zhihu.com/p/665044136
我们可以将 MTEB 作为选择向量模型的一个参考,但位于 MTEB 榜单 topK 的模型却并非一定适合企业自身的业务系统。在业务系统中,选择合适的 Embedding 模型是一个微妙的过程,受到多种因素的影响,比如知识库语言是中文、英文还是中英混合抑或是其他语言混合、切分文本块的长度、通用向量模型在垂类细分领域性能不佳、模型的精度、硬件的限制、检索时间限制等等。
在下面的表格中,笔者对比了几个向量模型在支持序列长度、向量维度和支持语言等方面的差异。
大部分开源向量模型只支持单一或者有限的文本语言,所以需要确保 Embedding 模型支持的语言种类。多语言模型如 OpenAI Embedding 和 bge-m3 等模型能够处理多种语言。bge-m3 支持 100 多种语言,适合多语言需求的场景。
另外,某些模型在主要语言(如中文)中的表现较好,但在处理较少使用的语言时可能会表现不佳。因此,需要评估模型在所有必需语言中的准确性,以确保一致的性能。
切分的文本片段后续需要通过 Embedding 模型进行向量化,所以必须考虑向量模型对输入文本块的 tokens 长度限制,超出这个限制则会导致模型对文本进行截断,从而丢失信息,影响下游任务的性能。
不同的 Embedding 模型对文本块长度的支持能力不同。比如,BERT 及其变体通常支持最多 512 个tokens,处理长文本时则需要将文本分成更小的块,意味着需要更加精细化的分块策略。而 Jina AI 的 Embedding 模型和 bge-m3 模型则支持 8K 的 tokens 输入,适合处理长文本块。
通用 Embedding 模型在特定垂直领域(如医学、法律和金融等)可能不如专用模型有效。这些领域通常需要专门训练 Embedding 模型来捕捉特定的专业术语和语境。为特定业务需求优化的 Embedding 模型能够显著提升检索和生成的质量。例如,通过结合向量检索和重排序(reranking)技术,可以进一步优化结果。
高维向量需要更多的存储空间,这可能会带来长期成本。例如,较高维度的模型如 text-embedding-ada-002 需要更多的存储资源。另外,较大的模型可能会占用更多内存,因此不适合内存有限的设备。
Embedding 模型的处理速度在实时应用中尤为关键。例如,intfloat/e5-base-v2 模型在处理速度上表现优异,但需要在 GPU上 运行以达到最佳性能。
在选择模型时,需要评估其在嵌入和检索过程中的延迟。例如,OpenAI 的 Embedding 模型在许多基准测试中显示出较高的性能和较低的延迟。
因此,在真实生产环境中选择合适的向量模型需要综合考量多个维度,而不仅仅依赖于某一单一因素。通过综合考量以上多个维度,可以帮助我们在生产环境中选择适合的向量模型,确保 RAG 系统的整体性能和用户体验达到最佳水平。
拓展阅读
通用的 Embedding 模型通常是在大规模、多样化的数据集上训练的,可能不完全适合特定领域的任务,比如医学、法律等专业领域,它们无法很好的理解一些专有词汇。通过微调,模型可以学习到特定领域的词汇和概念,使其在特定应用场景中表现更佳。
因此,在特定领域,对向量模型进行 Finetune 的主要目标是提高 Recall@N (前 N 个检索结果中包含相关文档的比例)的准确率和优化正例与负例的 similarity 值域分布。通过微调,模型可以更好地适应特定领域,提高 Embedding 表示的质量,减少检索结果中的噪声,提高相关文档的检索准确性。同时,微调可以更好地分辨正例和负例,使它们在向量空间中的分布更加明显,形成清晰的边界。这样,当检索结果的相似度值低于某个阈值时,可以舍弃对它们的召回,减少误判风险,从而减少生成模型的负担和幻觉风险,提升整体系统性能和用户体验。
下面,我以 BAAI/bge-large-zh-v1.5 为例,看看如何基于私有领域数据进行 Finetune。
首先,安装 FlagEmbedding 库:
pip install -U FlagEmbedding
训练数据是一个 json 文件,其中每一行都是一个独立的 json 对象,如下所示:
{"query": "如何提高机器学习模型的准确性?", "pos": ["通过交叉验证和调参可以提高模型准确性。"], "neg": ["机器学习是人工智能的一个分支。"]}
{"query": "什么是深度学习?", "pos": ["深度学习是机器学习的一个子领域,涉及多层神经网络。"], "neg": ["数据科学是一门交叉学科。"]}
其中,query 是问题,pos 是正样本列表,neg 是负样本列表,如果没有现成的负样本,可以考虑从整个语料库中随机抽取一些文本作为 neg。
将数据保存为 jsonl
文件,例如 finetune_data.jsonl
。
Hard Negatives 是指那些在向量空间中与查询较为接近但实际上并不相关的样本。挖掘这些样本可以提高模型的辨别能力,提供 Embedding 质量。具体方法可以参考以下代码:
python -m FlagEmbedding.baai_general_embedding.finetune.hn_mine \
--model_name_or_path BAAI/bge-large-zh-v1.5 \
--input_file finetune_data.jsonl \
--output_file finetune_data_minedHN.jsonl \
--range_for_sampling 2-200 \
--negative_number 15
其中,range_for_sampling
表示从哪些文档采样,例如 2-200
表示从 top2-top200 文档中采样 negative_number
个负样本 。
1.4. 训练
微调 Embedding 模型的命令如下:
torchrun --nproc_per_node {number of gpus} \
-m FlagEmbedding.baai_general_embedding.finetune.run \
--output_dir {path to save model} \
--model_name_or_path BAAI/bge-large-zh-v1.5 \
--train_data ./finetune_data.jsonl \
--learning_rate 1e-5 \
--fp16 \
--num_train_epochs 5 \
--per_device_train_batch_size {large batch size; set 1 for toy data} \
--dataloader_drop_last True \
--normlized True \
--temperature 0.02 \
--query_max_len 64 \
--passage_max_len 256 \
--train_group_size 2 \
--negatives_cross_device \
--logging_steps 10 \
--save_steps 1000 \
--query_instruction_for_retrieval ""
以上命令指定了训练参数,包括学习率、批次大小、训练轮次等,需要根据实际情况进行调整。
对通用模型进行微调可以提高其在目标任务上的性能,但可能会导致模型在目标域之外的一般能力退化。通过合并微调模型和通用模型,不仅可以提高下游任务的性能,同时保持其他不相关任务的性能。
为了将微调后的模型和原来的 bge 模型进行合并,我们需要先安装 LM_Cocktail
,如下所示:
pip install -U LM_Cocktail
合并代码参考如下:
from LM_Cocktail import mix_models, mix_models_with_data
# Mix fine-tuned model and base model; then save it to output_path: ./mixed_model_1
model = mix_models(
model_names_or_paths=["BAAI/bge-large-zh-v1.5", "your_fine-tuned_model"],
model_type='encoder',
weights=[0.5, 0.5], # you can change the weights to get a better trade-off.
output_path='./mixed_embedding_model')
拓展阅读
本文讨论了 RAG 系统中 Embedding 模型的选择和微调。Embedding 模型在 RAG 系统中扮演中语义召回的角色,通过生成高质量的向量表示来捕捉文本的语义信息,以便在检索阶段更准确地匹配用户查询和知识库中的相关文档。
在真实生产环境中选择合适的向量模型需要综合考量多个维度(如向量模型支持的语言、文本长度和向量维度等),以确保模型能够满足业务需求和系统性能。在效果没有明显差异的情况下,推荐选择向量维度短的模型,减少存储和内存等资源需求。
另外,通用的 Embedding 模型可能不完全适合特定领域(如医学、法律等)的任务,所以可能需要对其进行微调以更好地适应这些领域的需求。例如,在法律领域,通过使用法律文献和案例数据进行微调,模型可以更准确地解析法律文本,提高法律信息检索和分析的精度和效率。
文章来源微信公众号“AI花果山”
【开源免费】FASTGPT是基于LLM的知识库开源项目,提供开箱即用的数据处理、模型调用等能力。整体功能和“Dify”“RAGFlow”项目类似。很多接入微信,飞书的AI项目都基于该项目二次开发。
项目地址:https://github.com/labring/FastGPT
【开源免费】graphrag是微软推出的RAG项目,与传统的通过 RAG 方法使用向量相似性作为搜索技术不同,GraphRAG是使用知识图谱在推理复杂信息时大幅提高问答性能。
项目地址:https://github.com/microsoft/graphrag
【开源免费】Dify是最早一批实现RAG,Agent,模型管理等一站式AI开发的工具平台,并且项目方一直持续维护。其中在任务编排方面相对领先对手,可以帮助研发实现像字节扣子那样的功能。
项目地址:https://github.com/langgenius/dify
【开源免费】RAGFlow是和Dify类似的开源项目,该项目在大文件解析方面做的更出色,拓展编排方面相对弱一些。
项目地址:https://github.com/infiniflow/ragflow/tree/main
【开源免费】phidata是一个可以实现将数据转化成向量存储,并通过AI实现RAG功能的项目
项目地址:https://github.com/phidatahq/phidata
【开源免费】TaskingAI 是一个提供RAG,Agent,大模型管理等AI项目开发的工具平台,比LangChain更强大的中间件AI平台工具。
项目地址:https://github.com/TaskingAI/TaskingAI
【开源免费】XTuner 是一个高效、灵活、全能的轻量化大模型微调工具库。它帮助开发者提供一个简单易用的平台,可以对大语言模型(LLM)和多模态图文模型(VLM)进行预训练和轻量级微调。XTuner 支持多种微调算法,如 QLoRA、LoRA 和全量参数微调。
项目地址:https://github.com/InternLM/xtuner