DLAI-RAG-笔记-全-

DLAI RAG 笔记(全)

001:课程介绍与概述 🚀

在本节课中,我们将一起学习吴恩达与Zain Hasan关于检索增强生成的对话内容。我们将了解RAG是什么、为什么它如此重要,以及本课程将涵盖的核心内容。

课程概述

欢迎来到DeepLearning.AI的《检索增强生成》课程。

检索增强生成,简称RAG,是当前用于提升大型语言模型响应质量和准确性的最广泛应用技术。一个大型语言模型最初只具备其训练时所用的公共互联网数据知识。因此,当我们需要利用专有数据(例如您自己的文档)中的事实来回答问题时,RAG通过为模型提供访问这些额外数据的权限,使其能够完成这项任务。

简而言之,RAG让语言模型能够回答其训练数据之外的事实性问题。例如,您可能见过像ChatGPT或Claude这样的聊天机器人告诉您它正在“搜索网络”以帮助回答问题。这正是语言模型在访问额外信息,试图确保其回答是最新且准确的。

认识讲师

我很高兴向大家介绍本课程的讲师——Zain Hasan。Zain是一位经验丰富的AI和机器学习工程师、研究员和教育者。在过去的十年里,他在多家令人兴奋的AI公司工作过,例如Relevance AI(一家领先的向量数据库公司,提供RAG的关键组件之一)以及Together AI(一家提供LLM服务的公司)。

😊 谢谢,Andrew。我非常高兴来到这里。😊

我热爱RAG的原因在于,它提供了一种简单而实用的方法,能够聚焦大型语言模型的能力。RAG的核心思想是将经典搜索系统大型语言模型的推理能力相结合。

课程目标与内容

在本课程中,我们力求平衡涵盖搜索和LLM的基础概念将这些概念应用于构建高性能RAG系统的实用技巧。尽管RAG的概念并不复杂,但其实现方式有无数种,设计选择会对系统的准确性和速度产生巨大影响。

您将学习到:

  • 如何准备数据以用于此系统。
  • 如何提示您的语言模型,以充分利用这些数据。
  • 如何评估实际用户流量,以确保您提供高质量的响应。

因此,完成本课程后,您将掌握大量构建和调整RAG系统的实用技能,并对这些技术为何有效有基础性的理解。这是一套极其有用的技能组合,可应用于各种各样的行业。

RAG的应用与演进

我认为RAG可能是当今世界上构建的最常见的基于LLM的应用程序类型。大公司用它来帮助客户获取关于其产品问题的答案,或帮助员工获取公司内部政策或其他事务的答案。初创公司也在许多垂直领域(如医疗保健、教育等)构建RAG应用程序。

关于RAG的一个有趣之处在于,随着LLM技术的进步,RAG系统也在迅速融合这些新技术。例如,新一代模型在使RAG系统更“基于给定文档或上下文”方面,比一两年前的模型要好得多。因此,在过去一年左右的时间里,RAG系统的“幻觉”率似乎在稳步下降。

推理模型也让它们能够处理更复杂的问题,并能在提供的上下文之上进行推理。过去几年的一个有趣变化是,随着LLM的输入上下文窗口变大,关于“究竟将什么插入RAG”、“如何将文档切割成片段作为输入上下文”的最佳实践也在不断发展,因为现在您不再需要将大量信息挤进一个微小的上下文窗口。

随着智能文档提取和相关技术的改进,您现在也可以更轻松地在PDF文件、幻灯片或其他类型的文档之上构建RAG系统。因此,您可以构建RAG系统,更轻松地摄取、推理并回答与您可能拥有的更广泛材料相关的问题。

更广泛地说,随着团队构建更复杂的多步骤智能体工作流,RAG通常是复杂智能体工作流中的一个组件。在这个工作流中,RAG在某个步骤为智能体提供其处理文档或推理客户请求所需的信息。

前沿技术与课程价值

我完全同意。即使AI领域持续快速发展,我认为RAG也不会过时。LLM将继续受益于对高质量相关数据的访问。我也认为,本课程为与所有这些尖端进展合作提供了非常坚实的基础。

我们在本课程中包含了大量先进技术,从您提到的多模态或推理模型,到平衡RAG、微调和新型长上下文模型等方法。我个人非常兴奋的一项技术是智能体化RAG,即构建使用多个大型语言模型的系统,其中每个模型处理大型工作流的单个部分,并拥有决定检索什么数据的自主权。

这正处在公司推动基于LLM的应用程序性能的前沿。我认为早期的RAG系统是由人类工程师编写大量代码和规则来决定:给定查询,我们如何切割长文档、如何检索片段、以及我们将取多少个片段放入LLM的上下文。因此,是人类工程师决定提供什么作为上下文,然后让LLM回答问题。

而智能体化RAG真正有趣的地方在于,您可以给AI智能体提供检索信息的工具,并让它自己决定下一步是否要进行网络搜索、使用什么关键词,或者查询某个特定的专业数据库。在检索到第一轮信息后,它判断是否足够,或者是否需要进行第二轮检索。因此,这些高度智能化的系统可以自行决定检索什么信息来满足特定的信息需求。我发现这是使系统更加灵活和强大的重要方式。它给了它们一种处理现实世界复杂性的方法。如果搞错了,它们可以退回并修正其采用的方法。

因此,在本课程中,您将从基础RAG一直学习到高级的智能体化RAG,涵盖这一系列技术——既包括构建这些系统的核心原理和思维框架,也包括如何实际调整超参数(例如将长文档切割成多大块是合适的)以及如何管理上下文等实际问题。

如果您正处在构建生成式AI应用程序的早期阶段,我认为本课程不仅会让您对RAG有一个很好的概述,还会让您了解构成RAG的许多组件,这些组件对您未来可能构建的其他东西也可能有用。所以,我认为本课程绝对能让您做好进行RAG开发的准备,更广泛地说,能让您拥有一个良好的基础,去思考如何组装我们现在在生成式AI领域拥有的许多工具来构建应用程序、评估它并推动持续改进。

总结与预告

本节课中,我们一起学习了Zain和我关于RAG的讨论,了解了我们认为它重要的原因以及学习它的益处。在下一个视频中,Zain将从高层次概述RAG最重要的组成部分。这样,无论您是构建一个标准的RAG系统,还是将其作为更复杂的智能体工作流系统中的一个组件,您都能对“需要做哪些事情才能让一个有效的RAG系统运行起来”有一个清晰的思维导图。

接下来,让我们观看下一个视频,深入探讨RAG的细节。😊

002:简介

在本节课中,我们将要学习检索增强生成(RAG)的基础概念,了解RAG系统的主要组成部分,并开始构建一个功能性的RAG系统。

模块概览 🗺️

如果你想构建一个强大的RAG系统,你需要从一个蓝图开始。在本模块中,你将学习RAG的基础概念,熟悉RAG系统的主要组件,并开始构建一个功能性的RAG系统。

以下是本模块的学习路线:

首先,你将获得关于RAG的高层次介绍,包括它是什么、为什么需要使用它,以及它如何提升大语言模型生成回答的质量。

接下来,你将更深入地了解RAG系统的架构。RAG将一个大语言模型与一个检索器配对,这个检索器可以帮助大语言模型查找相关信息,并连接到一个包含可信信息的知识库。

你将深入研究每个组件,然后了解它们如何协同工作。

RAG在多种场景下都非常有用,因此你将看到几个生产级RAG系统的示例,并开始思考如何在你自己的基于大语言模型的项目中应用RAG。

在整个模块中,你将动手实践示例代码。在模块结束时,你将完成你的第一个编程作业,实现一个简单RAG系统的部分功能。

在课程后续部分,你将在这个初始系统的基础上进行扩展,添加更复杂的功能,例如一个健壮的检索器、一个向量数据库、更复杂的大语言模型使用方式,以及多种监控和评估技术。

本模块包含许多令人兴奋的主题,它为你在整个课程中的学习设定了路线图。

让我们在下一个视频中开始学习。

003:检索增强生成技术导论

概述

在本节课中,我们将要学习检索增强生成 (RAG) 的核心概念。这是一种通过为大型语言模型提供其训练数据之外的信息,来显著提升其性能的方法。我们将从人类处理问题的类比入手,逐步理解RAG的工作原理、必要性及其基本流程。


从人类思考到机器推理 🧠

人类是出色的思考工具。我们可以回答问题、总结和重写文本、对文档提供反馈、生成代码以及完成许多其他任务。就在几年前,这些任务对计算机来说似乎还遥不可及,而与一个强大的语言模型交互,感觉很像在与另一个人合作。

RAG是一种通过让大型语言模型访问其训练中未知的信息,来进一步提升其性能的方法。

为了阐明这个想法,让我们看几个例子。

假设我问你:“为什么周末酒店价格昂贵?” 你很可能可以回答这个问题。因为周末出行的人更多,所以对房间的需求竞争更激烈。

现在,假设我问你:“为什么温哥华的酒店这个周末超级贵?” 你需要更多信息才能回答这个问题。

如果你在网上搜索,你可能会发现国际巨星泰勒·斯威夫特本周末将在温哥华举办为期两晚的演唱会。有了这个额外信息,你很可能又可以回答这个问题了。

最后,假设我问你:“为什么温哥华市中心附近没有更多的酒店容量?” 要回答这个问题,你可能需要对温哥华的发展历史、城市规划等进行深入研究。换句话说,你需要访问大量专业信息。

你可以将你回答这些问题的方式视为两个阶段。首先,你收集任何必要的信息;然后,你基于这些信息进行推理,形成你的回答。

正如你在第一个问题中看到的,有时你不需要收集任何信息,基于你对世界的了解,你可以立即回答。然而,其他时候,你可能需要收集一点甚至很多信息。

在RAG中,收集有用信息的过程被称为检索。而基于这些信息进行推理和回答的过程被称为生成


大型语言模型为何需要检索?🤖

大型语言模型从检索阶段中受益,原因基本上与你相同。在本课程中,你将了解更多关于LLM的知识。但现在,你可以把它们想象成一个通过阅读互联网上海量信息而拥有广泛常识的人。

当你向LLM提问时,它依赖这些知识来生成回答。对于许多提示,这很有效。但在其他情况下,LLM并不知道准确回答所需的信息。提示可能涉及非常近期的事件,或者它以前从未见过的某些专业信息。正如对你而言一样,期望LLM成为每个主题的专家是不合理的,而当它们能够访问更好的信息时,它们能提供更好的回答。

认识到LLM也能从检索阶段中受益,这就是RAG的核心思想。当然,LLM不是那些花大量时间在维基百科上的人;相反,它们是在从整个开放互联网获取的海量数据集上训练出来的数学模型。

在训练过程中,模型学习训练数据中包含的任何信息。当你向LLM发送提示时,你希望与你的问题相关的信息被包含在训练数据中。不幸的是,很多信息不会被包含在内。公司拥有私有数据库,有些信息是隐藏的或难以访问的,并且新闻每天都在每分钟发布。

总会有一些LLM未训练过的信息存在。那么问题来了:你如何确保LLM知道这些有用的信息?


RAG的核心机制:增强提示 ✨

简单的答案是:直接把它放进提示里。RAG系统的关键思想是,你可以在将提示发送给大型语言模型之前修改它。除了用户的原始问题,你还可以添加有助于LLM回答的信息。

如果你问一个RAG系统:“为什么温哥华的酒店这个周末超级贵?”,它会首先执行一个检索步骤来收集相关信息。然后,语言模型会收到一个增强的提示,其中既包含原始问题,也包含任何检索到的信息。现在,LLM拥有了准确回答所需的信息。

当然,这些信息需要从某个地方检索出来。RAG系统中处理这个过程的组件被称为检索器。检索器管理着一个由可信、相关且可能是私有的信息组成的知识库。

当RAG系统收到一个提示时,检索器会从知识库中找到并检索出最相关的信息,与LLM共享。然后,模型在回答提示时使用这些检索到的信息。

“检索增强生成”这个名字,虽然有点拗口,但现在希望你能更好地理解了。你所做的,就是通过首先从知识库中检索相关信息,来改进或增强LLM生成文本的方式。


总结与展望 📚

本节课中,我们一起学习了检索增强生成 (RAG) 的基本原理。我们了解到,RAG通过引入一个检索阶段,为大型语言模型提供其训练数据之外的最新或专业知识,从而增强生成能力,使其回答更准确、更可靠。其核心流程是:用户提问 -> 检索器从知识库查找相关信息 -> 将原始问题与检索信息结合成增强提示 -> LLM基于增强提示生成最终回答。

这是一个关于RAG如何工作的高层次描述,但有时看一些应用实例会更有帮助。因此,在下一个视频中,我将介绍一些RAG已经在实际中应用的方式。

004:RAG的实际应用 🚀

在本节课中,我们将要学习检索增强生成(RAG)模型在现实世界中的多种应用场景。你将看到,通过将大型语言模型(LLM)与特定知识库结合,RAG能够解决许多传统LLM难以处理的问题。

正如我们所见,RAG的核心思想是将一个现成的大型语言模型(LLM)与一个知识库配对,这个知识库包含了模型在训练时可能无法获取的信息。

许多基于LLM的系统都实现了这种模式,现在让我们来探索其中的几个应用。

代码生成 💻

RAG的一个重要应用是代码生成。

这一点非常重要,因为虽然语言模型已经在大量代码上进行了训练(理论上包括每一个公共Git仓库),但要为特定项目生成正确的代码,需要专业化的信息。

LLM需要知道项目中的类、函数和定义,以及项目所使用的整体编码风格。构建一个以你自己的代码库作为知识库的RAG系统,可以让LLM获取这些信息。

通过从你的代码仓库中检索相关的类、定义和文件,LLM能够更好地生成代码或回答与你的项目相关的问题。

企业定制化聊天机器人 🏢

另一个主要应用是为单个公司定制聊天机器人。每家公司都有自己的产品、政策和沟通准则。

将这些企业文档视为知识库,可以让你以多种有用的方式部署LLM。

以下是两种典型的应用方式:

  • 你可以构建一个客户服务聊天机器人,它了解你公司的产品信息、当前库存或常见的故障排除步骤。
  • 你可以部署一个内部聊天机器人,它能准确回答关于公司政策的问题,或将你引导至有用的文档。

在这两种情况下,知识库都有助于将LLM的回应建立在公司特定的产品或政策基础上,并有助于减少LLM生成通用或误导性回应的情况。

医疗与法律领域 ⚖️

RAG在医疗和法律领域有重要应用。

在这些情况下,知识库可能包含特定案件的法律文件、最近发表的医学期刊文本等等。

在这些领域中,精确性至关重要,且存在大量专业且可能私密的信息,基于RAG的方法可能是部署一个足够准确并能使用私有信息的LLM产品的唯一途径。

AI辅助网络搜索 🔍

另一个主要应用是AI辅助网络搜索。历史上,搜索引擎的工作方式类似于检索器。给定一个搜索查询,它们返回相关的网站。

如今,搜索引擎会提供这些搜索结果的AI摘要,以便以可快速浏览的方式呈现最有用的信息。

这些AI网络摘要基本上就是一个RAG系统,其知识库是整个互联网。

个性化助手 📱

虽然大规模的RAG系统功能强大,但高度个性化的系统也同样如此。

现在,在你的短信、电子邮件客户端、文字处理器、日历等应用中的个性化助手,能够帮助你发送消息、安排日程、起草文档以及完成大大小小的项目。

在每种情况下,LLM对你正在进行的项目了解得越多,它们就越能更好地支持这项工作。

在这些情况下,知识库可能相对较小,例如你的短信、联系人列表、电子邮件或一个文档文件夹。这类文档充满了重要的上下文信息,因此一个能够访问小规模个人信息的RAG系统,可以以一种与你正在做的事情高度相关的方式完成任务。

总结 📝

正如你所看到的,RAG模型在各种各样的情境中都具有适用性。许多公司、组织,甚至是你自己,都拥有可以用来提高LLM生成文本质量的信息集合。

每当你拥有可能未被用于训练大型语言模型的信息时,就存在构建一个有用的RAG应用的潜力。它们甚至可能让LLM在原本不可能使用的场景中得到应用。

随着你继续学习本课程,希望你能开始在你的工作和生活中发现RAG方法可能派上用场的机会。

现在,请和我一起进入下一个视频,让我们更深入地探讨RAG系统的架构。

005:RAG架构概览 🏗️

在本节课中,我们将要学习检索增强生成(RAG)系统的整体架构。我们将了解其核心组件如何协同工作,将一个简单的用户查询转化为一个包含外部知识的、更准确的回答。

标准LLM使用流程

首先,我们来看看通常如何使用一个大语言模型(LLM)。你输入一个提示(prompt)并发送给LLM。LLM处理这个提示并生成一个回复。RAG系统的用户体验与此完全相同:你提交一个提示,然后得到一个回复。

RAG系统内部流程

然而,在系统内部,RAG包含了更多的步骤。当RAG系统收到你的提示时,它首先会将其路由到检索器(retriever)。检索器可以访问知识库(knowledge base),这实际上就是一个包含有用文档的数据库。

检索器查询数据库,返回它认为与提示最相关的文档。

接下来,系统会创建一个增强提示(augmented prompt),将相关文档中的信息整合到原始提示中。例如,一个增强提示可能是:“请回答以下问题:‘为什么温哥华的酒店这个周末这么贵?’以下是五篇可能帮助你回答的相关文章。”然后插入文章中的文本。


此时,系统的运作方式就和其他LLM一样了:增强提示被发送给LLM,LLM生成回复。LLM能够基于其训练数据中学到的知识,以及检索到的文档提供的额外上下文来做出回应。

用户体验始终如一(可能增加了一点延迟):你输入提示,然后得到回复。然而,由于经过了检索器的辅助路径,回答的准确性、时效性和上下文相关性都更高了。

RAG的优势

正如我们所见,直接使用LLM与使用RAG系统的主要区别在于增加了检索器。然而,这个相当直接的添加带来了许多优势。


以下是RAG系统的主要优势:

  • 提供外部信息:最重要的是,它能让LLM访问到原本无法获取的信息。无论是公司政策、个人信息还是今早的头条新闻,RAG通常是让LLM获取某些类型信息的唯一途径。

  • 减少幻觉:与第一点相关,RAG减少了产生幻觉或误导性回答的可能性。这些问题通常是由于LLM对其训练数据中未包含或很少提及的主题生成回答所导致的。在提示中直接添加相关信息,可以锚定(ground) 语言模型的回答,使其不太可能产生通用或误导性的文本。

  • 易于更新信息:RAG让LLM更容易跟上快速变化的信息。重新训练一个语言模型通常成本高昂且耗时,因此LLM难以跟上非常新的信息。然而,在RAG系统中,你可以像更新任何其他数据库中的条目一样,简单地更新知识库中的信息。一旦这些变更被索引,你的LLM就能基于新信息进行回应。

  • 改进引用能力:RAG提高了LLM引用来源的能力。RAG系统可以将引用信息添加到增强提示中,然后LLM就可以在其最终回答中包含这些信息。这不仅锚定了回答,还使人类读者能够深入挖掘并验证生成的文本。

  • 专注文本生成:最后,RAG允许LLM专注于文本生成。检索器从海量信息中筛选,找到最重要和最相关的内容,并简洁地呈现出来。LLM仍然需要写出一个好的回答,但它不再需要承担事实查找或筛选的步骤。换句话说,每个组件都被分配去完成其最擅长的领域。

代码示例演示

在本课程结束时,你将深入学习如何从头构建RAG系统。但这里有一个非常简单的代码演示,展示了RAG的工作原理,其中大部分细节已被抽象化。

假设我们有一个retrieve函数和一个generate函数。retrieve函数是检索器的封装,它接受一个文本查询并从知识库返回相关文档。generate函数是LLM的封装,它接受一个文本提示并返回LLM的回复。

以下是核心流程的伪代码演示:

# 1. 用户原始提问
prompt = “为什么温哥华的酒店这个周末这么贵?”

![](https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-rag/img/ff77f08407187b7ecc2136b4f00a3280_24.png)

# 2. 直接询问LLM(无RAG)
direct_response = generate(prompt)
print(“直接LLM回答:”, direct_response) # 可能不准确或过时

# 3. 使用检索器获取相关信息
retrieved_docs = retrieve(prompt)

# 4. 构建增强提示
augmented_prompt = f”””
请回答以下问题:{prompt}
请使用以下检索到的信息来帮助你回答:
{retrieved_docs}
“””

# 5. 将增强提示发送给LLM
rag_response = generate(augmented_prompt)
print(“RAG回答:”, rag_response) # 更准确,基于最新信息

现在,LLM能够整合从知识库检索到的信息,对问题提供准确的回答。RAG的本质就是向你的提示中添加额外的上下文,以帮助LLM更准确地回应

总结

本节课中,我们一起学习了RAG架构的概览。我们了解到,RAG通过在用户提示和LLM之间插入一个检索步骤,利用外部知识库来增强LLM的回答能力。这带来了提供外部信息、减少幻觉、易于更新、改进引用和让LLM专注生成等关键优势。RAG的核心思想可以概括为:最终回答 = LLM(用户问题 + 检索到的相关文档)

这无疑是对RAG架构一个非常高层次的概述。在下一个视频中,我们将开始更详细地研究每个组件。

006:大语言模型导论 🧠

在本节课中,我们将要学习大语言模型(LLM)的基本工作原理。理解LLM如何运作、它们的优势与局限,将帮助我们解释RAG系统中其他组件是如何设计来提升LLM性能的。

上一节我们介绍了RAG系统的整体架构,本节中我们将深入探讨其核心组件之一——大语言模型。

大语言模型如何工作

大语言模型有时被戏称为“花哨的自动补全工具”。这个描述实际上很贴切。LLM所做的全部工作,就是预测一段文本中应该出现的下一个词。

例如,如果给你一个不完整的短语:“多么美好的一天,太阳正在……”,你和我都能猜出哪个词应该完成这个句子。LLM也能做到。最合理的词可能是“照耀”,但“升起”或“出来”也可能成立。原始短语被称为提示词,而每个最终完成的短语被称为补全

LLM本质上使用一个神经网络,这是一个庞大而复杂的语言数学模型。该模型存储了关于哪些词通常一起使用、它们通常以何种顺序出现的信息,并在更高层次上捕捉这些词在上下文中的含义。这个语言的数学表示,就是模型最终用来生成新文本的工具。

以下是LLM生成文本的核心过程:

  1. 分词:LLM不直接生成单词,而是生成令牌,这是单词片段的更通用术语。例如,“London”和“Door”可能有自己的令牌,但常见的复合词如“programmatically”通常被拆分为多个令牌。标点符号如句号、逗号也可能有自己的令牌。
  2. 逐词生成:当LLM生成补全时,它所做的就是一次一个词地向提示词末尾添加新词。
  3. 概率计算:在添加每个新令牌之前,LLM会处理当前补全的状态,然后遍历其词汇表中的每个令牌(通常是数万到数十万个),计算每个令牌应该出现在下一个位置的概率。
  4. 随机选择:LLM根据这个概率分布随机选择下一个令牌。例如,100次中有80次可能选择“照耀”,但仍有可能选择“升起”,甚至“爆炸”。
  5. 自回归过程:当LLM要为补全添加另一个令牌时,它会重复整个过程。这意味着LLM在补全早期所做的令牌选择,将影响其后续的选择。这种行为被称为自回归,即自我影响。

大语言模型的训练与能力

LLM能够理解提示词的含义并做出合理的词预测,是因为它已经在大量文本集合上进行了训练。

驱动LLM的数学模型有数十亿个独立的参数或数值权重。在训练之前,这个模型只会产生乱码。在训练期间,LLM会看到来自训练数据的不完整文本片段,并尝试预测下一个词是什么。根据这些预测的准确性,它会更新其内部参数。通过这种方式,模型学会了复现训练数据中的事实信息和语言风格。

如今许多大语言模型都在数万亿令牌的文本上进行训练,这些文本主要来自开放的互联网。由此产生的模型能够生成各种风格、涉及各种主题的文本,因为这些风格和主题的信息都包含在其训练数据中。

大语言模型的局限性与幻觉

理解LLM的工作原理和训练方式,也解释了它们的许多行为。让我们从幻觉开始。

LLM所能做的,只是根据其在训练数据中学到的模式,生成可能的词序列。如果你向LLM询问你公司的私有内部数据或今日新闻,模型几乎肯定没有在这些信息上训练过,因此无法很好地回应。在这些情况下,LLM有时会给出听起来正确但实际上不真实的回答。

尽管这种行为被称为“幻觉”,但重要的是要记住,LLM并非出现了心理问题,甚至并非真正故障。LLM的设计目标是生成可能的文本,而非真实的文本。对于LLM而言,“真实”仅仅意味着一个词序列根据其训练数据是概率上可能的。通过高质量的训练数据,我们直觉理解的“真实”与LLM数学上理解的“可能词序列”可以保持一致。

RAG如何利用LLM的优势

那么,挑战在于确保LLM能够访问尽可能多的相关信息。RAG通过利用LLM善于理解上下文的能力来解决这个问题。

如果你的RAG系统将相关信息添加到提示词中,LLM就能够理解这些信息并将其纳入其回答中,即使这些信息不是其训练数据的一部分。通常,你会说这些信息锚定了LLM的回答。

然而,在实践中,你无法简单地将所有能找到的相关信息都添加到提示词中。原因如下:

  • 计算成本:更长的提示词需要更多的计算来运行。因为在生成每个新令牌之前,模型需要对补全中已有的每个令牌(包括原始提示词)执行计算复杂的扫描。
  • 上下文窗口限制:最终你会达到LLM上下文窗口的极限,即其一次能处理的最长序列。一些旧模型只有几千个令牌的上下文窗口,而较新的模型可以处理数百万个。这意味着,随着检索器向增强提示词中添加更多信息,起初你只会使提示词成本更高,最终你将完全耗尽模型的上下文窗口。

本课程使用的模型

市面上有各种各样的LLM提供商,但在本课程中,你将使用Together AI,它托管了许多流行的开源模型。使用开源模型可以更容易地深入了解大语言模型的内部机制,并探索你在整个课程中学到的许多概念。

关于LLM还有很多需要学习,但现阶段的主要结论是:LLM的设计允许它将提示词中的信息纳入其回答,即使这些信息并未包含在训练数据中。

本节课中我们一起学习了大型语言模型的基本工作原理、其自回归的文本生成方式、训练过程、以及产生“幻觉”的根源。最重要的是,我们理解了LLM能够利用提示词中的新信息来生成回答,这正是RAG系统得以构建的基础。

