基于亚马逊云科技服务,构建大语言模型问答知识库

随着大语言模型效果明显提升,其相关的应用不断涌现呈现出越来越火爆的趋势。其中一种比较被广泛关注的技术路线是大语言模型(LLM)+知识召回(Knowledge Retrieval)的方式,在私域知识问答方面可以很好的弥补通用大语言模型的一些短板,解决通用大语言模型在专业领域回答缺乏依据、存在幻觉等问题。其基本思路是把私域知识文档进行切片然后向量化后续通过向量检索进行召回,再作为上下文输入到大语言模型进行归纳总结。

 在这个技术方向的具体实践中,知识库可以采取基于倒排和基于向量的两种索引方式进行构建,它对于知识问答流程中的知识召回这步起关键作用,和普通的文档索引或日志索引不同,知识的向量化需要借助深度模型的语义化能力,存在文档切分,向量模型部署&推理等额外步骤。知识向量化建库过程中,不仅仅需要考虑原始的文档量级,还需要考虑切分粒度,向量维度等因素,最终被向量数据库索引的知识条数可能达到一个非常大的量级,可能由以下两方面的原因引起:

  • 各个行业的既有文档量很高,如金融、医药、法律领域等,新增量也很大。

  • 为了召回效果的追求,对文档的切分常常会采用按句或者按段进行多粒度的冗余存贮。

 这些细节对知识向量数据库的写入和查询性能带来一定的挑战,为了优化向量化知识库的构建和管理,基于亚马逊云科技的服务,构建了如下图的知识库构建流程:

  • 通过S3 Bucket的Handler实时触发Lambda启动对应知识文件入库的Glue job

  • Glue Job中会进行文档解析和拆分,并调用SageMaker的Embedding模型进行向量化

  • 通过Bulk方式注入到Amazon OpenSearch中去

 并对整个流程中涉及的多个方面,包括如何进行知识向量化,向量数据库调优总结了一些最佳实践和心得。

 知识向量化

 文档拆分

 知识向量化的前置步骤是进行知识的拆分,语义完整性的保持是最重要的考量。分两个方面展开讨论。该如何选用以下两个关注点分别总结了一些经验:

 a. 拆分片段的方法

 关于这部分的工作,Langchain作为一种流行的大语言模型集成框架,提供了非常多的Document Loader和Text Spiltters,其中的一些实现具有借鉴意义,但也有不少实现效果是重复的。

 目前使用较多的基础方式是采用Langchain中的RecursiveCharacterTextSplitter,属于是Langchain的默认拆分器。它采用这个多级分隔字符列表——[“\n\n”, “\n”, ” “, “”]来进行拆分,默认先按照段落做拆分,如果拆分结果的chunk_size超出,再继续利用下一级分隔字符继续拆分,直到满足chunk_size的要求。

 但这种做法相对来说还是比较粗糙,还是可能会造成一些关键内容会被拆开。对于一些其他的文档格式可以有一些更细致的做法。

  • FAQ文件,必须按照一问一答粒度拆分,后续向量化的输入可以仅仅使用问题,也可以使用问题+答案

  • Markdown文件,”#”是用于标识标题的特殊字符,可以采用MarkdownHeaderTextSplitter作为分割器,它能更好的保证内容和标题对应的被提取出来。

 PDF文件,会包含更丰富的格式信息。Langchain里面提供了非常多的Loader,但Langchain中的PDFMinerPDFasHTMLLoader的切分效果上会更好,它把PDF转换成HTML,通过HTML的

