2024年5月18日,阿里巴巴 OpenSearch 研发负责人刑少敏应邀参与AICon全球人工智能开发与应用大会暨大模型应用生态展,分享《OpenSearch RAG 应用实践》,介绍了阿里云OpenSearch在RAG方面的应用和探索。以下是主题演讲的逐字稿分享:
大家好,我叫邢少敏,负责阿里云的AI搜索。今天给大家分享的是,阿里云OpenSearch在过去一年时间做的RAG方面的应用和探索。
RAG的产生背景
我们先简单讲一下关于人机对话的背景,因为我们今天所谈的ChatGPT、RAG,本质上是人机对话。人机对话实际上从1950年就开始了,从图灵提出图灵测试以后,人机对话就一直在发展,历经了好几代的技术。这里面影响力比较大的事件有两个,一个是2011年,IBM的沃森在一档类似“最强大脑”的节目里面战胜了人类选手,那个时候影响非常的大。还有一次,就是ChatGPT出来以后,引爆了这种人机对话的场景,还有大模型的场景。跟以前不太一样是,这一次人机对话真正能够应用和落地的可能性已经非常大了,也就是商业化的价值已经非常大了。有一个小故事,就是我们家小孩在小学读书,有时候学校的老师会留一些作业,让他去分享一些东西,比如说名人故事,一般需要做PPT来演示,家长就需要去帮助小孩。我也没有那么多时间,碰到这种做PPT的作业,我一般就用大模型来生成。有一次我给他生成了一个PPT,他拿到学校去讲了,讲完以后回来告诉我,他们班的同学说这个PPT不是他做的,是用大模型生成的。我觉得很奇怪,小学生为什么能看出这个PPT是大模型生成的?我就问他这个是为什么?他说没有为什么,因为他们班同学的PPT也是大模型生成的,他们跟我们生成的一模一样。这个事情让我意识到已经有很多家长在用大模型辅导孩子写作业。当一个技术已经到了妇孺皆知的时候,就是走到了我们身边的时候,我觉得他的商业化前景已经非常的明显了。
我们言归正传,大模型出来以后,不管是在我们刚才举的例子中的PPT生成,还是这两天各位老师分享的一些东西,它在通用场景其实做的非常好,能做各种各样的事情。但是到了垂直领域,还是有很多问题的。首先是数据问题,大模型因为用的都是通用知识来训练模型,所以它不可能知道企业内部的业务。比如,我们最常见的场景—智能客服,我如果去问大模型,我买了一个商品,现在出问题了,怎么办?这种售后的流程,大模型是不可能知道的,因为这是企业的私有知识和业务规则,这种问题是大模型解决不了的。这些数据企业也不可能分享出来训练大模型,因为这是企业私有数据。另外,还有一些其他问题,一个是幻觉问题,这是我们经常会遇到的。因为它是生成式的,要联想,要发挥,会有很多幻觉问题,还有就是知识更新、成本等问题。由于这些问题的存在,垂直领域催生了RAG这个方向,RAG也是现在我们实现问答比较主流的方式。
RAG的技术方案
我们当时刚开始做RAG的时候,RAG还没有现在这么火。一年过去了,RAG看起来已经成为了一种实现问答的主流方式。这两天大家也听了不少RAG的Topic,有一篇RAG的论文总结的很好,它把RAG的发展分成了三个阶段。其实总结起来一句话,RAG是用搜索结果引导LLM的生成,让LLM在受限的范围内给出答案。所以它的优势就是知识可更新、可溯源,答案受控,这就是RAG的主要优势。
OpenSearch在过去一年做的RAG也跟前面论文里提到的方案是类似的,基本上分为三个链路。一个是离线链路,就是把各种不同格式的文档进行解析,解析完了以后切片做索引。这里面包括文本、图片、表格、代码。做完索引之后进入在线链路,就是混合检索、重排,最后给到大模型。在大模型这一块,有一个线下的训练链路,会用一些增强的数据。这些数据一般来自于阿里内部业务场景上的数据,然后再加上授权后的客户数据,会在RAG场景上对模型进行finetune。我们用的模型主要以通义千问为主,开源的模型,比如LLaMA也会用。预训练我们主要做的是SFT。SFT以后的模型在我们的客户场景上,一般情况下效果会达到GPT3.5的水平,在有些特定场景上能达到GPT4的水平。
我们实践下来认为RAG有几个关键的点。首先是场景效果要求比较高,就是它在我们业务核心主场景上,基本上都会要求最好百分之百准确率,但是在辅助场景上,其实做到百分之八九十也能上线。什么是辅助场景呢?辅助场景就是有它更好,没它也行。比如一个搜索场景,有一个搜索框承担主要的业务,但是在旁边有一个小的对话窗口,会辅助性的做问答。这对RAG的效果要求非常高,比如有些医药的客户,如果做不到百分之百,其实是不敢用的,效果其实是RAG的一个关键点,也是一个最大的难点。现在影响RAG落地应用的最核心的点,就是场景效果,实际上到了真正的客户业务场景以后,往往达不到那么高的要求。所以,客户很想用,但是不敢用,这也是现在RAG最核心的问题。其次就是性能问题,通常情况下,对一个问答产品会希望它能在1到3秒内就能够把答案生成出来,但是我们现在的大模型,很多生成答案其实都是十多秒、七八秒,这样给客户的体验就会不好。而且有很多的场景,如果不能实时给出答案的话,其实也没有办法用。所以我们就有了流式输出,有点像软件下载时用的进度条,来缓解这个问题,提升客户体验。性能问题有两点,一点是高性能召回,这个问题相对来说比较简单,因为搜索领域已经把召回性能问题解决的很好了。另一点就是大模型的推理生成,能不能在1到2秒内让一个13B的模型给出答案来。然后就是成本问题,也是我们过去一年很重要的一个研究方向。我们会发现RAG的主要成本就在GPU卡上,其他地方的成本相对卡来说几乎可以忽略。训练的成本是最高的,然后就是推理的成本。最后就是生成答案的隐私和安全性问题。我们先看第一块效果问题,我们怎么解决?这里面有很多点都需要去做,但是我觉得最核心的是三点。第一点就是准确的解析不同格式的文档。因为文档的格式很多,每一种格式的文档又有一些不同,所以想把文档解析做好,在现在我们看来是一件非常难的事情,但是在一年以前,我当时想的就是这个有什么难的,找一个开源软件挂上就行了,但其实不是那么回事,整个效果里面最重要的就是文档解析。接下来就是召回问题,本质上就是一个搜索问题,这对于我们做搜索的团队来说,不是一个特别大的问题。最后就是低幻觉率的大模型总结,因为整个场景的要求非常高,所以对大模型的要求是,如果你懂就回答,如果不懂就不要乱答,而且生成出来的每一个答案都要有依据,这个依据就是召回的检索结果。
接下来看一下数据这块,数据这块有很多格式,PDF、Word、PPT之类的,还有JSON、Markdown,还有各类数据库等等。这么多类型的数据,怎么准确的去解析呢?结构化数据就不用解析了,它本身就已经解析好了。非结构化的数据,PDF、Word、PPT这三个是最常见的,这里面文本本身是比较容易解析的,它无非就是位置可能有一些错乱,但文本解析本身是比较好解决的。比较麻烦的是表格,表格里面所有的线条都有的是比较好解析的,有些表格线条是缺失的,就要去补上线条,还有些表格内容是跨行的,需要能识别。表格解析整体就比文本稍微难一些。还有就是图表,图表有分析型的图表,还有一些架构图。最简单的是类似风景、人物的视觉图,可以用视觉模型去理解它。但是像论文里面常出现的架构图、分析图表这种,其实是很难解析的。最后就是文档结构,也比较复杂。比如一篇论文,什么地方是作者,什么地方是摘要,不同类型的论文,比如中文期刊,英文期刊,英文会议格式也是不太一样的。数据解析对效果影响是最大的,这是我们自己的感受,但可能大家往往又不太重视这块。
我们早期调研了一些开源软件,基于我们的想法是数据解析这块不需要花太多的精力,调研一下开源软件,用起来就可以了。经过实践以后发现根本没有办法找一个开源软件把这些问题都解决了,每一种开源软件解决的问题都是在特定的范围内,解决某些文档解析问题。我们做RAG的时候,发现我们需要支持的场景很多,文档格式也很多,很难找一个现成的开源软件用起来。所以我们被迫走上了自己去做文档解析的路,当然也要借助于开源软件进行二次开发。经过了一年多的打磨,很多问题已经解决的比较好了,但是仍然有一些问题解决的没有那么好,比如PPT的解析。另外还有一些复杂图,比如架构图,怎么把它表示出来,这些还在继续研究。
做完文档解析以后,接下来就是把大段的文本做切片。做切片的方法是,首先分析文档的结构,根据结构把文档建成一棵树,这棵树里面每一个原子段落是一个粗的切片,在此基础之上,这些段落再做多粒度切片,用固定的token或者单句来切分,切分的时候,会确保整个切片的语义完整性,不是随便切出来一个300token就可以。表格的话,首先会把完整的表格解析出来,然后把表头和每一行数据作为表格的一个切片。还有一种就是文章开头有一个主观点,下面分为三段来展开论述。如果问这个文章讲了几点内容,就需要对一些段落进行总结,生成一个总结性的切片。所以切片这一块,其实跟数据解析一样,都是非常复杂的工作。对于我们来讲,也是长期在做优化,一点一滴地打磨切片的方法。
有了切片以后,接下来就是做向量化。向量化这块,我们努力的目标不是把一个效果很好的、参数量很多的模型的效果做得更好。而是在一个参数量比较少的模型的基础上,经过微调以后,做到参数量高一级的模型的效果,比如1B的向量模型,能不能做到7B的效果。为什么我们的重点是这个呢?因为我们发现整个产品里面,向量化的流量要远远大于大模型推理的流量。因为我们想象一个场景,比如钉钉文档里面要做问答,那在编辑钉钉文档的时候,为了保证实时性,我每编辑一个词,写一句话,这个时候文档就需要更新,更新后的文档就需要用向量化模型再进行一次向量化。假设有7亿用户,如果每个人都在更新文档,那系统扛的向量化流量其实是非常大的。我们之前有一个场景,客户大概有几十亿的数据,需要做向量化,我们评估了一下,需要一个月,然后客户就觉得这个事儿没法干,需要一个月才能把数据向量化出来,那这个业务等不了。所以这块的话,我们把精力主要放在提升向量化性能上,因为我们判断效果的核心在于前面的数据解析,而向量化这块我们在做的就是在一个高性能的、参数量较少的向量化模型上微调,去达到更多参数模型的效果。举个例子,这个bloom 1B的模型,现在能够在短文本的效果上做到7B的效果。
前面讲的是离线链路,接下来是在线链路。做问答场景,用户给的问题都是短文本,在不对文本进行语义扩充的时,理解短文本用户意图是很难的,所以我们往往需要把短文本进行语义扩充。拼写有错的话要改错,文本很短时要联系上下文给扩充语义,做指代消解、省略补全等,当然大模型也能做,但是大模型做这件事情,成本其实是挺高的,我们也用大模型尝试过意图,做的倒是挺好,但延迟上是受不了的,所以我们单独做了query理解,核心就是把短文本的语义进行扩充联想,同时做意图识别。意图识别主要是根据不同的意图来决定怎么处理它。比如,我问“这篇文章讲了什么”,是总结意图,然后我说“你好吗?”是一个聊天的意图,说“最近三个月收入的情况”是一个分析意图,说“OpenSearch有什么功能”是一个文档问答的意图,需要根据不同的意图去决定后面要怎么处理。另外问题可能是含糊不清的,这个时候要反问用户澄清意图,澄清意图以后继续往下走。Query理解这块也是我们后面经过摸索以后加上去的。因为一开始我们做RAG的时候,也认为大模型能解决一切,后面经过逐步摸索,发现其实不是这样的,有很多事情如果在外部帮大模型做了,带来的效果和成本收益其实更好。
刚才提到有一种意图是分析型的意图。分析型意图可以用现在常用的NL2SQL 这种技术来解决,比如我要查一下属于电商业务的员工数少于50人的企业名称,首先识别它是分析意图,做NL2SQL,使用SQL查询把结果召回。NL2SQL的关键点是怎么从一个query里找到具体的实体,就是做NER,以及实体对应的是数据库表里面的哪个字段。比如出现一个名字,这个名字是数据库里面的商家名,还是商品名,还是别的什么名称,识别名字对应哪个字段是最关键的。
对于OpenSearch来讲,在NL2SQL的基础上,还衍生出了NL2OpenSearch,只是语法上的不同,因为OpenSearch提供了两种语法,一种是标准的SQL,还有一种是特有的OpenSearch原生语法,NL2OpenSearch使用上跟NL2SQL一样,问题来了以后,会把它转成OpenSearch的语法来查询OpenSearch,我们很多客户是用OpenSearch原生语法,它类似于Elasticsearch的DSL。我们也做了NL2SQL的模型,在一些数据集、榜单上测试,在Spider、BIRD这些榜单上也能排到前几名。
接下来是混合检索这块,我们在检索这块最早的时候用稠密向量,确实能解决一部分问题,但是有一些需要精准语义的问题,稠密向量是解决不了的。所以逐渐把稠密向量检索换成了混合检索,就是用稠密向量来解决模糊语义匹配的问题,用稀疏向量来解决精准关键词匹配的问题。提供了一个向量化模型,可以同时产出稠密向量和稀疏向量,再做一个混合检索,最后做重排,给出结果。混合检索在我们的向量引擎里面实现了,也跟别的产品进行了对比,可以说领先现有的几乎所有的向量引擎。这个混合检索的模型三月份的时候也在中文向量化的榜单C-MTEB上拿到了第一名。
接下来是重排。我们做完混合检索以后,持续地在混合检索上做优化,但是发现很难再提升了,不管怎么优化,整个提升非常的小。后来我们就加了重排,后面这个cohere rerank模型是商业化的,所以用了这个bge-rerank,用了bge rerank以后,发现召回率提升了20%,回答的准确率提升了12.5%。当然这个里面也做了相邻切片的overlap,还有其他一些小的优化。但是整体上加了rerank以后的效果提升,远远大于我们在混合检索上继续做提升。因为混合检索的效果已经挺好了,再往下优化收益比较小了。召回链路做完了以后,接下来就是大模型推理。大模型这块我们努力的目标是去SFT,让大模型的幻觉率更低。因为我们的很多场景都是一些非常严谨的场景,不允许有错,在客户场景上,幻觉率是能优化的很低的,当然反过来说,它的通用能力会有一些损失,但这种损失是可以接受的,很多通用能力也不需要。
在通义千问的72B上,用典型场景的数据测试,能做到4.3%的幻觉率,在同样的数据上,GPT4能做到7.1%。因为GPT4没有针对我们的场景做优化,所以这也是正常的。这里整个SFT的流程就不多讲了,基本上就是收集一些开源的数据、企业内部脱敏数据,然后用这些数据去SFT模型,因为数据是从我们的场景来的,SFT以后在我们的场景上效果是比较好的。
大模型微调,主要是微调出一些行业通用模型,还不是客户专属的。当然我们也有客户专属的模型,就是只用客户的数据来SFT。
评测这块,我们用的是开源的Ragas方案。因为我们的产品上有很多参数,大模型有很多个,向量化模型有很多个,召回的时候也要设很多参数,大模型本身又有很多参数,这些参数调完以后,我怎么知道我调的好还是调的不好呢?缺一个AB Test,所以这个大模型评测在我们的产品上,第一个场景是做AB Test,换个模型或者调完参数以后,跑一下大模型评测,看一下效果是好了还是差了。第二种场景是我们经常会遇到bad case,然后去优化,优化好了,但是发现把原来的good case又搞坏了,优化有回退现象。所以大模型评测会实时地去运行,每天跑一次监控线上效果,有点像工程上的系统报警,去监控线上的效果。当发现某些case有问题,就报警出来,算法同学会立刻去诊断。大模型评测,主要是在这两种场景上用。
RAG的第二个关键点就是高性能的答案生成,一块是怎么高性能召回,另外一块是怎么做推理生成。我们有一个高性能的向量引擎叫做VectorStore,去年用一个新的底层框架进行了重构,整体工程上的开销变小了。
比工程上开销更多的优化是来自于算法,主要算法有两类,一个是聚类算法,另外一个是图算法,向量引擎用的算法都差不多,只不过实现方式上有一些区别。我们主要优化是优化最常用的图算法,也就是HNSW算法,是一种分层世界图检索方法。从两个方面去优化,一个是从图结构,图建的好,搜索的时候就可以遍历更少的节点,更高性能地检索,但是建图是有成本的,图建的好,索引构建的时候会建的慢,慢工出细活。那能不能让它建的又快,搜的又快?这就是我们优化的一个方向。
另外一个是图检索的时候,能不能少遍历一些节点就能检索出结果,有些节点没有必要遍历,就不遍历了,减少一些不必要的开销,预测出哪些节点不用遍历,就可以减少遍历的节点数。
这是图结构的优化,这个efconstruction参数,大致可以理解成这个图的复杂度。绿色的这些线是越均匀越好,纵轴是节点数,要遍历的节点数越少越好,所以越低越好。但是现状是红色的这条线,它要遍历的节点数是3万以上,当我把efconstruction建图的复杂度调到750以后,它遍历1.5万左右就可以了。我们做了一个优化,优化到我还是让efconstruction这个参数等于500,但是我可以达到跟参数等于750的遍历同样的节点数,就是在建图复杂度不变的情况下,让它遍历的节点数更少。
这是检索优化,通过预测哪些节点是没有必要遍历的,去减少这些不必要的开销。在一些数据集上也做了测试,对QPS还是有比较大的提升的。除了这两个优化点之外,还有很多算法上的优化尝试,工程上的优化尝试,这里就不多说了。
异构计算就是怎么样利用GPU来加速检索,刚才说的HNSW主要是一个面向CPU的算法,在CPU上的性能再优化,其实空间没有那么大了。我们现在正在测试面向GPU的图算法,对向量检索的性能优化是非常大的,在自己的场景上也做过测试,用GPU加CPU并行加速的方式,在NVIDIA的T4卡上,性能能够提升3到6倍,在NVIDIA的A100、A800甚至更高性能的卡上,能提高30到60倍。
向量检索引擎我们做的工作其实还是很领先的。今年我们也开源了Havenask,就有前面我们做的一些关于向量召回的工作。这块大家有兴趣的话,也欢迎大家一起参与进来,共同去开发Havenask。
接下来是大模型的推理加速。我们做了三个点:一是缓存结果,避免重复计算;二是量化后内存减半,吞吐量翻番,三是并行计算,将模型的同层或者不同层分布到多卡上。我们现在大概能做到,13B的模型在3秒内生成200左右的答案,现在其实已经到2秒了。70B的模型可以在6秒内生成200token的答案,现在已经能做到4秒内了。
还有就是成本问题。刚才说了大模型的成本其实是很大的一个成本,我们在选择怎么去优化大模型的时候,也看了很多方法,其中pretrain、continue pretrain这些需要百卡、千卡,月级训练时间的方法,其实是没有办法在我们的业务上用的,所以我们重点看的是成本最低的prompt,以及SFT。SFT有全参数和Lora,全参数主要是线下使用,Lora主要是用在客户专属模型,成本会更低一些。当然我们也会使用DPO线下做一些实验,但主要还是用prompt和SFT这两种方式来做大模型的优化。
我们客户专属模型是针对单个客户定制模型。因为特别高端的卡成本很高,所以我们在A10、V100这样的卡上来做,用Lora的方式可以在很多廉价的多卡上来支持大模型推理。多卡有两种方式,一种是在单卡上共享相同的基座模型,然后把Lora分布到不同的模型上,一张卡可以放50个客户,一个Lora的小模型就是一个客户。另外一种是把基座模型和Lora全部切分,8卡就切8份,分别放在不同卡上。这两种不同的方式所带来的性能的收益几乎是没有的,效果的收益也不如全参数微调那样的效果,所以它主要带来的是成本收益,可以从之前每个月4000的成本,做到每个月100的成本,40倍的成本下降。
最后是隐私和安全性,是必须做的事情,需要去从输入端以及输出端过滤,这块我们是对接公司的绿网来可以解决这个问题。
RAG的应用实践
最后我们讲一下应用场景。主要在这几个方面:一个是电商,比如电商导购,看起来像推荐,但实际上是一个大模型导购的场景;另外一个是内容场景,比如说CSDN上,推荐一些技术内容之类的;还有就是知识问答,这是一个很重要的场景,比如自如的租房问答之类的;最后就是教育的一些场景。
最后看几个用户的例子,上面是我们给迪奥做的电商的搜索,可以在它的小程序上多模态地搜索一些商品出来。另外就是自如的租房问答,还有一些学术论文相关的工具。当然还有很多,比如工单的摘要总结等。
不同的方法在效果上有不同的影响。刚开始用初版的通义千问和向量检索,大概在客户场景上能够做到48%准确率,后来加了prompt,多路召回,层次切片,到了61%,再加SFT,到了72%。可以看到加SFT其实提升并没有那么高,但是能提升绝对点11个点也还不错。最后加了重排、多粒度切片、向量模型蒸馏LLM,这块提升到了87%。这个数据稍微有点滞后,我们现在的端到端的客户场景效果能做到90%,今年会努力做到95%,逐步把端到端的效果提升到接近100%。
RAG总结展望
这个产品后面会做成一个平台。这个平台底层做数据层,会对接各种各样的数据源,像MaxCompute、Hologres、HDFS这些数据源,结构化数据、半结构化数据、非结构化数据。引擎会有开源出来的Havenask引擎,Elasticsearch引擎,然后还有各类离线服务,上面会有几个大模型的服务,推理微调等,最上层会用现在主流的Langchain、LlamaIndex做编排,做一个开发平台。这样的话,刚才讲的各种各样的服务可以暴露出来给用户使用。
最后聊聊下一步我们的思考。首先,我们现在的多模态的问答,还仅限于文本和图片的交互,就是输入文本能输出图文结合的答案,或者输入图片进行搜索,或者以文搜图。但是像语音、视觉、视频这些还没有去处理过,这块我们后面也会做一些探索,做了这些以后,像GPT-4o那样交互式的To C场景,我们可能就可以切进去。其次是agent,对于一个问答场景来说,agent在里面可能还起不到太多的作用。如果把场景拓展到任务型场景的时候就很有用。比如我给大模型一个指令,说现在帮我购买一台ECS,然后大模型去决策怎么办,第一步干什么,第二步干什么,然后调哪些API,最后去完成购买。或者说是售后运维的场景,报出一个故障了,大模型去决策故障问题到底在哪里,应该去把哪些人拉过来处理故障。这些也是我们后续要去探索的场景。最后是关于Long-Context。从我们去年年初做的时候就有关于RAG和Finetune的争论,到底应该把知识参数化,还是应该把知识数据库化。知识参数化,就是把知识都放到模型里面,数据库化就是放在向量引擎里面。争论了好久,最后发现还是RAG的效果更好一些。Long-Context是把更多的上下文都交给大模型,让大模型去处理。我觉得这个事情如果能解决成本和性能问题的话,其实还是很好的,这么大的数据给大模型以后,多长时间能生成出来,需要消耗多少GPU资源。所以成本和性能问题,我觉得是long-context主要的问题,如果能解决,这是一个非常好的方向。另外这边是刚才说的开源出来的Havenask的二维码,大家有兴趣的话可以扫码加入这个群,跟我们一起探讨怎么做好一个搜索引擎。
了解更多OpenSearch RAG应用,可免费试用体验OpenSearch LLM智能问答版https://free.aliyun.com/?pipCode=opensearch