AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


SemanticRAG:如何实现全过程语义检索
发布日期:2024-08-08 06:15:56 浏览次数: 1701


浩如烟海的文字,是你宝贵的财富...

正文:

随着大语言模型的成熟,知识检索、知识问答等RAG应用快速落地,这里面确实有很大的商机。最近,GraphRAG也出来了,得到大家普遍欢迎,甚至被称为RAG2.0,那么LangChainLlamaIndex等一众先驱是否会成为大家眼中的牛夫人?大家折腾了快一年的向量检索是否又得打水漂?

虽然技术发展确实太快,但个人感觉这些技术还不至于被淘汰,向量检索和图(也用到向量)检索是两条并行的技术路线,不是替代关系。总体上,图检索适合固定关系和简单关系,向量检索适合时序性质及复杂属性关系。向量检索结果毕竟是第一手数据,没有加工过的;而目前的图主要保留了三元组信息,丢弃了一些辅助信息或无法识别抽取的信息。具体利弊合适的时间再说。


无论怎样,我们得想办法高效、准确地从海量历史素材中提取所需的知识,这点是非常关键的。把图检索和向量检索结合起来,发挥各自优势,也是以后可以讨论的话题。无论怎样,RAG服务Agent是长期目标,正所谓基础不牢,地动山摇。RAG越来越精细化,大家对它的准确性和性能要求越来越高,向量检索还需要继续卷起来。


这半年来,看了不少关于RAG的资料、源码,首先非常感谢社区各位大佬的分享。虽然大家都在说语义检索,但感觉现在的技术路线更多的是结合微观语义,和宏观语义结合的较少。我用业余时间断断续续手搓了一个实验软件,姑且叫他SemanticRAG。对于什么是语义、如何深层次的结合语义,在这里利用周末把个人的一些思考分享出来,以期抛砖引玉。


一、当前RAG的通用做法


假设这是一段文本:



现在RAG的通用做法会按照固定大小,或者兼顾标点符号,把全文拆分。比如下面不同颜色的文字被拆分为同一段:



再把不同文本组成首位相接或部分重叠的片段,进行向量化和存储:

然后从中去查找字面含义接近的片段,最后使用大语言模型生成回答。



二、对什么是语义的几点认识


我认为,上述当前RAG的通用做法是有缺陷的。下面直接说我的观点:


1、文档结构是最大的语义


语义不仅仅是文本单词。按照成语讲,我们不能“断章取义”,首先得把这个章断好,我觉得按照字符长度来断章并不科学。文档结构就是宏观的语义,在文档拆分、检索和生成等各个环节需要和文档的章节结构紧密结合起来。


2、文档标题和目录是递进的语义摘要


文档标题和章节目录的文字,是文档编写人员按照自己的原始理解归纳总结形成的核心表达。对于一段文本,他的语义不仅仅基于自身,还基于他处于什么章节中,并且要沿着文档的目录结构层级倒退,直到第一级目标、文档标题。这才是他更完整的语义。

当然,一些和文档相关的属性也属于文档整体语义的一部分。


3、需要构建和表格等价的语义模式


文档中会有很多表格,现在常规的做法就是按照文本出现的先后顺序,直接转换成文字。说实话,转换后的文本是很难看懂的,表格内容已经失去了和他原先对应的行列标题之间的关系。每一个单元格的内容,需要结合其所在的行列标题,包括复杂表头的多级标题进行重构,以保持其完整的语义。


4、通过权重来调整语义的重要性


前一段时间,刘焕勇老师转了一篇文章,说到人的思维是有权重的,这个很在理,符合直觉。在实际生活中,我们看到一篇文档会通过他的来源判断其权威性,小孩也会通过说话人的身份来判断其要求的重要级别。

对于类似语义的文字,如果来源存在差异,其语义相似性应该体现来源的权重。重要来源的文字,哪怕相似度小一些,有可能他对输出影响的优先级还应该排在前面。比如你的大Boss讲的话,能够和员工个人总结相提并论吗?如果将所有的文本片段只按照各自的向量余弦相似度进行排序,无异于鱼龙混杂。


三、SemanticRAG的实现思路


1、向量库构建


(1)文档结构识别