块进行切分,这种方式能保留每个块的字号信息,从而可以推导出每块内容的隶属关系,把一个段落的标题和上一级父标题关联上,使得信息更加完整。

 b. 模型对片段长度的支持

 由于拆分的片段后续需要通过向量化模型进行推理,所以必须考虑向量化模型的Max_seq_length的限制,超出这个限制可能会导致出现截断,导致语义不完整。从支持的Max_seq_length来划分,目前主要有两类Embedding模型,如下表所示(这四个是有过实践经验的模型)。

 模型名称

 Max_seq_length

 paraphrase-multilingual-mpnet-base-v2(sbert.net)

 128

 text2vec-base-chinese(text2vec)

 128

 text2vec-large-chinese(text2vec)

 512

 text-embedding-ada-002(openai)

 8192

 这里的Max_seq_length是指Token数,和字符数并不等价。依据之前的测试经验,前三个模型一个token约为1.5个汉字字符左右。而对于大语言模型,如chatglm,一个token一般为2个字符左右。如果在切分时不方便计算token数,也可以简单按照这个比例来简单换算,保证不出现截断的情况。

 前三个模型属于基于Bert的Embedding模型,OpenAI的text-embedding-ada-002模型是基于GPT3的模型。前者适合句或者短段落的向量化,后者OpenAI的SAAS化接口,适合长文本的向量化,但不能私有化部署。

 可以根据召回效果进行验证选择。从目前的实践经验上看text-embedding-ada-002对于中文的相似性打分排序性可以,但区分度不够(集中0.7左右),不太利于直接通过阈值判断是否有相似知识召回。

 另外,对于长度限制的问题也有另外一种改善方法,可以对拆分的片段进行编号,相邻的片段编号也临近,当召回其中一个片段时,可以通过向量数据库的range search把附近的片段也召回回来,也能保证召回内容的语意完整性。

 向量化模型选择

 前面提到四个模型只是提到了模型对于文本长度的支持差异,效果方面目前并没有非常权威的结论。可以通过leaderboard来了解各个模型的性能,榜上的大多数的模型的评测还是基于公开数据集的benchmark,对于真实生产中的场景benchmark结论是否成立还需要case by case地来看。但原则上有以下几方面的经验可以分享:

  • 经过垂直领域Finetune的模型比原始向量模型有明显优势

  • 目前的向量化模型分为两类,对称和非对称。未进行微调的情况下,对于FAQ建议走对称召回,也就是Query到Question的召回。对于文档片段知识,建议使用非对称召回模型,也就是Query到Answer(文档片段)的召回。

  • 没有效果上的明显的差异的情况下,尽量选择向量维度短的模型,高维向量(如openai的text-embedding-ada-002)会给向量数据库造成检索性能和成本两方面的压力。

 向量化并行

 真实的业务场景中,文档的规模在百到百万这个数量级之间。按照冗余的多级召回方式,对应的知识条目最高可能达到亿的规模。由于整个离线计算的规模很大,所以必须并发进行,否则无法满足知识新增和向量检索效果迭代的要求。步骤上主要分为以下三个计算阶段。

 文档切分并行

 计算的并发粒度是文件级别的,处理的文件格式也是多样的,如TXT纯文本,Markdown,PDF等,其对应的切分逻辑也有差异。而使用Spark这种大数据框架来并行处理过重,并不合适。使用多核实例进行多进程并发处理则过于原始,任务的观测追踪上不太方便。所以可以选用AWS Glue的Python shell引擎进行处理。主要有如下好处:

  • 方便的按照文件粒度进行并发,并发度简单可控。具有重试、超时等机制,方便任务的追踪和观察,日志直接对接到AWS CloudWatch

  • 方便的构建运行依赖包,通过参数–additional-python-modules指定即可,同时Glue Python的运行环境中已经自带了opensearch_py等依赖

 向量化推理并行

 由于切分的段落和句子相对于文档数量也膨胀了很多倍,向量模型的推理吞吐能力决定了整个流程的吞吐能力。这里采用SageMaker Endpoint来部署向量化模型,一般来说为了提供模型的吞吐能力,可以采用GPU实例推理,以及多节点Endpoint/Endpoint弹性伸缩能力,Server-Side/Client-Side Batch推理能力这些都是一些有效措施。具体到离线向量知识库构建这个场景,可以采用如下几种策略:

  • GPU实例部署:向量化模型CPU实例是可以推理的。但离线场景下,推理并发度高,GPU相对于CPU可以达到20倍左右的吞吐量提升。所以离线场景可以采用GPU推理,在线场景CPU推理的策略。

  • 多节点Endpoint对于临时的大并发向量生成,通过部署多节点Endpoint进行处理,处理完毕后可以关闭

 利用Client-Side Batch推理:离线推理时,Client-side batch构造十分容易。无需开启Server-side Batch推理,一般来说Sever-side batch都会有个等待时间,如50ms或100ms,对于推理延迟比较高的大语言模型比较有效,对于向量化推理则不太适用。

 OpenSearch批量注入

 Amazon OpenSearch的写入操作,在实现上可以通过bulk批量进行,比单条写入有很大优势。

 向量数据库优化

 向量数据库选择哪种近似搜索算法,选择合适的集群规模以及集群设置调优对于知识库的读写性能也十分关键,主要需要考虑以下几个方面:

 算法选择

 在OpenSearch里,提供了两种k-NN的算法:HNSW (Hierarchical Navigable Small World)和IVF(Inverted File)。

 在选择k-NN搜索算法时,需要考虑多个因素。如果内存不是限制因素,建议优先考虑使用HNSW算法,因为HNSW算法可以同时保证latency和recall。如果内存使用量需要控制,可以考虑使用IVF算法,它可以在保持类似HNSW的查询速度和质量的同时,减少内存使用量。但是,如果内存是较大的限制因素,可以考虑为HNSW或IVF算法添加PQ编码,以进一步减少内存使用量。需要注意的是,添加PQ编码可能会降低准确率。因此,在选择算法和优化方法时,需要综合考虑多个因素,以满足具体的应用需求。

 集群规模预估

 选定了算法后,可以根据公式,计算所需的内存进而推导出k-NN集群大小

 批量注入优化

 在向知识向量库中注入大量数据时,需要关注一些关键的性能优化,以下是一些主要的优化策略:

  • Disable refresh interval

  • 增加indexing线程

  • 增加knn内存占比

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/98139.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【24考研】:四川大学计算机学院23届874考研考情分析

