Embedding 模型的选择和微调

构建一个检索增强生成 (Retrieval-Augmented Generation, RAG) 应用的概念验证过程相对简单,但要将其推广到生产环境中则会面临多方面的挑战。

『RAG 高效应用指南』系列将就如何提高 RAG 系统性能进行深入探讨,提供一系列具体的方法和建议。同时读者也需要记住,提高 RAG 系统性能是一个持续的过程,需要不断地评估、优化和迭代

在本篇文章中,笔者将讨论以下几个问题:

  • • 向量模型在 RAG 系统中的作用
  • • 有哪些性能不错的向量模型(从 RAG 角度)
  • • 不同向量模型的评测基准 MTEB
  • • 业务中选择向量模型有哪些考量
  • • 如何 Finetune 向量模型

Embedding 简介

万物皆可 Embedding。在推荐系统、自然语言处理和计算机视觉等领域,Embedding 是一个非常重要的概念。Embedding 的本质是一种将高维稀疏数据转换为低维稠密向量的技术,通过这种转换,能够捕捉数据中的语义或特征关系。具体来说,Embedding 用一个多维稠密向量来表示事物的多维特征,从而在一个连续的向量空间中刻画事物之间的相似性和差异性。这种表示方式不仅提高了计算效率,还增强了模型对数据内在结构和关系的理解能力。比如,在处理文字时,我们可以把每个单词表示成一个向量(一个有方向和大小的数值列表),这种表示方法就叫做 word embedding。

图片

大多数数据,特别是文本数据,都是高维且稀疏的。高维意味着数据量庞大,稀疏意味着大多数数据的值都是零。这样的数据在计算机中处理起来非常复杂且低效。通过 embedding 技术,我们可以将高维离散数据转换成低维稠密向量,这样可以显著提高计算效率。

此外,Embedding 还能捕捉到数据中的潜在关系。比如,在文本处理中,经过训练的 word embedding 可以让相似的单词(如『猫』和『狗』)在低维空间中靠得更近,而不相似的单词(如『猫』和『汽车』)则会离得更远。这种语义上的相似性对很多 NLP 任务非常重要。

很多文本处理任务可以在文本相似性的基础上进行构建,比如:

  • • 内容审核:衡量社交媒体消息与已知的滥用案例的相似度有多高
  • • 意图分析:识别用户的消息与已知意图的例子中哪个最为接近
  • • 情感分析:衡量文本与已知情感标签的相似度,从而判断情感倾向
  • • 推荐系统:计算用户和物品的相似度,从而为用户推荐可能感兴趣的物品

如图所示,使用 bge-m3 模型计算一个句子与其他句子(含英文句子)的相似度,可以看到,bge-m3 模型比较准确地度量了不同句子间的语义相似度。

图片

拓展阅读

  • • https://www.zhihu.com/question/38002635
  • • https://zhuanlan.zhihu.com/p/49271699
  • • https://huggingface.co/BAAI/bge-m3

向量模型在 RAG 系统中的作用

Embedding 是文本的固定长度数值表示,这使得计算机能够轻松地测量文本之间的语义相关性。它们是一些重要自然语言处理任务的核心,比如文本相似性、语义搜索、信息检索和重新排序、聚类、下游任务的特征提取等。

Embedding 在 RAG 系统中扮演着至关重要的角色:如果 Embedding 模型在对私域知识进行向量化表示的过程中表现不佳,那么即使 RAG 系统在其他方面设计得当,最终效果也难以达到预期水平 。

为了让私域知识能在问答中被检索到,我们可以基于倒排和基于向量的方式构建知识库索引。倒排索引是一种基于关键词的精确性检索,但语义理解能力弱,而向量索引是基于文本向量的语义检索,可以捕捉文本的语义信息。一般情况下,我们会同时使用这两种检索方式。

图片

在 RAG 系统中,向量模型主要有以下几个方面的作用:

1. 对 query 和 私域知识 进行向量化表示