对于一篇文档,首先要进行文档结构重建。如果是Word文档、PowerPoint幻灯片、PDF文档,其可能已经包含了一些章节结构,这都是要识别和加以利用的。除了已有的章节结构,可能还有一些文档没有标出章节结构,此时需要进一步智能识别文档的章节名称、列表编号、手工编号、短标题,力争识别到最小层级的可以当做目录处理的程度。

虽然现在有一些开源工具可以用于判断Word文档的章节结构,但由于不同版本和样式的差异,其章节结构的表示方法存在巨大的差异,从中提取章节结构效果不理想,有很多坑。可能需要使用人工智能的方式来恢复章节结构,但大家好像现在热衷于版面识别和图标识别,鲜少看到相关的工作内容。


如下图,先识别文档的章节结构及包含关系:


(2)构建层级的语义等价模型


在系统中,对于解析完成的文档,要形成和文档章节结构相对应的树状结构,最小节点就是自然段(包括各级标题),这个层级关系在数据库的存储上也需要体现。

从语义上讲,拆分后的文档需要和原始文档是等价的,也就是能够通过工具反过来生成物理文档,其章节结构和文本逻辑顺序要和原始文档一致。其中,无论是文本片段、表格和图片都要能恢复。

通过这种方式,就不会存在跨章节、跨段落拆分的情况。



(3)段落拆分

原始文档的可能太长,超出大语言模型可以为输入预留的长度。此时,需要结合模型上下文长度,对段落内容按照自然句进行拆分。

这样,就不会出现跨自然句拆分的情况,并且打破常规的200个字符的约束,更好地发挥大语言模型长上下文的优势。


(4)文本节点预处理


首先,要形成摘要。包括末级节点内容的文本摘要、层级目录拼接形成的原始创作者设定语义摘要,并且将图表的标题文字提取为图表语义摘要(也可以在语义等价转换或识图后按照文字再次形成摘要)。

此外,除了生成向量外,还需要生成不同节点文本的Token长度。为什么要生成摘要和Token的长度,后面会结合使用来解释。


2、文本语义召回


(1)从上至下进行并发串行多路召回


从语义检索的角度这里有很大的区别,不能像LangChainSemanticKernel等工具逐条向量进行查找,需要和文档结构结合起来。

首先,对于可检索的向量库内容,需要找到这些内容的所有根节点。使用并发线程,从各个根节点开始往各自子节点进行广度遍历,如果某个节点满足召回要求,就把该节点及其子节点当做一条检索记录增加到结果集合中,并不再遍历其子节点。

其次,在检索的时候,可以按照优先级先后使用关键词查找、向量相似度判断等方式,只要一个满足就增加到检索结果中,避免在分开进行多路召回时可能存在的重复检索、合并检索结果的情况。

注意,检索结果可能是带子节点的子文档片段,要保持符合原文的自然层级结构,便于后续进行语义的生成。


(2)对相似度进行差异化处理


首先得到原始相似度。对全文或关键字匹配的情况,预设一个固定的相似度。对于向量检索的情况,使用实际向量相似度作为原始相似度。

接着,将原始相似度和该文档的权重相乘,得到权重相似度。

最后,对权重相似度按照相似度阈值进行判断,得到满足要求的检索结果。

我还没有使用专用的rerank模型,现在还无法判断其必要性。


3、语义生成


(1)从下至上按照层级生成回答


对于检索回的各个带层级信息的文本片段,先按照深度遍历的方式,使用正常问答的方式不断聚合,提取其有效答案信息,直到根节点形成一段文字。

最后,再基于各段文字,使用正常问答的方式进行又一轮聚合,形成最终的答案。

注意,只能把某个文本片段下属的相邻同级节点进行语义聚合,以保持语义的对等性。


(2)根据大语言模型的能力生成


在生成的过程中,要尽可能减少大语言模型问答的次数。要结合大语言模型的上下文窗口,合理把握对话的时机,尽量将语料累积到接近可使用的输入长度上限,减少生成次数。



上述整个处理流程如下图;



四、几点注意事项

1、关于提升性能

(1)缓存文档树形结构

可以在内存缓存需要处理的文档,包括其上下级结构、向量和token数量,便于快速检索。这个数据结构可以采用双向的无环图。


(2)按需动态使用摘要


根据不同的情况,分别对摘要或文本内容进行向量相似度判断,如目录可以使用摘要。减少对下级节点文本的检索。


(3)使用预处理形成的Token长度


