M
点击蓝字 / 微软开发者MSDN
关注我们
作者:王豫翔 - 微软最有价值专家(MVP)
排版:Alan Wang
王豫翔
微软最有价值专家(MVP)
王豫翔,拥有20余年编程经验,Microsoft AI MVP,一直致力于分享 Azure AI 相关技术。曾在多个大型研讨会担任讲者,包含 TechEd、Tech Summit、Ignite China、Al Bootcamp 等。专注人工智能领域技术创新,尤其是自然语言对话方向的颠覆性机会。
自从大模型爆火之后,如何在不直接改变大模型的数据(训练大模型)的基础上,将特定领域世界的数据和大模型世界的数据融合,使用大模型的推理能力获得新的整合后的信息,就是业界一直在探索的道路,这条路的名字就是 Retrieval Augmented Generation。RAG 的思路非常简单,将本次需要大模型推理的领域世界数据完整地提交给大模型,然后使用大模型的推理能力实现知识结论。
最早被大家熟知的 RAG 技术我们一般称为 Baseline RAG,也就是我们说的向量 RAG。但是因为向量天然的模糊性,让我们 Retrieval 的数据和应该获得的数据有差异,这些差异就造成了大模型最后的结论错误。所以所谓的大模型幻觉很大程度上可能是我们 RAG 技术的局限,大模型为 Retrieval 的数据背锅了。
我曾经设计了一个知识库应用,从大量文档中为用户的提问提供结论的智能服务,这个应用使用的就是向量库 RAG。在客户的配合下,这个知识库的所有知识源被梳理得非常漂亮:每一篇文档都被人工精心审阅,所有的内容都确保完整、逻辑清晰,更重要的是这个知识库的文档量有几十万份,这个知识库的确为企业带来了前所未有的知识激活体验,企业几乎所有的员工都喜欢上这个知识的知识库。
但是,作为项目的主导者,我在推进这个项目的时候发现了一个现象:影响最后大模型输出结论质量的关键因素竟然不是大模型的推理能力,而是大模型的 Token 窗口。造成这个现象的原因就是向量的召回不够准确,举个栗子:我的提问是我需要知道某机械设备的组装需要哪些配件。你可能会认为向量库召回的都是和某机械设备有关的信息,如果你这样想,那就说明你对向量库还不够理解。向量的检索维度是没有语义的,只有词的距离,因此召回的信息中会包含这几十万份文档中所有的配件,不管这些配件和某机械设备是不是有关。而且这些召回的信息在排序上也有着奇奇怪怪的逻辑,你几乎很难给出一个绝对的算法对距离进行一个判断,因此 Token 窗口越大的模型就越有优势,但是很显然,这个优势是以巨大的 Token 消耗为代价的。
而且,向量库 RAG 的模式不仅仅是通过 Token 的大窗口来装载召回解决结论的准确性,它还具有两个致命的缺点:
无法挖掘观点:如果知识库中是大量的行业分析报告,用户想了解某专家对具体一个现象的观点就很难做到,因为向量库返回的都是碎片化的信息,对这些碎片,大模型无法全局地推理出专家的观点。
无法对关键信息进行统计:如果我们要在知识库中进行数据统计,比如知识库里面有多少设备,有多少零配件,因为向量库的特征和 Token 窗口的有限,所以统计类的要求向量 RAG 也无法实现。
这些现象的核心原因是向量 RAG 的碎片化不具有全局看待知识库的能力,在这个背景下,微软提出了 GraphRAG 思路,并以这个思路提供了一款开源的 RAG 框架。首先我们要明白,任何技术都有他的目标场景,我们从来没有找到过银弹,GraphRAG 也不是一个用于替代向量 RAG 的技术,它提供了一些有趣的思路让我们在某些场景下会有帮助。
下面我们对 GraphRAG 的两篇核心文章做详细的了解。
Welcome to GraphRAG
文章的出处:https://microsoft.github.io/graphrag/
这篇是 GraphRAG 主页的产品介绍,这篇介绍文章中,微软指出基线 RAG 使用的向量相似性作为搜索技术,这种搜索技术对需要回答的内容被分散在知识库不同文档中时表现较差,所以微软提出可以使用 GraphRAG 的模式解决这个问题。
在这篇产品介绍中,微软提到他们使用了 Leiden 算法对 Graph 进行聚类。Leiden 算法由莱顿大学的研究员开发,并在2020年的《Scientific Reports》上发表(论文的位置在 From Louvain to Leiden: guaranteeing well-connected communities)。该算法的核心是通过贪婪地优化模块化和在压缩图中重复的过程,递归地将社区合并到单个节点中。首先,它将每个节点视为一个单独的社区,计算当前的模块度。然后,在每次迭代中尝试移动节点到另一个社区,以最大化局部模块度增益。如果这种移动导致全局模块度提高,则接受这次移动。这个算法经常被用到社交媒体网络分析和信息检索中。
From Local to Global: A Graph RAG Approach to Query-Focused Summarization
文章出处:https://arxiv.org/pdf/2404.16130
这篇 GraphRAG 的论文更值得我们细读。论文中详细的介绍了 Graph RAG 执行的思路:
第一步:从源文档到文本块
在2.1节“Source Documents →Text Chunks”中论文的作者分享他们的经验:
文本块的分割粒度会影响后期的提取召回率和处理效率。
较小的块大小(如600个 Token)具有更高的实体提取召回率。
使用适当的“gleanings”轮次,可以在保持效率的同时提升大块文本的提取质量。
第二步:从文本块到元素实例
GraphRAG 通过大模型对第一步分割的文本块中找到所有的实体以及和这个实体有关的实现以及他们的关系,记住 GraphRAG 是要找到所有的实体和实体的关系,然后形成元组(tuple)。那么怎么确保大模型能找到所有实体呢?只有一个办法,烧钱。Graph RAG 的机制我总结在下面:
评估提取结果:在初始提取之后,LLM 会被要求评估其提取的实体列表是否完整。这一步通过一个带有逻辑偏置(logit bias)的 Yes/No 问题来执行,这里逻辑偏置设为100,目的是强制 LLM 做出明确的二选一决定。如果 LLM 回答“是”,表示提取是完整的;如果回答“否”,即表示有遗漏的实体。
收集过程:
确定遗漏情况:如果 LLM 判断有遗漏,则会触发下一步,该提示内容会继续说明“在上次提取中遗漏了许多实体”(MANY entities were missed in the last extraction)。此时,LLM 会被鼓励去收集这些已知遗漏的实体。
平衡粒度和质量:通过执行多轮收集,Graph RAG 系统能显著提高从较大文本块中提取实体的精确度和完整性,同时避免因文本块过大导致的提取质量下降的问题。这种多轮收集机制确保即使在初始提取阶段存在遗漏,系统也有机会在随后的轮次中检测并补充这些遗漏的实体,从而提升整体提取效果。
这种通过烧钱的方式确保实体的提取精度就是所有人抱怨 GraphRAG 非常消耗 Token 的原因之一。别急,烧钱的还在后头呢。
不过对我来说,带有逻辑偏置的 Yes/No 问题设计是我对这个阶段最有兴趣的地方,logit bias 的质量会直接影响花费了巨大 Token 值后的质量。
第三步:从元素实例到元素总结
第二步我们得到的是抽象的实体和实体的关系,这一步需要将这些抽象的实体关系整合成一个统一的描述。GraphRAG 需要将同一类型和相关的实例进行聚合,通过大模型理解每一个实体节点和关系生成对关系的总结。但是网络越大,总结的描述的递归层次就越多,这样我们的 Token 消耗又再一次的燃烧。
但是好处是这个步骤完毕后对于每个实体、关系经过多轮提取和聚合后的实例进行统一的描述生成,使其具备独立可理解的意义。这些描述可以是对来源文本的抽象总结,因为它们能够反映文本中隐含但未明说的信息。
这个过程需要处理一个关键的问题,就是第二步提取的实体存在描述差异,这个差异是大模型可能因为描述的差异导致实体的重复。所以为了解决这个问题,GraphRAG 使用了我们刚才提到的 Leiden 算法进行必要的合并和去重。
第四步:从元素总结到图社区
在对源文本中的实体、关系和相关声明进行抽取并生成它们的描述后,接下来需要将所有的元素汇总为一个统一的描述性文本块。这个过程也是基于 LLM 的抽象性摘要功能。它不仅需要从源文本的明示内容中提取信息,还需要从隐含信息中推断关系。一旦需要在节点中便利,又一次的祭出 Leiden 算法,因为 Leiden 算法不仅能够检测图的平面社区结构,还能够检测层级社区结构。这意味着它可以生成不同层级的社区划分,每一层级的社区对图结构进行互斥且完全覆盖的划分。这样,可以在不同层级上总结和概述图结构中的数据,从全局概述到更细节的子集情况。所以,最后的总结是分为叶子级社区(Leaf-level communities)和较高层级的社区(Higher-level communities)。这一步再一次的燃烧您的 Token 预算。
第五步:从图社区到社区总结
第六步:从社区总结到社区回答,再到全局回答
这一步是通过对社区摘要的处理生成最终的全局回答。这一方法主要用于从大规模文本数据中提取有用信息,并生成针对用户问题的全面、详细的回答。这一步就是 RAG 的过程,具体的召回 GraphRAG 是这么做的:
将所有社区摘要随机打乱,以确保相关信息在不同的摘要块中分布均匀,避免集中在单一摘要中而丢失。
将打乱后的社区摘要分割成若干个预先指定大小的块,每个块的尺寸取决于上下文窗口的 token限制。
对每个摘要块,模型会生成一个中间回答,同时会给出一个评分(0-100),表示该回答对解决目标问题的帮助程度(对于评分为0的回答会被过滤掉)。
在获取到所有中间回答后,将所有中间回答按照它们的帮助评分从高到低排序,根据排序结果,将尽可能多的高评分中间回答逐一添加到新的上下文窗口中,直到达到 token 限制,使用填充好的上下文窗口,让模型生成最终的全局回答,并返回给用户。
现在是不是能全面理解 GraphRAG了?它的最后一步是试图解决向量 RAG 的召回无法精准排序精度缺陷,为了最后这一步,之前的五步在疯狂地消耗 Token。而且每一步的消耗要比上一步的消耗更多(个人感觉,没有具体详细测试)。消耗 Token 还只是成本,更重要的是整体的技术复杂:Source Documents → Text Chunks、Element Instances → Element Summaries、Element Summaries → Graph Communities、Graph Communities → Community Summaries、Community Summaries → Community Answers → Global Answer
需要六步才能完成整个 Graph 的构建。
Graph RAG 用在哪里?
我最讨厌的就是一个技术人员说 All in。所有的技术都是解决一个问题一个任务,哪里存在着可以解决一切问题的技术呢?理解不同技术的优势和劣势才能帮我们更好地用技术解决问题。
很多团队在尝试了 Graph RAG 后,基本的抱怨就是 Token 消耗大,对实际的落地没有明显的感觉准确率提升,并且微软在 https://github.com/microsoft/graphrag 上的案例也不够经典。
从我的经验出发给大家分享一下 Graph RAG 可能合适的场景。在前面分析 Graph RAG 产品页和论文的时候反复提到:实体、离散、层次、这三个关键字是 Graph RAG 技术最适合的场景。如果你的知识库是堆满了明显的实体关系的知识库,比如:产品成分配件、地理信息、人际关系、历史事件这类内容,那么我们显然可以发现这类的知识是密集的实体关系知识,Graph RAG 显然是非常擅长处理这样的知识,比如:
我们哪些产品都使用了 ABCD 四个配件?
我们国家长度在 m-n 之间的河流有哪些?
某某某参与过哪些活动?
某某某品牌商的广告在哪类赛事上经常会出现?
还记得我开头讲的嘛?这些基于全局的,统计的信息是向量 RAG 非常不擅长的场景,但是 Graph RAG 可以极快极准确地得到结果。前提是依赖于生成高质量的知识图谱,对于数据质量要求较高。
当下,Graph RAG 的收益可能不高,但是这个技术还是值得关注的。
From Louvain to Leiden: guaranteeing well-connected communities
最后说下 Graph RAG 论文中反复提到的 Leiden,论文出处在: https://arxiv.org/pdf/1810.08473。
Leiden 作者是因为认为 Louvain 算法存在的一个主要缺陷:算法可能产生连接性极差的社区。为了解决这个问题,作者提出了 Leiden 算法,并证明了它能生成保证内部连接的社区。此外,通过快速的局部移动方法,Leiden 算法比 Louvain 算法运行速度更快。
不过在实际生产环境下,Leiden 的表现可能也没有达到预期,可能也是 Graph RAG 在有些情况下表现不够好的原因。
对于新技术,先不要狂热追捧,也不能无视打击,花点实际理解技术的背景,设计的出发点,找到合适的场景,这才是我们需要去做的事情。
微软最有价值专家(MVP)
微软最有价值专家是微软公司授予第三方技术专业人士的一个全球奖项。31年来,世界各地的技术社区领导者,因其在线上和线下的技术社区中分享专业知识和经验而获得此奖项。
MVP 是经过严格挑选的专家团队,他们代表着技术最精湛且最具智慧的人,是对社区投入极大的热情并乐于助人的专家。MVP 致力于通过演讲、论坛问答、创建网站、撰写博客、分享视频、开源项目、组织会议等方式来帮助他人,并最大程度地帮助微软技术社区用户使用 Microsoft 技术。
更多详情请登录官方网站:
https://mvp.microsoft.com/zh-cn
微信公众号|微软开发者MSDN
新浪微博|微软中国MSDN
·END·
下一篇:进博会“老朋友”带来秘鲁美食试吃