导读:真正的RAG工作是由一系列复杂、细致的优化策略叠加而来

像Dify、Coze这样的低代码Agent搭建工具,通过将RAG内的各类能力进行封装,供用户在GUI界面上点击几下即可进行配置。这却给很多用户造成了一种假象——好像拖拉拽一下就能配置好一个知识库问答工具,打造一个企业级的知识库助手。从实际落地上来看,上层封装好的能力有其局限性,低代码平台能够达到的问答精准度上限明显,可能50、60分都算很不错的了;但这个分数,对于企业级场景是完全不可用的。你会允许AI在回答一些公司财务问题、行政问题上有一丝一毫的偏差吗?因此,从50分到90分的过程,才是RAG真正大显神威之处。但这个过程并不是一蹴而就的(即搞定1处就全盘皆赢),从知识的提取、向量化、分块、索引、检索到最终生成,每一步都有各种各样的优化策略可供选择,不同的策略适应不同的场景、数据的质量和生成的要求等。可以说,真正的RAG工作是由一系列复杂、细致的优化策略叠加而来,这不仅要求你随时更新自己的知识体系、掌握最新的优化方向进程,更需要你了解数据形态和业务场景,能够结合最终生成诉求来倒推如何去选择这一系列策略的配合。之前在一文了解RAG到底是什么?一文中浅介绍了RAG核心技术。那么,本文将分享下各个环节上的核心选型和优化思路,作为一张RAG策略地图供大家交流学习。知识的形态可以分为:结构化(表格)、半结构化(网页)、非结构化(PDF、Word等)。和数据库这样结构化数据不同的是,知识库往往存在大量非结构化数据(如视频、音频、PDF、网页等),这虽然极大地扩展了知识面,但也为准确的识别带来了技术难题。像Dify、Langchain、LlamaIndex这些框架都自带了一些提取器,但同时也支持丰富的其他loader器的能力集成。以Dify为例,它不仅支持自研的文件抽取方案,同时也支持了Unstructured的抽取方案。其中,Unstructured是目前较火的一种通用抽取工具,支持常见各种丰富的文档格式,适合作为一种基础通用的抽取工具选型。抽取阶段的难点其实在于——PDF和图片文字提取上。PDF的难点在于其灵活、丰富的布局本质上蕴含和嵌套了大量的关系,例如图片插在一堆文字中间,它可能是上一段话的一个示意图;同时,PDF这种格式又把标题、小标题、第一点/第二点等这样的布局拍平了,难以通过像读取网页里的title、body那样能够很轻易的读取到内容结构。而企业的大多数正式流通的文件都是PDF格式(不能随意被篡改和编辑),因此,这里就需要应用PDF类抽取工具(Pymupdf、MinerU、PyPDF)等对PDF文件做专门的处理,这些工具的特点是:会对PDF格式文件做单独的适配和处理,类似于一个元素解析器,能够清晰的读取不同元素是什么——如标题、正文、页眉、页脚、插图等。另外,企业内大量还存在的一类文档为图片,图片的精准识别尤其在金融行业应用极多。以某基金公司为例,其需要对新设管理人提交的资料进行审核,资料中包含大量的管理人学历、简历等照片;另外,针对中期监管诉求,需要定期收集基金的银行电子回单去进行监管审核等。这些都对从图片中提取和识别文字的精准度有极高要求,例如上图中纳税人识别号这种比较小的字母,直接使用大模型效果较差,通常我们会借助OCR(光学字符识别Optical Character Recognition)来进行实现。目前我们自己应用过的产品中,闭源工具Textin和开源工具百度飞浆整体效果和性价比还算可控,大家也可以结合自己的业务去试试,平衡下准确度和费用的关系。将知识抽取完成后,我们就拥有了大量的知识信息,这些信息可能是文字、图片等,这些知识以文档集合整理在一起。但在交给大模型进行向量化处理之前,需要进行分块处理。这是因为大模型一次吞吐的上下文有限。例如Qwen3的上下文长度为32768tokens,约5万字左右),这些上下文不只是查询知识库召回的内容块长度,还有用户问题query、提示词prompt等。另外,即使有段时间各家的大模型都在努力加长上下文长度,但足够的上下文并不代表着精确性,也有可能会召回干扰性的内容块,从而更容易造成模型的幻觉。因此,在有限上下文长度背景下,分块技术相对能更精准检索,从而降低模型幻觉和算力成本。那么,该按照什么逻辑进行分块呢?常见的分块方式有如下几种:当然,实际按照什么逻辑分块,是需要渐进式调整后得出的。例如,最开始可以先按照最常规的固定字符数分块,通过查看分块和召回测试看看效果;如果效果不佳,再调整字符数大小或是增加分隔符递归分块,甚至手动调整分块内容等。另外,分块本身是为了服务于检索,这就避不开要面向索引去进行分块逻辑的处理了。常见的几种在分块阶段就要为后续索引进行逻辑呼应的分块技巧有这几种:- 混合生成父子文本块:先生成粒度较大的文本块,再切分成更小的子文本块,父子文本块用ID进行映射关联。在检索阶段,先检索到子文本块,再通过ID找出其父文本块,从而将2者一并传递给大模型,提升更加丰富和准确的回答。
- 生成文本块元数据:分块后同步为该文本块生成对应的元数据(如标题、页码、创建时间、文件名等),从而在检索时,能够结合元数据作为过滤器来更高效进行检索(该功能目前Dify v1.1.0版本已经开始支持做配置了)
- 生成摘要+细节文本块:类似于父子关系,摘要则是由粗及浅,为文档生成概要性摘要信息,再将摘要和细节文本块关联起来
- 生成递归型多层级索引:类似于父子、摘要+细节,递归型则是划分了更多层级的索引树,自上而下是逐渐由粗到细的信息量
后续还会专门展开索引相关内容,这里先抛砖引玉带一下,分块、索引、检索这3块技术应当整合在一起进行整体考虑。分块好后,下一步则需要对这些不同块的知识进行语义理解和编码了,这也是整个RAG过程中,第一次需要使用到大模型的场景。常见的嵌入方式有2种——稀疏嵌入和稠密嵌入,而我们通常讨论较多的都是稠密嵌入。简而言之,稠密嵌入能够更好的捕捉语义关系,而稀疏嵌入在计算存储上更高效。1. 稠密嵌入是一种将离散符号(如词、句子、用户、物品等)映射到低维连续向量空间 中的表示方法。在这个向量中,大部分元素都是非零的实数 ,每个维度都隐式地表达某种语义或特征。
2. 稀疏嵌入是一种将数据映射到高维向量空间 中的表示方法,其中大多数维度的值为0,只有少数维度有非零值 。
目前应用较多的方式是2者进行结合实现混合检索,稠密嵌入负责捕捉语义关系,稀疏嵌入则更多应用如BM25(基于词的重要性对文档和查询进行匹配)这样的方法,既做到了语义上的相关性,也做到了关键词匹配的精准性。常见的稠密嵌入大模型有OpenAI、Jina、Cohere、Voyage、阿里Qwen这几家公司的,可以在https://huggingface.co/spaces/mteb/leaderboard去查看全球目前较新的Embedding模型排名。截至当日,多语言embedding模型中排名第一的为gemini-embedding-001,第二三四名竟然都是阿里的Qwen-Embedding系列,这还挺让人惊喜的。不过排名仅供参考,还是要根据自己实际任务类型去做测量。另外,不止生成模型可以做微调(我们往往说的大模型微调都是指偏生成响应侧侧大模型),其实嵌入模型也是支持做微调的,但很少有公司涉及。如果有一些高度专业化的知识(如医学、律师)、有特定的格式要求或者文化本地化需求,则最后一步再可以考虑嵌入模型的微调。通过微调,可以生成更优质的文本嵌入,使语义相似的文本在嵌入空间中的距离更加接近。经过embedding后,我们会生成大量的嵌入数据,这些数据当然不能以我们常见的关系型/非关系型数据库进行存储了,而是需要特定的向量数据库来以嵌入形式存储向量。存储的目标是为了更好更快的检索,因此,这一部分我们会将存储和索引一起来展开。先来看有哪些向量数据库?目前比较火的有Milvus、Faiss、Chroma、Weaviate、Qdrant、Pinecone、ElasticSearch,当然国内各家大厂(如腾讯)也都建立了向量数据库的生态。如果你想轻量级测试和小项目应用,可以首选Faiss(Facebook开源的向量数据库);如果你是企业商用,则可以考虑Milvus;如果你之前在用ElasticSearch的搜索/数据库功能,也可以继续考虑使用他们的向量数据库功能。另外,Dify官方默认的向量数据库则是Weaviate,说明该组件在企业商用上也是ok的。
当我们将向量存入数据库后,则需要对应建立索引。索引是有效组织数据的过程,就像我们去一家医院后的指南图一样,它通过显著降低对大型数据集的耗时查询,在相似度检索上起到重要作用。- FLAT精确搜索:对所有数据进行暴力性遍历,当然只适合小批量数据啦
- IVF_FLAT倒排文件索引+精确搜索:将向量数据划分为若干个簇,计算查询向量与每个簇中心的距离,找出相似度最高的n个簇,再在这些簇里面检索目标向量。就像你要找到「猫」在哪里,先快速找到「动物类」的簇在哪里。
- HNSW基于图结构的近似最近邻搜索:目前性能最好的ANN(近似最近邻搜索)算法之一,它通过构建一个多层导航图(如顶层、中层、底层),不同层级的密度逐步变大,让查询时能像坐地铁一样“跳跃式”地快速接近目标点。目前Dify中Weaviate的默认索引方式就是HNSW。
前面准备了这么多之后,才来到最后的检索部分,而这也是RAG(Retrieval-Augmented Generation) 中R(Retrieval)真正起作用的开始。检索前,常见的处理方式有如下几种,其中查询结构转化和查询翻译是常用的一些检索前优化方式,查询路由应用相对没那么多:通过上述处理,完成检索后,对应也有一些可以优化的策略:上述提供了一些检索前后的优化思路,其中像查询结构转化、查询翻译、重排基本都是相对必须的一些优化点,查询路由、压缩、校正等是否需要可以根据问答效果再考虑是否选用。还有一些新兴方向,如Self-RAG(让大模型自我决策是否要搜索、搜什么、搜到的够不够、是否要需要搜索),让大模型自己对检索效果进行优化目前成本和响应时间上还不甚理想,但这未来注定会是一个长期会进化的方向,可能会通过微调多个特定的小模型来进行实现,可以持续关注。当我们检索到了相关知识分块后,最后一步就是将用户查询、检索到的知识库文本块一并喂给大模型,让大模型利用自身的能力来回答用户的问题了。到这一步,其实知识库RAG的工作就结束了。那么,为了更好的生成结果,我们还能做的有什么呢?评估某种程度上对整个系统的价值起着决定性的作用,假设我们要给客户去交付一款知识库问答产品,到底用什么指标去衡量效果就成为了验收的关键卡点。但事实上,不同的客户和场景对应进行效果评估的评测集、评测模型都是不一样的。这里先推荐几种市面上常见的通用评估指标或框架:实际上,在我们自己业务交付过程中,这个评测集往往是我们结合客户业务先写一个初版,让客户参考后整理出自己最常询问的一些问题和期望答案,以此作为初始评测集;后续可按需对评测集进行AI智能的扩展等。但这个过程仍旧存在一定的问题,即客户是否真正了解自己的用户会问什么问题?很可能出现在交付时客户认可了,但实际使用过程中的真实用户并不会这样问的情况。因此,评估的过程注定也是一个渐进式不断完善的过程。以上就是本文对于RAG更全面策略的一个指南,实际企业应用中,只会用到其中的部分。通过上述内容,其实我们会发现:RAG真正想做好并不是一件易事,有非常多的策略和实现方式可供选择,这都会影响到最终的生成质量。btw,推荐一本书《RAG实战课》,个人读完觉得还不错,适合入门和进阶读。最后,建议想做RAG的朋友先重点把核心能力用深、同时一定要持续了解和尝试新兴方向。因为,RAG领域目前虽然已经沉淀出来了一些经验和范式,但很有可能因为大模型本身的能力进化,导致一些现在有些ugly和不fancy的处理方式推翻,从而找到更简约和直接的实现方式。