接下来,让我们将注意力转向检索器,看看它是如何运作以提供这些信息的。

007:信息检索技术导论 📚

在本节课中,我们将要学习检索增强生成 (RAG) 系统中检索器的核心工作原理。我们将通过一个图书馆的比喻来理解其各个组件,并探讨检索器如何从知识库中找到最相关的信息提供给大语言模型。

检索器的目的与类比

上一节我们介绍了RAG系统的整体架构,本节中我们来看看其中的关键组件——检索器。检索器的目的很明确:它需要向大语言模型提供在模型训练时可能无法获取的有用信息。

现在,让我们通过一个类比来理解检索器是如何工作的。想象一下,你为了回答“如何在家制作纽约风格披萨?”这个问题而去图书馆查找资料。

这个图书馆拥有一个包含许多主题书籍的大型馆藏。为了帮助你浏览,书籍会根据其主题、体裁、作者等特征被分类整理在不同的区域和书架上。如果你向图书管理员提出你的问题,他们可以帮助你找到图书馆中最相关的区域,甚至是具体的书籍。

检索器的核心组件

检索器包含许多类似的组件。图书馆有馆藏书籍,而检索器则拥有一个由文档组成的知识库。检索器会为知识库中的文档创建一个索引,这类似于图书馆的分类系统,用于组织文档并使其易于搜索。

接下来的步骤是实际检索相关信息。在图书馆,你可以直接询问图书管理员。图书管理员能够理解你问题的含义,并知道去查找关于烹饪、意大利菜或纽约的相关区域。这种理解问题含义的能力使他们能够确定需要搜索的正确书架,并最终找到相关的书籍。

在RAG系统中,检索器执行类似的任务。它首先需要处理用户的提示,以理解其潜在含义。

# 伪代码:检索器处理提示
processed_prompt = understand_prompt(user_prompt)

然后,它利用这种理解去搜索文档索引。

文档检索与排名

检索器会从知识库中返回它认为与提示最相关的文档。在完成搜索时,检索器会根据文档与提示的相关性对它们进行排名。

每个文档都会获得一个量化的相关性数值分数。通常,这意味着提示文本与文档文本之间某种相似性的度量。分数最高的文档将被返回。

有多种方法可以计算这些相似性分数,你将在课程后续部分了解更多。

一个设计良好的检索器当然应该返回相关文档,但它也需要过滤掉不相关的文档。如果你询问如何在家制作纽约风格披萨,而检索器返回了知识库中的所有文档,从技术上讲你确实拥有了每一个相关文档,但它们会被淹没在大量无关信息的海洋中。正如之前所见,这还会导致提示成本高昂,甚至完全耗尽大语言模型的上下文窗口。

另一方面,如果只检索知识库中排名最高的文档,你可能会错过排名第二、第三或第四的文档中包含的宝贵相关信息。

在理想情况下,检索器能完美地对文档进行排名,并选择恰好正确数量的文档返回。然而在实践中,检索器有时会将某些相关文档排名过低,而将某些不相关文档排名过高,这使得难以自信地决定返回多少文档。

为了优化检索器的性能,你需要长期监控它,并尝试不同的设置,这在本课程中你会广泛接触到。

相关技术与实现基础

值得注意的是,许多我们熟悉的软件都执行着与检索器非常相似的任务。网络搜索引擎检索与网络搜索相关的网页,而关系型数据库则检索与SQL查询匹配的行和表。

当大语言模型首次被开发时,信息检索这一更广泛的领域已经相当成熟。该领域的理念构成了检索器和RAG系统设计方式的基础。

理论上,在RAG系统中有很多方法可以实现检索器。由于大多数公司已经将数据存储在传统的关系型数据库中,如果能将数据保留在那里,并找到一种从该数据库检索信息来驱动RAG系统的方法,那将非常理想。

然而,在大规模应用中,虽然并非严格必需,但大多数检索器都将构建在向量数据库之上。这是一种专门类型的数据库,针对快速查找知识库中与提示最匹配的文档进行了优化。

在本课程中,你将学习支撑多种搜索技术的信息检索通用原理,以及通常在生产级RAG系统中用作检索器的向量数据库。

关于检索器还有很多需要学习的内容,但目前我们已经涵盖了最重要的几点。在下一节视频中,我们将一起总结本模块的内容。

总结

本节课中我们一起学习了RAG系统中检索器的核心机制。我们通过图书馆的比喻理解了其知识库、索引和检索过程,知道了检索器如何通过计算相似性分数来对文档进行排名和筛选。我们还了解到信息检索领域的成熟理念是RAG的基础,并且在实际应用中,向量数据库常被用作高效的检索器实现。理解这些原理是构建有效RAG系统的关键一步。

008:总结 🎯

在本节课中,我们将对检索增强生成(RAG)的核心概念进行总结,并概述后续课程的学习路径。

通过前面的介绍,检索增强生成技术应该已经显得更加易于理解了。它的目标是通过让大语言模型(LLM)能够访问其在训练时可能没有接触过的信息,从而使它们变得更加有用和准确。

为了实现这一目标,大语言模型需要与一个称为知识库的数据集合配对使用。这些数据可能是私有的、近期的,或者仅仅是高度专业化的,因此没有被包含在通用大语言模型的训练数据中。

RAG 系统的工作流程

上一节我们介绍了RAG的目标和知识库的概念,本节中我们来看看其核心的工作流程。

当用户提交提示词时,系统首先会将它们路由到检索器

检索器会在知识库中搜索相关的文档,并将这些文档中的文本内容添加到用户的原始提示词中。

随后,大语言模型能够将这些从提示词中获取的额外信息整合到它生成的回复中。检索到的信息为最终的回答提供了依据,使其更加准确和相关。

后续学习路径

当然,以上只是一个非常高层次的描述。因此,在本课程的剩余部分,我们将深入探讨RAG系统的每一个组成部分。

以下是您将学习到的核心内容:

  • 组件原理:您将了解每个组件(如检索器、知识库、生成器)的实际工作原理。
  • 优化技术:您将学习多种用于优化系统性能的技术。
  • 实践考量:您将了解在根据您的具体项目和数据进行系统调优时需要考虑的重要因素。

本节课中我们一起学习了RAG的基本概念、目标及其核心工作流程。这是一个强大的框架,旨在扩展大语言模型的能力。接下来,请加入下一个模块,让我们正式开始深入探索RAG的旅程。🚀

009:检索器简介 🎯

在本模块中,我们将要学习检索增强生成(RAG)系统中检索器的核心工作原理。检索器是RAG系统的关键组件,负责从知识库中快速、准确地找到与用户查询最相关的文档,以供大语言模型(LLM)参考并生成回答。

检索器的任务与挑战

检索器的工作目标很容易描述。它需要做的就是在知识库中找到能够帮助大语言模型(LLM)响应用户提示(prompt)的文档。

然而,仔细想想,这是一项相当困难的工作。

用户并非向你的RAG系统提交结构良好的SQL查询。他们是以与人交谈的方式在与你的LLM聊天。与此同时,你的知识库中的文档可能五花八门,从个人电子邮件到公司内部备忘录,再到医学期刊文章。

这些文档可能信息丰富,但其结构通常是为了方便人类阅读,而非便于计算机搜索。检索器必须以某种方式处理所有这些结构混乱的信息,并在几分之一秒内快速返回最相关的片段。

本模块学习内容

上一节我们了解了检索器任务的复杂性,本节中我们来看看我们将要学习哪些技术来应对这些挑战。

在本模块中,你将学习检索器用于完成这一壮举的主要技术。你将建立对每种技术工作原理的理论理解,探索它们的相对优势和劣势,并了解检索器如何组合使用它们以提供最佳结果。

以下是本模块将涵盖的核心内容:

  • 检索技术:学习向量搜索、关键词匹配等核心检索方法。
  • 组合策略:了解如何结合不同技术以提升检索效果。
  • 性能评估:学习评估检索器性能的策略和指标。

你还将被介绍一些评估检索器性能的策略。并且和往常一样,你将找到一些动手编码练习和一个编程作业,在那里你可以直接应用所学知识。

我相信你会享受这次关于信息检索的深入探讨,所以请在下一个视频中加入我,让我们开始吧。

总结

本节课中我们一起学习了RAG系统中检索器的基本职责及其面临的主要挑战——即处理非结构化的用户查询和多样化的知识库文档,并实现快速精准的检索。我们也预览了本模块将深入探讨的检索技术、组合策略以及性能评估方法,为后续的动手实践打下基础。

010:检索器架构综述 🧠

在本节课中,我们将要学习检索增强生成系统中检索器的整体架构。我们将了解当系统收到用户提示时,检索器如何协同使用多种搜索技术,从知识库中快速找到最相关的文档。


当RAG系统收到您的提示时,它首先会被发送给检索器。检索器可以访问知识库,您可以将知识库想象为存储在数据库中的一堆文本文件。

检索器的任务是快速决定哪些文档与提示最相关,并返回它们,以便传递给大语言模型。

大多数现代检索器在此过程中会使用两种不同的搜索技术。

以下是两种核心搜索技术:

  1. 关键词搜索:这是一种更传统的搜索方式。这意味着检索器会查找包含提示中确切词汇的文档。这种方法久经考验,为信息检索系统提供了数十年的支持。
  2. 语义搜索:这意味着检索器会查找与提示含义相似的文档。这种方法使检索器更加灵活,因为它允许系统找到与提示相关,但可能不包含用户提示中确切词汇的文档。

每种搜索技术都会返回一组文档,可能各自返回20到50个。通常,会有许多文档同时出现在两个列表中,但由于搜索方式不同,同一文档在两个列表中的排名可能不同。

此时,每个列表都会根据其元数据进行过滤。例如,您的知识库中的某些文档可能与工程团队成员相关,而另一些则与人力资源部门的人员更相关。系统会知道用户属于哪个团队,并在此刻应用元数据过滤器,以确保只有与该部门相关的文档才能进入下一阶段。

现在,检索器得到了两个经过过滤的列表:一个由关键词搜索生成,另一个由语义搜索生成。

这两个列表现在被合并,以创建最相关文档的最终排名。检索器从这个最终列表中返回排名最高的文档。至此,检索过程完成。这些文档将被发送出去,添加到增强提示中。

这种搜索风格被称为混合搜索,因为它依赖多种技术来生成最终的文档排名。

每种技术都提供了有助于提升检索器整体性能的优势:

  • 关键词搜索确保系统对用户提示中包含的确切词汇敏感。
  • 语义搜索赋予系统更大的灵活性,以找到含义与提示相似的文档,即使它们没有使用相同的词汇。
  • 元数据过滤允许系统根据严格的标准排除文档,这是其他两种方法都无法做到的。

设计一个高性能的检索器意味着理解每种技术的相对优势,然后调整它们之间的平衡,以符合您项目的需求。


上一节我们介绍了检索器的整体架构和混合搜索的概念,本节中我们来看看构成混合搜索的三种技术之一:元数据过滤。


本节课中我们一起学习了检索器的核心架构。我们了解到,一个高效的检索器通常结合了关键词搜索语义搜索元数据过滤这三种技术,通过混合搜索策略来确保返回的文档既精确又全面。理解这些组件如何协同工作是优化RAG系统性能的第一步。

011:元数据过滤技术 📁

在本节课中,我们将要学习元数据过滤技术。这是一种在检索器中最直接、也最可能最熟悉的技术。我们将了解它的工作原理、优势以及局限性。

概述

元数据过滤使用刚性标准来缩小检索器返回的文档范围,其依据是文档的元数据。元数据可能包括文档标题、作者、创建日期、访问权限等信息。

元数据过滤的工作原理

元数据过滤的核心是依据预设的、非此即彼的条件来筛选文档。以下是其工作原理的一个简单示例。

假设您在一家报社工作,希望为报社历史上发表过的所有文章构建一个检索器。知识库将包含数千篇不同的文章。每篇文章都附有多个元数据标签,包括其标题、发布日期、作者、文章所属的报纸版面等。

虽然每篇文章的全文都存储在知识库中,但系统只能基于这些元数据进行搜索。查询这类索引很像编写一个SQL查询语句。

以下是几种过滤方式:

  • 单一条件过滤:您可以找到在特定日期发布的每一篇文章,或者由特定作者撰写的每一篇文章。
  • 多条件组合过滤:您可以编写更复杂的查询,基于多个元数据进行过滤。例如,您可以找到您最喜欢的记者在2024年6月至7月期间为“观点”版面撰写的所有文章。

只有满足所有条件的文章才会被返回,其余文章则会被过滤掉。如果您曾经在电子表格中筛选过表格,那么您已经做过元数据过滤了。您只是使用一套严格的标准来决定要使用大数据集中的哪些成员。

在RAG系统中的实际应用

在一个典型的RAG系统中,您不会单独使用元数据过滤来执行检索,而是用它来帮助缩小其他检索技术返回的结果范围。

这些过滤器本身通常也不是由用户在提示词中说了什么决定的,而是由发出请求的用户的其他属性决定的。

以下是两个应用示例:

  • 访问权限控制:沿用之前的报纸例子,假设您的一些文章免费发布在公开互联网上,而另一些文章只有付费订阅者才能访问。每篇文章可以有一个元数据字段来存储它是免费还是付费文章。当用户搜索数据库时,系统可以检测他们是否以付费订阅者身份登录。如果没有,则会设置一个元数据过滤器,将付费文章排除在搜索结果之外。
  • 区域内容分发:如果您的报纸在世界许多地区发布文章,每篇文章可以有一个元数据字段来存储文章发布的地区。当读者查询系统时,您可以检测他们所在的地区,并只返回来自他们所在地区的文章。

元数据过滤的优势与局限

上一节我们介绍了元数据过滤的基本应用,本节中我们来看看它的优缺点。

元数据过滤具有以下优势:

  1. 概念简单:易于理解系统工作原理和调试问题。
  2. 快速成熟:这是一种快速、成熟且经过良好优化的方法。
  3. 刚性控制:最重要的是,它是唯一一种允许您的系统基于刚性标准决定是否检索文档的方法。如果您想严格定义哪些类型的文档应该或不应该被包含在检索中,元数据过滤是唯一能提供这种行为的方法。

然而,元数据过滤也有显著的局限性:

它并非真正的搜索技术,而更像是一种用于优化本模块中您将看到的另外两种技术结果的工具。它过于僵化,忽略了文档的内容,并且一旦文档通过过滤器,就缺乏任何对文档进行排序的方法。

虽然您构建的RAG系统很可能包含某种形式的元数据过滤器,但构建一个完全依赖元数据过滤的检索器基本上是无效的。元数据过滤简单有效,但需要与其他搜索技术配对使用才能提供真正的价值。

总结

本节课中我们一起学习了元数据过滤技术。我们了解到它是一种基于文档元数据(如标题、作者、日期等)的刚性筛选方法,主要用于控制访问权限或内容分发等场景。它的优点是简单、快速且能实现精确控制,但缺点是无法理解文档内容,且过于僵化。因此,它通常作为辅助工具,与其他能理解语义的检索技术结合使用。

特别地,您需要一种方法来确定文档的内容是否真的与您的提示词相关。所以,请加入下一节视频,看看关键词搜索如何满足其中的一些需求。🔍

012:关键词搜索与TF-IDF算法 🔍

在本节课中,我们将要学习关键词搜索技术,这是一种在数据库和搜索引擎中应用了数十年的检索方法。其简洁性和有效性使其成为现代RAG系统中检索流程的关键组成部分。我们将探讨其工作原理以及它为检索器管道带来的优势。

概述

关键词搜索是一种根据文档是否与提示词共享共同词汇来进行检索的技术。其基本思想是,包含大量提示词词汇的文档更可能是相关的。

上一节我们介绍了检索增强生成的基本概念,本节中我们来看看最基础的检索方法之一:关键词搜索。

关键词搜索的工作原理

关键词搜索将提示词和每个文档都视为一个“词袋”。这意味着词汇的顺序被完全忽略,唯一重要的是文本中包含哪些词以及它们出现的频率。

例如,文本 “making pizza without a pizza oven” 包含单词 “pizza” 两次,以及单词 “making”、“without”、“a” 和 “oven” 各一次。

这些词频计数被存储在一个向量中。

构建稀疏向量与倒排索引

该向量为系统词汇表中的每个单词预留一个位置,因此可能包含数万个位置。向量中的每个数字记录了该单词在文本中出现的次数。由于大多数位置的值都是零,这种向量也被称为稀疏向量

为了准备用于检索的知识库,需要为每个文档生成一个稀疏向量。

所有这些向量可以排列在一个网格中,这被称为词项-文档矩阵。每一列代表一个不同的文档,每一行代表一个不同的单词。

这有时也被称为倒排索引。因为它使得从某个单词出发,查找包含该单词的所有文档变得容易。之所以称为“倒排”,是因为通常我们是从文档出发,思考它包含哪些词,而这里是从单词出发,查找包含该单词的文档。

这个倒排索引可以在处理任何搜索之前一次性创建完成。

文档评分与排名

当提示词发送给检索器时,会快速为其生成一个稀疏向量。现在,每个文档和提示词都有了稀疏向量,就可以开始对文档进行评分和排名了。

最简单的方法是,当文档包含提示词中的单词时,就给文档加分。提示词中的每个单词被称为一个关键词

以下是评分的基本步骤:

  1. 从提示词的第一个关键词开始,在索引中找到其对应的行。
  2. 遍历该行,为每个至少包含一个该关键词的文档加一分。
  3. 对提示词中的其他每个关键词重复此过程。

如果文档包含关键词,它就得分。提示词包含五个关键词,最高可能得分是5。完成后,总分可用于对文档进行排名,得分最高的文档将被检索出来。

改进评分方法:考虑词频

简单评分方法的一个缺点是,它没有捕捉到文档是否多次包含关键词,而多次出现可能表明相关性更高。

一个简单的改进方法是,每次文档包含关键词时都增加其分数,而不仅仅是第一次。现在,你可以找到矩阵中每个关键词所在的行,并直接给予每个文档其在该行对应列中的数值作为分数。

然而,这引入了一个新问题:较长的文档可能仅仅因为篇幅长而多次包含关键词。

为了纠正这一点,可以将每个文档的分数除以其总词数。这种归一化的分数使竞争环境更加公平。它奖励那些关键词在总文本中占比较高的文档,并降低那些仅仅因为篇幅长而多次包含关键词的长文档的权重。

引入逆文档频率 (IDF)

上述方法相当不错,但它对所有关键词都给予相同的权重,无论是像 “the” 这样的填充词,还是像 “pizza” 这样不太常见的词,而后者的出现更能表明相关性。

为了纠正这一点,可以再次对词项进行加权,但这次使用一种称为逆文档频率 的度量方法。

要使用这种方法,需要为系统词汇表中的每个单词计算一个IDF值。

对于每个单词,你需要计算它出现在多少个文档中,然后除以文档总数。如果你的知识库有100个文档,单词 “pizza” 出现在其中5个里,那么它的文档频率就是 5/100 或 0.05。像 “the” 这样的常见词可能出现在所有100个文档中,因此其文档频率为 100/100 或 1。

由于你想要奖励稀有词汇,现在需要将这个分数倒置(取倒数)。此时,“pizza” 的IDF将是20,而 “the” 的IDF仅为1。此时,稀有词的IDF值显著高于常见词,这可能会过度奖励稀有词。因此,通常使用IDF的对数值。稀有词仍然有更高的权重,但不像之前那么夸张。

最终,每个单词都会得到一个IDF值,它反映了该词在整个知识库中的稀有程度。

TF-IDF矩阵与最终评分

为了在评分中使用这些值,首先需要更新倒排索引中的数值,将每一行的数字乘以该单词的IDF分数。得到的矩阵称为词频-逆文档频率矩阵,即 TF-IDF矩阵

为了对知识库中的文档进行评分,只需使用与之前相同的方法:对于提示词中的每个关键词,遍历其所在的行,并给予每个文档该行中对应的TF-IDF分数。

这种方法产生的TF-IDF分数是衡量关键词检索性能的标准基线。得分最高的文档通常会频繁使用关键词,特别是那些在整个知识库中都很少见的关键词。

回顾之前的提示词,包含像 “pizza” 或 “oven” 这样的稀有词的文档,其得分很可能远高于仅包含像 “a” 或 “without” 这样常见词的文档。

总结与展望

本节课中我们一起学习了关键词搜索的基础——TF-IDF算法。这是一种通过统计词频和逆文档频率来评估文档与查询相关性的经典方法。它简单有效,是许多检索系统的基石。

虽然TF-IDF是关键词搜索的基础方法,但现代系统倾向于使用一个略微改进的版本,称为BM25。

在下一个视频中,我们将一起学习BM25是如何工作的,并反思关键词搜索的优势以及它如何融入你的RAG系统。

013:BM25算法 🧮

在本节课中,我们将要学习关键词搜索领域的一个重要算法——BM25。我们将了解它如何改进经典的TF-IDF算法,其核心公式是什么,以及它在实际检索系统中的优势和应用。

概述

上一节我们介绍了TF-IDF这一经典的关键词搜索算法。本节中我们来看看其更先进的继任者——BM25算法。BM25在TF-IDF的基础上进行了关键改进,使其成为现代生产级检索系统中事实上的标准关键词搜索算法。

BM25算法介绍

虽然TF-IDF仍然是经典的关键词搜索算法,但大多数检索系统中使用的算法被称为“最佳匹配25”,或简称为BM25。它之所以被这样命名,是因为它是其创建者提出的一系列评分函数中的第25个变体。它对TF-IDF做了一些改进,下面我们来探讨这些改进是如何工作的。

以下是BM25的公式。它实际上与TF-IDF的工作原理非常相似,只是增加了一些关键部分,您马上就会看到。

score(D, Q) = \sum_{i=1}^{n} IDF(q_i) \cdot \frac{f(q_i, D) \cdot (k_1 + 1)}{f(q_i, D) + k_1 \cdot (1 - b + b \cdot \frac{|D|}{avgdl})}

这个公式为特定文档中的单个关键词生成一个相关性分数。将所有关键词的这些分数相加,就得到了单个文档的总相关性分数,然后可以用于排序。

BM25的改进之处

现在让我们看看BM25是如何改进TF-IDF的。

以下是BM25相较于TF-IDF的两个主要改进点:

  1. 词频饱和:随着文档包含更多关键词实例,其得分会呈现收益递减。这里的理念是,一个包含“pizza”这个词20次的文档,其相关性实际上并不是包含10次“pizza”的文档的两倍。这种对关键词额外实例进行折扣的行为被称为“词频饱和”。

  2. 文档长度归一化:较长的文档仍然会受到惩罚,就像在TF-IDF中一样。但在BM25中,这些惩罚也是递减的。虽然惩罚长文档很重要,但TF-IDF有时惩罚得过于激进,以至于过度折扣了较长的文档。BM25随着文档长度的增加,会施加递减的额外惩罚。结果是,只要长文档具有相当高的关键词频率,它们仍然可以获得高分。这种根据文档长度调整分数的过程被称为“文档长度归一化”。

BM25的可调参数

BM25与TF-IDF的另一个不同之处在于,它包含了两个可调的超参数。这些参数允许您控制词频饱和和文档长度归一化的程度。换句话说,您可以控制文档因重复关键词而停止获得奖励的速度,以及因长度增加而受到惩罚的速度。在生产级检索器中,您需要调整这些超参数,以形成一个最适合您知识库数据的整体评分系统。

在生产级检索器中,标准的关键词搜索算法是BM25。

BM25的优势

它在寻找相关文档方面的表现通常显著优于TF-IDF,所需的计算资源大致相当,并且能够根据您的数据集调整其超参数,这使其灵活性大大提高。

让我们简要回顾一下关键词搜索,并讨论其优势如何在典型的检索器管道中使用。


关键词搜索的核心思想与BM25的地位

关键词搜索的核心思想是,根据提示中的关键词在每个文档中出现的频率来匹配文档与提示。作为这个过程的一部分,提示和文档都被转换为稀疏向量,用于统计系统词汇表中的每个单词在该文本片段中出现的频率。TF-IDF或BM25只是处理这些稀疏向量以对文档进行评分和排序的不同方法。这些方法还考虑了重要因素,如关键词的稀有度、文档包含关键词的频率以及文档长度。

BM25是最常用的关键词搜索算法,自发明以来经受住了数十年的时间考验。它在实际应用的复杂性和性能之间取得了良好的平衡。

关键词搜索的优势

关键词搜索的主要优势在于其简单性。它是一种相对直接的方法,在实践中效果良好,通常能够独立表现良好,并经常设定一个具有竞争力的基准,更先进的技术可能难以超越。它还确保检索到的文档将包含用户提示中的关键词,尤其是在您期望用户使用技术术语或确切产品名称的情况下。这种精确的关键词匹配尤为重要。

关键词搜索的局限性与过渡

尽管具有所有优势,关键词搜索确实存在弱点。它最终依赖于查询中包含与文档中单词完全匹配的关键词。如果用户发送的提示与某个文档含义相似,但只是没有包含正确的单词,关键词搜索将无法找到该匹配项。

因此,让我们来看看语义搜索,以及它如何解决这个问题。

总结

本节课中我们一起学习了BM25算法。我们了解到BM25是TF-IDF的改进版本,通过引入词频饱和文档长度归一化机制,更合理地评估文档相关性。其公式包含可调超参数,使其能灵活适应不同数据集。BM25因其在效果、效率和灵活性上的良好平衡,成为生产环境中关键词搜索的标准算法。然而,它仍依赖于精确的关键词匹配,这引出了对能够理解语义的搜索方法的需求。

014:语义搜索技术入门 🧠

在本节课中,我们将要学习语义搜索技术。与基于关键词匹配的传统搜索不同,语义搜索能够根据文本的共享含义来匹配文档与提示,从而捕捉到关键词搜索可能遗漏的细微差别。

语义搜索的基本原理

上一节我们介绍了关键词搜索的局限性。本节中我们来看看语义搜索是如何工作的。

从高层次来看,语义搜索的工作流程与关键词搜索类似。每个文档都被映射为一个向量,提示词也是如此。然后通过比较提示向量和文档向量来生成分数,并找到与提示最匹配的文档。

主要区别在于为每个文档和提示分配向量的方式。

  • 关键词搜索中,你只需统计每个单词在文本中出现的频率。
  • 语义搜索中,你需要通过一个称为嵌入模型的特殊数学模型来处理文档或提示,从而生成向量。

嵌入模型如何工作

嵌入模型将单词映射到空间中的一个位置。这个位置由一个向量表示。