在 RAG 系统中,用户的 query 和知识库中的文档需要被表示为向量。向量模型不仅支持文本、也支持图像和视频等多模态数据。通过使用预训练的语言模型(如 BERT、DPR 等),我们可以将 query 和分块文本转换为向量。这些向量捕捉了文本中的语义信息,使得相似的 query 和分块文本在向量空间中彼此接近,从而便于后续的 ANN 检索操作。

2. 动态更新知识库

在 RAG 系统中,随着新数据的不断加入,知识库需要动态更新。向量模型在此过程中也发挥了重要作用。新文档经过处理之后会被实时转换为向量并添加到向量数据库中,这保证了知识库的实时性和扩展性。向量模型的高效性使得这一过程能够迅速完成,不会对系统性能造成显著影响。

3. 数据隐私和安全

向量模型通过将私域知识转换为向量表示,实现了数据的匿名化。原始文本经过向量化处理后,其具体内容难以直接还原,从而保护了敏感信息。即使攻击者获得了向量表示,也难以重建原始信息。比如在金融领域,向量模型将敏感的金融交易记录转化为向量表示,RAG 系统可以在保护客户隐私的同时,进行高效的信息检索和生成,从而支持金融决策和客户服务。

拓展阅读

  • • https://hub.baai.ac.cn/view/34277
  • • https://arxiv.org/abs/2312.10997

有哪些性能不错的向量模型

RAG 系统需要高性能向量模型,现有开源/闭源的向量模型比较多,这里笔者推荐几个性能不错的向量模型。

  • OpenAI Embedding
  • https://platform.openai.com/docs/guides/embeddings

OpenAI 的最新 embedding 模型如text-embedding-ada-002,在长文本搜索、文本相似性和代码搜索等任务上表现出色,它支持 8K(8191)tokens 的输入长度。不过,OpenAI Embedding 并不是免费的,而是根据 token 数量来收费,这可能会增加一定的使用成本。

  • JinaAI Embedding
  • https://huggingface.co/jinaai/jina-embeddings-v2-base-zh

目前大部分开源向量模型仅支持 512 tokens 或者 1024 tokens 的输入长度,支持 8K tokens 的开源向量模型不多,Jina AI 发布的 jina-embeddings-v2 是其中一个。一般而言,如果文本的输入长度大于向量模型支持的最大 tokens 长度,则文本被会截断,从而破坏了文本的完整性,这样会直接影响下游任务的效果

  • BAAI/bge Embedding
  • https://huggingface.co/BAAI/bge-large-zh-v1.5