四川大学计算机学院23届CS考研考情分析 作者:老李 往年都是大佬们做的, 今年正好自己在做公众号这一块, 因此不自量力的承担这个工作,顺便锻炼一点pandas包和plt包的应用能力。 所以形式上我也会仿照一下往年的大佬。 21考情&a…

助力网络管理的利器:企业办公网络中的VLAN划分策略

企业办公网络的性能和安全性对员工的高效工作和信息安全具有重要意义。在实现这一目标时,VLAN(Virtual Local Area Network)划分在网络设计中发挥着至关重要的作用。通过将办公网络划分为多个虚拟局域网,VLAN划分可以实现网络资源…

FFI绕过disable_functions

文章目录 FFI绕过disable_functions[RCTF 2019]NextphpPHP7.4 FFI参考 FFI绕过disable_functions [RCTF 2019]Nextphp 首先来看这道题目 index.php <?php if (isset($_GET[a])) {eval($_GET[a]); } else {show_source(__FILE__); }查看一下phpinfo 发现过滤了很多函数&…

使用openpyxl来创建一个月的日程表

首先你心里要有一张表的样子&#xff0c;openpyxl才能帮你创建出其余的29张。 import openpyxl from openpyxl.styles import Alignment, Font import calendar from datetime import datework_path rXX\YY\ZZ\日报-九月.xlsxtry:workbook openpyxl.load_workbook(work_path…

系统架构设计高级技能 · 面向服务架构设计理论与实践

点击进入系列文章目录 系统架构设计高级技能 面向服务架构设计理论与实践 一、SOA的相关概念1.1SOA的定义1.2 业务流程与业务流程执行语言 二、SOA的发展史三、SOA与微服务的区别三、SOA的参考架构四、SOA的主要协议规范五、SOA的设计标准要求六、SOA的作用与设计原则七、SOA的…

Linux土遁术之监测监测进程打开文件

分析问题过程中&#xff0c;追踪进程打开的文件可以在许多不同情况下有用&#xff0c;体现在以下几个方面&#xff1a; 故障排除和调试&#xff1a; 当程序出现问题、崩溃或异常行为时&#xff0c;追踪进程打开的文件可以帮助您找出问题的根本原因。这有助于快速定位错误&…

运维Shell脚本小试牛刀(四): 多层嵌套if...elif...elif....else fi