例如,嵌入模型可能将单词 pizza 映射到二维空间中的向量 [3, 1],将单词 bear 映射到向量 [5, 2]。在二维空间中,这些向量可以表示为 X-Y 轴上的点。

嵌入模型的核心在于,它会将语义相似的单词映射到空间中相近的位置

例如,单词 foodcuisine 的嵌入位置会彼此靠近,而单词 trombonecat 的嵌入位置则会相距较远。相似的含义导致相似的位置。

这里的 X 轴和 Y 轴并没有简单的解释(例如,没有“食物轴”或“动物轴”),至少不容易看出来。你应该将这些点想象成漂浮在二维平面上,含义相似的单词会聚集在一起。

从单词到文本

由于单词之间存在许多复杂的关系,仅用两个维度可能无法形成有意义的聚类。如果向量有三个分量,你可以想象将它们嵌入到三维空间中。这样,相关概念就有更多空间形成聚类,并捕捉它们之间微妙的关系。

然而,在大多数嵌入模型中,这些向量拥有数百甚至数千个分量,为每个点的嵌入位置提供了极大的灵活性。我们无法绘制甚至想象这个高维空间,但从数学上讲,所有相同的原理都成立:向量给出了该空间中位置的坐标,相似的概念被嵌入得彼此靠近,不同的概念则被嵌入得相距较远。

尽管前面的例子聚焦于单个单词,但嵌入模型可以处理多种输入数据。以下是几种常见的嵌入模型:

  • 针对单个单词的嵌入模型。
  • 针对句子的嵌入模型。
  • 针对整个文档的嵌入模型。

这些模型接受不同类型的输入,但在每种情况下,都会输出一个指定空间中位置的单一向量。与单个单词一样,如果向量彼此靠近,那么这些文本片段就具有相似的含义。

考虑以下三个句子:

  1. He spoke softly in class.
  2. He whispered quietly during class.
  3. Her daughter brightened the gloomy day.

当投影到向量空间时,前两个句子的向量会更接近,而第三个句子的向量会远离前两个。

量化文本相似度

为了量化不同文本片段的相似度,你可以测量它们向量之间的距离。有几种方法可以实现。

例如,欧几里得距离(你可能在几何课上学过)通过绘制从一个向量到另一个向量的直线来测量两个向量之间的距离,即它们之间的最短可能距离。计算这个距离的公式本质上是勾股定理,但扩展到更多维度。然而,在非常高维的空间中,每个点往往都与其他点相距甚远。

一种更常用的距离度量是余弦相似度,它测量两个向量在方向上的相似性,而不管它们在空间中是否彼此靠近。向量 [10, 10][100, 100] 在位置上并不接近,但它们指向相同的方向。

余弦相似度的范围从 1(向量方向完全相同)到 -1(向量方向完全相反)。

你偶尔也会看到点积,它测量一个向量在另一个向量上投影的长度。如果两个向量在长度和方向上相似,投影长度就较大;如果它们成 90 度角,投影长度为 0;如果它们方向相反,点积将为负值。

如果数学不是你的强项,不用担心。你可能永远不需要自己实现这些距离度量,但了解它们的工作原理是有帮助的。例如,对于点积和余弦相似度,更高的值都反映了向量更接近,这最终反映了概念更相似。余弦相似度范围在 -1 到 1 之间,而点积可以在负无穷到正无穷之间取任何值。

语义搜索的完整流程

了解了距离度量后,让我们看看如何利用它来实现语义搜索。

首先,所有文档都通过嵌入模型投影到向量空间中。得益于嵌入模型的设计,含义相似的文档会彼此靠近,含义不同的文档会彼此远离。

接下来,你对提示词进行嵌入,得到它自己的向量。

现在,你可以测量提示向量与每个文档向量之间的距离。同样得益于嵌入模型的设计,距离最近的文档也将具有最相似的含义。

此时,对文档进行排序就很简单了。你只需按照文档与提示向量的距离进行排序,并返回距离最短的文档。由于嵌入模型的工作原理,你刚刚找到了与你的提示含义最相似的文档。

总结

本节课中我们一起学习了语义搜索技术。语义搜索的核心在于使用嵌入模型将文本转换为高维空间中的向量,并通过计算向量间的距离(如余弦相似度)来量化文本的语义相似性,从而找到与查询意图最匹配的文档,克服了传统关键词搜索的局限。理解嵌入模型如何将相似概念映射到邻近位置,是掌握语义搜索的关键。

015:语义搜索嵌入模型深度解析 🧠

在本节课中,我们将要学习嵌入模型的工作原理。嵌入模型是语义搜索和RAG系统的核心,它能够将文本转换为向量,并让含义相似的文本在向量空间中彼此靠近。

概述

嵌入模型的任务描述起来相当简单。它需要将相似的文本嵌入到彼此接近的向量中,并将不相似的文本嵌入到彼此远离的向量中。如果你试图想象嵌入模型是如何做到这一点的,你就会意识到它们需要多么复杂。计算机怎么可能理解一段文本的含义呢?让我们更深入地看看嵌入模型是如何实现这一惊人壮举的。

嵌入模型的任务:正负样本对

你可以从正样本对和负样本对的角度来理解嵌入模型的工作。一个正样本对是两段相似的文本,例如“good morning”和“hello”,它们应该被嵌入到彼此接近的位置。

一个负样本对,例如“good morning”和“that's a noisy trombone”,具有不同的含义,应该被嵌入到彼此远离的位置。嵌入模型需要工作,使得正样本对最终更接近,而负样本对最终更远离。

训练过程:从随机到有序

训练嵌入模型的第一步是编译一个包含大量正负样本对的集合,在许多系统中这也被称为示例。这意味着真正庞大的数据集合,通常包含数百万对样本。一个单独的单词或文本片段将包含在许多示例中,以捕捉它与各种文本和概念的关系。

一旦这些示例被编译完成,训练就可以开始了。

在训练开始时,嵌入模型将每段文本嵌入到一个随机向量中。这些向量是无意义的,与文本的含义没有任何关系。如果你使用这个未经训练的嵌入模型进行检索,结果将是胡言乱语。

现在,模型查看其训练数据中的所有正负样本对,并询问:我将正样本对放在一起、将负样本对分开的效果如何?由于模型使用正负示例提供的对比来评估其性能,这种技术被称为对比训练

基于其表现,模型更新其内部参数。它使用一种算法,试图将正样本对拉得更近,将负样本对推得更远。

一旦嵌入模型的参数被更新,你只需重复这个过程。使用模型更新后的参数将文本嵌入到新的向量中。再次使用正负样本对评估模型的性能,并根据该性能再次更新其参数。

这个过程重复多次,迭代地更新模型的参数,将样本对拉近或推远。经过多轮训练后,正样本对将被拉得很近,而负样本对应该被推得很远。

从单个文本的视角看训练过程

让我们从单个文本片段的视角来看这个过程。以短语“he could smell the roses”为例,我将其称为我们的锚点。它与短语“a field of fragrant flowers”构成一个正样本对,与短语“a lion roared majestically”构成一个负样本对。

在训练开始时,这三个短语被映射到随机位置,没有反映它们的含义。从锚点的角度来看,它希望将正样本拉近,并希望将负样本推远。只有三个文本片段时,这个过程很容易可视化。

经过多轮训练后,锚点希望尽可能地将正样本拉近,并将负样本推得尽可能远。也就是说,你永远不会只用两对样本来训练一个嵌入模型。

当你尝试用数百万个锚点、正样本和负样本来完成这个过程时,情况会变得混乱得多。每个向量同时在许多方向上被推拉。这有助于解释为什么模型使用具有数百甚至数千个维度的向量——高维空间为算法提供了许多选择,可以将向量推拉到何处,以反映训练数据中微妙的关系。

训练后的向量空间

训练后,向量能够捕捉含义,因为相似的单词或文本被拉到了向量空间中相似的区域。你不需要为了构建一个RAG系统而去训练一个嵌入模型,但理解它们是如何训练的可以帮助你更好地理解它们生成的向量。

需要了解的主要要点是,语义向量是抽象且有些随机的。在训练之前,空间中的一个位置没有任何意义,向量被随机放置。训练之后,空间中的不同位置确实具有语义含义,但这只是因为在那里形成了一个相似概念的集群。例如,某个地方可能有一个与狮子相关的所有单词的集群,而另一个集群则与长号相关。如果你运行两次训练过程,但使用不同的初始随机向量,这些相同的集群仍然会形成,但它们会位于向量空间中的不同位置。

另一个关键要点是,你只比较由同一个嵌入模型生成的向量。每个模型都是用不同的训练数据、不同的维度数量和不同的随机初始化值训练的。尝试比较来自两个不同模型的向量只会导致无意义的结果。

实践与应用

在实践中,你可能会使用现成的嵌入模型,它们会非常出色地将相似的单词、句子或文档放置在向量空间中相似的位置。你可能甚至不需要实现这些向量之间的距离测量。也就是说,更深入地理解它们的工作原理可以帮助你更好地推理如何在你的RAG系统中使用它们。

总结

本节课中我们一起学习了嵌入模型的核心工作原理。我们了解到,模型通过对比训练,利用海量的正负样本对,将文本含义编码为高维空间中的向量。相似含义的文本在向量空间中彼此靠近,从而实现了语义搜索。理解这一过程有助于我们更好地选择和使用嵌入模型来构建高效的RAG系统。

接下来,请和我一起进入下一个视频,看看如何将这些密集向量应用到你的检索器中。

016:混合搜索策略 🧩

在本节课中,我们将学习如何将之前介绍的多种搜索与过滤技术结合起来,形成一种混合搜索策略,从而综合发挥它们各自的优势。

上一节我们介绍了检索器中使用的不同搜索和过滤技术。本节中,我们来看看如何将它们结合使用,构成混合搜索技术的一部分,以利用它们各自不同的优势。

回顾各搜索技术

首先,让我们回顾每种技术的运作方式及其主要优点。

  • 元数据过滤:使用存储在文档元数据中的严格标准来缩小搜索结果范围。
    • 优点:速度快、易于实现、易于解释。它本身可能不是一个强大的搜索技术,但它提供了一个严格的“是/否”过滤器,这是其他方法无法提供的。
  • 关键词搜索:根据提示词中找到的相同关键词对文档进行评分和排序。
    • 优点:速度仍然很快,易于实现,并且在查找相关文档方面可以做得非常出色。当提示词和文档包含技术关键词或产品名称时,它表现得尤其出色,因为结果将包含这些确切的词语。
    • 缺点:关键词搜索依赖于精确匹配,因此无法检索到含义相似但用词不同的文档。
  • 语义搜索:根据与提示词含义的相似性对文档进行评分和排序。
    • 原理:文档和提示词被嵌入为向量,其在高维空间中的位置捕捉了它们的含义。找到与提示词最相似的文档,意味着需要找到向量嵌入与提示词向量最接近的文档。
    • 优点:它提供了其他搜索技术无法提供的灵活性。
    • 缺点:比关键词搜索速度慢,计算强度更大。

构建混合搜索管道

鉴于这三种方法各有相对优势,以下是它们通常如何组合成一个混合搜索管道的。

  1. 接收提示词:检索器首先接收到一个提示词。
  2. 并行执行搜索:检索器随后使用该提示词同时执行关键词搜索和语义搜索。
  3. 生成排序列表:结果是两个已排序的文档列表:一个使用关键词搜索评分和排序,另一个使用语义搜索评分和排序。可以想象每个搜索技术返回50个文档,许多文档会同时出现在两个排名中,但顺序可能不同。
  4. 应用元数据过滤:接下来,使用元数据过滤器对这两个列表进行过滤,以移除不相关的文档。例如,过滤器可能会移除与工作无关的文档。在这个例子中,关键词搜索列表剩下35个文档,语义搜索列表剩下30个。
  5. 合并排序列表:现在,需要将这两个排序列表合并成一个单一的排名。

合并排名的算法:倒数排名融合 (RRF)

一种常用的合并这些排名的算法称为倒数排名融合。该算法奖励在任一列表中排名靠前的文档,同时允许你控制是给予关键词排名还是语义排名更多的权重。

以下是倒数排名融合的公式:

score = 1 / (K + rank)

文档根据其在每个列表中的排名获得积分。K 是一个超参数,但暂时假设它为0。在这种情况下,每个文档获得的积分等于其排名的倒数。

  • 第一名得 1 分。
  • 第二名得 1/2 分。
  • 以此类推。

文档从每个排序列表中获取积分,其总积分用于计算最终排名。对于你的检索器来说,就是两个排名:关键词排名和语义排名。

示例:如果一个文档在一个列表中排名第二,在另一个列表中排名第十,那么它将从第一个排名中获得 1/2 = 0.5 分,从第二个排名中获得 1/10 = 0.1 分,总分为 0.6 分。然后使用这些分数对所有文档进行重新排序。

调整混合搜索参数

让我们回到那个 K 参数。K 用于控制最高排名文档的影响。

  • K = 0 时,任何列表中排名第一的文档都会立即跃升至总排名的顶部,即使它只在一个列表中排名很高。例如,排名第一的文档得1分,排名第十的文档得0.1分,这是10倍的差异。
  • K 增加到类似 50 的值可以平衡这一点。现在,排名第一的文档得 1/(50+1) ≈ 0.0196 分,排名第十的文档得 1/(50+10) ≈ 0.0167 分,这是一个更温和的分数差异。它仍然可能排名第一,但不会达到主导其他列表排名的程度。

请注意,RRF 只关心文档在每个列表中的排名,而不关心导致这些排名的原始分数。即使排名第一的文档比第二名的分数高得多,这些信息也不会在 RRF 中被考虑。

检索器混合搜索通常还有第二个超参数,称为 Beta。它允许你对语义搜索或关键词搜索产生的排名进行加权。

例如,你可以将 Beta 设置为 0.8,将 80% 的重要性或权重分配给语义搜索提供的排名,仅将 20% 分配给关键词搜索提供的排名。一个 70/30 的分割(70% 语义,30% 关键词)通常是一个很好的起点,你可以针对你的特定系统进行调整,看看哪种效果最好。

  • 在精确词语匹配非常重要,但又希望有一些语义相似性的应用中,你会希望给予关键词搜索结果比语义搜索结果更重的权重。
  • 在其他情况下,如果语义相似性更重要,而关键词不那么关键,你会希望给予向量搜索结果比关键词搜索结果更重的权重。

返回最终结果

至此,你的检索器实际上已经准备好返回其结果了。根据最初请求的文档数量(通常称为 top K),检索器会从这个最终的混合排名中返回最相似的 K 个文档。

总结与展望

本节课中,我们一起学习了混合搜索策略。混合搜索允许检索器利用关键词搜索、语义搜索和元数据过滤提供的不同优势。关键词搜索提供精确的词语匹配,语义搜索允许基于含义进行模糊匹配,而元数据过滤则使用严格的标准过滤掉文档。

此外,还有充足的机会来改变这个混合系统的工作方式,无论是调整 BM25 算法的参数、选择过滤哪些元数据,还是在倒数排名融合步骤中改变关键词搜索与语义搜索的权重。这种混合方法让你可以发挥每种方法的优势,并根据知识库中的数据或整个项目的需求来调整系统的性能。

然而,要进行这种调整,你需要一种方法来衡量检索器的性能。因此,请加入下一节视频,了解如何评估检索器。

017:检索质量评估 📊

在本节课中,我们将学习如何评估检索器的性能。与任何软件一样,一旦检索器开始运行,你需要知道它是否真的有效。虽然你可以从延迟、吞吐量、资源使用等方面评估检索器,但最终重要的是搜索质量。换句话说,它是否找到了相关的文档。让我们看看几种回答这个问题的方法。

评估指标的核心要素

大多数检索器质量指标都包含几个共同的要素。

首先,你需要查询本身,因为检索器可能在一个查询上表现良好,而在另一个查询上表现不佳。

其次,你需要检索器根据该查询返回的文档排序列表

最后,你需要一个真实相关文档列表,即你的知识库中检索器应该返回的所有相关文档。换句话说,如果你想给你的检索器打分,你需要知道正确答案。

精确率与召回率

上一节我们介绍了评估所需的核心要素,本节中我们来看看两个最常用的检索器质量指标:精确率和召回率。

精确率的计算方法是:相关检索到的文档数量除以检索到的文档总数

召回率的计算方法是:检索到的相关文档数量除以知识库中相关文档的总数

以下是帮助你理解两者区别的一个例子。

假设你通过人工标注,知道你的知识库中有10个与某个查询相关的文档。你在该查询上运行检索器,它返回了12个文档,其中8个是相关的。那么精确率是66%(因为12个中有8个相关),召回率是80%(因为10个相关文档中找到了8个)。

现在,你调整检索器设置并再次运行查询。在第二次运行中,它返回了15个文档,其中9个是相关的。你的检索器比上次多返回了3个文档,但只多找到了1个相关文档。精确率下降到60%(15个中有9个),然而召回率增加到90%(因为这次找到了10个相关文档中的9个)。换句话说,你牺牲了一点精确率,换来了更高的召回率。

精确率惩罚检索器返回不相关的文档,可以理解为衡量结果的可信度。召回率惩罚检索器遗漏相关文档,衡量检索器的全面性。要同时获得完美的召回率和精确率,唯一的方法是只返回相关文档,并且将它们排在最高位。否则,你通常需要在两者之间进行权衡。

Top K 标准化

检索指标受检索器返回的文档数量影响。因此,为了标准化,通常讨论的是Top K文档,即检索器排名最高的K个文档。

例如,考虑检索器返回的这个文档排序列表。

在这个例子中,Top 5的精确率是40%,因为前5个文档中只有2个是相关的。同时,Top 10的精确率上升到60%,因为前10个文档中有6个是相关的。

假设知识库中有8个相关文档。这里的Top 10召回率将是6/8,即75%。根据你选择的Top K值,你可以快速生成新的精确率和召回率值。当需要更严格的标准时,可以使用Top 5、Top 2或Top 1指标。不过,通常使用Top 5到Top 15之间稍宽松的范围。

平均精确率均值 (MAP)

为了更全面地了解检索器性能,平均精确率均值 (MAP@K) 评估了前K个检索到的文档中,相关文档的平均精确率。

首先,让我们为这个例子计算一个相关的指标,称为平均精确率@6

你列出检索器排名最高的6个文档,并为每一行计算精确率@K。接下来,你只对包含相关文档的行(这里是第1、4、5行)的精确率求和,即1 + 0.5 + 0.6。最后,除以Top K中检索到的相关文档数量(本例中为3)。这给出了0.7的平均精确率。

要计算平均精确率均值,你只需计算多个查询及其检索到的文档集的平均精确率,然后对这些值取平均。这告诉你检索器接收到的典型查询的平均精确率会是多少。

MAP奖励将相关文档排在较高位置。如果一个不相关的文档挤进了排名靠前的位置,它会降低其下方每个相关文档所在位置的精确率,从而拉低整体平均值。因此,高MAP值是检索器将其找到的相关文档排在较高位置的良好指标。

倒数排名 (MRR)

最后一个常见指标是倒数排名,它衡量返回列表中第一个相关对象的排名。

例如,如果第一个相关对象出现在第2位,倒数排名就是1/2,即0.5。如果它在第4位,倒数排名就是0.25。第一个相关文档在列表中出现的越靠后,倒数排名就越差。这通常会在多个查询上执行,以获得平均倒数排名 (MRR)

MRR反映了平均而言,你能多快在检索器的排名中找到相关项目,并强调了在排名中尽可能高地包含至少一个相关文档的重要性。

例如,如果你使用检索器完成了四次搜索,每次排名中第一个相关文档分别出现在第1、3、6和第2位,你可以通过用1除以每个数字来计算平均倒数排名,然后对这些值取平均。这里,这些值是1、1/3、1/6和1/2。将这些值相加并除以4,得到平均倒数排名为0.5。

如何综合使用这些指标

有了这么多可用的指标,了解如何最好地结合使用它们很重要。

召回率召回率@K是检索器最基本、最常被引用的指标,因为它抓住了检索器最根本的目标:找到相关文档。

精确率MAP在此基础上,通过评估检索器是否包含了许多不相关文档,或者检索器对它们的排名有多有效。

平均倒数排名更专业一些,但有助于识别你的模型在其排名最顶端的表现如何。

这些指标既可以用来评估检索器的性能,也可以帮助你判断对系统所做的调整是否有效。例如,你可以调整混合检索系统中语义搜索或关键词搜索的权重,然后观察这对你的检索器在一组示例查询上的召回率或精确率有何影响。

如果这些指标有缺点,那就是它们都依赖于拥有一组示例查询的真实相关文档。编译这些数据可能是一个耗时且需要人工操作的过程。然而,最终的结果是一个你可以在开发期间以及上线后都能监控的系统。

总结

本节课中,我们一起学习了评估检索器质量的核心方法。我们介绍了评估所需的三个要素:查询、检索结果和真实相关文档。我们深入探讨了精确率和召回率这两个基础指标,理解了它们如何衡量结果的准确性和全面性。接着,我们学习了如何通过Top K进行标准化评估,并引入了更全面的指标——平均精确率均值 (MAP),它能反映检索器对相关文档的排序质量。最后,我们了解了平均倒数排名 (MRR),它特别关注第一个相关结果出现的位置。掌握这些指标,你将能够有效地监控和优化检索增强生成系统中的检索组件。

018:信息检索原理总结 🎯

在本模块中,我们学习了信息检索的核心原理及其在检索器中的组合应用。现在,让我们回顾一下本模块探讨的主要概念。

上一节我们介绍了检索器的基本构成,本节中我们来总结整个模块的核心内容。

以下是本模块涵盖的主要概念:

  1. 混合检索技术:检索器通常结合使用三种搜索技术:关键词搜索、语义搜索和元数据过滤。
  2. 关键词搜索:根据文档包含提示词中关键词的频率对文档进行排序。这是一种成熟的方法,其优势在于能确保返回的文档包含提示词中的确切关键词。
  3. 语义搜索:根据文档与提示词语义的相似性对文档进行排序。这得益于嵌入模型,该模型能将文本片段转换为数学向量,其特性是语义相似的文本在向量空间中的向量位置也相近。语义搜索提供了关键词搜索所不具备的灵活性。
  4. 元数据过滤:根据文档元数据中记录的严格标准来排除文档,通常用于确保结果与用户相关。
  5. 混合搜索:结合上述技术,首先在知识库中并行执行关键词搜索和语义搜索,然后使用元数据过滤器对结果进行过滤,最后将两个列表中的文档合并,形成一个单一的、经过排序的文档列表,从中可以返回最匹配的结果给用户。
  6. 评估指标:我们了解了几种用于评估检索质量的常见指标,这些指标可用于判断在调整混合搜索流程中的各种可调超参数时,检索质量是提高还是降低。

至此,你已经对典型RAG系统中使用的所有信息检索概念有了扎实的理解。接下来,请与我一起进入下一个模块,看看这些概念是如何在生产级检索器中应用的。

019:向量数据库与生产环境优化 🚀

在本模块中,我们将把之前学到的信息检索理论知识应用到生产环境中。我们将探讨为什么传统数据库在处理海量向量数据时会遇到瓶颈,并学习如何使用专为向量优化的数据库——向量数据库。此外,我们还将了解生产级RAG系统中用于提升检索性能的关键技术。

从理论到生产 📈

上一节我们建立了坚实的信息检索基础,本节中我们将把所有理论投入生产实践。

你可以使用传统的关系型数据库来实现之前看到的大多数检索技术。然而,一旦需要搜索数百万甚至数十亿份文档,某些操作——特别是作为语义搜索基础的向量运算——性能将显著下降。

此时,你可能需要转向使用向量数据库。向量数据库是专门为存储和搜索海量向量数据而优化的数据库,因此它们几乎已成为RAG系统的代名词。

模块学习目标 🎯

在本模块中,你将学习向量数据库为何对向量检索如此优化,并动手使用一个向量数据库来执行多种不同的搜索。

你还将看到生产环境RAG系统中使用的一系列技术,例如文档分块、查询解析和重排序。这些技术在生产环境中用于进一步提升检索器的性能。

与往常一样,本模块最后将有一个编程作业,供你应用所有这些概念。

总结

本节课中,我们一起学习了将信息检索理论应用于生产环境的重要性,并介绍了本模块的核心内容:向量数据库的优势及其在生产级RAG系统中的关键优化技术。希望你享受这个能将所有信息检索知识付诸实践的模块。

020:近似最近邻 (ANN) 算法 🧭

在本节课中,我们将要学习向量检索的核心算法。我们将从最简单的算法开始,分析其局限性,然后探讨如何通过近似最近邻算法来高效地处理大规模数据。

虽然关键词和语义搜索构成了生产级检索器的基础,但随着这些技术的扩展,新的问题会出现。如果实现方式过于简单,向量搜索的性能会尤其低下,需要大量的计算资源并增加系统的延迟。

让我们先看看向量搜索的基础算法,以理解问题的根源,然后再探索如何改进它。

向量检索的基础:K最近邻算法

上一节我们介绍了向量检索的基本概念,本节中我们来看看其最直接的实现方式。

最简单的向量检索形式被称为K最近邻搜索。这是你在课程中迄今为止一直看到的算法。首先,为知识库中的每个文档以及你的提示词创建嵌入向量。然后,计算提示词向量与每个文档向量之间的距离。接着,根据文档与提示词向量的距离对文档进行排序。用户可以选择一个数字K,它代表要返回的最近邻文档的数量。

K最近邻算法易于理解且易于实现。问题在于它的扩展性极差。每次搜索所需的计算量随着知识库中文档数量的增加而线性增长。如果你有1000个文档,每次搜索必须计算1000个向量距离。但如果你有10亿个文档,就必须计算10亿个向量距离。第二次搜索将比第一次慢一百万倍。

如果你希望你的检索器在大规模数据上表现良好,就需要一个更好的方法。

近似最近邻算法简介

为了改进K最近邻算法,检索器使用了一系列被称为近似最近邻的算法。这些算法使用巧妙的数据结构来实现显著更快的搜索。为了做到这一点,它们在结果质量上做出了一点牺牲,这意味着它们不能保证找到知识库中绝对最接近的文档,但仍然能找到非常接近的文档。

可导航小世界算法

让我们看一个典型的近似最近邻算法,称为“可导航小世界”。在进行任何搜索之前,算法会创建一个名为“邻近图”的数据结构。为此,首先计算每个向量与其他每个向量之间的距离。然后,在这个邻近图中,为每个文档添加一个节点。最后,在每个文档与其最接近的几个其他文档之间建立一条边。这就形成了一个网状结构。你可以想象通过沿着连接它们的边从一个文档跳转到其最近邻来遍历邻近图。

