作者:来自 Elastic Jessica L. Moszkowicz
星期天晚上 10 点,我九年级的女儿哭着冲进我的房间。她说她对代数一无所知,注定要失败。我进入超级妈妈模式,却发现我一点高中数学知识都不记得了。于是,我做了任何一位超级妈妈在 2024 年都会做的事情,前往 ChatGPT 寻求帮助。这些生成式 AI 聊天机器人太棒了。我很快就得到了关于如何解决她所有问题的详细解释。“但是妈妈,”她抱怨道,“我们不是这样做的!”如果我能让 ChatGPT 的答案与班级的特定做事方式保持一致就好了……
幸运的是,语义搜索和检索增强生成 (RAG) 使这成为可能。在这篇博文中,我将展示如何在你自己的数据上训练 LLM 聊天机器人,使其适用于你的用例并可在整个组织中扩展。这不是教程,尽管您可以在 Elastic 的 Search Labs 中找到很多教程。相反,我们将重点介绍伟大的创意以及它们可以为你的业务带来的价值。我们将回答如何让生成式 AI 比现在更好这个问题。
大型语言模型
大型语言模型 (LLMs) 及其构建的聊天机器人在过去几年中改变了世界,这是有充分理由的。它们通过在用户所在位置与用户会面,出色地理解和响应用户输入。我们不再被迫找出完美的搜索词;我们可以像与能够以我们容易理解的语言提供示例和专家级知识的人类交谈一样提出我们想要的内容。但它们并不完美。
LLMs 面临的挑战
LLM 接受通用公共数据的训练,而这些数据往往在聊天机器人可以使用时已经过时了。它们之所以能很好地工作,是因为如今有大量此类数据可用,但是他们无法访问的数据怎么办?我女儿坚持要我们按照他们在学校教的精确方法做她的家庭作业,这似乎是一个微不足道的例子(但对她来说不是!)。然而,对于那些希望将这项新技术变成可以销售的产品但需要 LLM 能够谈论他们的私人内容的用户来说,类似的场景正在上演。
此外,如果 LLM 在他们的训练集中没有问题的答案,他们很容易产生幻觉。他们通常会自信地告诉用户完全不真实的信息来提供一些东西,而不是令人失望的“我不知道”。不过,有些事情这些模型不应该知道。我们不希望他们访问我们的专有信息,我们当然也不希望他们编造只能使用专有信息回答的问题的答案。
那么,由 LLM 驱动的聊天机器人是否注定永远只是娱乐消遣,在生产和规模上没有实际用途?当然不是!让我们讨论一下如何两全其美:基于私人数据源的信息提供可爱的自然语言答案。
语义搜索 - Semantic search
要实现利用生成式人工智能无法访问的信息来改进生成式人工智能的目标,第一步是确定需要哪些信息。但是,这种搜索需要有多好?假设你有一个数据集,其中包含您想要询问聊天机器人的所有问题的答案。让我们考虑几种可能性,并针对每种可能性进行一些案例研究。
BloombergGPT:从头开始培训 LLM
在理想世界中,这种选择是理想的,但培训 LLM 的现实情况使这种方法对大多数公司来说都不切实际。LLM 培训需要真正海量的高质量数据(数千亿个 token),以及使用昂贵计算资源的训练有素的数据科学家。
一家能够实现这一目标的公司是彭博社,其推出了专为处理金融领域内容而设计 的BloombergGPT 大语言模型。为了实现这一点,彭博社利用了其 40 年来积累的金融数据、新闻和文档,并补充了大量来自金融申报文件和互联网上的通用信息。彭博社的数据科学家使用了 7000 亿个标记和 130 万小时的图形处理单元(GPU)时间。大多数公司都没有这种资源。因此,即使您的公司拥有可以正确回答问题的所有数据,距离从零开始训练一个大语言模型,所需的信息量仍可能远远不够。
Med-PaLM:对现有 LLM 进行微调
与从头开始训练模型相比,第二种选择所需的计算能力和时间要少得多,但这种方法仍然成本很高。谷歌在 Med-PaLM(医学领域的 LLM)中采用了这种方法。它所取得的成就令人印象深刻,但我们不可能都成为谷歌。这项工作需要一个庞大的数据科学家团队以及谷歌最初被允许进行微调的 LLM。并非所有 LLM 供应商都允许微调,例如 OpenAI 和 GPT-4。
Elastic 支持助手:检索增强生成
幸运的是,另一种方法可以在现有 LLM 提供商建立的参数范围内工作,充分利用已投入到 LLM 开发中的巨大努力。这种技术,即 RAG,使用提示工程,允许现有 LLM 处理附加内容,而无需修改 LLM,只需在提示中包含必要的信息即可。这种方法的一个很好的例子是 Elastic 支持助手,这是一个聊天机器人,可以使用 Elastic 的支持知识库回答有关 Elastic 产品的问题。通过将 RAG 与此知识库结合使用,支持助手将始终能够使用有关 Elastic 产品的最新信息,即使底层 LLM 尚未接受过新添加功能的培训。
为了使这种方法实用且可扩展,我们必须仔细确定这些额外内容应该是什么。LLM 供应商通常按 token 收费,因此发送给他们的每个字都很重要。下表显示了几个流行 LLM 的一些费用。
Assumptions | |
Requests per day | 86,400 |
Low Prompt Tokens | 1,000 |
High Prompt Tokens | 2,000 |
Low Response Tokens | 250 |
High Response Tokens | 500 |
Cost per day | ||
Low Price | High Price | |
GPT-4 | $3,888.00 | $7,776.00 |
GPT-3.5 | $129.60 | $259.20 |
Claude-v2.1 | $1,209.60 | $2,419.20 |
Claude Instant | $120.96 | $241.92 |
因此,尽管将数据集中的所有内容发送给 LLM 可能很诱人,但这根本不是一种实用的提示工程方法。相反,我们希望提出尽可能严谨的提示,以帮助 LLM 正确回答。我们稍后将讨论构建提示的各个部分,但首先,我们需要弄清楚如何找到我们想要包含的额外内容。我们如何确定 LLM 需要什么才能给出正确的答案?
向量
文本搜索长期以来一直依赖于以关键字为中心的算法。关键字搜索是一种信息检索的句法方法。在语言学中,句法是指单词和短语如何排列在一起。单词的含义并不重要。考虑以下句子:
- Jack and Jill went up a hill.
- A hill is what Jack and Jill went up.
- Jack and Jill went up a dune.
这些句子的意思都是一样的,但只有前两个句子是使用关键字搜索单词 hill 得到的匹配结果。关键字搜索是一个众所周知的问题,并且在一定程度上效果非常好。使用关键字的搜索算法永远不会返回给定搜索词 hill 的句子 (3)。获得句子 (1) 和 (2) 可能是用例所需的全部内容,但如果我们也想要句子 (3),我们需要超越句法,转向语义。
语义是指语言学中单词和短语的含义。计算机发现 “理解” 这一点更具挑战性,因为它需要深入理解,而这很难通过编程实现。普通英语使用者可能知道山丘(hill)和沙丘(dune)是相似的概念,但我们如何向计算机传授这一点呢?计算机真正擅长的一件事就是数学。如果我们能将语义搜索问题转化为数学问题,计算机就会非常擅长!所以,这就是我们要做的。
将语义搜索变成数学问题
让我们从一个简单的例子开始。我们想用数字的方式描述一个概念的含义。假设我们正在描述一只猫的概念。在我们的例子中,我们将使用图像来表示概念。我们可以有一个从 -1 到 1 的尺度来表示给定图像看起来有多像一只猫。在图 1 中,我们在数字线上表示这个尺度,你可以把它看作坐标系的 x 轴。最右边的图片被分配了值 [1],因为它看起来很像一只猫。左边的飞机看起来绝对不像一只猫,所以它得到了值 [-1]。点 [0] 处的图像有一些像猫的特征,但不足以在看起来像猫的尺度上获得更高的分数。
我们现在有一个一维模型,可以用它来描述任何概念。在这个模型中,我们唯一能说的概念就是它们是否看起来像猫,这使得这个模型几乎没有用处。如果我们想添加更多描述概念的方法,我们必须添加更多维度。
让我们为模型添加一个新维度,我们可以用它来表示图像的真实程度。我们将用坐标平面中的 y 轴来表示它(见图 2)。将这两个尺度结合起来,我们就能得到一个二维模型,如图 3 所示。请注意,现在有两个值代表概念;第一个数字告诉我们图像有多像猫,第二个数字告诉我们图像有多真实。
这个值列表称为向量嵌入。你可以将其视为模型中概念的地址。像我们在这里开发的二维模型的地址类似于纬度和经度点。如果我们添加第三个维度,比如图像的颜色,我们将在向量嵌入中获得第三个值。这就像在纬度和经度上添加海拔一样。
最近邻居 - nearest neighbors
由于概念是根据特定特征在模型中定位的,因此模型中彼此接近的概念可能在某种程度上相似。这些最近邻居就是我们在进行语义搜索时返回的内容。要找到相似的概念,我们首先在模型中找到我们要寻找的概念。然后我们看看附近还有哪些其他概念。非常接近的概念更适合搜索词,而较远的邻居则不太好。图 4 使用我们的二维向量空间或模型展示了一个简单的示例。
模型中的维度数量决定了描述概念的详细程度。维度越多,概念的描述越细,但也会导致更复杂的最近邻搜索。OpenAI 目前提供了几种嵌入模型,最新的是 text-embedding-3-small 和 text-embedding-3-large。后者的维度高达 3,072,而小版本则有更易于管理的 1,536。
很难想象一个具有如此多维度的向量空间;事实上,许多人都难以理解任何高于三维的东西。相反,你可能会发现将嵌入中的每个数字视为概念地址的一部分会有所帮助。如果模型有 1,536 个维度,那么每个概念的地址将有 1,536 个部分来描述概念在多维向量空间中的位置。这也意味着有 1,536 种方法来描述这个概念。
最近邻搜索(Nearest neighbor search)仍然可以在这些大型嵌入上工作,但数学变得更加棘手 —— 比我们在本博客中讨论的要棘手得多。可以说,增加更多描述概念的方式可能非常有价值,但在如此高的特异性和实际使用模型的实用性之间存在权衡。如果我们要在生产中大规模执行语义搜索,就必须取得适当的平衡。
到目前为止,我们已经使用图像来表示概念。图像的嵌入模型的工作方式与我们在此处展示的大致相同,尽管维度更多,但我们现在将注意力转向文本。使用向量描述像猫这样的概念是一回事,但如果我们想搜索更详细的东西,比如 a mischievous cat about to pounce (一只即将扑向你的淘气猫),该怎么办?即使在这个短语中,也有很多事情发生,在现实世界中,你可能会处理更大的段落。现在,我们将讨论如何将语义搜索应用于散文。
将语义搜索应用于散文
在过去,当你尝试使用互联网上的大量数据来回答问题时,你会仔细考虑关键字的选择,并希望其中一个返回的链接包含你需要的答案。随着搜索引擎的改进,它们开始在页面上包含他们认为答案所在的预览,因此有时你甚至不需要单击链接。获得完整答案仍然有点像寻宝游戏,因此让生成式 AI 聊天机器人将所有部分整合在一起是非常有吸引力的。
要做到这一点,我们首先需要找到这些部分。本质上,我们正在做过去需要做的事情,然后让聊天机器人从这些 “链接” 中找出完整的答案。在上一节中,我们介绍了语义搜索作为句法搜索的替代方案,以提高我们发送给聊天机器人的内容的相关性。现在应该清楚为什么搜索含义可以提供比找到精确匹配更好的结果。
但是,超链接另一端的内容是什么意思呢?你可能经历过这样的情况:点击一个链接后,迷失在页面上,试图弄清楚为什么首先返回该链接。页面上可能有数百甚至数千个 token。我们已经讨论过为什么将所有 token 发送给聊天机器人是不切实际的。发送如此多的数据可能成本高昂,而且一次可以发送的数据量也存在技术限制。因此,找到 “链接” 并将页面上的所有内容发送给 LLM 是没有意义的。在执行语义搜索之前,我们需要将内容分解成有意义的部分。
分块
将内容分解的过程称为分块,它之所以必要,不仅仅是因为你可以发送给 LLM 的内容有限。再次考虑一下 mischievous cat about to pounce(调皮的猫即将扑向前方)的例子。向量嵌入是概念的数值表示,但这个短语中至少有四个不同的概念。不过,我们并不真正关心不同的概念。我们关心的是它们的整体情况,所以我们真正想要的是整个短语的单一嵌入。
这是当今的嵌入模型可以做到的,但它们如何做到这一点的细节超出了本文的范围。简单来说,mischievous, pounce, about 及 to 的嵌入会影响猫的数值表示,使我们能够对像示例这样的复杂概念进行语义搜索。然而,考虑一下如何将单一嵌入分配给关于我们调皮的猫的整个段落。那么短篇小说甚至整部小说呢?
当你在向量嵌入中包含更多概念时,你自然会丢失一些细节。也就是说,随着你包含的内容越来越多,语义精度会下降。例如,一部小说可以涉及很多东西,而不仅仅是一个概念。另一方面,如果你将整部小说发送给 LLM,你几乎肯定会找到问题的“ 答案”。我们知道我们实际上无法做到这一点,但还有另一个原因导致我们无法对整部小说进行向量化。正如 LLM 限制它们一次可以接收的数据量一样,大多数嵌入模型限制了嵌入中可以包含的标记(token)数量。达到该标记限制后,其余内容将被删除。因此,即使我们尝试为一部小说获取单个嵌入,我们也可能只会捕捉到第一段左右的含义,然后忽略其余部分。
因此,对数据进行分块的任务比乍一看要棘手。如图 5 所示,块的大小严重影响我们发现准确答案的能力。细粒度或小块具有较高的语义精度,因为块的向量表示较少被多个概念稀释。然而,小块不太可能包含我们正在寻找的完整 “答案”。想象一下,如果 Google 返回的每个链接都只指向几个单词。你几乎肯定需要点击多个链接才能获得所需的所有信息。另一方面,粗粒度或大块可能有完整的答案,但由于数字表示受到许多概念的影响,因此很难将它们识别为良好匹配。
有许多不同的分块策略试图缓解这些问题。在块大小和语义精度之间找到适当的平衡通常需要反复试验,最佳策略通常因用例而异。让我们考虑几种最常见的方法。
基于标记的分块 - Token-based chunking
第一种选择最直接。我们只是根据它们包含的标记数量来划分块。虽然段落中的标记数量可能相差很大,但合理的平均值是 150 个单词。如果我们的块每个都有 150 个标记,我们可能会达到正确的平衡,但你可能可以想象这种策略很容易失败。只要你的段落不是正好有 150 个标记,你就可能会有跨越段落边界的块和需要多个块的段落。这将产生级联效应,如图 6 所示。想象一下以这种方式阅读一本书,并在每读完一个块后停下来喝杯咖啡。几乎不可能跟上。如果你以这种零散的方式阅读一本书,你很可能不得不回头重读一些文字,以免迷失方向。策略 2 和策略 3 就是基于这一原则。
标记重叠 - Token overlap
标记重叠是指每个块与其旁边的块重叠(见图 7)。例如,我们可能有 50 个标记重叠,因此每个块都是 200 个标记。标记重叠增加了块包含完整想法、主题转换或上下文线索的机会。但是,这种方法必然存在一些冗余。这可能没问题,但当我们考虑大规模运行 RAG 应用程序时,资源管理很重要。
周围块 - Surrounding chunks
我们将在这里讨论的最后一个策略是检索周围块。基本思想类似于通过查看前后内容来熟悉所读内容的上下文。我们从与策略 1 相同的基于标记的块开始。然后,我们应用语义搜索来找到 “最佳”块(即,与我们要搜索的内容最近的邻居)。此时,我们已准备好将信息发送给 LLM,但不是只发送最相关的块,而是直接发送最相关匹配之前和之后的块。这有望确保我们向 LLM 发送完整的想法,以便聊天机器人拥有回答我们问题所需的一切。
检索增强生成 - Retrieval augmented generation
到目前为止,我们专注于检索增强生成的检索部分。我们知道我们将使用 LLM 进行生成部分,这给我们留下了一个问题,即我们检索的内容将如何增强聊天机器人生成的内容。要理解这一点,我们首先需要考虑我们如何与 LLM 进行交互。我们使用提示与 LLM 驱动的聊天机器人交谈。简而言之,提示就是我们对聊天机器人说的话,对于像 ChatGPT 这样的网站,它真的就像输入一些内容并等待响应一样简单。然而,在幕后,还有更多的事情发生 —— 提示实际上由几个部分组成。
提示工程 - prompt engineering
系统提示 - system prompt
首先,总是有一个系统提示来定义我们希望聊天机器人通常如何表现。使用 ChatGPT,不会显示此系统提示,但当我们创建自己的 RAG 应用程序时,我们需要定义它才能让聊天机器人执行我们想要的操作。由于我们将检索数据以增强聊天机器人的知识,因此我们需要确保生成使用该数据。此外,如果我们想限制应用程序使用检索到的数据来防止幻觉,也应该在系统提示中指定这一点。例如,以下系统提示将确保我们正在寻找的行为:
You are a helpful AI assistant who answers questions using the following supplied context. If you can’t answer the question using this context, say, “I don’t know.”
提供的上下文
提示的下一部分是提供的上下文。这是我们使用搜索检索到的数据的地方。例如,如果我们运行语义搜索并找到搜索词的三个最近相邻块,我们可以在提供的上下文中提供这三个块。或者,我们可能只发送最近的最近邻居以及前面和后面的块。我们在此部分中包含什么取决于我们,并且可能需要反复试验才能找出最适合我们应用程序的内容。
用户输入
提示的最后一部分是用户输入。当我们使用 ChatGPT 之类的聊天机器人时,我们只能使用提示的这一部分。但是,对于我们的 RAG 应用程序,此部分具有双重用途。像往常一样,这是我们要求聊天机器人执行特定操作的地方,例如解释如何回答特定的代数问题,但这也是我们提供用于为提示提供上下文的搜索词的地方。有了所有这些部分,我们就可以开始查看我们的 RAG 应用程序的实际运行了。
更多关于这个的描述请阅读文章 “为生成式人工智能制作 prompt 三明治”。
图 9 显示了它如何解决我们最初的问题。我们如何让聊天机器人仅使用课堂上提供的信息来回答有关代数的问题?我们首先确定哪些信息是允许的,并将其提取到可搜索的数据存储中,例如 Elasticsearch。例如,我女儿的老师提供了 PDF 格式的课堂笔记以及指向经批准的入门主题网站的链接。在提取数据时,我们需要为语义搜索做好准备。幸运的是,Elasticsearch 通过提供一种字段类型来执行分块并计算出每个块的嵌入,使这一操作变得非常容易。我们有这个简单的语义搜索按钮,还有一个 AI playground,我们可以在开发 RAG 应用程序时看到它的工作情况。使用游乐场,我们可以查看我们的应用程序是否符合我女儿的标准(见图 10)。
使用 Elasticsearch 构建您自己的应用程序
我们已经看到了为什么检索增强生成对于使 LLM 驱动的聊天机器人实用且可扩展是必要的。仅仅依靠 LLM 所训练的公共数据根本毫无意义,但我们还需要了解我们如何以及与他们分享了什么。语义搜索可以根据其含义而不是关键字来检索高度相关的数据。
Elasticsearch 可以轻松设置语义搜索,然后使用其 AI Playground 功能查看其实际效果。一旦 Playground 中的一切都看起来不错,你就可以下载聊天机器人的代码,以便将其插入你自己的应用程序中。Elastic 的 Search Labs 提供了有关如何使用此处描述的工具执行此操作的详细教程。
你无需成为专家数据科学家即可使用语义搜索或生成 AI。RAG 可以轻松充分利用这项技术。现在,你知道幕后发生了什么,使它如此有效。
准备好深入了解了吗?接下来阅读这本电子书:高管实施生成式人工智能的指南。
原文:The big ideas behind retrieval augmented generation | Elastic Blog