运维Shell脚本小试牛刀(一) 运维Shell脚本小试牛刀(二) 运维Shell脚本小试牛刀(三)::$(cd $(dirname $0)&#xff1b; pwd)命令详解 运维Shell脚本小试牛刀(四): 多层嵌套if...elif...elif....else fi_蜗牛杨哥的博客-CSDN博客 一&#xff1a; if...elif...elif..else fi多层…

【UniApp开发小程序】小程序私聊页面完善(仿微信带尾巴聊天气泡组件封装、滑至顶端获取历史聊天数据逻辑优化)【后端基于若依管理系统开发】

文章目录 说明仿微信带尾巴聊天气泡组件效果展示组件整体代码气泡主体气泡尾巴 使用 私聊页面滑动到顶部获取历史数据页面整体代码 说明 之前已经在【UniApp开发小程序】私聊功能uniapp界面实现 (买家、卖家 沟通商品信息)【后端基于若依管理系统开发】这篇文章中介绍了私聊页…

跨屏无界 | ZlongGames 携手 Google Play Games 打造无缝游戏体验

一款经典游戏&#xff0c;会在时间的沉淀中被每一代玩家所怀念&#xff0c;经久不衰。对于紫龙游戏来讲&#xff0c;他们就是这样一群怀揣着创作出经典游戏的初心而聚集在一起的团队&#xff0c;致力于研发出被广大玩家喜爱的作品。 从 2015 年团队成立&#xff0c;到 2019 年走…

Shell - 加固系统配置

文章目录 #! /bin/bash # Function:对账户的密码的一些加固 read -p "设置密码最多可多少天不修改&#xff1a;" A read -p "设置密码修改之间最小的天数&#xff1a;" B read -p "设置密码最短的长度&#xff1a;" C read -p "设置密码失效…

matlab 点云的二进制形状描述子

目录 一、功能概述1、算法概述2、主要函数3、参考文献二、代码示例三、结果展示四、参数解析输入参数名称-值对应参数输出参数五、参考链接本文由CSDN点云侠原创,

【python爬虫】—图片爬取

图片爬取 需求分析Python实现 需求分析 从https://pic.netbian.com/4kfengjing/网站爬取图片&#xff0c;并保存 Python实现 获取待爬取网页 def get_htmls(pageslist(range(2, 5))):"""获取待爬取网页"""pages_list []for page in pages:u…

数据库——Redis 没有使用多线程?为什么不使用多线程?

文章目录 Redis6.0 之后为何引入了多线程&#xff1f; 虽然说 Redis 是单线程模型&#xff0c;但是&#xff0c; 实际上&#xff0c;Redis 在 4.0 之后的版本中就已经加入了对多线程的支持。 不过&#xff0c;Redis 4.0 增加的多线程主要是针对一些大键值对的删除操作的命令&a…

怎么用postman连接websocket

点击右侧栏的Collections&#xff0c;然后点击旁边的New&#xff0c;然后点击其中的WebSocket Request,然后输入Url&#xff0c;点击Connection&#xff0c;这里需要注意的是Url不能加上http://&#xff0c;因为这个不是http协议。

alibabacloud的简单使用,nacos配置中心+服务中心。作者直接给自己写的源码

文章目录 依赖关键主要的程序启动文件配置文件bootstrap.yml依赖文件nacos配置中心上的文件截图 启动成功截图参考文档 依赖关键 SpringBoot版本和com.alibaba.cloud版本需要对应&#xff0c;不然会程序会启动失败作者使用的版本 SpringBoot: 2.1.6.RELEASE alibabacloud: 2.…

YOLOv7-tracker 目标追踪 输入视频帧

目录 1 项目安装1.1 环境搭建1.2 项目下载1.3 权重下载1.4 环境安装1.5 上传待检测的视频帧 2 视频帧检测与追踪2.1 检测与追踪2.3 结果 参考项目&#xff1a;https://github.com/JackWoo0831/Yolov7-tracker/tree/master github链接&#xff1a;https://github.com/Whiffe/Yo…

自然语言处理(NLP)是什么?

NLP(自然语言处理) 和 Phoebe Liu 的简介 您有没有和聊天机器人互动过&#xff1f;或者您是否向虚拟助手&#xff0c;例如 Siri、Alexa 或您车上的车载娱乐系统发出过某些请求&#xff1f;您使用过在线翻译吗&#xff1f;我们大多数人都曾与这些人工智能 (AI) 互动过&#xff…

vue naive ui 按钮绑定按键

使用vue (naive ui) 绑定Enter 按键 知识点: 按键绑定Button全局挂载使得message,notification, dialog, loadingBar 等NaiveUI 生效UMD方式使用vue 与 naive ui将vue默认的 分隔符大括号 替换 为 [[ ]] <!DOCTYPE html> <html lang"en"> <head>…

C语言指针进阶(3)

这节我们来总结一下指针和数组面试题。 在这节我们主要用到这样几个知识点&#xff1a; 1.数组名是数组首元素的地址。 但是有两个例外&#xff1a; 2.sizeof(数组名)&#xff0c;这里的数组名表示整个数组&#xff0c;计算的是整个数组的大小&#xff0c;单位是字节。 3.&…

如何在Windows本地快速搭建SFTP文件服务器,并通过端口映射实现公网远程访问

文章目录 1. 搭建SFTP服务器1.1 下载 freesshd服务器软件1.3 启动SFTP服务1.4 添加用户1.5 保存所有配置 2 安装SFTP客户端FileZilla测试2.1 配置一个本地SFTP站点2.2 内网连接测试成功 3 使用cpolar内网穿透3.1 创建SFTP隧道3.2 查看在线隧道列表 4. 使用SFTP客户端&#xff0…