现在,让我们看看这个邻近图如何加速搜索。当收到一个提示词时,它被向量化以创建一个查询向量。目标是找到最接近该查询向量的文档。为此,算法随机选择一个称为候选向量的入口点开始。

这只是邻近图中的一个节点。这是一个完全随机的选择,甚至不假设它接近提示词向量。

现在,算法开始遍历图。它查看当前候选向量的每个邻居,并计算其中哪一个最接近提示词向量。由于只需要考虑几个邻居,这是一个非常快的过程。最接近的那个成为新的候选向量。然后,这个过程在每个候选向量处重复:算法查看哪个连接的相邻向量最接近查询向量,该向量就成为新的候选向量。这个过程持续进行,直到没有一个邻居比当前候选向量更接近,此时返回候选向量。通过小的修改,这种方法可以返回多个文档,但核心思想仍然相同:你只是在邻近图上移动,每次都选择能让你更接近提示词的邻居。

这种方法不一定能找到知识图中可能的最佳向量。可能有一个向量更接近提示词向量,但算法无法到达它,因为它无法选择通过邻近图的最佳整体路径,只能选择每个时刻的最佳路径。然而在实践中,这个算法能以比K最近邻快得多的速度找到非常接近的向量。

分层可导航小世界算法

虽然这个可导航小世界算法已经比K最近邻更高效,但一个称为分层可导航小世界的变体通过显著加速搜索的早期部分带来了进一步的改进。

分层可导航小世界依赖于一个具有多层的分层邻近图。

以下是一个拥有1000个文档的知识库可能的分层邻近图的样子:

  • 第1层:包含全部1000个向量,并像通常那样计算邻近图。
  • 第2层:随机丢弃所有向量,只保留100个,并为这100个向量创建一个新的邻近图。
  • 第3层:随机丢弃所有向量,只保留10个,并再次为剩余的10个向量创建一个邻近图。

为了搜索这个邻近图,搜索从第3层(顶层)开始。算法在该层随机选择一个入口点,然后像通常那样搜索,以找到第3层中的最佳候选向量。接着,它下降到第2层,从第3层中找到的最佳候选向量开始。由于这里有更多的向量,可能有一个更接近提示词向量。算法像通常那样在第2层中移动,直到找到第2层中的最佳候选向量。此时,它下降到第1层(最底层),该层包含知识库中的每个向量。算法像通常那样遍历这个最底层,而这次找到的最佳候选向量就是算法实际返回的向量。

这种分层方法非常高效,因为在最高层,算法进行大的跳跃以进入提示词向量的近似邻域。当在第1层考虑任何可能的向量时,候选向量应该已经非常接近提示词向量了。

与K最近邻搜索相比,分层可导航小世界算法要快得多。随着层级的上升,需要遍历的向量数量呈指数级减少。因此,分层可导航小世界的运行时间近似为对数级,而K最近邻是线性级。

正是这一点使得向量搜索能够扩展到数十亿个向量,并且仍然只需要几百毫秒的延迟。

近似最近邻算法的关键特性

你不需要自己实现这样的近似最近邻算法,但理解它们的一些关键特性仍然很重要。

以下是近似最近邻算法的几个关键特性:

  1. 速度显著更快:它们比K最近邻算法快得多,使得向量搜索在大规模数据上仍然可行。
  2. 结果近似最优:虽然它们倾向于找到接近提示词向量的文档,但不能保证找到绝对最佳的匹配。
  3. 依赖预计算的邻近图:整个过程依赖于构建一个好的邻近图。这是一个计算量相当大的过程,但幸运的是,它可以在收到任何提示词之前进行预计算。

这就是近似最近邻算法如何使向量搜索能够大规模进行的一个很好的总结。

本节课中我们一起学习了向量检索的核心算法。我们从基础的K最近邻算法开始,了解了其计算复杂度高、难以扩展的局限性。为了解决这个问题,我们深入探讨了近似最近邻算法家族,特别是可导航小世界及其更高效的分层变体。这些算法通过构建邻近图数据结构,以牺牲少量精度为代价,换来了对数级的搜索速度,从而使得在海量数据中进行实时向量检索成为可能。理解这些原理,将帮助我们更好地运用后续介绍的实际工具。

021:向量数据库技术 🗄️

在本节课中,我们将要学习向量数据库技术。向量数据库是生产级RAG系统的核心组件,专门用于高效存储和检索高维向量数据。我们将了解其基本操作、工作原理以及如何为RAG应用中的检索任务奠定基础。

什么是向量数据库?

上一节我们介绍了近似最近邻搜索算法,本节中我们来看看承载这些算法的专用数据库。

向量数据库是一种从底层设计用于存储高维向量数据并实现向量导向算法(如你刚看到的近似最近邻算法)的数据库。它们在2020年代初因大语言模型的普及和基于向量嵌入的技术(如语义搜索)的爆发而流行起来。

标准的关系型数据库在语义搜索任务上表现不佳,其性能更接近于效率极低的穷举最近邻算法。向量数据库针对构建支持HNSW搜索的邻近图或计算向量距离等任务进行了优化,因此在大多数基于向量的应用中,尤其是在构建RAG系统时,能够实现良好的扩展性和显著更快的运行速度。

向量数据库的选择与准备

本课程中你将使用的向量数据库叫做 Weaviate。它是一个流行的开源向量数据库,你可以在本地或云端运行。市场上也有多种其他向量数据库可供选择。如果你在未来项目中选择不同的向量数据库,它们几乎肯定会提供与Weaviate非常相似的功能。

这里的目的是让你亲身体验任何RAG项目中常见的一些工作流程。让向量数据库准备好处理搜索涉及几个步骤,其中一些是自动为你处理的。

以下是准备向量数据库以进行搜索的关键步骤:

  1. 设置数据库。
  2. 加载文档。
  3. 创建支持关键词搜索的稀疏向量。
  4. 创建支持语义搜索的密集嵌入向量。
  5. 最后,创建支持近似最近邻搜索算法(如你刚看到的HNSW索引)的索引。

完成这些步骤后,你就可以运行实际的搜索了。

Weaviate 操作示例

在接下来的非评分实验中,你将详细看到所有这些步骤。现在,让我们通过几个例子来看看这些步骤在Weaviate中是如何处理的。

第一步:创建或连接数据库

使用Weaviate的第一步是创建一个数据库实例或连接到现有的一个。你将在非评分实验中看到如何完成此操作的示例。

第二步:创建集合

接下来,你需要创建一个集合来保存数据。这里我创建的集合名为 article,用于保存新闻文章的标题和正文。此代码还指定了每种数据类型为文本。更重要的是,这个调用指明了应该使用哪个嵌入模型或向量化器来为添加的每篇文章创建语义向量。

# 示例:在 Weaviate 中创建集合并指定向量化器
client.collections.create(
    name="article",
    properties=[
        Property(name="title", data_type=DataType.TEXT),
        Property(name="body", data_type=DataType.TEXT)
    ],
    vectorizer_config=Configure.Vectorizer.text2vec_openai()  # 指定使用的嵌入模型
)

第三步:插入数据

配置好集合后,就可以向其中添加数据了。这段代码使用集合的批处理方法添加数据。batch.add_object 实际上是将对象添加到集合中,但它也会计数和跟踪错误,从而可以在之后纠正错误,或者在遇到太多错误时中断循环。数据插入后,你就可以执行向量搜索了。

第四步:执行搜索

在第一个查询中,我指定了刚刚创建的集合,然后你可以传入一个文本查询。这里还传入了一个特定的元数据请求,它会返回距离。

# 示例:执行向量搜索
response = client.query.get(
    "article",
    ["title", "body"]
).with_near_text({
    "concepts": ["你的查询文本"]
}).with_additional(["distance"]).with_limit(3).do()

这个距离将是查询向量与每个对象向量之间的距离。

第五步:关键词搜索与混合搜索

你也可以执行关键词搜索。Weaviate会自动为你创建一个倒排索引,它允许你映射每个文档中使用了哪些词以及使用频率。在这里,你可以执行你在上一个模块中学到的简单BM25查询,并要求基于此查询返回排名前三的文档。

你还可以继续以混合搜索的形式将向量搜索与关键词搜索结合起来。使用混合搜索时,关键词搜索和向量搜索将在后台并行执行,然后使用这个 alpha 参数(当前设置为0.25)来相应地对向量搜索和关键词搜索的分数进行加权。

因此,当 alpha 为0.25时,向量搜索获得25%的权重,另外75%的权重分配给关键词搜索。这些结果会相应地进行重新排名,然后我们得到排名前三的结果。在生产实践中,这是大多数公司使用的方法,因为它允许你平衡向量搜索的语义相似性和关键词搜索的严格匹配相似性。

# 示例:执行混合搜索
response = client.query.get(
    "article",
    ["title", "body"]
).with_hybrid(
    query="你的查询文本",
    alpha=0.25  # 向量搜索权重为25%,关键词搜索权重为75%
).with_limit(3).do()

第六步:应用过滤器

你还可以在此基础上应用过滤器。例如,这里可以有一个应用于特定属性的过滤器,并检查该属性的值。如果匹配,对象通过过滤器并可以被返回。如果不匹配,则不会被返回。

# 示例:在搜索中应用过滤器
response = client.query.get(
    "article",
    ["title", "body"]
).with_hybrid(
    query="你的查询文本",
    alpha=0.25
).with_where({
    "path": ["category"],  # 属性路径
    "operator": "Equal",
    "valueText": "科技"     # 过滤条件:category 等于 "科技"
}).with_limit(3).do()

工作流程总结

从开始到结束的整个循环大致如下:你配置数据库,然后加载并索引数据,最后编写一个包含混合搜索和过滤器的特定查询。

这就是如何使用向量数据库的一个很好的概述。请查看非评分实验,亲自动手实践所有这些步骤。

课程总结

本节课中我们一起学习了向量数据库技术。我们了解到向量数据库是专为高效处理高维向量和相似性搜索而设计的数据库,是RAG系统的关键基础设施。我们以Weaviate为例,学习了从创建集合、插入数据、生成向量索引,到执行向量搜索、关键词搜索、混合搜索以及应用过滤器的完整工作流程。掌握这些操作是构建高效、可扩展的生产级RAG应用的基础。

022:文本分块技术 🧩

在本节课中,我们将要学习文本分块技术。这是优化检索增强生成系统性能的关键策略之一,旨在将长文档分解为更小、更易于管理的片段,以提升检索的准确性和效率。

概述

上一节我们介绍了向量数据库的架构和API。本节中我们来看看如何通过文本分块技术来优化向量检索。简单来说,分块就是将知识库中的较长文本文档拆分为较小的文本块。

为何需要分块?

分块的原因主要有三点:

  1. 许多嵌入模型对单次可嵌入为向量的文本长度有限制。
  2. 分块可以提高检索器的搜索相关性指标。
  3. 分块确保只将文档中最相关的文本发送给大语言模型。

为了理解分块的价值,假设你有一个包含一千本书的知识库。如果直接索引,每本书会被嵌入模型向量化,结果是1000个向量,每个向量代表一本书的全部内容。问题在于,你将整本书的含义压缩到了一个向量中。这些向量无法精确表示特定章节或页面中讨论的任何具体主题,而是对所有内容进行了平均。因此,搜索相关性会很差。即使使用这个系统进行检索,每次也会检索整本书,这会迅速填满大语言模型的上下文窗口。

因此,通常需要将书籍分块成更小的片段,例如页面、段落或句子级别。这样,你的知识库可能包含100万个段落,而不是1000本书,但向量数据库可以轻松扩展以存储和搜索所有这些向量。

如何选择分块大小?

分块时的首要考虑因素是使用多大的分块尺寸。如果分块太大,例如在章节级别,就会遇到与向量化整本书相同的问题。分块仍然太大,无法用单个向量捕捉细微的含义,并且会迅速填满大语言模型的上下文窗口。

反之,分块也可能太小。考虑极端情况:按单词分块。向量将丢失周围句子和段落的所有上下文,这同样会降低搜索相关性。即使在句子级别分块也可能过于精细。

没有一种适用于所有情况的分块大小,但通常你会在“向量试图一次捕获过多上下文”和“捕获过少上下文”之间找到一个平衡点。

分块策略

以下是两种常见的分块策略:

固定大小分块

最简单的方法是使用固定大小的分块策略。一开始就确定每个分块大小相同,例如250个字符。

  • 字符1到250是分块1。
  • 字符251到500是分块2。
  • 字符501到750是分块3,依此类推,直到文档结束。

当然,这不能保证分块之间的分割点位于合理的位置。分割通常可能落在一个单词的中间,或者将一个段落中连贯的思想分开。

这通常通过允许分块重叠来解决。例如,分块可能长250个字符,但与前后分块重叠25个字符。

  • 分块1是字符1到250。
  • 分块2是字符226到475。
  • 分块3是字符451到700,依此类推。

通常,这种重叠表示为整个分块的百分比。这里就是10%的重叠。重叠分块可以最大限度地减少单词与其上下文被切断的情况。位于分块中间的单词有其两侧的上下文,位于分块边缘的单词会出现在两个分块中,增加了它们与相关上下文一起出现的几率。

允许更多重叠通常会对搜索相关性产生积极影响,但代价是向数据库中添加了更多包含冗余信息的向量。

递归字符文本分割

一种更动态的分块策略称为递归字符文本分割。其思想是选择一个特定的字符进行分割。例如,可以按换行符分割,这通常出现在段落之间。这会产生可变的分块大小,因此根据换行符的位置,你更有可能得到非常大或非常小的分块。

然而,这样做的好处是,你考虑了文档结构,并增加了相关概念被保留在单个分块内的机会。如果你的知识库有各种文档类型,当然可以对不同类型的文档进行不同的分割。例如,可以按段落或标题标签分割HTML,按函数定义分割Python代码,按换行符分割文本文档。

实践与工具

固定大小重叠分块或按特定字符分块非常简单,你可以自己实现,但也可以找到专门帮助你完成此任务的外部库。如果你的文档有元数据,你当然会希望分块继承其源文档的元数据,可能还会附带关于其位置的其他信息。你将在本模块的未评分实验中看到如何实现这一点的示例。

总结

本节课中我们一起学习了文本分块技术。对文档进行分块对向量检索有多种好处,从提高搜索相关性到最小化大语言模型上下文窗口的使用。如果你在寻找一个好的起点,只需使用大约500个字符的固定大小分块,并设置50到100个字符的重叠。在某些其他情况下,更高级的分块技术可能会有所帮助,所以请继续观看下一个视频,探索其中一些技术的样子。

023:高级分块方法论 🧩

在本节课中,我们将要学习几种超越固定大小和递归字符分割的高级分块技术。这些方法旨在根据文本的语义来构建分块,从而更好地保留上下文信息,提升检索质量。

分块有多种好处,但将文档分割成较小的块也存在风险,即可能以丢失相关上下文的方式破坏文本的连贯性。

考虑这个句子:“那天晚上,她像往常一样梦到,自己终于成为了奥运冠军。” 根据分割位置的不同,分块可能会让读者误以为做梦者已经是金牌得主,而不是在梦想未来的荣耀。固定大小和递归字符分割无法防止这类问题。因此,让我们来看看一些更高级的技术,它们试图基于文本的含义来智能地构建分块。

语义分块

上一节我们介绍了基础分块方法的局限性,本节中我们来看看第一种高级技术:语义分块。这种方法尝试将含义相似的句子放在同一个分块中。

该算法的工作原理是逐句遍历文档。对于每个句子,算法会判断它与之前句子的相似度是否足够高,从而决定它是否属于同一个分块。

以下是算法的核心步骤:

  1. 将当前累积分块的内容和下一个待判断的句子分别向量化。
  2. 计算两个向量之间的距离。
  3. 如果距离低于某个预设的阈值(表示含义相似),则将新句子加入当前分块。
  4. 如果距离超过阈值(表示含义不同),则切断当前分块,并从下一个句子开始新的分块过程。

这个过程持续进行,直到遍历完整个文档。当用图表表示时,增长中的分块与后续句子的差异度由峰值线表示,而向量距离或差异度的阈值用红线表示。

最终,分块与下一个句子之间的差距会超过阈值,从而创建一个新的分块。

这个过程的结果是生成大小可变的分块,这些分块遵循作者的思路。例如,如果作者在一个段落中偏离主题进行概念性探讨,或者连续两个段落讨论同一个想法,语义分块都会在合适的位置进行分割。

可以想象,语义分块在计算上可能比较昂贵,因为你需要为知识库中的每个句子反复计算向量。然而,作为交换,你通常会获得更高质量的检索结果,这可以通过精确率和召回率等熟悉指标来衡量。

基于大语言模型的分块

为了获得更大的灵活性,你可以尝试基于大语言模型的分块。这种方法将文档连同你希望创建的分块类型的指令一起提供给语言模型。

例如,你可以指示它根据含义来分隔分块,将相似的概念保留在一个分块中,并在讨论新主题时将文本分割成不同的分块。然后,语言模型会像生成任何其他文本一样生成分块输出。

虽然这本质上是一种“黑盒”方法,但它实际上是一种性能非常高的分块策略。随着语言模型成本的下降,基于大语言模型的分块在经济上变得更加可行。

上下文感知分块

对任何分块策略的最后一个改进是使用语言模型为每个分块添加上下文。

例如,你可以要求语言模型从文档中创建分块,但同时为每个分块添加总结性文本,解释其在更广泛文档中的上下文。一位作者可能在博客文章的结尾感谢一系列支持者和贡献者。

这意味着在博客文章末尾附近会有一个分块,其中只是一长串名字,使得这个分块本身难以理解。大语言模型可以为该分块添加文本,解释其在整篇博客文章中的上下文。

这些添加的文本在分块被向量化时可用,有助于提高搜索相关性;在分块被检索到时也可用,最终帮助大语言理解分块的整体含义。

上下文感知分块需要计算成本较高的预处理,因为大语言模型需要逐个文档、逐个分块地遍历你的整个知识库来添加上下文。然而,其好处是搜索更相关,并且对搜索速度基本没有影响。

如何选择分块策略

大多数RAG系统都会实现某种形式的分块。然而,使用何种复杂程度的方法取决于具体情境。

以下是选择分块策略的考量点:

  • 固定大小或递归字符分割通常是构建系统原型时的良好起点,也是不错的默认方法。
  • 语义分块和基于大语言模型的分块可以带来更高的性能,但它们在计算上更昂贵,并且可能难以调整、维护或审计。
  • 更合理的做法是使用一小部分数据子集进行实验,看看这些更高级的技术是否真的能提高搜索相关性。
  • 由于上下文感知分块可以应用于任何分块策略之上,并且可以同时改善搜索相关性和后续生成效果,它通常是探索固定大小技术之外的首个改进方向。

作为RAG系统的设计者,目标不是实现市场上最前沿的分块技术,而是了解有哪些可用的选项,它们对你的数据有多合适,以及实施的成本和收益是否值得在你的系统中采用。

本节课中我们一起学习了三种高级分块方法论:语义分块、基于大语言模型的分块以及上下文感知分块。希望这次对分块技术的快速概览能为你做出这些决策奠定坚实的基础。

024:查询语句解析 🔍

在本节课中,我们将要学习生产级RAG系统中一个至关重要的步骤:清理和优化用户提交的查询提示。用户通常以对话方式与LLM交互,但这些自然语言提示往往不适合直接用于向量数据库检索。我们将探讨如何通过解析查询意图、改写或转换提示来优化检索效果。

查询解析的必要性

生产级RAG系统的一个重要步骤是清理用户提交的提示。

RAG系统通常部署在终端用户期望以对话方式与LLM交互的场景中,就像与另一个人聊天一样。因此,人类书写的LLM提示往往不适合作为检索查询。

与其将这些提示直接输入向量数据库,检索器可以解析提示以识别其意图,并编辑、改写或完全转换提示以优化检索效果。

有多种查询解析技术,让我们来看其中几种。

基础查询改写

处理杂乱提示最简单且目前应用最广泛的解决方案,是在将查询提交给检索器之前,使用LLM对其进行改写。

例如,考虑一个围绕医学信息知识库构建的RAG系统。

你可以设置一个LLM作为查询改写器,并赋予其如下提示:

以下提示由用户提交,用于查询一个链接症状与诊断的医学文档数据库。请通过以下方式改写该提示以优化其数据库搜索效果:澄清模糊短语,在适用时使用医学术语,添加能提高匹配文档几率的同义词,移除不必要或分散注意力的信息。

然后插入用户提示。

用户可能提交如下提示:

我出去遛我的狗,一只名叫Poppy的漂亮黑色拉布拉多,她突然从我身边跑开,在我牵着绳子时猛地一拽。😊。三天后,我的肩膀仍然麻木,手指也像针刺一样。这是怎么回事?

这个提示显然没有为检索进行优化。

以下是经过查询改写器处理后的改写提示:

肩部经历突然、猛烈的拉扯,导致肩部持续麻木和手指麻木三天。潜在原因或诊断是什么,例如神经病变或神经压迫。

这个新提示移除了不必要的信息,澄清了模糊之处,甚至使用了可能提高知识库匹配几率的医学术语。

虽然你可以并且应该迭代用于查询改写的提示,但从中获得的收益是巨大的,并且很容易证明为清理每个提示所需的额外LLM调用成本是合理的。

高级查询解析技术

虽然基础查询改写通常是你唯一需要考虑的查询解析技术,但确实存在更高级的技术。

例如,命名实体识别是一种识别查询中信息类别的技术,如地点、人物、日期、虚构角色等。这些信息随后可用于通知检索器执行的向量搜索,或流程后期的元数据过滤。

这里有一个名为Giner的模型示例,它是一个通用的命名实体识别模型。你可以给它一段文本,以及一个你希望它识别的实体类型列表,比如人物或日期。模型将分析查询并返回一个带有这些类别标识的标记化查询。

在这个特定示例中,我提供了一些输入文本,并告诉Giner模型尝试标记任何提及的人物、书籍、地点、日期、演员和角色。在响应中,你可以看到它标记了每次看到这些不同实体的地方。

这是一个非常高效的模型,我们可以在每次查询到来时运行它。包含这一步会增加一点额外的延迟,但检索质量因此可以得到显著提高。

另一个高级查询解析技术称为假设文档嵌入。

假设文档嵌入

这种方法通过生成一个理想的搜索结果——即假设文档——来优化搜索查询。

例如,如果你试图检索关于之前那个医学问题的信息,将使用一个LLM来生成一份关于因快速拉扯导致肩部和手部麻木的假设文档,然后嵌入该假设文档,并使用其向量表示来完成实际搜索。

这里的理念是,你不仅帮助检索器理解提示或问题的意图,还理解高质量结果应该是什么样子。

通常,检索器需要将提示与文档进行匹配。因此,在某种程度上,检索器是在匹配不同类型的文本,或者说是在比较苹果和橘子。

通过生成一个假设文档,检索器现在可以比较更相似的文本:一份假设的完美文档,以及知识库中实际包含的文档。

在实践中,HyDE确实能提供性能改进,代价是搜索中增加了一些延迟,以及运行生成假设文档的LLM所需的一些计算资源。

总结与建议

根据我的经验,拥有某种查询解析功能是RAG系统的关键部分。

在几乎所有情况下,基础查询改写——即使用一个精心设计的提示让LLM对用户提交的提示进行基本修饰——是正确的方法。

更高级的技术,如使用命名实体识别、HyDE等,可能会带来额外的好处,但它们运行起来可能更复杂,并且不一定能产生更好的结果。可以尝试这些高级技术,并让结果决定你的项目需要如何发展。

在本节课中,我们一起学习了RAG系统中查询解析的重要性。我们探讨了基础查询改写技术,它通过LLM优化用户提示以提高检索相关性;也介绍了命名实体识别和假设文档嵌入等高级技术,它们能进一步细化搜索意图和提升匹配精度。对于大多数应用,从基础查询改写开始通常是最佳实践。

025:交叉编码器与ColBERT模型 🧠

在本节课中,我们将要学习两种更先进的语义搜索架构:交叉编码器和ColBERT模型。我们将探讨它们的工作原理、各自的优缺点,以及它们如何在不同场景下提供比基础的双编码器更高质量的检索结果。

概述

到目前为止,我们所见的语义搜索技术都使用了基础的架构。每个文档和提示词都被分配一个单一的向量,通过比较这些向量来找到与提示词相似的文档或文本块。虽然这种方法效果很好,但使用更复杂的架构可以实现更高质量的检索。让我们来看看其中的两种:交叉编码器和ColBERT,并考虑它们的优缺点。

双编码器架构回顾

本课程中用于驱动语义搜索的架构被称为双编码器。文档通过嵌入模型被分配一个语义向量。当收到提示词时,它也会被嵌入成一个向量。然后,向量数据库使用近似最近邻算法来快速识别向量与提示词向量接近的文档。

术语“双编码器”指的是文档和提示词是分开嵌入的。这很重要,因为它意味着所有文档都可以提前嵌入,只需要在收到提示词后嵌入提示词本身,从而显著加快了搜索速度。

然而,如果你愿意牺牲一些速度,你可以获得更高质量的搜索结果。

交叉编码器:追求最高质量

让我们从交叉编码器开始,它可以提供比双编码器质量高得多的文档排序。

为了给文档打分,交叉编码器将文档与提示词拼接起来,然后将组合后的文本传递到一个本质上是专门的嵌入模型中。由于提示词和文档都在输入中,这使得模型能够理解提示词和文档文本之间深层的上下文交互,而这些交互可能是双编码器会遗漏的。

交叉编码器被设计为直接输出一个相关性分数,通常是一个介于0和1之间的数字。你可以将这个分数看作是提示词与文档之间匹配为正的概率。

以下是交叉编码器的工作原理。假设你的知识库中有三个文档,并且你收到了提示词:“great places to eat in New York”。

  1. 交叉编码器将提示词拼接到每个文档的前面。
  2. 每个“提示词-文档”对然后通过交叉编码器。
  3. 交叉编码器输出提示词与文档匹配的概率。

如果这是一个训练有素的交叉编码器,你会期望第一个文档得分相当高,比如0.7或70%,因为该文档与提示词相当相关。然后,你对每个文档重复这个过程:将提示词拼接到前面,通过交叉编码器架构传递“提示词-文档”对,并生成一个分数。

与双编码器相比,交叉编码器几乎总是能提供更好的搜索结果,这是通过搜索相关性等常见指标来衡量的。