在预处理环节,所有摘要和文本内容都会预先生成Token长度,在进行生成检索的时候,可以对累积的文本动态计算总的Token长度,在恰到好处的提交给大语言模型进行生成,减少调用次数缩短时间开销。


(4)并发召回

从各个文档片段的根节点,同时进行广度遍历,无需检索所有末级节点,无需使用不同算法重复检索,前面已经提到。

(5)按照权限对数据进行预过滤


按照当前用户权限及指定的检索范围,如文档类型、组织机构等,预先构建符合需要的树形结构,再进行检索,减少召回的范围、加快遍历速度,同时确保信息安全。


2、关于提升检索生成的准确性


(1)答案预生成


可以预先生成的答案,再将原始问题和答案一起进行向量化,最后再进行向量比较。

从逻辑上,答案进一步启发了答案的可能向量,便于求出更多的向量余弦相似度文本。这也是当前多个大佬推荐的做法。


(2)选择合适的大语言模型进行嵌入和生成


现在的RAG系统,一般都使用专门的嵌入模型,这个可能性能会好一点。但我的理解不同:


首先,要使用同一个大语言模型进行嵌入和生成。大语言模型经过大量的语料训练和微调,肯定是见多识广,在向量化上应该是更精准的。让一个模型做嵌入,另外一个模型做生成,就好比一个人负责采购买回来一匹马,但另外一个人负责入库非说这个是一头鹿。这两个模型的知识面和理解能力都不在一个层次上,各管一头合适吗?哪个说这个文本里面有我要的东西,谁就负责给我找出来,别互相踢皮球。可能我的观点不对,欢迎批评指正。


其次,如果条件允许,建议对不同语料使用不同的大语言模型进行向量化,包括文本和问题。有兴趣可以看看我的上两篇文章,不同大语言模型的文本生成能力和向量化能力差异很大,尤其是对不同语言的文本。建议结合具体要解决的领域内容,使用不同的大语言模型进行向量化比较,查看不同大语言模型的向量相似性值及空间分布。

一个适用的大语言模型,相似的文本对和不相似的文本对,其向量余弦相似度值的差异越大越好,比如是0.80.3的区别。一个不大适用的大语言模型,可能把貌似不相关的文本对的向量余弦相似度都整到0.6。比如,对于 “王大力的籍贯在哪里?”与“单行。甘肃电信网络采用三级结构, 汇聚层:”的向量余弦相似度,WizardLM-2-7B_Q8给出的值是0.6022135615348816Yi-1.5-9B-Chat-Q6_K给出的值是0.49132296442985535,0.6就超出直觉了无法接受。当然,WizardLM很棒很全面我很喜欢,这里可能是他训练语料中中文素材不足导致的。


(3)实现QOS按需检索


人有慢思维和快思维,有简单思考和仔细琢磨的区别,RAG也应该是一样。

对于快速检索,可以只检索摘要,或者检索权重相对大的文档。如果实在找不到,或者想仔细翻箱倒柜找一下,可以再仔细检索节点文本,或者不断降低对相似度阈值和权重的要求。这样,就实现了逐步递进的思考过程,当然是以计算量和时间作为代价的。

这里,还有一个数据置信度的概念,不做讨论。

3、关于检索生成的安全性和便利性


(1)要细化数据权限控制


在企业级应用或多租户的场景,大家的文档都搁在一起,要严格控制访问权限,并且就是同一个文档,可能同时涉及技术、商务甚至保密信息等不同内容,更是要控制不同章节的查看人员。因此,要考虑组织机构、文档类别、角色、目录、文档、章节等细粒度控制权限。


(2)实现向量数据和关系数据一体化存储


现在开源的系统在企业很难拿来直接使用,主要的原因是权限数据、文档数据、向量数据三者脱节,难以进行细粒度的权限控制。虽然像Postgres支持向量字段和向量检索,但开源系统一般倾向于使用专用向量数据量。

向量数据库检索速度是快了,但是和结构化的数据很难快速有效建立起关系,制约系统功能开发。

我采用了SQLite数据库,将文档结构、文本片段、组织机构权限及向量全部存储在一起,其中向量当做文本存储,虽然在从数据库加载时有性能损耗,但在使用上很方便,尤其是对数据和关系缓存后,对性能基本没啥影响。

一体化存储的最大好处,是可以给已有的信息化系统快速添加向量检索和知识问答功能。


RAG的探索就告一段落。欢迎留言讨论。



53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询