北京智源人工智能研究院(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 包含以下任务类别,每个类别对应不同的评估指标和数据集:

  1. \1. 文本分类(Classification):如情感分析、意图分类等。
  2. \2. 聚类(Clustering):如将相似文本分为同一类。
  3. \3. 成对分类(Pair Classification):判断两个文本是否重复或具有相似含义。
  4. \4. 重排序(Reranking):根据查询重新排序相关和不相关的参考文本。
  5. \5. 检索(Retrieval):从大量文档中找到与查询相关的文档。
  6. \6. 语义文本相似性(STS):评估句子对之间的相似性。
  7. \7. 摘要(Summarization):评估机器生成摘要的质量。

虽然我们可以通过 MTEB 排行榜对比不同向量模型的差异,但也只能作为一个参考,这些模型在公开数据集上的 benchmark 在垂直领域、企业自身的业务领域不一定成立,具体选择哪个向量模型还需结合业务特点进行综合比较、权衡

拓展阅读

  • • https://arxiv.org/pdf/2210.07316
  • • https://zhuanlan.zhihu.com/p/665044136
  • • https://huggingface.co/spaces/mteb/leaderboard

业务中选择向量模型有哪些考量

我们可以将 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 系统的整体性能和用户体验达到最佳水平。

拓展阅读

  • • https://crescitaai.com/multilingual-embedding-models/

如何 Finetune 向量模型

通用的 Embedding 模型通常是在大规模、多样化的数据集上训练的,可能不完全适合特定领域的任务,比如医学、法律等专业领域,它们无法很好的理解一些专有词汇。通过微调,模型可以学习到特定领域的词汇和概念,使其在特定应用场景中表现更佳。

因此,在特定领域,对向量模型进行 Finetune 的主要目标是提高 Recall@N (前 N 个检索结果中包含相关文档的比例)的准确率和优化正例与负例的 similarity 值域分布。通过微调,模型可以更好地适应特定领域,提高 Embedding 表示的质量,减少检索结果中的噪声,提高相关文档的检索准确性。同时,微调可以更好地分辨正例和负例,使它们在向量空间中的分布更加明显,形成清晰的边界。这样,当检索结果的相似度值低于某个阈值时,可以舍弃对它们的召回,减少误判风险,从而减少生成模型的负担和幻觉风险,提升整体系统性能和用户体验。

下面,我以 BAAI/bge-large-zh-v1.5 为例,看看如何基于私有领域数据进行 Finetune。

  1. 1. 安装 FlagEmbedding

首先,安装 FlagEmbedding 库:

pip install -U FlagEmbedding
  1. 2. 数据准备

训练数据是一个 json 文件,其中每一行都是一个独立的 json 对象,如下所示:

{"query": "如何提高机器学习模型的准确性?", "pos": ["通过交叉验证和调参可以提高模型准确性。"], "neg": ["机器学习是人工智能的一个分支。"]}
{"query": "什么是深度学习?", "pos": ["深度学习是机器学习的一个子领域,涉及多层神经网络。"], "neg": ["数据科学是一门交叉学科。"]}

其中,query 是问题,pos 是正样本列表,neg 是负样本列表,如果没有现成的负样本,可以考虑从整个语料库中随机抽取一些文本作为 neg。

将数据保存为 jsonl 文件,例如 finetune_data.jsonl

  1. 3. Hard Negatives 挖掘(可选)

Hard Negatives 是指那些在向量空间中与查询较为接近但实际上并不相关的样本。挖掘这些样本可以提高模型的辨别能力,提供 Embedding 质量。具体方法可以参考以下代码:

在这里插入图片描述

其中,range_for_sampling 表示从哪些文档采样,例如 2-200 表示从 top2-top200 文档中采样 negative_number 个负样本 。

  1. 4. 训练

微调 Embedding 模型的命令如下:

在这里插入图片描述

以上命令指定了训练参数,包括学习率、批次大小、训练轮次等,需要根据实际情况进行调整。

  1. 5. 模型合并(可选)

对通用模型进行微调可以提高其在目标任务上的性能,但可能会导致模型在目标域之外的一般能力退化。通过合并微调模型和通用模型,不仅可以提高下游任务的性能,同时保持其他不相关任务的性能。

为了将微调后的模型和原来的 bge 模型进行合并,我们需要先安装 LM_Cocktail,如下所示:

pip install -U LM_Cocktail

合并代码参考如下:

在这里插入图片描述

拓展阅读

  • • https://github.com/FlagOpen/FlagEmbedding/tree/master/examples/finetune
  • • https://github.com/FlagOpen/FlagEmbedding/tree/master/LM_Cocktail

总结

本文讨论了 RAG 系统中 Embedding 模型的选择和微调。Embedding 模型在 RAG 系统中扮演中语义召回的角色,通过生成高质量的向量表示来捕捉文本的语义信息,以便在检索阶段更准确地匹配用户查询和知识库中的相关文档。

在真实生产环境中选择合适的向量模型需要综合考量多个维度(如向量模型支持的语言、文本长度和向量维度等),以确保模型能够满足业务需求和系统性能。在效果没有明显差异的情况下,推荐选择向量维度短的模型,减少存储和内存等资源需求。

另外,通用的 Embedding 模型可能不完全适合特定领域(如医学、法律等)的任务,所以可能需要对其进行微调以更好地适应这些领域的需求。例如,在法律领域,通过使用法律文献和案例数据进行微调,模型可以更准确地解析法律文本,提高法律信息检索和分析的精度和效率。

​ ​

如何学习AI大模型?

作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

img

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

img

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

img

四、AI大模型商业化落地方案

img

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。

  • 42
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是用于微调pkuseg模型的train函数的源代码: ```python import os import time import torch import argparse from tqdm import tqdm from pkuseg.models import BiLSTM_CRF from pkuseg.utils import load_model, load_data, batch_yield, evaluate def train(args): # 加载训练数据和字典 train_data, word2id, tag2id = load_data(args.data_dir, data_type='train') # 加载验证数据 dev_data = load_data(args.data_dir, data_type='dev', word2id=word2id, tag2id=tag2id) # 创建模型 model = BiLSTM_CRF(len(word2id), len(tag2id), args.embed_size, args.hidden_size, dropout=args.dropout, init_embedding=None) # 加载预训练的模型 if args.pretrained_model_path: print('Loading pretrained model from {}'.format(args.pretrained_model_path)) model = load_model(model, args.pretrained_model_path) # 将模型移动到GPU上 if torch.cuda.is_available(): model.cuda() # 设置优化器和学习率 optimizer = torch.optim.Adam(model.parameters(), lr=args.lr) # 开始训练 print('Start training...') best_dev_f1 = 0. for epoch in range(args.num_epochs): start_time = time.time() model.train() total_loss = 0. for i, (words, tags) in tqdm(enumerate(batch_yield(train_data, args.batch_size, word2id, tag2id))): # 将数据移动到GPU上 if torch.cuda.is_available(): words = words.cuda() tags = tags.cuda() # 前向传播和计算损失 loss = model.neg_log_likelihood(words, tags) total_loss += loss.item() # 反向传播和更新参数 optimizer.zero_grad() loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), args.clip_grad) optimizer.step() # 计算验证集的F1值 dev_f1 = evaluate(model, dev_data, word2id, tag2id, batch_size=args.batch_size) # 保存最好的模型 if dev_f1 > best_dev_f1: best_dev_f1 = dev_f1 if not os.path.exists(args.save_dir): os.makedirs(args.save_dir) torch.save(model.state_dict(), os.path.join(args.save_dir, 'best_model.pth')) # 打印训练结果 print('Epoch: {}, Loss: {:.4f}, Dev F1: {:.4f}, Time: {:.2f}s'.format(epoch+1, total_loss, dev_f1, time.time()-start_time)) if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('--data_dir', type=str, default='./data', help='Directory of training data.') parser.add_argument('--pretrained_model_path', type=str, default=None, help='Path of pretrained model.') parser.add_argument('--save_dir', type=str, default='./models', help='Directory to save the trained model.') parser.add_argument('--embed_size', type=int, default=100, help='Dimension of word embedding.') parser.add_argument('--hidden_size', type=int, default=128, help='Dimension of hidden layer.') parser.add_argument('--dropout', type=float, default=0.5, help='Dropout rate.') parser.add_argument('--clip_grad', type=float, default=5.0, help='Clip gradient.') parser.add_argument('--lr', type=float, default=0.001, help='Learning rate.') parser.add_argument('--batch_size', type=int, default=64, help='Batch size.') parser.add_argument('--num_epochs', type=int, default=10, help='Number of epochs.') args = parser.parse_args() train(args) ``` 这个函数的作用是用于在训练数据上微调pkuseg模型。它首先加载训练数据和字典,然后创建一个BiLSTM_CRF模型。如果指定了预训练的模型,则加载预训练的模型。接下来,设置优化器和学习率,并开始训练。在每个epoch中,模型进行前向传播和计算损失、反向传播和更新参数。在每个epoch结束时,计算验证集的F1值并保存最好的模型。最后,输出训练结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值