交叉编码器的主要问题是其扩展性极差。你的知识库可能轻松拥有数百万甚至数十亿的文档,这意味着对于每一个提示词,你都需要通过交叉编码器运行数十亿个“文档-提示词”对来生成每个文档的相关性分数。你也不能进行任何预处理来加速,因为交叉编码器是在“提示词-文档”对上运行的,而在用户提交之前你不会有提示词。

因此,交叉编码器效率太低,无法作为默认的搜索技术,但其结果的质量使其成为改进其他搜索技术结果的绝佳工具,这一点你将在本课程稍后部分进行探索。

ColBERT:速度与质量的折衷

一些技术试图在双编码器的速度和交叉编码器的质量之间取得平衡。让我们来看看一个越来越受欢迎的最终架构,称为ColBERT

ColBERT代表“基于BERT的上下文化后期交互”。ColBERT的理念是,你仍然像在双编码器中一样提前生成文档向量,但试图像交叉编码器一样捕捉提示词文本与每个文档之间更深层的交互。

以下是其工作原理:

  1. 首先,对知识库中的每个文档进行嵌入。但不是为整个文档生成一个语义向量,而是为文档中的每个词元生成一个语义向量。因此,一个包含1000个词元的文档需要被转换成1000个密集向量。
  2. 当提示词传入时,它以同样的方式被嵌入,为提示词中的每个词元生成一个密集向量。

现在,ColBERT中打分的核心理念是,提示词中的每个词元都试图在文档中找到与其最相似的词元。

让我们看一个例子来了解它是如何工作的。我们使用之前相同的四个文档和提示词“Great places to eat in New York”,看看第一个文档是如何被打分的。

首先,算法找到文档和提示词中每对词元之间的向量距离,或者说相似度分数。如果提示词有10个词元,文档有100个,结果就是一个包含1000对相似度分数的网格。

这创建了一个网格,显示每个文档词元与提示词词元的相关程度。例如,提示词中的词元“New”和“York”会与文档中的“New”、“York”和“city”匹配得很好,而“eat”会与“cuisine”匹配良好。

每个提示词词元都会有一个与其具有最高相关性分数的文档词元。这些最高分数被求和,以得到整个文档的一个相关性分数。这被称为最大相似度分数

对知识库中的每个文档重复此过程,可以对所有文档进行评分并检索最相关的文档。

ColBERT既提供了双编码器的可扩展性,又提供了交叉编码器中发现的提示词与文档之间的大部分丰富交互。虽然对每个“文档-提示词”对进行评分所需的计算量比双编码器更大,但它仍然相当快,可以在需要实时或接近实时搜索的上下文中使用。

ColBERT架构的最大缺点是,你需要存储的向量数量与提示词和文档中的词元数量成比例增加。如果你有一个2000个词元的文档,你需要存储2000个向量。而在双编码器中,你只需要存储一个密集向量。

架构对比与总结

在本节课中,我们一起学习了三种主要的语义搜索架构:

  • 标准双编码器模型提供了相当好的质量、极快的速度,并且需要最少的向量存储空间。这组特性使其成为语义搜索的默认架构。
  • 交叉编码器在搜索质量方面提供了黄金标准,但它们速度太慢,以至于无法作为默认搜索技术使用。
  • ColBERT提供了接近交叉编码器的质量,但速度更接近双编码器。这种权衡的代价是它需要存储数量级更多的向量数据。

越来越多的向量数据库开始提供对ColBERT或类似方法的支持,特别是对于需要精确性和深度上下文理解的项目。例如,在法律或医学领域,为了搜索质量而显著增加向量存储内存占用可能是值得的。

交叉编码器本身用于搜索的计算成本太高,但幸运的是,它们并不需要单独使用。在下一个视频中,我们将一起看看交叉编码器是如何被集成到生产检索系统中的,尽管它们效率低下。

026:结果重排序技术 🎯

在本节课中,我们将要学习一种结合多种搜索技术优势的方法——结果重排序。这是一种在向量数据库初步检索之后,使用更强大但成本较高的模型对文档进行重新评分和排序的技术,旨在确保返回最相关的文档。

概述

上一节我们介绍了混合搜索,本节中我们来看看如何通过“重排序”技术进一步提升检索质量。重排序是在向量数据库返回初始结果集之后、将结果发送给大语言模型之前的一个后处理步骤。其核心在于利用更强大的模型对已检索到的文档进行重新评分和排序。

重排序的工作原理

重排序旨在改善已检索到的文档或文本块集合的质量。一旦向量数据库返回结果,重排序器便会介入,使用性能更强但成本更高的模型对这些检索到的文档进行重新评分和排序。

由于只需要对少量文档进行重评分和重排序,因此可以使用那些在搜索整个知识库时因成本过高而不切实际的高性能模型。

让我们看一个简化的例子。如果用户提问是“加拿大的首都是什么?”,你的向量数据库可能会检索到语义相关但并未直接回答问题的文档。

例如:

  • “多伦多在加拿大。”
  • “法国的首都是巴黎。”
  • “加拿大是世界枫糖浆之都。”

这些句子都与提问有某种语义关联,但最终都没有回答问题。这时,重排序器就可以介入,对这些结果进行重新评分和排序,从而最终只返回真正相关的文档。

重排序的实施流程

在使用了重排序器的系统中,你通常会在初始的向量数据库检索中“过量获取”文档。

以下是典型的实施步骤:

  1. 初始检索:使用混合搜索等方法,检索出较多数量的文档(例如20到100个)。
  2. 重排序:重排序器对这些文档进行重新评分,生成最终的排名。

最终,你仍然只返回向量搜索检索到的文档中的一个子集(例如,得益于重排序器,返回5到10个)。然而,这些经过重排序的文档将比仅进行简单混合搜索得到的结果相关性高得多。

重排序模型架构

通常,重排序器采用交叉编码器架构。

正如之前所见,交叉编码器比标准的双编码器能提供更好的结果,但速度明显更慢,对于数百万或数十亿的文档来说不切实际。然而,如果双编码器已经缩小了需要考虑的文档列表范围,那么在质量与时间之间的权衡就变得合理得多。

即使只对通常的20到100个文档进行重排序,交叉编码器也会给整个系统增加一点延迟。但这种权衡几乎总是值得的。

基于大语言模型的重排序

目前,基于大语言模型的重排序也越来越被使用。其思路与交叉编码器相当类似,但不是将“提示-文档”对提供给交叉编码器进行重排序,而是直接提供给一个大语言模型。专门为此任务设计的大语言模型能够分析这对信息,评估其相关性,并返回一个数值化的相关性分数。

虽然前景看好,但这种方法本质上和交叉编码器一样低效。在两种情况下,都必须等到收到提示后才能开始评分,并且对单个文档进行评分仍然是一个相对昂贵的操作。因此,基于大语言模型的评分方法可能会进一步改进,但它将始终是一种重排序技术,只能在典型的向量搜索缩小了需要重排序的文档列表之后使用。

重排序的优势与实现

虽然RAG系统并不严格要求使用重排序,但它通常很容易实现,并且能为许多向量数据库带来更好的性能。实现起来可以像在你的搜索查询中添加一行代码一样简单,表明你想要使用重排序器。

因此,当试图提高搜索相关性时,使用重排序器是你应该首先考虑添加到RAG流程中的技术之一。通常,你可以过量获取15到25个文档,然后在它们之间进行重排序,从而以增加少量延迟为代价,显著提升相关性。

总结

本节课中我们一起学习了结果重排序技术。我们了解到,重排序是一种在初步向量检索之后,使用高性能模型(如交叉编码器或专用大语言模型)对结果进行二次评分和排序的后处理步骤。它通过“过量获取再精筛”的策略,有效提升了最终返回给大语言模型的文档的相关性,是优化RAG系统检索质量的一个简单而强大的工具。

027:总结 🎯

在本模块中,我们一起学习了构建高效检索器的核心技术与方法。现在,让我们对所学内容进行回顾与总结。

模块回顾 📋

以下是本模块涵盖的主要知识点:

首先,我们介绍了近似最近邻算法。该算法执行向量搜索的速度远快于暴力最近邻搜索,其代价是可能无法在知识库中找到绝对最佳匹配的文档。

接下来,我们认识了向量数据库。这类数据库专为存储高维向量数据和执行近似最近邻搜索而优化,使其成为扩展RAG系统时的首选数据库。

之后,我们探讨了生产级RAG系统中常用于提升检索效果的几种技术。文档分块将文档分割成更小的片段,使向量能更精确地捕捉文本片段的含义,并减少在大型语言模型上下文窗口中的占用空间。查询解析优化用户提交的提示词,使其更适合检索。最后,重排序利用高性能架构,在向量数据库通过标准混合搜索检索到的文档集合中,更好地识别相关文档。

对于上述每种技术,我们既学习了适用于大多数项目的标准方法,也了解了一些有时能进一步提升检索器性能的高级技巧。

最后,在模块末的实践项目中,我们亲手应用了这些概念,在一个功能性的RAG系统中实现了它们。

技能掌握 ✅

现在,你已经掌握了建立强大检索器所需的所有技能。

后续展望 🚀

接下来,是时候将注意力转向RAG系统的另一个主要组件了——那个将实际处理所有检索到的文档并生成响应的大型语言模型。

所以,请加入下一个模块,让我们一起深入探索如何最大限度地发挥大型语言模型的潜力。

028:大语言模型简介 🧠

在本模块中,我们将要学习大语言模型(LLM)在检索增强生成(RAG)系统中的核心作用。我们将了解其工作原理,并学习提升其在RAG系统中表现的具体技术。

检索器是RAG系统的关键部分,但大语言模型才是整个操作的核心大脑。检索器能够查找并准备有用的信息,但最终需要由大语言模型来实际使用这些信息,以生成高质量的回应。

学习内容概览

以下是本模块将要深入探讨的核心内容。

  • 深入理解架构:我们将深入探讨大语言模型所基于的Transformer架构
  • 构建LLM调用:学习如何在代码中构建对大语言模型的调用。
  • 迭代优化工作流:在基础工作流之上进行迭代,确保大语言模型能够基于检索器提供的信息,生成高质量且有理有据的回应。

技术与实践

上一节我们介绍了本模块的学习框架,本节中我们来看看具体会涉及哪些技术与实践。

  • 高级技术:我们将看到一些能够突破大语言模型性能极限的先进技术。
  • 实用建议:同时,我们也会获得关于在典型RAG项目中哪些方法往往行之有效的实用建议。

动手实践环节

与往常一样,在本模块的最后,你将找到一个动手编程作业。你将有机会基于本模块所涵盖的主题,亲手构建一个RAG系统。

我希望你能享受动手实践大语言模型的乐趣。请加入下一节视频,让我们正式开始学习。

029:Transformer架构解析 🧠

在本节课中,我们将要学习Transformer架构的核心工作原理。理解这一架构是理解大语言模型(LLM)如何工作,以及为何检索增强生成(RAG)系统能够有效的基础。

上一节我们介绍了如何将检索到的文档构建成增强提示。本节中,我们将深入一层,探讨大语言模型为何能够理解这些检索到的信息。

为什么需要了解Transformer?

你的检索器返回了一系列相关文档,你已准备好构建增强提示。将其发送给大语言模型,就能得到基于检索信息的回答。在本课程中,你已多次见过这个过程。现在是时候深入一步,问一问:这为什么能行得通?大语言模型是如何理解那些检索到的信息的?更重要的是,你如何利用这些知识来构建更强大的RAG系统?为了解答这些问题,我们需要深入了解大语言模型所基于的Transformer架构。

Transformer的起源与构成

Transformer架构由2017年一篇名为《Attention is All You Need》的开创性论文提出,该论文主要聚焦于机器翻译问题。Transformer包含两个主要组件:一个编码器和一个解码器。编码器会处理原始文本(例如一段德语段落),形成对段落含义的深度上下文理解。解码器则会利用对德语段落的这种深度理解,生成其对应的英语版本。

大多数大语言模型只包含第二个组件,即解码器,因为它们只关心文本生成。而编码器则通常用于嵌入模型内部,因为其目标是生成丰富的文本语义表示。

提示词在大语言模型中的旅程

让我们追踪一个提示词在大语言模型(也就是Transformer的解码器组件)中的旅程。

第一步:分词与初始嵌入

首先,你的提示词会被分割成一个个词元。文本被分词后,每个词元会被分配一个初始的密集向量表示。这个向量基本上是对该词元含义的“第一猜测”。这些猜测是静态的,因此每次你向大语言模型输入相同的词元,它都会被分配相同的“第一猜测”向量。

接下来,每个词元会被赋予一个位置向量,用于捕捉它在提示词中的位置。一旦这些“第一猜测”嵌入向量和位置向量被创建出来,它们就会被送去进行下一步处理。

第二步:注意力机制

现在,词元们进入了Transformer的注意力机制。每个词元本质上都会“看”提示词中的其他每一个词元,并能看到它们的含义和位置。

然后,每个词元会决定它应该最关注哪些其他词元。

注意力本质上是一种花哨的说法,指的是“哪些其他词元应该对我的含义产生最大影响”。

在一个句子中,例如“The brown dog sat next to the red fox.”,单词“dog”可能会最关注“brown”和“sat”,因为这些词与“狗”直接相关。你可以认为“dog”将其70%的注意力分配给“brown”,20%给“sat”,剩下的10%分配给所有其他词元。

用于分配这种注意力的机制被称为一个“注意力头”。实际上,大多数模型包含许多注意力头,它们专门处理词语之间不同类型的关系。你可以这样理解:一个注意力头专门处理对象与其描述之间的关系(因此单词“fox”可能会将其所有注意力集中在“brown”上)。另一个注意力头可能专门处理对象之间的空间关系(因此在该注意力头中,“fox”可能会更多地关注“sat”和“next”)。

实际上,每个注意力头捕获的关系并非由人类分配的一套整齐的关系,而是在模型训练过程中学习到的一套复杂而抽象的关系集合。

较小的模型可能使用8到16个注意力头,但较大的模型可能使用超过100个。这一点之所以重要,是因为不仅每个词元都在追踪它与文本中其他每个词元的关系,而且它们会以许多不同的视角或焦点多次进行这种追踪。结果是,注意力机制对文本中所有词元之间的关系形成了非常详细的表示。

第三步:前馈网络

一旦每个词元都分配了其所有的注意力分数,信息就进入了前馈阶段。这是迄今为止大语言模型中最大的部分。这意味着,它包含了迄今为止最多的参数。

基于每个词元的原始嵌入、位置和注意力信息,它为每个词元分配更新后的向量嵌入。这些新向量基本上是对每个词元真实含义的“第二猜测”,但现在这个猜测受到了文本中其他词元上下文的影响。

大多数大语言模型会重复整个过程。“第二猜测”向量被反馈到注意力和前馈机制中,生成新的、更精细的关于每个词元含义的“第三猜测”向量。一个典型的大语言模型实际上可能会将这些向量通过这些层传递8到64次,在每个阶段逐步完善其理解。

第四步:生成与采样

现在,大语言模型准备基于其生成的高度精细的向量嵌入开始生成内容。模型会问:根据我的训练数据,接下来可能出现哪些词元?这被计算为模型词汇表中所有词元的概率分布。

通常,少数几个词元具有较高的出现概率。但如果你的模型识别10万个词元,每个词元都会被分配一个概率,即使绝大多数概率基本上为零。

最后,大语言模型从这个分布中挑选一个词元,选择时会根据每个词元被分配的概率进行加权。概率高的词元被选中的频率更高,但从理论上讲,任何词元都至少有一点点被选中的机会。你将在本模块后面学习如何调整这些概率,从而影响大语言模型选择新词元的方式。

被选中的词元会被附加到提示词的末尾。经过所有这些工作,大语言模型生成了一个额外的词元。如果你想生成第二个词元,模型必须重复整个过程,只是这次需要考虑原始词元以及它自己添加的那个词元。这确保了新词元在原始词元及其自身生成的词元的上下文中都是有意义的。这也意味着早期随机的词元选择也会影响后期被选中的词元。

为了生成一个完整的补全内容,模型会一遍又一遍地重复这个过程,直到达到你为该补全设置的词元限制,或者它选择生成一个特殊的“补全结束”词元,表明它已完成。

大语言模型生成的词元可能完成一个短语,或回答一个问题。但无论其目的是什么,它们都可以被反分词成纯文本并返回给用户。

Transformer架构对RAG系统设计的启示

我们刚刚经历了一次大语言模型的内部旅程。现在,让我们看看Transformer架构的哪些部分启发了RAG系统的许多设计元素。

以下是Transformer架构对RAG设计的几点关键启示:

第一,它有助于解释RAG为何有效。 大语言模型能够深刻理解添加到提示词中的信息的含义和相关性。这要归功于注意力机制所做的处理以及前馈层中包含的世界知识。

第二,它强调了大语言模型本质上仍然是随机的。 即使你在提示词中注入了有意义的信息,大语言模型也可能随机地选择不基于该信息生成文本。😊 控制这种随机性,并确保你的大语言模型将其答案建立在检索到的信息之上,仍然是必要且重要的。

第三,它凸显了大语言模型的计算成本有多高。 😡 生成单个词元需要大量处理,而且这个成本实际上会随着提示词或补全内容的长度增加而增长。毕竟,每个词元都需要“看”其他每一个词元,以充分理解自身的含义。正如你稍后将探索的,运行RAG系统的大部分成本来自于运行这些强大但昂贵的Transformer模型。

总结

本节课中,我们一起深入探讨了大语言模型内部的工作原理,特别是其核心的Transformer架构。我们了解了提示词从分词、嵌入,到经过注意力机制和前馈网络的多层处理,最终生成新词元的完整过程。更重要的是,我们看到了这种架构如何解释了RAG系统有效的原因,并指出了大语言模型固有的随机性和高昂的计算成本,这些都是在设计和优化RAG系统时必须考虑的关键因素。

现在,让我们将注意力(无意双关)转向如何在RAG系统中优化大语言模型的行为。

030:LLM采样策略 🎯

在本节课中,我们将要学习如何理解和控制大型语言模型生成文本时的随机性。理解并调整LLM的采样策略,是优化其输出行为、使其更符合应用需求的关键。

概述

与大型语言模型合作的一个重要部分是理解并控制其运行核心的随机性。本节我们将通过一个典型的LLM API,探索其提供的不同选项,以控制LLM选择下一个标记的方式。

理解LLM的随机选择

大型语言模型为你的补全内容添加的每一个标记,都是一个加权的随机选择。

如果你使用开源的语言模型,你可以看到这个选择是如何做出的。这些模型允许你查看每一步生成的标记概率分布,这个分布被用来选择下一个标记。

例如,对于提示词 “the sky is”,其概率分布可能如下所示:“blue”有50%的概率成为下一个词,“bright”有25%的概率,其他所有标记的概率都在10%或以下,并迅速降至1%以下。

以下是该分布的可视化表示。

当曲线在左侧有一个高耸的尖峰时,可以说模型对其选择非常有信心,只有一两个其他标记有被选中的真实机会。

另一方面,像这样平坦的分布可以被解释为模型的不确定性。模型有许多可能的方向可以选择,没有明确的胜出者。

理解和控制这个分布曲线,是调整LLM行为的重要部分。接下来,我们来看看几种实现此目标的策略。

采样策略详解

以下是几种控制LLM输出随机性的核心策略。

贪婪解码

一种简单的方法是指导LLM不进行随机选择,而总是选择概率最高的标记。这被称为贪婪解码

贪婪解码的主要优点是它使LLM具有确定性。如果你给模型相同的提示,它总是会生成相同的响应。

贪婪解码的主要缺点是它可能导致文本过于可预测。最终生成的文本可能感觉平淡甚至生硬。

贪婪解码的另一个问题是,语言模型有时会陷入重复生成相同单词序列的循环。LLM实际上并不关心整体补全内容是否有意义,它只是不断选择可能性最高的下一个标记。一旦模型陷入重复循环,就没有机制可以摆脱它。

尽管存在这些潜在的缺点,在需要高度可预测和确定性输出的场景中,贪婪解码是有意义的,例如代码补全,或者作为调试系统的临时设置。

温度参数

在大多数情况下,你并不想完全消除随机性,只是想控制它。控制LLM随机性最广泛使用的参数叫做温度

你可以将温度想象成一个旋钮,它可以改变你的语言模型生成的概率分布形状。默认温度值1会给出原始分布。较低的温度会导致分布更加尖锐,只有最有可能的标记才有机会被生成。

标记的排序不会改变,但它们被选中的概率会改变。将温度一直调到0,会使模型执行贪婪解码,只有单个最可能的标记拥有100%的概率。

将温度调高一点,比如在1.1到1.3的范围内,会使概率分布变得平坦,给不太可能的标记多一点被选中的机会。这会导致更多样化,有时甚至是更有趣或听起来更有创造性的文本。

将温度设置得太高,会导致非常平坦的概率分布。所有标记被选中的机会大致相等,即使它们可能不太合理。

Top-K 与 Top-P 采样

无论你将LLM的温度设置为多少,分布曲线仍然会有一条向右延伸的长尾,充满了无意义的标记。你的LLM仍有很小的可能性选择它们。为了帮助控制这一点,会使用一些额外的采样技术。

Top-K采样是最简单的,它将LLM的选择限制在概率最高的前K个标记中。例如,你可以将温度设置为1.1,但同时限制LLM只能从前五个最可能的下一个标记中选择。

Top-P采样是一种类似的方法,它将语言模型的选择限制在累积概率低于某个阈值的标记中。例如,你可以将Top-P设置为85%。你会从分布的左侧开始,不断累加每个标记的概率,直到总和大于85%。

Top-P往往是这两种方法中反应更灵敏或更动态的一种。在Top-K中,LLM总是从相同数量的标记池中选择,而不考虑分布的形状。而在Top-P中,如果LLM相当确定(意味着少数标记具有非常高的概率),LLM会将其选择限制在最有可能的几个标记内。相反,如果LLM更不确定(意味着分布平坦,没有明确的最佳选择),则允许LLM从更大的潜在标记池中进行选择。

针对特定标记的策略

一些技术也针对单个单词的概率,而不是分布的整体形状。

例如,大型语言模型可能倾向于重复使用相同的单词或短语,这听起来可能不自然。许多LLM允许你应用重复惩罚,这会降低已经出现在补全内容中的单词的概率。这可以使生成的文本听起来更自然、更多样。

大多数LLM还允许你增加或减少特定标记的概率,这通常被称为对数偏置。这种偏置会永久性地向上或向下调整这些标记被选中的概率。

如果你不希望你的RAG系统生成亵渎语言,你可以将某些词的权重调低。另一方面,如果你的RAG系统是一个旨在输出少数几个类别之一的分类器,你可以提高这些类别的概率,以确保LLM总是在它们之间进行选择。

参数组合示例

以下是一个结合了本视频中介绍的多种技术的API调用示例。

这是一个相当合理、通用的参数组合:温度设为0.8,Top-P设为0.9,重复惩罚设为1.2。这个LLM在标记选择上会稍微保守一些,避免从分布的长尾部分选择,并轻微惩罚重复的标记。

通过试验每个参数,你可以根据应用程序的上下文,精确调整LLM的行为。

总结与建议

本节课中,我们一起学习了控制LLM固有随机性的多种技术,本视频仅涵盖了最常见的一部分。

总的来说,我建议设置最适合你需求的温度和Top-P值。如果你正在生成代码或回答事实性问题,较低的温度和较低的Top-P是有意义的。如果你在更具创造性的领域工作,较高的温度和Top-P可以给你的LLM带来更有趣和探索性的语气。

之后,可以考虑引入重复惩罚、对数偏置或你研究的其他采样技术,以应对你在LLM性能表现中发现的具体问题。

最终,理解有多种方法可以调整LLM的随机选择,并迭代找到适合你项目的设置,将使你获得所需的性能。

031:大模型选择方法论 🧠

在本节课中,我们将要学习如何为你的RAG应用选择合适的大语言模型。这是一个关键决策,会直接影响应用的性能、质量和成本。

构建RAG应用时,一个主要的决策是选择使用哪个大语言模型。市面上有大量不同性能水平、独特能力和成本结构的大语言模型可供选择。选择正确的模型对你的应用速度、质量和预算都有重大影响。因此,让我们来看看如何做出最适合你项目的选择。

可量化的差异

上一节我们介绍了选择模型的重要性,本节中我们来看看一些易于量化的模型差异。

模型大小是一个经常被引用的指标,通常以模型拥有的参数数量(以十亿计)来衡量。小型模型可能拥有1到100亿个参数,而大型模型则拥有1000到5000亿甚至更多。大型模型通常(但不总是)比小型模型能力更强,但运行成本也总是更高。

成本当然是一个重要因素。模型提供商通常按每百万个令牌的固定价格收费,有时输入和输出令牌的价格不同。通常,更新、更大、能力更强的模型成本更高。

模型的上下文窗口告诉你一个模型能处理的最大令牌数,这些令牌在提示词和生成内容之间分配。虽然大的限制提供了处理长提示词和长回复的灵活性,但你仍需为每个令牌付费。

首令牌生成时间和速度(以每秒令牌数表示)是另一个重要因素。如果你的RAG系统依赖于实时交互,你可能愿意为了一个快速、低延迟的模型而容忍其他方面稍差的性能。

模型的训练截止日期或知识截止日期告诉你模型训练数据所代表的最新时间点。即使在RAG系统中,较晚的截止日期通常也被认为是更可取的,尤其是在模型需要回答近期事件相关问题的场景下。

模型质量评估

虽然易于量化的指标可以帮助缩小模型选择范围,但你通常最关心的是模型的质量,而质量则更难量化。这里的“质量”涵盖了一切,从大语言模型解决复杂数学问题的推理能力,到仅仅生成可读性强的文本。

为了帮助在所有这些不同的质量维度上比较模型,存在大量令人眼花缭乱的大语言模型基准测试,试图对模型进行评分和比较。没有一个单一的权威基准测试列表可供参考,但了解可用的各种选项可以帮助你选择最适合你项目的基准测试。

以下是三种主要的基准测试类型:

  • 自动化基准测试:这类基准测试通过代码可评估的任务来给大语言模型打分。一个经典的格式可能是针对特定兴趣领域的多项选择题测试,或一系列数学或编程挑战,其中模型的回答可以由计算机轻松验证。一个很好的例子是MMLU,它使用多项选择题涵盖了从STEM到人文再到法律的57个学科。
  • 人工评分基准测试:这类基准测试通常让两个匿名的大语言模型回答同一个提示词,然后请人类评估者选择他们更喜欢的回答。这些结果被输入用于国际象棋选手排名的Elo算法,从而生成大语言模型的比较排行榜。一个流行的此类评级系统是LMS Arena,其排名是被引用最广泛的大语言模型基准之一。
  • 大语言模型作为评委的基准测试:这类基准测试使用一个大语言模型来评判另一个大语言模型对一系列测试问题的回答。作为评委的大语言模型可以访问一组参考答案,本质上只是判断被评估的大语言模型提供的答案有多接近正确答案。这为你提供了一个胜率,可用于比较不同的大语言模型。

