自从我写了我的上一篇文章以来,时间并不长,但进步没有停止,发生了一些重要的变化。在这里,我不会覆盖基础知识——你可以阅读原文来了解这些内容。
上下文第一个显著的变化是上下文窗口大小的大幅增加以及token成本的降低。例如,Anthropic公司最大的模型Claude的上下文窗口大小超过200,000个token,根据最新的新闻,Gemini的上下文窗口可以达到1000万个token。在这种情况下,对于许多任务(或至少不是所有组件),RAG(检索增强生成)可能不再需要,因为所有数据都可以放入上下文窗口中。我们已经遇到多个金融和分析项目,在这些项目中,任务完全可以通过不使用向量数据库作为中间存储来解决。token成本降低和上下文窗口大小增加的趋势可能会继续,从而减少使用外部机制对LLM的相关性。然而,目前它们仍然需要。
然而,如果上下文大小仍然不足,已经设计了不同的总结和上下文压缩方法。LangChain为此引入了一个类:ConversationSummaryMemory。
llm = OpenAI(temperature=0)
conversation_with_summary = ConversationChain(
llm=llm,
memory=ConversationSummaryMemory(llm=OpenAI()),
verbose=True
)
conversation_with_summary.predict(input="Hi, what's up?")
知识图谱
随着LLM需要导航的数据量增加,导航这些数据的能力变得越来越重要。有时,如果没有分析数据结构和其他属性的能力,就无法有效地使用这些数据。例如,假设数据源是一家公司的维基百科。维基百科中有一页包含公司的电话号码,但这一点在任何地方都没有明确说明。那么,LLM如何理解这是公司的电话号码呢?它无法理解这一点,因此标准的RAG不会提供关于公司电话号码的任何信息(因为它看不到任何联系)。在这种情况下,人是如何理解这是公司的电话号码的呢?很简单——页面存储在一个名为“公司信息”的子目录中。因此,人们可以通过数据存储的约定(即结构或元数据)来理解数据的含义,并有效地使用它。对于LLM来说,这个问题是通过带有元数据的知识图谱(也称为知识地图)来解决的,这意味着LLM不仅拥有原始数据,还拥有关于存储结构和不同数据实体之间连接的信息。这种方法也被称为基于图谱的检索增强生成(GraphRAG)。
图是表示和存储结构化的异构和相互连接的信息的优秀方式,可以轻松捕捉不同类型数据之间的复杂关系和属性,而这正是向量数据库难以应对的。
图片由作者提供
知识图谱示例如何创建知识图谱?这是一个有趣的问题。通常,这个过程涉及收集和整理数据,需要对领域知识和图模型有深入的理解。借助大语言模型(LLM),这个过程可以很大程度上实现自动化(令人惊喜 🙂)。由于大语言模型对语言和上下文的理解,它们可以自动完成知识图谱创建过程中的许多重要部分。通过分析文本数据,这些模型可以识别实体,理解它们之间的关系,并建议如何最好地将它们表示为图结构。
一个普通的 RAG 看起来像这样:
图片由作者提供
修改后的流程将如下所示:
图片由作者提供
所以实际上,这是一套向量数据库和知识图谱的组合。正如我在上一篇文章的组合部分提到的,它们通常会提高准确性,并且通常包括通过常规数据库或关键词(例如 Elasticsearch)进行搜索。
我不会详细介绍向量检索器,因为它已经在第一篇文章中有所覆盖。但让我们来看看知识图谱检索器。如上所述,最明显的方法是询问大语言模型。例如,用户询问公司的电话号码:
图片由作者提供
如果你在代码中这样做,你可以要求将找到的实体格式化为 JSON 格式,或者使用 with_structured_output 来自 LangChain。因此,问题中的实体被提取出来了——接下来呢?接下来我们要看看我们公司如何应用这些实体的 100500 个用例 😂。开玩笑的。接下来,我们需要在知识图谱中搜索这些实体。这如何实现取决于图谱存储的位置。
已经有很多图存储解决方案(尽管公司经常会开发自己的版本),所以我们以Nebula为例。
documents = parse_and_load_data_from_wiki_including_metadata()
graph_store = NebulaGraphStore(
space_name="Company Wiki",
tags=["entity"]
)
storage_context = StorageContext.from_defaults(graph_store=graph_store)
index = KnowledgeGraphIndex.from_documents(
documents,
max_triplets_per_chunk=2,
space_name=space_name,
tags=tags=["entity"]
)
query_engine = index.as_query_engine()
response = query_engine.query("告诉我关于我们公司的更多信息")
如你所见,搜索与在向量数据库中搜索并没有太大区别,除了我们搜索的是属性和相关实体,而不是相似的向量。回到第一个问题,由于维基结构已经转移到了图中,如果一切工作正常,公司的电话号码应该已经被添加为图中的相关实体。
然后,我们将这些数据和向量数据库搜索的数据传递给大语言模型以生成完整答案。
看起来很简单,但其实存在几个问题。
访问控制第一个问题是数据访问可能不统一。在同一维基中,可能存在角色和权限,不是每个用户都能看到所有信息。这个问题在向量数据库中的搜索也存在。因此,出现了访问管理的问题。这个问题进一步复杂化的原因是存在许多不同的方法及其混合体,例如,任何使用过SharePoint的人都知道,那些熟悉它的人不会嘲笑马戏团。
至少包括基于角色的访问控制(RBAC)、基于属性的访问控制(ABAC)和基于关系的访问控制(ReBAC)及其组合。一般来说,用户目录(如 Active Directory),例如,也代表一个图,其中访问问题大约是“从节点用户 U 到节点资源 R 是否存在路径”。如果存在这样的路径,访问将被授予。
权限和类别也是一种元数据,为了使整个系统正常运行,这些元数据必须在知识图谱和向量数据库的数据导入阶段得到保留。相应地,在向量数据库中搜索时,需要检查找到的文档是否符合用户的角色或其他访问属性。一些(尤其是商业公司使用的向量)数据库已经具备了这种功能。如果数据在训练大型语言模型(LLM)时被嵌入进去,那么这种方法将无法工作 😄。在这里,我们只能依赖大型语言模型的合理性,而我现在不会这么做。
此外,还可以在上面添加一个审核(保护)功能,过滤模型的输出,以防有任何内容漏网。大家都熟悉Lakera;我们公司也开发了一个类似的产品。
摄入和解析数据需要以某种方式插入到图和向量数据库中。然而,对于图来说,格式至关重要,因为它反映了数据结构并充当元数据。这里就开始了所有数据科学家的噩梦,也被称为PDF格式。你可以将一切内容放入PDF中:表格、图片、文本、图形。但有时将所有内容都取出来是不可能的(尤其是嵌套表格)。
有不同的框架和库可以实现这一点,但效果各有不同,其中最值得一提的是 LLama Parse。
不幸的是,目前还没有很好的解决方案,有时候使用OCR或识别文档图像反而更简单,而不是进行解析。也许有人会创建一个专门用于将PDF解析为更可接受格式的模型,但梦想不会伤害任何人。
一般来说,当前的重点是提高答案的质量。除了使用知识图谱之外,还有几种方法:
CRAG(修正增强检索生成)我们发现 RAG 有时会产生不正确的结果,可以使用不同的方法来评估这些结果,例如使用 LLM 本身(或某种轻量版本)。如果结果不相关,可以进行提示修正、图搜索,甚至使用 Google 搜索。CRAG 则更进一步,提供了一个自动化此过程的框架。本质上,这又是一个图,实现了一个状态机(令人惊讶 🙂),大致如下所示:
图片由作者提供
要实现它,最简单的方法是使用 LangGraph,这将在后面进一步讨论。
自我RAG自反思型RAG基于研究,认为这种方法比常规RAG提供更好的结果。总体而言,这个想法与之前的CRAG非常相似,但更进一步。其想法是微调LLM,使其在生成常规令牌的同时生成自反思令牌。这样非常方便,无需猜测LLM的自信程度及其处理方式。生成的令牌包括:
- Retrieve token 决定是否需要为给定提示 x 检索 D 中的片段。选项:是、否、继续
- ISREL token 决定片段 d 是否与给定提示 x 相关。选项:相关、不相关
- ISSUP token 决定 LLM 对片段 d 的响应 y 是否由片段 d 支持。选项:完全支持、部分支持、不支持
- ISUSE token 决定 LLM 对每个片段 d 的响应是否是对查询 x 的有用回答。选项代表从 5 到 1 的有用性等级。
使用这些令牌,可以使用上述 LangGraph 构建一个状态机,大致如下所示:
图片由作者提供
了解更多详情,请参阅这里。
HyDe另一种方法类似于 RAG Fusion,它修改了常规的 RAG 检索过程。HyDe 代表 Hypothetical Document Embeddings,基于研究 “Precise Zero-Shot Dense Retrieval without Relevance Labels.” 这个想法非常简单——不是使用用户的提问在向量数据库中搜索,而是使用 LLM 生成一个响应(一个虚拟的假设文档),然后用该响应在向量数据库中搜索(以找到相似的答案)。
图片由作者提供
为什么要做这些?有时候用户的问题太抽象,需要更多的上下文信息,而这些信息LLM可以提供,没有这些信息的话,数据库中的搜索就没有意义了。
我认为这并不是对新变化的全面回顾;如果我遗漏了什么,请在评论中指出。
共同學習,寫下你的評論
評論加載中...
作者其他優質文章