优秀基准测试的特征

上一节我们介绍了不同类型的基准测试,本节中我们来看看一个好的基准测试应具备哪些特征。

好的基准测试有几个特征。首先,它们与你的项目相关。如果你的应用永远不会生成代码,那么在大语言模型的代码生成基准测试上进行比较就没有多大帮助。

其次,基准测试需要足够困难,才能很好地区分高性能和低性能模型。如果每个模型在某个基准测试上得分都很高,那么这个基准测试就没那么有用。

基准测试应该是可复现的,这意味着分数本身在不同测试运行之间不会发生剧烈变化,并且模型提供商引用的结果应该是可验证的。

基准测试还应与实际性能保持一致。一个在编程基准测试上表现良好的大语言模型,在实践中也应该能写出好代码。在这里,你可能需要阅读一些开发者论坛,以确保基准测试分数能很好地反映实际性能。

这个问题可能出现的一个原因是数据污染。大语言模型是在从互联网抓取的数十亿甚至数万亿令牌上训练的。基准测试使用的数据集有可能被包含在这些训练数据中。在这种情况下,语言模型可能在该基准测试上表现过好,因为它已经在训练中见过完全相同的问题和答案。

基准测试的演变

虽然基准测试可以帮助你区分模型,但它们也突显了整个领域的发展速度有多快。

以下是大多数人工智能模型评估中会重复出现的普遍模式。起初,每个基准测试的平均分数相当低。然后,仅仅几年时间,模型的表现与人类专家持平就变得司空见惯。这些基准测试被称为饱和,意味着它们不再有助于区分模型,因为几乎所有先进模型的得分都接近最大值。在这一点上,需要引入新的、更具挑战性的基准测试来有意义地衡量性能的改进。然而,这些新的评估本身也会迅速饱和,甚至需要引入更新的评估。

这里的主要启示是,今天发布的模型通常比几年前发布的模型要好得多。而且,你今天选择的任何模型,随着更强大的模型快速推出,很可能都需要被替换。

总结

本节课中我们一起学习了如何为RAG系统选择大语言模型。选择合适的大语言模型是设计RAG系统的一个重要但暂时的决策。像成本或延迟这样的易于量化的因素可以帮助缩小选择范围,而各种各样的质量指标可以指引你找到最适合你用例的最佳模型。由于模型改进的速度很快,你应该计划最终换入适合你RAG系统的新发布模型。

032:增强指令构建 🧠

在本节课中,我们将学习如何通过提示工程技术,构建高质量的指令来充分发挥大型语言模型的潜力,从而提升RAG系统的整体性能。

理解提示构建格式

为了有效地构建提示,首先需要了解在代码中实现它的常见格式。最常用的格式是OpenAI的消息格式。

该格式使用简单的JSON结构,将提示组织为一系列消息。每条消息包含content(消息的文本内容)和role(角色)。角色可以是systemuserassistant

  • 系统消息:提供给LLM,用于影响其整体行为,通常包含高级指令。
  • 用户消息:记录系统用户已发送的提示。
  • 助理消息:记录LLM先前生成的回复。

当您与LLM进行多轮对话时,LLM并不会“记住”之前的对话。实际上,整个对话会在后台被转换成这种消息格式,您的新用户消息会附加在末尾。然后,每次提交新的用户提示时,整个对话历史都会连同新消息一起提交给LLM处理。

JSON消息对象随后会被转换成一个单一的文本字符串供LLM处理。这个聊天模板字符串使用特殊的文本标签(如尖括号或竖线)来指示每条消息的开始和结束。LLM经过训练,能够识别这些标签并理解系统、用户和助理消息之间的区别。

这种格式非常灵活,允许您向提示中添加各种上下文信息,以帮助控制LLM的响应方式。接下来,我们看看几种具体的应用方法。

编写系统提示

为您的RAG系统构建提示时,首先要做的是编写系统提示。这为您的LLM提供了关于其应如何行为的高级指令。

如果您希望LLM始终以特定的语气说话或遵循某些流程,这些信息就应该放在系统提示中。为了了解系统提示可以包含哪些内容,可以看看一个流行的LLM聊天机器人的系统提示示例。

首先引人注目的是它的长度——非常长。虽然您不一定总是需要编写多段式的系统提示,但知道您有这种灵活性是很好的提醒。在提示的开头部分,包含了模型训练数据的知识截止日期以及当前日期等信息。这类信息帮助LLM判断其信息有多过时,以及它是否有能力回答某些问题。

后面的部分则指导LLM响应提示时应遵循的流程和语气。例如,它要求模型逐步推理答案、不协助可能有害的请求,并以Markdown格式回复。系统提示还告诉LLM,它具有求知欲,喜欢听取人类对问题的看法,并乐于就广泛的话题进行讨论,这可以说是赋予了LLM一种特定的“个性”。

您可以运用相同的原则来构建自己的系统提示。例如,您可以指示LLM详细回答或简洁回答问题。鉴于您正在为RAG应用程序构建系统提示,您可以告诉语言模型仅使用检索到的文档来回答问题,或判断文档是否相关,或在回复中引用来源。

系统提示通常会被添加到LLM将要处理的每一个提示中,因此花时间优化系统提示是提升RAG系统最终生成结果的风格和质量的有效方法。

构建增强提示模板

此时,您已准备好构建增强提示。这个提示可能包含许多信息片段,因此构建一个经过深思熟虑的提示模板会很有帮助。模板设定了提示的高级结构,并有助于决定某些内容片段将被插入的位置。

例如,您可以始终以一个高级系统提示开始,为系统提供关于其应如何行为的高级指导。如果您的系统支持多轮对话,您可以包含用户和LLM之间先前发送的消息。接下来,您可以添加检索器检索到的前5个或前10个文本块,以及任何关于如何处理它们的说明。最后,您可以附上LLM需要回应的最新用户提示。

以下是一个根据此模板构建的提示可能的样子。使用这样的模板的好处在于,它使得尝试不同的提示结构变得容易。您可以修改整体提示的各个组成部分,并观察这如何影响最终生成的响应。

总结与展望

本节课中,我们一起学习了如何为RAG系统构建高质量的提示。我们首先了解了OpenAI消息格式这一核心构建方式,它通过systemuserassistant三种角色组织对话。接着,我们重点探讨了编写系统提示的重要性,它可以设定LLM的行为准则、知识范围和回复风格。最后,我们介绍了如何利用提示模板来系统性地组织系统指令、检索到的上下文、历史对话和当前用户问题,从而构成一个完整的增强提示。

这就是在RAG系统中构建典型提示的过程:结合精心编写的系统提示、检索到的上下文、先前的对话细节,当然还有最新的用户提示。在下一个视频中,让我们一起来看一些进一步改进LLM性能的高级技术。

033:高级提示工程技术 🧠

在本节课中,我们将学习如何为你的RAG系统应用更高级的提示工程技术,以提升大语言模型(LLM)的响应质量。我们将探讨上下文学习、思维链提示等核心方法,并了解如何管理日益增长的上下文窗口。


一旦你为RAG系统设置了基础的提示模板,就可以开始尝试更高级的提示工程技术。让我们看看其中几种技术以及它们的使用场景。

上下文学习

上下文学习是一种技术,它允许你通过向提示中添加示例,来帮助LLM学习你期望生成的输出类型。

例如,如果你正在构建一个客户服务聊天机器人,你的提示可以包含过往客户请求的示例,以及对这些请求的高质量回复。这些示例帮助LLM学习在生成新回复时应使用的结构和语气。就像在RAG中一样,你是在向提示中添加额外信息,以“锚定”LLM的响应方式。

如果你包含多个示例,这种方法被称为少样本学习。如果只包含一个示例,则被称为单样本学习

实现上下文学习有几种方式。在需要稳定LLM行为的情况下,你可以直接将一个或多个示例问题和回复硬编码到提示中。仅此一项就可能有助于提高响应质量。然而,如果你想每次更换示例,则可以使用RAG从你的知识库中检索示例问题和回复。

例如,如果你正在处理同一个客户服务聊天机器人,你可以将成功的客户聊天记录索引到向量数据库中。当新客户就某个特定主题发来消息时,你可以检索关于该主题的过往对话文本,并将其注入到你的提示中。

在许多方面,这只是普通的RAG。但你专门检索示例回复这一事实,可以进一步帮助提高LLM响应的质量。

引导推理的提示技术

上一节我们介绍了如何通过示例引导模型,本节中我们来看看另一类强大的提示工程技术集合,它们本质上鼓励LLM以逐步推理的方式处理提示。

例如,你可以告诉LLM在提供最终答案之前,先“大声思考”或“逐步思考”解决问题的最佳方法。其理念是,你本质上为语言模型提供了一个“草稿纸”,让它在回答前组织思路。

一种常见的方法是告诉LLM,位于 scratchpad 标签之间的标记被视为思考和头脑风暴的空间,不属于其最终答案的一部分。

类似的方法被称为思维链提示。在这种方法中,LLM被指示以逐步的方式处理问题,而不是立即回答。LLM可能被指示先生成回答问题所需的步骤,然后遵循这些步骤。

鼓励LLM进行规划和采取这种渐进式方法,可以增加最终响应更准确的可能性。由于LLM会“展示其工作过程”,因此当LLM的推理出现问题时,也更容易追踪问题所在。

像这样的面向推理的策略非常成功,以至于现在许多LLM在设计时就是开箱即用的推理模型。推理模型擅长复杂的推理任务,例如编码、数学、规划、谜题以及需要多个步骤的复杂工作流。

在内部,这些推理模型首先生成推理标记,它们可能在其中提前计划和考虑选项,很像之前看到的草稿纸。然后,它们输出响应标记,其中包含给用户的预期最终响应。

一些推理模型的提供商只允许访问那些最终的响应标记,而另一些则允许你同时访问推理标记。这些推理标记是使这些模型比非推理模型更准确的部分原因,但它们仍然只是常规标记,生成它们会产生所有相关的成本。因此,运行推理模型通常更慢且更昂贵。

根据你的具体情况,围绕推理模型构建RAG系统可能非常值得付出每次LLM调用更高的成本。例如,推理模型可能特别擅长评估检索文档的相关性,并且可能更擅长决定如何最好地将这些信息整合到响应中,尤其是需要更复杂推理步骤的响应。

有趣的是,许多提示工程技术对推理模型效果不佳。例如,你不需要要求它们逐步思考,因为这是它们已经训练过要做的事情。它们也可能不擅长上下文学习,因为它们会尝试将提供的示例回复整合到当前正在回答的问题中。它们往往在你有明确希望它们达成的具体目标,以及你希望它们遵循的非常具体的回答格式信息时,表现更好。

你仍然可以提供高层次的指导原则,并明确说明你希望模型采取或避免的方法。之后,你可以直接将从RAG系统检索到的整个文档上下文“倾倒”给它们。

包括推理模型在内的新模型不断发布,大多数LLM提供商会包含关于如何最好地提示它们的信息。

上下文窗口管理

随着你开始采用更多的提示工程技术,上下文窗口管理将变得重要。请记住,初始提示和LLM为补全生成的任何标记,都会占用其上下文窗口的一部分。

无论你是从检索器中注入文档、向每个提示添加上下文学习示例,还是让推理模型在回答问题前规划其响应,所有这些高级技术都会增加你的提示长度、生成的响应长度或两者兼而有之。如果你不注意,很容易迅速填满你的上下文窗口。

对于单轮对话,最好的解决方法是验证你的提示工程技术是否带来了价值。如果思维链提示或上下文学习没有带来更好的性能,最好将这些组件从你的系统中移除。

多轮对话会迅速消耗你的上下文窗口,因为每次来回的消息都需要包含在提示中。一系列统称为上下文修剪的方法可以解决这个问题。

以下是几种上下文修剪的方法:

  • 简单方案:在提示中只保留固定数量的最近消息。例如,用户和LLM发送的最后五条消息。
  • 更复杂的方法:使用一个单独的LLM来总结较早的消息,缩小其大小,但保留其关键点。

如果你在多轮对话中使用推理模型,几乎肯定需要从聊天历史中删除推理标记,只保留响应标记。同样,在RAG系统中,通常只希望包含为支持回答最近问题而检索到的文本块,而不是之前所有问题的文本块。

当然,如果你的应用程序需要具有深入丰富上下文的多轮对话,你总是可以切换到使用具有更长上下文窗口的模型。即便如此,你仍然需要仔细考虑如何设计提示,因为即使在具有较长上下文窗口的模型上,长提示运行起来也慢且昂贵。

总结与实践建议

本节课中我们一起学习了多种高级提示工程技术,包括上下文学习和引导推理的方法,并了解了管理上下文窗口的重要性。

提示工程技术可以提高LLM的性能,但你的RAG系统不一定需要采用它们。一个简单的提示模板和一个精心编写的系统提示可能就是你项目所需的全部。

当涉及到更高级的技术时,我建议你只有在明确需要它们之后,才将其添加到你的项目中。总的来说,提示工程更像是一门艺术而非精确的科学。因此,无论你使用什么策略,都要尝试不同的提示,找到最适合你系统的那些。

034:幻觉处理机制 🧠

在本节课中,我们将要学习大型语言模型(LLM)中一个关键问题——幻觉,并探讨如何在检索增强生成(RAG)系统中检测和减少幻觉,以确保生成内容的准确性和可信度。

什么是幻觉?

幻觉是使用LLM时一个持续存在的问题。即使是一个设计良好的RAG系统,仍然可能产生幻觉。因此,检测幻觉、减少幻觉并确保LLM准确引用来源,是构建RAG流程中最重要的部分。

为什么会产生幻觉?

理解LLM产生幻觉的根本原因很重要。语言模型的设计目标是生成概率上可能的文本序列,并加入一些随机性以增加多样性。概率上可能的文本序列通常是事实准确的,但并非总是如此。语言模型的设计并非为了区分真假,而只是区分可能和不可能。

幻觉带来的问题

幻觉之所以成问题,有几个原因。第一个原因显而易见:你不希望语言模型向用户提供不准确的信息。第二个原因是,幻觉听起来通常是合理的,因此比完全无意义的内容更难检测。最后,随着时间的推移,偶尔的幻觉会导致用户对你的RAG系统失去信任,即使生成的大部分内容是准确的。

RAG如何帮助减少幻觉?

当然,构建RAG流程的一个重要原因就是为了减少幻觉。从知识库中检索到的信息可以帮助“锚定”LLM的回应,并可能提供模型训练数据中缺失的信息。即便如此,RAG系统仍然容易出现幻觉,因此需要额外的步骤来防止它们。

幻觉的类型

幻觉有多种类型和程度。回到折扣的例子,LLM可能准确地描述了真实存在的老年人折扣及其获取方式,但错误地将折扣说成5%而不是10%。在更极端的情况下,LLM可能错误地声称不存在老年人折扣,而实际上存在;或者如之前所见,编造出公司根本不提供的新折扣。这意味着,如果你希望对其准确性有信心,就需要从多个层面评估LLM生成的文本。

处理幻觉的挑战

现在,需要面对一个冷酷而严峻的事实:目前没有完美的解决方案来完全消除幻觉。或者至少目前还没有。然而,幸运的是,RAG是目前可用的最佳方法之一,并且有方法可以优化RAG系统,以进一步降低幻觉发生的频率。

检测幻觉的方法

首先,思考一下如果没有知识库,如何检测LLM输出中的幻觉。如果没有一个可信的外部事实来源来比较输出,你的选择将非常有限。然而,一种方法是自洽性检查,即让模型为同一个提示词重复生成补全内容,并检查其中包含的事实信息是否一致。

其基本理念是,如果语言模型在编造信息,它会不一致地编造,并且不同补全内容之间的事实差异是可以被检测到的。然而,在实践中,这种方法可能成本高昂且不可靠。如果你有知识库可以参考,那是最好的起点。

在RAG系统中减少幻觉

由于在RAG系统中,你可以访问知识库,减少幻觉的最佳方法是确保回应基于检索到的信息。

例如,你可以修改系统提示词,规定LLM只能基于检索到的信息做出事实性声明。

要求引用来源

如果你希望进一步确信LLM的回应是基于检索到的文档,你可以进一步要求LLM引用其来源。有时,这仅仅意味着提示模型在每个句子或段落的末尾引用来源。这可以进一步增加LLM将其回应锚定在检索到的来源中的可能性,并且引用也使得人类读者更容易验证回应中的主张。

然而,这种方法的一个风险是,LLM可能会编造引用。一些经过微调以引用来源的模型会更可靠地生成有效的引用,但如果你希望对引用有更高的信心,就需要使用外部系统。

使用外部系统验证

例如,Context Site 是一个评估回应在一组源材料中锚定程度的系统。该模型逐句处理回应,并将每个句子归因于检索到并提供给LLM的上下文文档之一。然后,Context Site为每个句子生成标签,注明哪个文档是该句子的来源。对于没有支持材料的陈述,则标记为“无来源”。一些实现甚至可能提供句子与已识别源文档之间的相似度分数。

这些标签既可以用于在最终生成的LLM输出中生成来源引用,也可以作为评估LLM将其回应锚定在RAG系统检索到的文档中的频率的一部分。

评估基准

最近的努力,例如ALCE基准,旨在衡量系统在生成回应时引用和标注来源的能力。该系统提供预组装的知识库和示例问题,然后你可以在这些提示上使用你的RAG系统,并要求ALCE系统评估生成的回应。该基准为三个关键指标生成分数:流畅度、正确性和引用质量。换句话说,就是最终文本有多清晰,事实有多准确,以及提供的引用与应引用的正确来源的匹配程度。

这些基准并不能控制你生产系统中的幻觉,但它们确实能让你了解你的系统在避免幻觉和引用来源方面的表现如何。

总结

幻觉检测是基于LLM的系统中的一个持续挑战。尽管如此,通过构建RAG系统,你已经采取了最有效的一步来最小化幻觉。之后,将精力集中在通过优化系统提示词来确保LLM将其答案锚定在检索到的信息上。最后,使用专注于幻觉的基准测试你的系统,以确保你的系统提供有根据、引用良好的回应。综合运用这些方法,可以显著减少幻觉,并帮助你构建一个提供可信回应的系统。

035:大模型性能评估 🧪

在本节课中,我们将学习如何评估检索增强生成 (RAG) 系统中大型语言模型 (LLM) 的性能。无论你是刚刚构建了第一个概念验证系统,还是在迭代一个已上线的系统,了解 LLM 的表现都至关重要。我们将探讨一些常见的评估方法,帮助你量化模型调整或更换所带来的影响。

明确评估目标 🎯

上一节我们介绍了 RAG 系统的整体架构,本节中我们来看看如何评估其中的核心组件——大型语言模型。首先,需要明确 LLM 在 RAG 流水线中的具体职责。

你的检索器负责从知识库中查找相关信息,而 LLM 的任务是利用这些信息构建高质量的回复。这意味着,当你考虑调整 LLM 甚至完全替换底层模型时,所使用的评估指标应聚焦于 LLM 的角色和整个 RAG 流水线的表现。如果问题根源在于检索器,那么花时间重写系统提示词将是徒劳的。

假设你的检索器运行良好,它应该能找到大部分相关信息,可能附带少量无关文档。此时,LLM 的职责是响应用户提示,将相关信息整合到回复中,适当地引用来源,并抵制被检索到的任何无关信息所干扰。

需要注意的是,LLM 的这些行为大多具有一定的主观性。如何定量地判断一个回复是否很好地回答了用户的原始问题,或者是否忽略了无关信息?因此,大多数针对 LLM 的评估指标都依赖于使用其他 LLM 来评判回复的质量,将 LLM 纳入评估过程,可以在可扩展的范围内引入一定程度的灵活性或主观性。

使用 RAG 专用评估指标 📊

开源库 Ragas 是获取 RAG 专用评估指标的良好来源。以下是它提供的一些关键指标:

回复相关性 (Response Relevancy)
此指标衡量回复是否与用户提示真正相关。它检查回复是否与原始提示相关,而不考虑其事实准确性。其工作原理如下:

  1. 首先,将你的 RAG 系统生成的回复输入给一个新的 LLM,该 LLM 会生成几个它认为可能导致该回复的示例提示。
  2. 然后,将原始用户提示和这些示例提示都嵌入到语义向量空间中。
  3. 接着,计算实际用户提示与每个示例提示之间的余弦相似度。
  4. 最后,对这些相似度分数进行平均,得出最终的回复相关性度量。

注意:此指标不一定能确保回复提供的是事实信息,但它会检查你是否能从 LLM 给出的回复合理地回溯到它最初收到的提示。

忠实度 (Faithfulness)
为了衡量 LLM 是否真正使用了检索到的信息,可以使用忠实度指标。此指标使用一个语言模型来识别回复中做出的所有事实性主张。然后,它使用更多的语言模型调用来确定这些主张中有多少能得到从知识库检索到的某条信息的支持。被支持的主张所占的百分比,就是该特定提示、检索和回复的忠实度。

Ragas 库中包含的其他指标也采用类似的方法来评估 LLM 对知识库中检索到的无关信息的敏感性,或准确引用来源的能力。然而,所有这些指标的一个共同模式是,在评估过程的某个环节都依赖于 LLM 的调用,甚至可能依赖于真实正确答案的示例。这说明了 RAG 系统中 LLM 的角色是复杂的,难以用更简单的自动化指标来评估。

结合系统级指标进行评估 🔄

除了这些针对 LLM 的特定评估外,你还可以使用贯穿整个系统的指标来评估 LLM 的性能。

例如,如果你的用户可以对 RAG 系统的回复进行“点赞”或“点踩”评分,那么你可以对系统提示词的更改进行 A/B 测试,观察这种改变对整体用户满意度的影响。这里的思路是,你测量的是系统级的性能,但将改动隔离在 LLM 的设置上,从而能够将整体性能的变化归因于 LLM 的更改。

总结 📝

本节课中我们一起学习了如何评估 RAG 系统中大型语言模型的性能。LLM 性能指标是决定调整 LLM 设置甚至切换到新模型的有用工具。由于 LLM 回复的质量具有一定的主观性,你应该计划使用基于“LLM 作为裁判”的评估方法或人工反馈来评估 LLM 的质量。结合这些技术,你将能够自信地评估你的 LLM 运行得如何。

036:自主式RAG系统 🧠

在本节课中,我们将要学习如何通过引入自主式工作流来提升RAG系统的性能。我们将探讨自主式系统的核心概念、常见工作流模式以及它们如何使系统变得更强大和高效。

随着RAG系统的成熟,一个提升其性能的有效方法是开始引入自主式工作流。

自主式工作流意味着在整个RAG系统中使用多个大语言模型,每个模型负责整个流程中的一个独立步骤。


什么是自主式系统?

上一节我们提到了自主式工作流的概念,本节中我们来看看它与传统使用方式的区别。

通常,使用语言模型的方式是输入一个提示词,然后它直接输出一个简单的响应。在自主式系统中,这个过程有两个主要变化。

首先,任务被视为一系列步骤和决策,每一步都可以通过调用不同的大语言模型来完成。其次,大语言模型被赋予了使用更广泛工具的能力,例如代码解释器、网络浏览器,或者在RAG的情况下,一个用于参考信息的向量数据库。


一个自主式RAG工作流示例

以下是自主式RAG系统的一个可能工作流程:

  1. 路由决策:用户向系统提交提示词,首先由一个轻量级的“路由”大语言模型处理。该模型的任务是判断提示词是否需要调用向量数据库。它经过专门调优,只会输出“是”(需要检索)或“否”(无需检索)。
  2. 条件分支:根据路由模型的决策,提示词要么被发送到向量数据库进行检索,要么跳过该步骤。
  3. 直接响应:如果无需检索,提示词将直接发送给另一个独立的大语言模型来生成响应。
  4. 检索与评估:如果需要检索,系统会使用一个独立的“评估”大语言模型来判断检索到的文档是否足以回答问题。
  5. 迭代检索:根据评估模型的判断,可能会向向量数据库请求额外的检索,直到获取足够的信息。
  6. 生成响应:一旦检索到足够信息,系统会构建一个增强提示词,并交给大语言模型生成最终响应。
  7. 添加引用:最后,再由一个大语言模型检查响应并添加引用。

这只是一个可能的自主式RAG系统,但它突出了任何自主式系统都具备的几个关键点。

首先,设计一个自主式系统本质上就像绘制一个流程图。图中的每个大语言模型仍然只是接收文本输入并生成文本输出,但系统的设置使得每个模型只负责提示词在RAG系统中旅程的一个任务。

其次,工作流中的每一步不需要使用相同的大语言模型。例如,路由和评估模型可以是轻量级、运行快速且成本低廉的模型,因为它们任务单一且相对简单。然后,可以使用一个更大的模型来生成草稿响应,并为添加引用这一步选择一个专门擅长此任务的模型。


常见的自主式工作流模式

在考虑为RAG应用添加自主式工作流时,以下是几种常见的模式。

顺序工作流:这种模式以线性方式将输出通过一系列大语言模型。这意味着发送到系统的每个提示词都可能依次经过基于大语言模型的查询解析器、查询改写器和引用生成器。每个大语言模型只专注于整体流程中的一个步骤,因此可以在该步骤上做到专业化。

条件工作流:这种模式使用一个大语言模型来决定提示词应遵循多条路径中的哪一条。你刚刚看到的“路由”大语言模型就实现了这种工作流,用于决定是否需要检索来响应提示词。你也可以使用路由来决定应该使用多个具有不同优势和专长的大语言模型中的哪一个来生成响应。

迭代工作流:这种模式与条件工作流类似,但它会将提示词路由回系统流程中更早的节点,形成一个循环。例如,如果你的RAG系统旨在生成与现有代码库集成的代码,系统可能需要多次尝试才能编写出有效的代码。一个“评估”大语言模型可以用来评估每个草稿(可能借助代码解释器),并提供反馈,直到它认为解决方案合适为止。

并行工作流:在这种模式中,一个“协调器”语言模型将一个提示词分解为多个不同的子任务,并将每个子任务分配给独立的大语言模型。在另一端,一个“合成器”语言模型将他们的工作重新组合。如果你的应用是比较两篇研究论文的关键见解,你可能希望两个不同的大语言模型分别总结和评估每一篇,然后由协调器合并他们的发现。


工具与思维转变

对于简单的自主式系统,你可以自己实现所需工作流的逻辑。然而,随着系统变得复杂,市面上有各种各样的工具、库和平台旨在帮助你构建和管理自主式系统。构建自主式系统的创意可能性是无穷无尽的。

这里还涉及一个重要的思维转变:大语言模型开始看起来不那么像独立的解决方案,而更像是可以嵌入到更大工作流中的模块化组件。突然间,你会更乐意使用较小的模型或只擅长少数任务的模型,因为它们的能力与其负责的工作流部分高度契合。添加自主式组件可以让你灵活地构建能力更强大的RAG系统。


本节课中我们一起学习了自主式RAG系统的构建方法。我们了解了如何将单一任务分解为由多个专业化大语言模型协同完成的步骤,探讨了顺序、条件、迭代和并行四种常见的工作流模式,并认识到这种模块化设计带来的灵活性与性能提升。通过引入自主式思维,你可以将RAG系统从简单的问答工具转变为更智能、更强大的信息处理管道。

037:RAG与微调技术的比较 🔄

在本节课中,我们将要学习两种提升大型语言模型性能的核心技术:检索增强生成与微调。我们将详细探讨微调的工作原理、适用场景,并比较它与RAG的异同,帮助你理解如何根据具体需求选择或结合使用这两种技术。

微调的核心概念

上一节我们介绍了RAG如何通过外部知识增强模型回答。本节中我们来看看另一种常用技术——微调。

微调的核心思想是使用你自己的数据重新训练一个语言模型,以更新其内部参数。这通常通过监督微调 实现,因为模型是使用来自目标领域的带标签数据集 进行重新训练的。

指令微调 是一种特定方法,其数据集既包含给语言模型的指令(通常是提示或问题),也包含期望的标准答案

以下是微调模型的基本过程:

  1. 向模型输入指令。
  2. 将模型的输出与数据集中正确答案进行比较。
  3. 根据比较结果调整模型的内部参数,使其输出更接近正确答案。

这个过程与语言模型的初始训练非常相似,但使用的数据集来自特定领域,目的是让模型在该领域专业化

微调的作用:领域适应

假设你想让一个模型在医疗领域工作。首先选择一个通用语言模型。如果你向这个模型询问一组特定症状,例如关节痛、皮疹、光敏感,模型可能会给出一个通用语气、泛泛的答案。这是因为现成的模型并未在医学数据上专门训练。

如果你使用指令微调对同一模型进行训练,使用大量医学领域的指令和回答作为数据集,模型本质上就会变得更擅长回答此类问题。现在,如果你给出相同的提示,它将能够以更高的准确性、更详细的细节以及更适合医疗领域的风格进行回应。

微调在以下情况效果良好:你希望模型在特定领域专业化,例如提供初步医疗诊断或总结法律简报。

然而,虽然模型在该领域的性能会提高,但微调实际上可能会降低其在其他领域的性能。微调过程仅优化模型在目标领域的性能,这意味着有时对模型内部参数的调整会导致处理其他类型请求时性能下降。只要模型仅在其专业化的领域内使用,这种权衡通常是值得的。

RAG与微调的对比与应用选择

这一点引出了RAG与微调的一些优缺点。接下来我们谈谈何时使用每种技术是合理的。

简而言之,当前的共识是:RAG最擅长知识注入,而微调最擅长领域适应

如果你需要LLM能够访问新信息,检索增强生成是最佳解决方案。你可以将该信息注入到提示中,现成的LLM将能够在响应中整合这些新信息。

另一方面,如果你希望你的LLM在特定任务或领域专业化,微调是正确选择。特别是当你的LLM将处理一个离散任务时,例如在你的RAG系统中路由提示,或仅响应特定类型的提示,微调更有意义。

结合使用RAG与微调

RAG和微调也可以结合使用。具体来说,你可以专门微调一个模型,使其更好地将检索到的信息整合到最终响应中。换句话说,你是在帮助模型在RAG系统内的角色上专业化。

在决定使用微调还是RAG时,最佳选择可能是两者都用。每种方法以不同方式提升模型性能,结合使用二者会带来额外益处。

如果你想在自己的RAG系统中加入微调,建议你学习一门单独的微调课程,探索如何微调你自己的语言模型。微调是一个复杂的主题,不可能在本课程中充分涵盖。

尽管如此,你通常可以找到已经为你微调好的模型,并将其适配到特定任务或领域。如果你认为系统需要一个微调模型,许多在线仓库提供了先前微调好的模型,你或许可以直接使用其中一个,而无需自己进行微调。

总结与展望

微调和RAG有时被描述为相互竞争的替代方案,但更准确地说,它们是互补的工具。将微调模型加入你的RAG流水线,甚至微调生成最终响应的核心LLM,都有助于提升系统性能。

虽然本课程不会深入探讨微调技术,但随着你继续构建生成式AI技能并寻找优化RAG系统的方法,这绝对值得探索。

本节课中我们一起学习了微调技术的工作原理、它与RAG在知识注入和领域适应方面的核心区别,以及如何根据需求选择或结合使用这两种技术来构建更强大的AI系统。

038:总结 🎯

在本模块中,我们深入探讨了大型语言模型(LLM)的核心概念与应用技术。从理解其内部工作原理到掌握如何评估与优化其性能,我们为构建一个强大的RAG系统奠定了坚实的基础。

模块内容回顾 📚

上一节我们完成了模块四的学习,现在让我们快速回顾一下本模块涵盖的所有关键主题。

核心概念与技术

以下是本模块学习的主要内容:

  1. Transformer架构深入:在模块开始时,我们深入探讨了Transformer模型的核心。理解了它如何处理文本,以深入理解其含义并生成相关的补全内容。其核心注意力机制可以用公式表示为:Attention(Q, K, V) = softmax(QK^T / √d_k) V

  2. 采样策略:随后,我们学习了如何使用各种采样策略来调整语言模型生成文本时固有的随机性,以适应应用程序的需求。例如,在代码中可以通过设置 temperature 参数来控制随机性:model.generate(input_ids, temperature=0.7)

  3. 模型选择与提示工程:接下来,我们学习了如何使用基准测试来选择LLM,掌握了多种提示工程技术,并了解了如何检测和防止模型产生“幻觉”(即生成不准确或虚构的信息)。

  4. 性能评估:然后,我们学习了一系列用于评估LLM性能的技术。

  5. 系统能力扩展:最后,我们探讨了如何通过添加智能体组件或对模型进行微调,来突破RAG系统能力的极限。

总结与展望 🚀

至此,您已经对LLM概念有了扎实的理解,并掌握了构建第一个RAG系统所需的所有工具。

在本节课中,我们一起学习了从Transformer内部机制到高级应用策略的完整知识链。您现在具备了评估、优化和扩展LLM应用的能力。

请加入本课程的最后一个模块,共同探索如何将您的RAG应用程序从一个简单的原型,发展为可用于生产环境的成熟系统。

039:生产就绪 🚀

在本模块中,我们将学习如何将设计好的RAG系统投入生产环境。我们将探讨系统评估、性能权衡以及集成多模态数据等关键主题,以确保系统的高性能和可靠性。

模块5简介 📋

上一模块我们掌握了设计和构建RAG系统所需的核心技能。然而,当准备将应用部署到生产环境时,会出现一系列新的考量因素。

在本模块中,你将学习如何使你的RAG系统达到生产就绪状态。

系统评估与监控 🔍

首先,我们将回顾针对RAG系统的多种评估策略以及运行这些评估的平台。

无论你是评估单个组件还是整个系统,都需要具备观察系统性能的能力。

以下是评估RAG系统时需要考虑的几个方面:

  • 组件级评估:分别评估检索器和生成器的性能。
  • 端到端评估:评估整个系统对用户查询的最终响应质量。
  • 评估平台:利用工具和平台自动化运行评估。

你还会探索日志记录如何帮助你追踪对RAG系统的每一次调用,并识别低质量响应的根源。

在结束关于评估的探讨前,你将学习如何从应用程序的流量中构建自定义数据集,以便使用真实的客户数据来测试对RAG系统的更改。

性能权衡与优化 ⚖️

上一节我们介绍了系统评估,本节中我们来看看在设计和调整RAG系统时经常遇到的各种权衡。

无论你是希望控制成本、内存占用还是延迟,你都将研究一些策略,帮助RAG系统在不显著损失响应质量的前提下,满足项目的特定需求。

以下是常见的权衡领域及应对策略:

  • 成本控制:优化嵌入模型和LLM的调用次数,例如通过缓存或使用更经济的模型。
  • 内存与速度:在索引大小(影响召回率)和检索速度之间取得平衡。
  • 质量与延迟:调整检索文档的数量(k值)以平衡答案的准确性和响应时间。

集成多模态数据 🌐

最后,你将探索一些前沿方法,将多模态数据集成到RAG系统中。

这将允许你的系统从一个不仅包含文本,还包含图像或PDF等数据的知识库中提取信息。

实践与总结 🎯

与往常一样,本模块以一个编程作业结束,你可以在此尝试运用所学的所有技能。

我相信你会喜欢这个专注于让你的生产级RAG系统表现更出色的最终模块。

在下一个视频中与我一起,让我们开始吧。


本节课中我们一起学习了如何为RAG系统的生产部署做准备,涵盖了从评估策略、性能监控、成本与质量的权衡,到集成多模态数据等关键生产环境考量。这些知识将帮助你构建出更健壮、高效且实用的RAG应用。

040:生产化部署的挑战 😰

在本节课中,我们将探讨当RAG系统从原型阶段迈向实际生产环境时所面临的一系列全新挑战。理解这些挑战是构建稳定、可靠且高效的生产级应用的关键第一步。

上一节我们介绍了RAG的基本原理和构建流程,本节中我们来看看当系统真正面对用户和真实世界数据时,会遇到哪些棘手的问题。

挑战一:系统扩展性

生产环境首先带来的挑战是规模扩大。更多的用户会给系统带来压力,主要体现在以下方面:

以下是系统扩展性带来的具体问题:

  • 吞吐量与延迟:系统需要处理更多的并发请求,同时要保证请求接收与回复之间的延迟保持在较低水平。
  • 资源消耗与成本:更多的请求意味着更高的内存和计算资源使用量,最终导致运营成本上升。
  • 性能维持:在规模扩大时,维持系统的基础性能表现是一项挑战。

挑战二:用户请求的多样性与不可预测性

一旦系统交到用户手中,你将面临请求的多样性和不可预测性。即使经过严格测试,也难以预测RAG系统会收到的每一种请求类型。

以下是这方面的具体表现:

  • 未知请求的挑战:你可能会发现系统在某些新类型的请求上表现不佳,即使它在发布前的测试中表现良好。
  • 真实世界数据的复杂性:生产环境的另一个挑战在于,真实世界的数据通常很混乱。数据常常是碎片化的、格式不佳的、缺少元数据的,等等。

挑战三:多模态数据与安全隐私

许多数据甚至根本不是文本格式,而是存在于图像、PDF文件和幻灯片中。如果你想将这些数据纳入知识库,就需要有访问它们的方法。

此外,安全和隐私问题也值得关注。许多RAG系统的部署正是因为知识库中的数据是私有的或专有的。

以下是相关的核心要求:

  • 数据访问:需要一种方法来处理非文本格式的数据,例如使用 extract_text_from_pdf(pdf_file) 这样的函数或专用库。
  • 安全与隐私:在允许授权用户使用RAG系统访问数据的同时,确保数据保持私有是一项重要的功能需求。

挑战四:错误的实际影响

在所有这些挑战之上,生产环境最大的问题是:错误可能产生真实的业务影响,无论是财务上的还是声誉上的。

以下是几个著名的案例:

  • 谷歌的“吃石头”事件:谷歌首次推出AI搜索摘要功能时,曾回应某些提示,建议用户“为了营养益处而吃石头”。经调查,问题源于一个用户提问“我应该吃多少石头”,这是一个看似愚蠢且难以预测的问题。系统在检索相关信息时,找到了许多滑稽的文章或论坛对话,但未能识别出这些内容的荒谬性。
  • 航空聊天机器人的“虚假折扣”:航空公司的聊天机器人曾向善意的顾客承诺实际上并不存在的折扣。
  • 恶意攻击风险:恶意行为者会试图欺骗你的RAG系统,例如让其免费出售产品或泄露机密信息。

应对策略与总结

总而言之,生产环境对RAG系统的运行而言是一个充满挑战的领域。因此,建立一套系统来预测问题、在问题发生时追踪根源,并验证你所做的更改是否带来了真正的改进,是至关重要的。

有多种技术可用于应对所有这些生产挑战。在下一节视频中,我们将一起探讨第一个关键策略:构建一个健壮的可观测性系统。

本节课中我们一起学习了RAG系统在生产化部署时面临的四大类核心挑战:系统扩展性压力、用户请求的不可预测性、多模态数据与安全隐私处理,以及错误可能带来的真实业务风险。理解这些挑战是设计稳健生产流程的基础。

041:RAG评估策略实施 🧪

在本节课中,我们将学习如何为生产环境中的RAG系统构建一个健壮的可观测性系统。我们将探讨该系统应包含的组件、需要追踪的各类指标,以及不同评估方法之间的权衡。

概述:构建RAG可观测性系统

处理生产环境挑战的一个良好开端是构建一个健壮的可观测性系统。首先,让我们看看它应该包含哪些不同的组件。

一个可观测性平台需要追踪几种不同类型的信息。

可观测性系统的核心组件

以下是构建可观测性系统时需要考虑的几个关键方面。

1. 软件性能指标

与几乎任何生产软件系统一样,你需要了解系统处理的请求数量、处理所需时间以及消耗的资源量。因此,系统需要追踪常见的软件性能指标,例如延迟吞吐量内存计算资源使用率

2. 质量指标

除了了解系统运行的速度或效率,你还需要知道最终结果是否达到你设定的质量标准。这里的“质量”可能涵盖从用户对最终回复的满意度,到检索器的召回率等各个方面。

3. 数据收集与报告方式

信息如何被收集和报告也很重要。你的系统应该捕获随时间推移的聚合统计数据,以帮助你跟踪性能的高层趋势,并快速识别性能退化。同时,系统还应记录详细的日志。这些日志能让你追踪单个提示词在RAG管道中的完整旅程,这在试图理解性能不佳的响应来源时特别有用。

4. 实验支持能力

理想情况下,你的评估系统应该支持实验。如果你考虑切换到新的语言模型、添加系统提示词或调整检索器的设置,你需要在安全环境中运行定制化实验,或在生产环境中对用户进行A/B测试。监控这些变更对性能和质量指标的影响,最终将帮助你决定是否将这些实验成果部署到生产系统中。

评估指标的框架:范围与评估者类型

了解了高层结构后,我们来看看需要追踪的具体指标。一个思考所有这些指标的良好框架是范围评估者类型

  • 范围:指评估是针对RAG系统的某个组件,还是针对整个系统。
  • 评估者类型:指评估是基于代码、使用LLM作为评判者,还是依赖人工反馈。

你可以将这两个维度想象成一个网格,你选择的评估方法就位于其中一个方格内。让我们先探讨每个维度,然后看看一些常见的评估方法在这个网格中的位置。

评估范围:系统级与组件级

上一节我们介绍了评估框架的两个维度,本节中我们先来看看评估范围

  • 系统级评估:通常用于总结整体系统性能,或提供系统运行状况的高层视图。
  • 组件级评估:帮助你调试单个问题的根源。例如,你可能会追踪整个系统的延迟,并发现它过高。然而,为了追踪该问题的根源,你需要组件级评估来确定是检索器、你的大语言模型,还是其他组件最终导致了问题。

评估者类型:代码、人工与LLM

了解了评估范围,接下来我们看看评估者类型,它关注评估是如何生成的。

  • 基于代码的评估:这是成本最低、最简单、最直接的实现方式。这可以是从记录系统每秒处理的提示词数量,到运行单元测试以确保LLM输出有效的JSON等一切操作。关键在于这些评估可以自动运行、是确定性的,并且运行成本几乎为零。
  • 人工反馈与评估:这是成本较高的一种方法,但它能捕获基于代码的评估会遗漏的信息。一个常见的例子是应用程序的用户用“点赞”或“点踩”来标记响应。即使这不能提供很多详细信息,但更多用户给你的响应点“踩”这一事实,就是一个需要解决问题的有用信号。你也可以给用户一个文本框来提供更详细的反馈。其他一些评估可以自动运行,但最初依赖于人工输入。例如,你可以让人工预先编译一个包含提示词和应被检索的相关文档的数据集。一旦该数据集编译完成,你就可以快速计算精确率召回率等常见指标。但值得记住的是,在某个时间点,需要人工来编译那个初始的测试数据集。
  • LLM作为评判者:这种方法试图通过使用语言模型来给你的系统各个组件的表现打分,从而在成本和灵活性上取得平衡。例如,LLM可以判断检索器检索到的文档是否真的与用户的提示词相关。LLM作为评判者比基于代码的评估更灵活,又比人工反馈更便宜。然而,LLM作为评判者仍然需要仔细调整。模型可能存在偏见,并倾向于由它们自己家族模型生成的响应。它们还需要清晰的评分标准,并且通常在像“相关”或“不相关”这样的离散标准上表现最佳,而不是在0到100的评分尺度上。

构建初始评估指标集

现在,让我们看看如何将所有这些不同的评估概念整合成一个简单但全面的指标集,作为你开始收集数据的起点。

一个好的开始思路是为每个主要组件以及整个系统收集软件性能指标质量指标

  • 系统性能指标:如延迟吞吐量内存使用率或每秒生成的令牌数,这些都是基于代码的评估,使得它们成本低廉且易于收集。你可以在组件级别和系统级别轻松捕获这些数据。
  • 质量指标:对于质量指标,你通常需要依赖使用人工标注或LLM作为评判者的技术。

以下是针对不同范围和质量维度的具体评估方法:

系统级质量评估

你可以允许用户对生成的回复进行“点赞”或“点踩”,为你提供关于整体回复质量的反馈。

检索器评估

你可以花时间编译一个由人工标注的测试数据集,包含提示词和期望检索到的文档,从而允许你计算召回率精确率等常见指标。

LLM质量评估

你通常会使用基于LLM的评估,例如Ragas库中提供的那些,来评估诸如回复相关性引用质量或LLM忽略不相关检索信息的能力等方面。

像这样的方法让你既能了解整个系统的性能和品质,也能洞察各个组件的状况。它还在廉价的评估(如延迟)和依赖人工标注或LLM调用的更昂贵指标之间取得了良好的平衡。在此基础上,你可以决定希望更仔细地关注哪些额外的领域。

总结

本节课中,我们一起学习了RAG可观测性系统应包含的组件,以及在设计它时需要考虑的权衡。我们对系统级与组件级评估、基于代码、人工和LLM的评估方法有了一个快速的高层概览。在下一个视频中,我们将更深入地探讨实际实施这个系统时出现的一些具体考虑因素。

042:日志监控与可观测性

在本节课中,我们将学习如何为你的RAG系统构建一个可观测性系统,以收集和分析性能数据。我们将了解可用的工具平台,并探讨如何利用它们来监控、评估和持续改进你的RAG应用。

可观测性平台概述

上一节我们讨论了需要收集哪些指标,本节中我们来看看如何构建系统来收集这些数据。

市面上有许多专为基于大语言模型(LLM)的应用设计的可观测性平台。这些平台旨在执行常见的评估任务,例如捕获系统级或组件级的指标、帮助记录系统流量,以及支持使用新系统设置进行实验。使用这类平台意味着你可以减少设计和实现可观测性系统的时间,从而将更多精力投入到监控RAG系统性能和探索改进方法上。

平台工具示例:Phoenix

作为一个例子,我们来看一个名为Phoenix的开源可观测性和评估平台。它由Arize公司构建,提供了多种工具来帮助你评估RAG系统的性能。

以下是Phoenix平台提供的一些核心工具:

追踪 (Traces)

追踪工具允许你跟踪一个提示(prompt)在整个RAG管道中的流转路径。你可以看到它如何被系统中的每个组件修改。

例如,你可以看到:

  • 初始的文本提示。
  • 发送给检索器的查询。
  • 检索器返回的文本块。
  • 这些文本块如何被你的重排序器处理。
  • 最终发送给核心语言模型的提示。
  • 生成的最终响应。

此外,像每一步的延迟(latency)这类有用信息也可以被记录下来。追踪是评估RAG系统的常用工具,无论它是早期原型还是已投入生产。例如,如果你知道某个提示在你的RAG系统中表现不佳,你可以追踪它的路径,并尝试确定哪一步是错误来源。

集成评估指标

Phoenix平台还便于收集你在本模块中已经见过的许多评估指标。例如,它与Ragas库集成,该库用于计算不同的评估指标。因此,如果你想计算检索器的搜索相关性,或者判断你的LLM是否准确地引用了检索到的来源,可以轻松添加这些评估步骤。

实验与A/B测试

一旦你建立了一个基本的评估管道,就可以开始运行简单的实验。例如,你可以迭代式地尝试自己的提示,并观察它们会如何被你的RAG管道处理。你还可以对系统更改进行A/B测试,以观察它们如何影响系统性能。这类功能帮助你决定一个新的系统提示是否真的提高了响应质量,或者观察添加一个重排序器能带来何种性能提升。

聚合统计与报告

虽然追踪让你能访问底层信息,但你通常也需要高级的聚合统计数据来跟踪系统性能。Phoenix能够提供关键指标的每日报告,从检索器的准确性到你模型的幻觉率。

补充工具与持续改进循环

虽然Phoenix和其他LLM可观测性平台覆盖了你想要为RAG系统收集的大部分评估指标,但仍会存在一些空白。例如,它并不是监控向量数据库计算和内存使用情况的理想工具。在这些情况下,你可以使用更经典的监控和可观测性工具,如Datadog和Grafana。

一个良好的可观测性管道最终会形成一个系统改进的飞轮。通过观察你的系统如何处理真实的生产流量,你能够识别错误或确定需要改进的目标领域,然后观察你所做更改的影响。随着时间的推移,这使你能够调整系统中的每个组件,以最好地匹配用户实际使用它的方式。

在这个过程中,一个宝贵的工具是能够创建由RAG系统先前处理过的提示的自定义数据集。通过保存这些提示,然后在你的系统中重新运行它们,你可以看到系统更改对你的应用实际接收到的提示所产生的影响。

本节课中我们一起学习了如何利用可观测性平台(如Phoenix)来构建RAG系统的监控与评估体系。我们探讨了追踪、指标集成、实验测试和聚合报告等关键功能,并了解了如何结合传统工具填补监控空白,最终形成一个持续改进的系统优化循环。

043:定制化评估体系 📊

在本节课中,我们将学习如何为你的RAG系统构建一个定制化的数据集。这个数据集不仅能帮助你深入理解系统过去的表现,还能让你通过实验来验证系统设计的改进如何影响其在真实世界提示上的性能。

构建定制化数据集

上一节我们介绍了评估的重要性,本节中我们来看看如何具体构建一个用于评估的定制化数据集。

一个定制化数据集,本质上是你系统先前处理过的提示集合,以及你选择收集的关于该提示在系统中流转过程的任何信息。

你可以选择只保存初始提示和最终响应,也可以向你的定制化数据中添加大量信息。

例如,你的向量数据库检索到了哪些文档、这些文档在你的重排序器处理前后的排名情况、你的查询重写器的输出等等。拥有如此大的灵活性,构建定制化数据集时的一个重要决策是:我应该存储哪些数据?

简单的答案是:你想评估什么,就存储什么。

例如,你几乎肯定需要保存用户提交的输入提示和你的RAG系统生成的最终响应。这两个基本数据点能让你对系统性能有一个初步了解,并可以追踪随着提示的编辑,响应是如何变化的。

然而,这些信息实际上只对端到端的评估有帮助。如果你想进行组件级别的评估,以了解你的检索器、重排序器或查询重写器的表现如何,那么就需要保存这些组件各自使用的输入和输出数据。

通常,你会希望记录这些详细的组件级步骤。因此,用于记录RAG系统调用的表格很容易就有几十列。

以下是可能存储的数据类型示例:

  • 发起调用的客户ID
  • 你的重排序器筛选过的文本块
  • 你的智能体工作流中每个路由语言模型的输出

😡

存储这样多样化的数据,使你能够单独分析系统的每个组件,并从多个维度检查性能。

例如,如果你正在构建一个客户服务聊天机器人,你可以按问题主题进行筛选,从而发现关于“退款”的问题收到了高质量的响应,但关于“产品延迟”的问题表现却很差。

当你去调查为什么这些与产品延迟相关的提示导致了低质量的响应时,你或许可以通过分析日志发现,你的检索器无法为这些提示找到很多相关文档。这可能意味着你需要向知识库中添加更多相关信息。

如果你构建了合适的可观测性系统,你将能够发现问题、精确定位其根源,并对解决方案的有效性充满信心。

案例分析:问题诊断与解决

让我们通过一个来自我职业生涯的真实例子,看看定制化数据集和日志如何帮助诊断和解决问题。

我曾在一个专业的RAG系统上工作,该系统能够生成文本、图像,以及使用Mermaid JS生成代码支持的图表和示意图。

我们开始收到投诉,称系统生成的一些图表质量很低。通过回溯我们的日志,我们意识到许多问题出现在用户要求系统“绘制一个图表”时。路由语言模型误解了这个提示,因此将其发送给了用于图像生成的文生图模型。这些模型在生成人物或事物的图像方面相当不错,但在生成图表方面却很差。

一旦我们找到了问题的根源,我们就能够更新路由LLM的系统提示,使得这类提示会创建代码支持的图表,而不是生成图像。得益于一个健壮的监控和日志系统,在我们收到客户的问题报告后,就能直接追踪到其源头,并迅速将修复方案投入生产。

数据可视化与趋势分析

虽然有时你会想像上面那样追踪表现不佳的单个提示,但一旦你记录了大量数据,你通常会希望将其可视化。

这可以让你识别整个系统或每个组件性能的高层趋势。例如,你可以将系统中所有输入提示进行可视化,并使用某种聚类算法来识别客户询问的高层主题,比如“产品发布”或“故障排除问题”。

如果你能区分所有这些不同的提示,那么你就可以仅针对该类型的提示运行你的评估流程,看看你的系统是否在某些类型的问题上表现不佳。

总结

本节课中我们一起学习了定制化评估体系的核心——构建定制化数据集。定制化数据集是使你的RAG应用程序适应其处理的真实请求的重要工具。将其纳入你的系统评估方式中,是改进系统响应用户实际提示和问题的最佳途径。通过记录详细的日志、进行组件级分析、可视化数据趋势,你可以系统地诊断问题、优化性能,从而构建出更强大、更可靠的RAG系统。

044:模型量化技术 🧮

在本节课中,我们将要学习一个重要的概念——模型量化。量化是一种用于压缩大型语言模型和嵌入向量的技术,它能在成本、速度和质量之间取得平衡。我们将探讨量化的工作原理、不同类型及其在RAG系统中的应用。

概述

当你能够评估RAG系统并尝试不同配置后,你将面临许多软件项目中常见的权衡:成本、速度和质量。在接下来的视频中,你将探索这些权衡。首先,让我们介绍一个重要概念:量化。

什么是量化?

简而言之,量化是针对LLM和嵌入模型生成的向量的压缩技术。量化将LLM内部的模型权重或嵌入向量的值,替换为压缩后的低精度数据类型。

这使得模型或向量变得更小、运行成本更低、速度更快,通常在检索相关性或响应质量方面不会有太大牺牲。

量化的工作原理

一个很好的类比是图像压缩。一张高质量图像使用24位数据来表示每个像素的颜色。颜色看起来很棒,但它确实使用了大量数据来存储所有信息。你可以通过为每个像素使用12位甚至6位来压缩图像。

压缩后的图像大小分别是原始图像的一半和四分之一,这是显著的内存节省。然而,12位图像看起来已经不那么好了,而在6位图像中,有许多可见的颜色伪影。不过,根据你使用图像的场景,这种质量下降可能值得换取大量的内存节省。

量化对LLM和嵌入向量采用相同的方法,以牺牲一些质量损失为代价来缩小它们的大小。

大型语言模型的量化

典型语言模型中的每个参数使用16位内存,现代模型的参数数量大约在10亿到1万亿之间。这些模型非常庞大,需要大量内存来存储它们,并需要强大的GPU来运行它们。

量化模型将这些16位参数压缩到8位甚至4位的等效值。这显著减少了运行模型所需的GPU内存,代价是模型性能和质量略有下降。

嵌入向量的量化

量化嵌入向量的工作原理类似。一个相当典型的768维向量将使用768个32位浮点数。这意味着你的知识库中每个向量都有3KB的数据。更高维度的模型很容易需要数倍于此的数据量。一旦你存储了数百万甚至数十亿个这样的向量,你将面临海量的向量数据需要处理。

这些向量需要存储在某个地方才能使用,特别是如果你想在快速向量搜索中使用它们,它们需要加载到昂贵的RAM中。整数量化是缩小这些向量的常用方法。

它将32位浮点数替换为小得多的整数,例如一个8位整数。这意味着你的向量现在立即变为原始大小的四分之一,这是巨大的空间节省。这些整数值也非常容易计算。

以下是该过程的运作方式:

  1. 为你的向量数据,找出每个维度中出现的最小值和最大值。这将定义该维度中数值的分布范围。
  2. 然后将该范围划分为256个等大小的区间(这是8位可以表示的独特值的数量)。
  3. 这些区间被编号为0, 1, 2, 3,依此类推,直到255。
  4. 然后,原始向量中的每个浮点数都被分配一个整数值,该值等于它落入的区间编号。

如果你还存储了最小值和每个区间的宽度,你就拥有了计算原始32位浮点数近似值所需的所有信息,但只使用了8位数据。

尽管只使用了四分之一的数据,并且采用了看似简单的压缩算法,但8位整数量化在诸如召回率@K等基准测试中表现非常出色。使用8位量化时,你可能只会看到几个百分点的下降。

这些量化后的嵌入向量意味着你的向量数据库中需要存储的数据更少,同时由于所需的计算被简化,还能实现更快的搜索。

量化模型的性能与权衡

量化模型在使用常用基准测试进行测量时,通常性能下降幅度很小。同时,它们使用更少的GPU内存,并且可以更快地生成文本。换句话说,这是以微小的质量下降为代价,换取了巨大的内存和性能提升。

虽然8位整数量化向量被广泛使用,但1位或二进制量化向量也越来越受欢迎。这种方法将向量的大小压缩了32倍(从每个维度32位压缩到仅1位),这是巨大的节省。在这种压缩级别下,向量中的每个值要么是1,要么是0,仅表示该维度上的值是正数还是负数。

正如你可能想象的那样,在这种极端的压缩级别下,基于嵌入模型的检索性能可能会明显下降。尽管如此,1位量化能带来显著更小、更快的基于向量的检索。它也可以与其他技术结合使用,例如,基于1位量化嵌入模型执行快速检索,然后使用完整的原始32位向量进行重新评分。

嵌套娃娃嵌入模型

另一种缩小向量大小的方法是使用嵌套娃娃嵌入模型。这些向量的设计使得你在进行相似性比较等操作时,可以选择只使用向量维度的一个子集。

例如,如果完整向量有1000个维度,你可以选择只使用前500个或前100个维度来实现这一行为。嵌套娃娃嵌入模型有一个特殊属性:它们的维度是根据信息密度排序的。这里的“信息”指的是在嵌入大量文本时,你预期在该维度中看到的统计方差量。

在典型的嵌入模型中,每个维度都有大致相同的方差或信息量。在嵌套娃娃模型中,由于所使用的训练过程,较早的维度会有更多的方差,这意味着更高的信息含量。较晚的维度方差较小,意味着它们提供的信息相对较少,因此排除它们所付出的代价也更小。

有几种使用嵌套娃娃向量的方法:

  • 你可以选择只使用前100个维度,在保存尽可能多信息的同时节省空间并实现更快的计算。
  • 或者,你可以始终使用前100个维度执行初始检索,然后从速度较慢、成本较低的内存中提取剩余的900个维度,使用完整的1000个维度来帮助重新评分初始检索到的文档集。

嵌套娃娃模型的灵活特性使其最适合动态环境,在这种环境中,你可能希望快速从低保真度向量表示切换到高保真度向量表示。

核心要点与实验建议

虽然这些先进技术展示了量化前沿的可能性,但核心要点是:你应该尝试使用整数量化的LLM和嵌入模型。

大多数LLM和嵌入模型提供商都会在其基础模型旁边提供8位或4位量化模型。它们提供的空间和成本节省可能是显著的,而质量下降则相当小。

总结

本节课中,我们一起学习了模型量化技术。我们了解到量化是一种通过降低数据精度来压缩LLM和嵌入向量的方法,它能在成本、速度和质量之间取得平衡。我们探讨了整数量化、二进制量化以及嵌套娃娃嵌入模型等具体技术。对于构建高效的RAG系统,尝试使用量化模型通常是降低成本和提升速度的有效策略,同时质量损失可控。

045:成本与响应质量的平衡 💰⚖️

在本节课中,我们将探讨在构建和扩展RAG系统时,如何平衡成本与响应质量。我们将分析系统的主要成本来源,并学习一系列策略来有效控制成本,同时尽可能维持高质量的输出。

成本构成分析

上一节我们介绍了RAG系统的核心组件,本节中我们来看看其主要的成本构成。在一个典型的RAG应用中,最大的两项成本通常来自向量数据库和大语言模型。

管理LLM成本的策略

为了控制大语言模型的成本,我们可以采取以下几种方法。

1. 尝试使用更小的模型

无论是负责生成最终响应的核心LLM,还是智能体系统中的路由LLM,你都有可能通过使用更小、更便宜的模型来达到相似的整体质量。模型更小可能有两种原因:一是模型参数总量更少;二是模型参数被量化为更低精度的格式(例如8位)。在这两种情况下,小模型的表现常常会带来惊喜,尤其是在LLM执行的任务数量有限时。对小模型进行微调,可以以较低成本获得良好结果。

2. 限制输入与输出令牌数量

RAG提示词的大小会迅速膨胀,特别是当每次提示都检索许多冗长的文档块时。可以尝试检索更少的文档,即减少 top K 的值。许多LLM的回复可能比较冗长,请记住,你需要为它们生成的每一个令牌付费。更新系统提示词以鼓励简洁的回复,甚至设置严格的令牌数量限制,是另一种直接降低成本的方法。

3. 在专用硬件上托管LLM

像Together AI、AWS和Google这样的云LLM提供商提供了便捷的推理端点,在构建原型时使用它们通常很合理。然而,当你的项目扩展到处理成千上万甚至数百万个请求时,通过在这些公司租用专用硬件来运行模型,可能会节省大量成本。专用端点的额外好处是更好的可靠性,因为该硬件只服务于你的用户流量。

以下是使用专用硬件时成本计算方式的对比:

  • 云推理端点:通常按使用量(如每百万令牌)付费。
  • 专用硬件:按小时为你模型所需的GPU付费。

在规模较大时,按小时付费相比按令牌付费,可能带来非常显著的成本节约。

管理向量数据库成本的策略

在向量数据库方面,了解其存储架构是控制成本的关键。大多数数据库提供多种类型的内存,通常需要考虑以下三种:RAM(内存)、磁盘存储和云对象存储。RAM速度最快但最昂贵,云对象存储最慢但最便宜,磁盘存储则介于两者之间。

如果你想节省成本,就需要确保只有那些真正能提升系统性能的信息才被存放在快速且昂贵的存储中。例如,HNSW索引应保存在RAM中,以确保向量搜索尽可能快地运行。然而,你的文档内容可能不需要存储在RAM中。你可以决定将最常访问的文档放在磁盘存储中,而将很少访问的对象放在云对象存储中。

许多向量数据库包含帮助你监控这种权衡的功能,甚至可以根据应用程序的需求动态地将数据移动到不同类型的存储中。

多租户架构

这种方法的一个典型例子是多租户架构,即按用户或所属组织来划分向量数据库中的所有文档。例如,你的向量数据库中可能有100万个文档,分属于1000个不同的用户。每个用户只能访问自己的文档,因此每个用户实际上都有自己独立的HNSW索引来关联其文档。

这种系统使得仅在必要时将租户的数据快速加载到昂贵的高速内存中变得容易。例如,你可以等到客户实际登录你的网站时,才将其向量加载到RAM中;或者,你可以默认在夜间将欧洲租户的数据保留在存储中。在这两种情况下,你都是在将数据移入或移出昂贵的内存,但按租户组织信息使得能够更高效地执行此任务。

实验与监控

无论是减小模型规模还是缩短提示词长度,建立一个健壮的可观测性管道,将允许你评估这些更改的影响,并判断成本节约与响应质量下降之间的权衡是否真的值得。

总结

本节课中我们一起学习了RAG系统成本优化的核心策略。所有优化的核心思想是,作为一名工程师,你需要理解成本的来源,并确保它们被性能提升所证明。对于LLM,通常的方法是使用更小的模型和更短的提示词。对于向量数据库,主要节省成本的方法是在昂贵存储中存储更少的数据,并在RAM、磁盘和对象存储之间灵活迁移数据。通过实验并监控这些更改对性能的影响,你将能够判断它们带来的成本节约是否值得。

046:时延与响应质量的权衡 ⚖️

在本节课中,我们将探讨在生产环境中部署RAG应用时一个至关重要的平衡点:查询时延与响应质量之间的权衡。我们将分析时延的主要来源,并提供一系列优化策略,帮助您根据应用场景找到合适的平衡。

概述:时延与质量的固有矛盾

在RAG系统中,时延与响应质量之间通常存在此消彼长的关系。简单地向系统中添加检索器就会增加时延。当您为了提升响应质量而引入更多组件时,例如重排序器或构建更复杂的智能体系统,时延可能会进一步增加。因此,我们需要仔细审视这种权衡,并为您的系统找到合适的平衡点。

时延的重要性取决于应用场景

时延对您系统的重要性,很大程度上取决于其使用场景。例如,浏览电子商务网站的用户通常对缓慢的响应时间容忍度极低。因此,您可能需要优化商品推荐服务,使其具有极低的时延,即使这可能意味着无法从商品目录中推荐出最完美的商品。

另一方面,一个旨在帮助医生诊断罕见疾病的RAG系统,则很可能优先优化响应质量,即使这意味着生成响应需要更长的时间。

时延的主要来源:Transformer模型

在处理时延问题时,一个简单的准则是:几乎所有的时延都源于运行Transformer模型。因此,最大的“元凶”将是您的大型语言模型调用。

虽然检索过程确实会增加一些时延,但许多数据库,特别是向量数据库,速度非常快且扩展性良好。然而,一些基于Transformer的重排序技术除外。

优化策略一:从核心语言模型入手

如果您想降低时延,最佳的起点是您的核心语言模型。

以下是几种有效的优化方法:

  • 使用更小的语言模型:在相同硬件和内存条件下,更小的LLM或量化模型总是运行得更快。
  • 使用路由LLM:部署一个较小的路由LLM,其职责是分析提示词,并决定使用更小还是更大的LLM来处理任务。对于需要复杂推理的查询,可以路由到更大、更强大的模型;而对于简单查询,则路由到更小、更快的模型。这有助于为简单提示保持低时延,同时仅在需要时为复杂提示增加时延。
  • 利用缓存:对于经常收到相似提示的系统,缓存可以显著降低时延。具体做法是维护一个常用提示及其响应的缓存库。当收到新提示时,快速计算新提示与缓存中提示的相似度得分。

如果找到足够接近的匹配项,您可以立即返回缓存的响应,完全跳过相对缓慢的生成过程。经过精心调优,这种方法可以极大地改善许多提示的系统时延。

如果您仍想利用缓存,但又希望获得一定程度的个性化响应,可以先检索缓存响应,然后将缓存响应和用户提示一起输入到一个更小、更快的LLM中,对响应进行微调,使其更贴合当前提示。

优化策略二:处理其他基于Transformer的组件

在优化了核心LLM的时延之后,下一步是处理流程中其他基于Transformer的组件。

这些组件可能是查询改写器、重排序器或路由LLM等。它们各自扮演着重要角色,但同时也增加了时延。

这里的建议是:测量每个组件为系统增加的时延,以及它们提供的增量响应质量。例如,您可能会发现查询改写器带来的收益不大,从而选择移除该组件。

优化策略三:优化检索器时延

虽然生成过程通常是时延的最大来源,但仍有一些方法可以减少检索器引起的时延。

  • 使用二进制量化嵌入:在向量数据库中使用经过二进制量化的嵌入向量。

这简化了底层的向量距离计算,有助于加速检索。

  • 数据库分片:将大型数据库分片到不同的实例中,尤其是在数据库变得相当庞大时,这也有助于减少搜索时延。这些是改善任何数据库时延的常用方法,大多数向量数据库提供商都包含帮助您实施这些方法的工具。

总结与行动指南

在您的RAG系统中,时延与质量之间几乎总是存在某种权衡。首先,您应该了解系统能够容忍多少时延。

如果您需要降低时延,请遵循以下步骤:

  1. 从核心LLM入手,考虑使用更小、更快的模型或引入路由和缓存机制。
  2. 转向其他基于Transformer或LLM的功能组件,评估其性价比,必要时进行精简。
  3. 如果时延仍是问题,再着手处理流程中的其他组件,例如优化检索器。

通过建立一个健壮的可观测性系统,您应该能够看到每次更改的影响,并迭代地将时延降低到项目所需的水平。

本节课中,我们一起学习了RAG系统中时延与响应质量的权衡关系,识别了时延的主要来源,并掌握了一系列从核心LLM到其他组件的优化策略。理解并管理这种权衡,是构建高效、实用RAG应用的关键。

047:安全防护机制 🔒

在本节课中,我们将探讨如何为你的RAG应用构建安全防护机制。网络安全是一个深奥且不断发展的领域,我们无法覆盖所有可能的风险。因此,我们将重点关注RAG系统特有的一些安全挑战与应对策略。

概述

构建RAG系统的一个常见原因是处理私有或专有信息。这些信息通常被刻意排除在公开网络之外,以避免被大型语言模型(LLM)训练时使用。即使在构建了RAG系统之后,你通常仍希望保持这些数据的私密性。本节将介绍保护知识库信息安全的几种方法。

知识库信息泄露的途径

你的知识库信息可能通过几种方式泄露。以下是几种主要的风险场景。

1. 用户通过提示词直接请求

一个精心设计的提示词可能会说服LLM直接引用从你知识库中检索到的文本块内容。即使有防护措施,一个合理的假设是:你的应用用户至少可以间接访问知识库的内容。

针对此风险,有以下几种直接的解决方案:

  • 用户身份验证:根据用户被允许访问的信息级别,采用适当的身份验证方式。例如,如果你的知识库包含公司私有数据,确保只有登录的员工才能向你的RAG系统提交提示词是一个良好的开端。
  • 基于角色的数据隔离:确保数据根据基于角色的访问控制(RBAC)权限,被分割存储在多个独立的“租户”中。理论上,当用户提示触发向量数据库检索时,用户应只能访问与其角色和权限级别相匹配的文档。

虽然理论上你可以将所有文档存储在单一租户中,并使用元数据过滤器来决定用户应访问哪些文档,但在实践中,这种方法太容易出错。元数据过滤最适合用于个性化推荐,而非安全防护。为了安全,将数据存储在多个独立的租户中是更可靠的方法。

2. 向LLM提供商发送提示词

当你将增强后的提示词发送给LLM提供商以生成补全内容时,知识库数据也可能泄露。这个增强提示词包含了从你知识库中检索到的文档或文本块。此时,你便失去了对安全性的控制。根据知识库信息的安全级别,这可能是一个无法容忍的风险。

幸运的是,在这种情况下,你可以选择完全在本地或内部部署环境中运行RAG系统。这意味着在你自己的硬件上托管LLM和向量数据库。虽然这可能会为你的项目增加额外的复杂性和成本开销,但你现在可以控制整个RAG流程中知识库内容的访问。

3. 知识库被直接攻击

你的知识库也可能像任何传统数据库一样,被直接黑客攻击。传统数据库防御未授权访问的一种方式是对其内容进行加密。这意味着即使黑客获得了数据库的访问权限,也无法轻易读取加密信息。

然而,向量数据库对这种攻击向量提出了一些独特的挑战。为了使AI算法能够运行,至少你的文档的密集向量表示需要以解密的形式存储在内存中。文本块本身可以以加密形式存储和检索,然后在构建增强提示词时再解密。

一些向量数据库提供商现在提供这项服务,或者你也可以选择自己加密和解密文本块。这为系统增加了额外的复杂性和可能的延迟,但提供了额外的安全层级。不幸的是,那些需要保持未加密状态的密集向量本身仍然可能构成安全风险。研究表明,存在从其密集向量表示中重建原始文本的可能性。

目前正在探索一些技术来解决这个安全问题,例如向密集向量添加噪声、对它们进行变换,或者以保留距离但模糊语义的方式降低维度。然而,这些技术都会增加检索器的复杂性,并倾向于降低系统性能。向量数据库这种特有的潜在安全漏洞是一个持续研究的课题,但值得了解。这种攻击要求黑客既能直接访问你的数据库,又能使用实验性技术从密集向量中重建文本,但这确实是一个可能的安全隐患。

总结

本节课我们一起学习了保护RAG系统知识库安全的核心策略。我们探讨了信息可能泄露的几种途径:用户直接请求、向外部LLM发送数据以及数据库被直接攻击。针对这些风险,我们介绍了相应的防护措施,包括用户身份验证、基于角色的数据隔离、本地化部署以及对存储内容的加密。

主要收获是,请记住你的知识库很可能包含私有信息,你应该理解并控制这些信息如何被访问。将本视频中的技术与更广泛的网络安全预防措施结合使用,将有助于提高你生产环境RAG系统的安全性。

048:多模态RAG系统 🖼️📄

在本节课中,我们将要学习如何构建能够处理多种数据类型的检索增强生成系统。我们将探讨多模态模型如何工作,以及如何将它们集成到RAG架构中,使其能够理解和利用图像、幻灯片、PDF等非文本信息。


在本课程中,你已经看到了基于文本数据构建的RAG系统。然而,如今信息以多种多样的格式存储。幻灯片、PDF或图像也包含有价值的信息,理想情况下,你希望将这些信息纳入知识库,并供你的大语言模型使用。

得益于多模态模型的前沿发展,构建能够处理多种数据类型的RAG系统变得越来越可行。让我们来看看它们是如何工作的。

什么是多模态模型?

一个多模态模型被设计用于处理多种数据类型。最常见的组合是文本和图像,但音频和视频也是可能的。一个典型的多模态RAG系统可以接受文本和图像作为提示,在知识库中存储文本和图像文件,并最终生成文本响应。

为了支持这些新功能,检索器和LLM都需要更新以具备多模态能力。让我们看看每个组件需要如何改变。

多模态嵌入模型

第一个需要实现多模态的组件是向量数据库使用的嵌入模型。多模态嵌入模型能够将多种格式的数据嵌入到同一个向量空间中。

如果你使用这种模型来嵌入单词“狗”和“小狗”,你会期望它们的向量彼此相当接近,这与纯文本嵌入模型类似。然而,如果你给同一个模型一张狗的图片,该图片的向量最终也会位于向量空间中相近的区域。

如果你嵌入一张树的图片和单词“树”,这两个对象也会被嵌入到彼此接近的位置,但在向量空间的不同区域。换句话说,多模态嵌入模型的工作原理与文本嵌入模型非常相似,将含义相近的项目放置得更近。然而,由于其设计,它们可以对多种类型或模态的数据执行相同的功能。

一旦你有了多模态嵌入模型,基于向量的检索工作方式就非常熟悉了。

多模态检索过程

上一节我们介绍了多模态嵌入模型,本节中我们来看看如何利用它进行检索。

知识库中的图像和文本都可以嵌入到同一个向量空间中。当收到提示时,无论它是图像还是文本,都使用同一个多模态模型来嵌入该提示。然后像往常一样完成向量搜索,返回其向量最接近提示向量的图像或文档。从知识库中检索到的文本和图像随后可以像往常一样添加到增强提示中,并发送给语言模型。

语言视觉模型

为了让语言模型处理文本和图像,你需要使用语言视觉模型。这种模型的工作原理与纯文本LLM非常相似,但具有处理同样被分词化的图像的能力。

为了做到这一点,图像必须被分词化。分词化图像的典型过程是将图像分割成单独的图像块,每个块表示为一个标记。根据分辨率,图像可能由低端约100个标记到高端接近1000个标记来表示。

这里重要的不是使用了多少标记,而是这些模型的设计使得图像和文本都可以像纯文本模型一样被转换成标记序列。

语言视觉模型的工作方式与标准LLM非常相似,将这个多模态标记序列通过一个转换器,该转换器可以对提示中的文本和图像及其关系形成细致的理解。然后,模型通常会生成文本标记作为输出,以响应初始提示。

升级RAG系统架构

一旦你拥有了多模态嵌入模型和语言视觉模型,将你的RAG系统升级为在知识库中存储图像和文本就相当简单了。

高层架构基本上相同,但它现在可以处理文本和图像。

处理幻灯片和PDF

更新RAG系统以处理图像的一个好处是,这使你的系统能够摄取许多容易转换为图像的常见文件格式。例如,幻灯片和PDF很容易被视为图像文件。

然而,这些格式面临的一个挑战是幻灯片和PDF的信息密度可能非常高。一页或一张幻灯片可以包含文本、图表、标题和图像。单个向量很难捕捉PDF一页上的所有细微差别。换句话说,你需要像分割文本一样分割你的图像。


图像分块与PDF Rag方法

最初,这是通过相当复杂的技术来检测PDF页面的不同部分。这些算法试图确定页面的哪一部分是图表,哪一部分是图像,哪一部分是文本等等。然而在实践中,这些技术仍然容易出错且难以处理。

一种称为PDF Rag的新方法只是将每一页分割成网格状的正方形,而不担心这些边界是否落在合理的位置。然后,每个正方形通过多模态嵌入模型嵌入到一个密集向量中。这意味着你的页面由,比如说,1000个向量而不是一个向量来表示。

然后,向量搜索的工作方式与Colbert非常相似。提示中的每个单词在给定页面上寻找其最佳匹配的正方形。然后将这些分数相加,以得出文档整体页面的分数。

这种方法非常灵活,因为任何图像都可以分割成网格状的正方形。在实践中,它在检索任务上也表现良好。这种方法如此灵活且性能良好的事实意味着它是支持多模态检索的一个有前景的方向。

它的主要缺点是要求你的向量数据库存储大量的向量。尽管如此,向量数据库提供商正在越来越多地实施工具来支持这种多模态检索,你应该可以预期围绕多模态知识库构建RAG系统会继续变得更加容易。

总结与展望

本节课中我们一起学习了多模态RAG系统。多模态RAG仍然是一项前沿技术,正在快速积极地发展。大多数AI提供商都提供语言视觉模型,而多模态嵌入模型则是相对更实验性的产品。也就是说,当你希望突破RAG系统能力的前沿时,可以期待在多模态RAG领域看到令人兴奋且持续的进展。

049:总结

在本模块中,我们学习了如何将RAG系统从原型阶段部署到生产环境,并应对随之而来的新挑战。现在,让我们对整个模块的内容进行回顾和总结。

模块回顾

上一节我们介绍了RAG系统的安全挑战与多模态扩展,本节我们将对整个模块的核心内容进行梳理。

以下是本模块涵盖的主要主题:

  1. 生产环境与原型阶段的差异:生产环境面临更高流量、不可预测的错误以及更严重的错误后果。
  2. 评估系统的重要性:一个精心设计的评估系统对于确保系统平稳运行和排查问题至关重要。
  3. 评估策略的平衡:结合组件级评估端到端评估,以及传统软件性能指标与RAG特有的质量指标,可以全面了解系统在真实流量下的表现。
  4. 权衡管理:在实际操作中,通常无法仅优化响应质量,还需考虑系统成本(如 cost < budget)和延迟(如 latency < target_range)。需要策略来应对这些权衡。
  5. 安全与多模态挑战:探索了RAG系统特有的安全挑战,以及多模态RAG如何拓展RAG系统的能力边界。

课程总结

本节课中,我们一起学习了管理生产环境RAG系统的核心知识。你已掌握了从设计到构建自有生产级RAG系统所需的所有独特基础。

希望你喜欢从原理开始深入了解RAG如何运作的过程,并希望你在离开本课程时,对下一步想要构建的项目有了新的想法。

非常感谢你参与这门课程的学习,并祝愿你在接下来的AI探索之旅中一切顺利。

posted @ 2026-03-26 08:12  绝不原创的飞龙  阅读(2)  评论(0)    收藏  举报