WithAI.Design

5 min read

我们从一年的大语言模型构建中学到的经验上

我们从一年的大语言模型构建中学到的经验上

最近看到一篇关于LLM的文章,觉得有用,翻译分享给大家,将分为两期呈现。原文地址:https://www.oreilly.com/radar/what-we-learned-from-a-year-of-building-with-llms-part-i/

从一年使用大型语言模型 (LLM) 的经验中我们学到了什么(第一部分) - O’Reilly

现在是使用大型语言模型(LLM)构建应用的激动人心的时刻。在过去的一年里,LLM 已经足够“好用”,可以用于现实世界的应用。LLM 的改进速度,加上社交媒体上层出不穷的演示,将推动预计在 2025 年达到 2000 亿美元的 AI 投资。LLM 也广泛可用,让每个人,而不仅仅是机器学习工程师和科学家,都能将智能融入他们的产品。虽然构建 AI 产品的门槛降低了,但要创建一个超越演示的有效产品仍然是一个具有欺骗性的困难任务。

我们从机器学习中汲取了一些至关重要的经验和方法论,这些经验和方法论对于开发基于 LLM 的产品至关重要,但却经常被忽视。了解这些概念可以让你在该领域中胜过大多数人,而无需机器学习专业知识!在过去的一年里,我们六个人一直在基于 LLM 构建现实世界的应用。我们意识到需要将这些经验总结在一个地方,以便造福社区。

我们来自不同的背景,担任不同的角色,但我们都亲身经历了使用这种新技术的挑战。我们中的两个人是独立顾问,他们帮助了许多客户将 LLM 项目从最初的概念阶段发展到成功的产品阶段,见证了决定成败的模式。我们中的一位是研究机器学习/AI 团队如何工作以及如何改进其工作流程的研究人员。我们中的两个人是应用 AI 团队的领导者:一个在科技巨头,一个在初创公司。最后,我们中的一位教了成千上万的人深度学习,现在致力于使 AI 工具和基础设施更易于使用。尽管我们有着不同的经历,但我们对在所学经验中发现的一致主题感到震惊,我们惊讶于这些见解没有得到更广泛的讨论。

我们的目标是将这篇文章打造成一个有关围绕 LLM 构建成功产品的实用指南,从我们自己的经验中汲取教训,并指出行业中的示例。在过去的一年里,我们亲身体验并从中吸取宝贵教训,往往是以痛苦的方式。虽然我们不声称代表整个行业,但在这里我们分享了一些针对使用 LLM 构建产品的任何人的建议和经验。

这项工作分为三个部分:战术、运营和战略。这是三篇文章中的第一篇。它深入探讨了使用 LLM 的战术细节。我们分享了关于提示、设置检索增强生成、应用流程工程以及评估和监控的最佳实践和常见陷阱。无论你是使用 LLM 的从业人员还是在周末进行项目的黑客,本节都是为你而写。请关注未来几周发布的运营和战略部分。

准备好潜入了吗?让我们开始吧。

战术


在本节中,我们将分享新兴 LLM 堆栈的核心组件的最佳实践:提示技巧以提高质量和可靠性、评估策略以评估输出、检索增强生成的想法以提高基础,等等。我们还将探讨如何设计人机交互工作流程。虽然技术仍在快速发展,但我们希望这些经验教训,是我们共同进行的无数实验的副产品,将经得起时间的考验,帮助你构建和交付强大的 LLM 应用。

提示

我们建议在开发新应用程序时从提示开始。很容易低估 高估它的重要性。之所以被低估,是因为正确的提示技巧,如果使用得当,可以让我们走得很远。之所以被高估,是因为即使是基于提示的应用程序也需要围绕提示进行大量的工程设计才能正常工作。

专注于从基本的提示技术中获得最大收益

一些提示技巧始终如一地帮助提高了各种模型和任务的性能:n-shot 提示 + 上下文学习、思维链和提供相关资源。

通过 n-shot 提示进行上下文学习的想法是向 LLM 提供几个演示任务的示例,并将输出与我们的期望相一致。一些提示:

  • 如果 n 太低,模型可能会过度依赖这些特定示例,从而影响其泛化能力。一般来说,目标是 n ≥ 5。不要害怕将其提高到几十个。
  • 示例应能代表预期输入的分布。如果你正在构建一个电影摘要器,请从不同的类型中包含示例,其比例大致与你期望在实践中看到的比例相同。
  • 你并不一定需要提供完整的输入-输出对。在许多情况下,仅提供所需输出的示例就足够了。
  • 如果你使用的是支持工具使用的 LLM,那么你的 n-shot 示例也应该使用你希望代理使用的工具。

在思维链 (CoT) 提示中,我们鼓励 LLM 在返回最终答案之前解释其思维过程。可以把它想象成向 LLM 提供一个草稿板,这样它就不必将所有内容都记在脑海中。最初的方法只是在说明中添加短语“让我们一步一步地思考”。但是,我们发现使 CoT 更具体会有所帮助,在说明中添加一两句话通常可以显着降低幻觉率。例如,当要求 LLM 总结会议记录时,我们可以明确说明步骤,例如:

  • 首先,在草稿板上列出关键决策、后续事项和相关负责人。
  • 然后,检查草稿板中的详细信息与记录是否事实一致。
  • 最后,将关键点概括成简洁的摘要。

最近,一些质疑 已经对这种技术是否像人们认为的那样强大提出了质疑。此外,关于在使用思维链时推理过程中究竟发生了什么存在很大争议。无论如何,这是一个值得尝试的技术。

提供相关资源是一种强大的机制,可以扩展模型的知识库、减少幻觉并增强用户的信任。通常通过检索增强生成 (RAG) 来实现,向模型提供它可以将其直接用于响应的文本片段是一种必不可少的技术。在提供相关资源时,仅仅包含它们是不够的;不要忘记告诉模型优先使用它们、直接引用它们,有时还要说明何时没有任何资源足够。这些有助于将代理的响应“绑定”到资源库中。

结构化你的输入和输出

结构化的输入和输出有助于模型更好地理解输入,并返回可以可靠地与下游系统集成的输出。在输入中添加序列化格式化有助于向模型提供更多关于上下文中的标记之间关系的线索、特定标记的附加元数据(如类型)或将请求与模型训练数据中的类似示例相关联。

例如,许多关于编写 SQL 的网络问题首先指定 SQL 模式。因此,你可能会预期,针对文本到 SQL 的有效提示应包括结构化的模式定义;事实上

结构化输出起到类似的作用,但它还可以简化与下游系统组件的集成。InstructorOutlines 在结构化输出方面表现出色。(如果你正在导入 LLM API SDK,请使用 Instructor;如果你正在导入 Huggingface 以使用自托管模型,请使用 Outlines。)结构化输入清楚地表达了任务,并且类似于训练数据的格式,增加了获得更好输出的可能性。

在使用结构化输入时,请注意,每个 LLM 系列都有自己的偏好。Claude 偏爱 xml,而 GPT 更喜欢 Markdown 和 JSON。使用 XML,你甚至可以通过提供 response 标记来预先填充 Claude 的响应,如下所示。

                                                     `</> python
messages=[     
    {         
        "role": "user",         
        "content": """Extract the <name>, <size>, <price>, and <color>` 
                   `from this product description into your <response>.   
                <description>The SmartHome Mini` 
                   `is a compact smart home assistant` 
                   `available in black or white for only $49.99.` 
                   `At just 5 inches wide, it lets you control` 
                   `lights, thermostats, and other connected` 
                   `devices via voice or app—no matter where you`
 `place it in your home. This affordable little hub`
                  ` brings convenient hands-free control to your`
                  ` smart devices.             
                </description>"""     
   },     
   {         
        "role": "assistant",         
        "content": "<response><name>"     
   } 
]`

让小型提示只做好一件事,并且只做好一件事

软件中一种常见的反模式/代码异味是“上帝类”,其中我们有一个类或函数执行所有操作。同样的事情也适用于提示。

提示通常从简单开始:几句话的说明、几个示例,我们就开始了。但当我们尝试提高性能并处理更多边缘情况时,复杂性就逐渐蔓延开来。更多的说明。多步骤推理。几十个示例。在我们意识到之前,我们最初简单的提示已经变成了一个 2000 个标记的怪胎。更糟糕的是,它在更常见和更直接的输入上的性能更差!GoDaddy 将此挑战列为他们在 使用 LLM 构建应用的第 1 课

就像我们努力(阅读:挣扎)使我们的系统和代码保持简单一样,我们也应该为我们的提示做同样的事情。与其为会议记录摘要器使用单个万能提示,不如将其分解成几个步骤:

  • 将关键决策、行动项目和负责人提取成结构化的格式
  • 检查提取的详细信息与原始记录的一致性
  • 从结构化详细信息中生成简洁的摘要

因此,我们将单个提示拆分成多个提示,每个提示都简单、专注且易于理解。通过将它们分解,我们现在可以分别迭代和评估每个提示。

精心设计你的上下文标记

重新思考,并挑战你关于实际需要发送给代理多少上下文的假设。像米开朗基罗一样,不要构建你的上下文雕塑——去除多余的材料,直到雕塑显现出来。RAG 是一种流行的将所有可能相关的石块整理在一起的方法,但你对提取必要内容做了什么?

我们发现,将发送给模型的最终提示——包含所有上下文构建、元提示和 RAG 结果——放到一张空白页面上,然后仔细阅读它,真的有助于你重新思考你的上下文。我们通过这种方法发现了冗余、自相矛盾的语言和糟糕的格式。

另一个关键的优化是你的上下文的结构。你的文档包表示对人类来说没有帮助,不要假设它对代理来说有任何帮助。仔细考虑如何构建你的上下文以强调其各部分之间的关系,并使提取尽可能简单。

信息检索/RAG

除了提示之外,另一种有效的引导 LLM 的方法是在提示中提供知识。这将 LLM 绑定到提供的上下文中,然后用于上下文学习。这被称为检索增强生成 (RAG)。从业人员发现,RAG 在提供知识和改善输出方面非常有效,同时与微调相比,所需的努力和成本要少得多。RAG 的好坏取决于检索到的文档的相关性、密度和细节

RAG 输出的质量取决于检索到的文档的质量,而检索到的文档的质量可以根据几个因素来考虑。

第一个也是最明显的指标是相关性。这通常通过排名指标量化,例如平均倒数排名 (MRR)归一化折扣累积增益 (NDCG)。MRR 评估系统在排名列表中将第一个相关结果排在首位的程度,而 NDCG 则考虑所有结果的相关性和它们的位置。它们衡量系统将相关文档排在更高位置,并将不相关文档排在更低位置的程度。例如,如果我们正在检索用户摘要以生成电影评论摘要,我们将希望将特定电影的评论排在更高位置,同时排除其他电影的评论。

与传统的推荐系统一样,检索到的项目的排名将对 LLM 在下游任务中的表现产生重大影响。为了衡量影响,请运行基于 RAG 的任务,但将检索到的项目打乱——RAG 输出的表现如何?

其次,我们还需要考虑信息密度。如果两个文档同样相关,我们应该优先选择更简洁、无关细节更少的文档。回到我们的电影示例,我们可能会认为电影记录和所有用户评论从广义上讲都是相关的。但是,最受欢迎的评论和编辑评论可能在信息方面更密集。

最后,考虑文档中提供的细节水平。想象一下,我们正在构建一个 RAG 系统,从自然语言生成 SQL 查询。我们可以简单地提供包含列名称的表模式作为上下文。但是,如果我们包含列描述和一些代表性值呢?额外的细节可以帮助 LLM 更好地理解表的语义,从而生成更正确的 SQL。

不要忘记关键字搜索;将其用作基准和混合搜索。

鉴于基于嵌入的 RAG 演示有多么普遍,很容易忘记或忽略信息检索领域数十年的研究和解决方案。

但是,虽然嵌入无疑是一个强大的工具,但它们并不是万能的。首先,虽然它们擅长捕捉高级语义相似性,但它们可能难以处理更具体、基于关键字的查询,例如当用户搜索名称(例如,Ilya)、首字母缩略词(例如,RAG)或 ID(例如,claude-3-sonnet)时。基于关键字的搜索,例如 BM25,专门为此设计。经过多年的基于关键字的搜索,用户可能已经将其视为理所当然,如果他们期望检索的文档没有返回,他们可能会感到沮丧。

向量嵌入_不能_神奇地解决搜索问题。实际上,在你使用语义相似性搜索重新排序之前,繁重的工作是在这一步中完成的。要真正改进 BM25 或全文搜索非常困难。

Aravind Srinivas,Perplexity.ai 首席执行官

我们已经向我们的客户和合作伙伴传达了这一点好几个月了。使用朴素嵌入的最近邻搜索会产生非常嘈杂的结果,你最好从基于关键字的方法开始。

Beyang Liu,Sourcegraph 首席技术官

其次,更易于理解为什么使用关键字搜索检索到某个文档——我们可以查看与查询匹配的关键字。相比之下,基于嵌入的检索更难解释。最后,由于 Lucene 和 OpenSearch 等系统经过数十年的优化和实战检验,关键字搜索通常计算效率更高。

在大多数情况下,混合方法效果最佳:对明显的匹配使用关键字匹配,对同义词、上位词和拼写错误以及多模态(例如,图像和文本)使用嵌入。Shortwave 分享了他们如何构建 RAG 管道,包括查询重写、关键字 + 嵌入检索以及排名。

优先选择 RAG 来获取新知识,而不是微调

RAG 和微调都可以用于将新信息纳入 LLM 并提高特定任务的性能。因此,我们应该先尝试哪一个?

最近的研究表明,RAG 可能具有优势。一项研究 将 RAG 与无监督微调(又称持续预训练)进行了比较,在 MMLU 的一个子集和当前事件上对两者进行了评估。他们发现,对于训练期间遇到的知识以及全新的知识,RAG 始终优于微调。在另一篇论文 中,他们将 RAG 与农业数据集上的监督微调进行了比较。同样,RAG 带来的性能提升也大于微调,特别是对于 GPT-4(见论文中的表 20)。

除了性能提升之外,RAG 还拥有几个实际优势。首先,与持续预训练或微调相比,更容易——也更便宜!——将检索索引保持最新。其次,如果我们的检索索引包含有问题的文档,这些文档包含有毒或有偏见的内容,我们可以轻松删除或修改这些有问题的文档。

此外,RAG 中的 R 提供了对我们如何检索文档的更细粒度的控制。例如,如果我们为多个组织托管 RAG 系统,通过对检索索引进行分区,我们可以确保每个组织只能从自己的索引中检索文档。这确保我们不会无意中将一个组织的信息暴露给另一个组织。

长上下文模型不会使 RAG 过时

随着 Gemini 1.5 提供高达 1000 万个标记的上下文窗口,有些人开始质疑 RAG 的未来。

我倾向于认为 Gemini 1.5 被 Sora 大大炒作了。1000 万个标记的上下文窗口实际上使大多数现有的 RAG 框架变得不必要——你只需将你的数据放入上下文中,像往常一样与模型对话即可。想象一下,它对所有将大部分工程工作投入到 RAG 中的初创公司/代理/LangChain 项目的影响😅 或者用一句话来说:1000 万个标记的上下文让 RAG 不复存在。Gemini 干得漂亮。

Yao Fu

虽然 1000 万个标记的上下文窗口确实将成为分析多个文档或与 PDF 交谈等用例的改变游戏规则,但 RAG 即将消亡的传言被大大夸大了。

首先,即使上下文窗口有 1000 万个标记,我们仍然需要一种方法来选择信息以馈送到模型中。其次,除了狭窄的“大海捞针”评估之外,我们还没有看到令人信服的数据证明模型可以有效地推理如此大的上下文。因此,如果没有好的检索(和排名),我们可能会用干扰项淹没模型,甚至可能会用完全不相关的信息填充上下文窗口。

最后是成本。Transformer 的推理成本与上下文长度呈二次方增长(或在空间和时间上呈线性增长)。仅仅因为存在一个可以读取你组织的整个 Google Drive 内容然后回答每个问题的模型,并不意味着这是一个好主意。考虑一个与我们如何使用 RAM 的类比:我们仍然从磁盘读取和写入,即使存在 RAM 达到数十 TB 的计算实例。

所以,现在不要急着把你的 RAG 扔进垃圾桶。即使上下文窗口的大小不断增加,这种模式仍然有用。

调整和优化工作流程

提示 LLM 只是开始。为了充分利用它们,我们需要超越单个提示并拥抱工作流程。例如,我们如何将一个复杂的任务分解成多个更简单的任务?微调或缓存何时有助于提高性能并降低延迟/成本?在本节中,我们将分享经过验证的策略和现实世界的示例,以帮助你优化和构建可靠的 LLM 工作流程。

分步、多轮“流程”可以带来巨大的提升。

我们已经知道,通过将单个大型提示分解成多个小型提示,我们可以获得更好的结果。AlphaCodium 就是一个例子:通过从单个提示切换到多步骤工作流程,他们将 GPT-4 在 CodeContests 上的准确率(pass@5)从 19% 提高到了 44%。该工作流程包括:

  • 反思问题
  • 对公共测试进行推理
  • 生成可能的解决方案
  • 对可能的解决方案进行排名
  • 生成合成测试
  • 在公共和合成测试上迭代解决方案。

具有明确目标的小型任务最适合代理或流程提示。并非每个代理提示都需要请求结构化输出,但结构化输出有助于与正在协调代理与环境交互的任何系统进行交互。

一些值得尝试的事情

  • 一个明确的计划步骤,尽可能地具体。考虑使用预定义的计划供选择(参见 https://youtu.be/hGXhFa3gzBs?si=gNEGYzux6TuB1del)。
  • 将原始用户提示改写成代理提示。请谨慎操作,此过程是有损的!
  • 代理行为作为线性链、DAG 和状态机;不同的依赖关系和逻辑关系对于不同的规模可能或多或少地适用。你是否可以从不同的任务架构中挤出性能优化?
  • 计划验证;你的计划可以包含有关如何评估来自其他代理的响应的说明,以确保最终的组装效果良好。
  • 使用固定上游状态的提示工程——确保你的代理提示针对可能发生在之前的一系列变体进行评估。

目前优先考虑确定性工作流程

虽然 AI 代理可以动态地对用户的请求和环境做出反应,但它们的不确定性使它们难以部署。代理采取的每一步都有失败的可能性,而从错误中恢复的可能性很小。因此,代理成功完成多步任务的可能性随着步骤数量的增加呈指数下降。因此,构建代理的团队发现很难部署可靠的代理。

一种很有希望的方法是让代理系统生成确定性计划,然后以结构化、可重现的方式执行这些计划。在第一步中,给定一个高级目标或提示,代理会生成一个计划。然后,以确定性的方式执行该计划。这使得每一步都更可预测和可靠。优点包括:

  • 生成的计划可以作为少样本示例来提示或微调代理。
  • 确定性执行使系统更可靠,因此更容易测试和调试。此外,可以将故障追溯到计划中的特定步骤。
  • 生成的计划可以表示为有向无环图 (DAG),与静态提示相比,DAG 更容易理解和适应新情况。

最成功的代理构建者可能是那些在管理初级工程师方面拥有丰富经验的人,因为生成计划的过程与我们指导和管理初级工程师的方式类似。我们给初级工程师明确的目标和具体的计划,而不是含糊的开放式指导,我们也应该对我们的代理做同样的事情。

最终,构建可靠的工作代理的关键可能在于采用更结构化、更确定性的方法,以及收集数据以改进提示和微调模型。如果没有这些,我们就会构建出可能在某些情况下表现非常出色,但平均而言会让用户失望,从而导致用户保留率低下的代理。

获取超出温度范围的多样化输出

假设你的任务需要 LLM 输出的多样性。也许你正在编写一个 LLM 管道,根据用户之前购买的产品列表来建议购买哪些产品。当你多次运行你的提示时,你可能会注意到生成的建议过于相似——因此你可能会在你的 LLM 请求中增加温度参数。

简而言之,增加温度参数会使 LLM 响应更加多样化。在采样时,下一个标记的概率分布变得更加平坦,这意味着通常不太可能出现的标记被选择的频率更高。但是,在增加温度时,你可能会注意到一些与输出多样性相关的故障模式。例如,

  • 目录中可能适合用户的一些产品可能永远不会被 LLM 输出。
  • 如果某些产品在 LLM 训练期间非常有可能出现在提示之后,那么它们可能会在输出中过度出现。
  • 如果温度过高,你可能会得到引用不存在的产品(或乱码!)的输出。

换句话说,增加温度并不能保证 LLM 会从你期望的概率分布(例如,均匀随机分布)中采样输出。但是,我们还有其他技巧可以增加输出多样性。最简单的方法是调整提示中的元素。例如,如果提示模板包含一个项目列表,例如历史购买记录,每次将这些项目插入提示时,对它们的顺序进行随机排序可能会产生重大影响。

此外,保留最近输出的简短列表可以帮助防止冗余。在我们的推荐产品示例中,通过指示 LLM 避免建议来自此最近列表中的项目,或者通过拒绝和重新采样与最近建议类似的输出,我们可以进一步使响应多样化。另一个有效的策略是改变提示中使用的措辞。例如,包含诸如“选择用户会经常使用并喜欢的物品”或“选择用户可能会推荐给朋友的产品”之类的短语,可以改变重点,从而影响推荐产品的多样性。

缓存被低估了。

缓存通过消除对相同输入重新计算响应的需要来节省成本并消除生成延迟。此外,如果以前对响应进行了安全审查,我们可以提供这些经过审查的响应,从而降低提供有害或不恰当内容的风险。

一种简单的缓存方法是使用正在处理的项目的唯一 ID,例如,如果我们正在对新文章或产品评论 进行摘要。当一个请求到来时,我们可以检查缓存中是否存在摘要。如果存在,我们可以立即返回它;如果不存在,我们会生成、安全审查并提供它,然后将其存储在缓存中以供将来请求使用。

对于更开放式的问题,我们可以借鉴搜索领域的技术,搜索领域也利用缓存来处理开放式输入。诸如自动完成和拼写纠正之类的功能也有助于规范化用户输入,从而提高缓存命中率。

何时微调

对于某些任务,即使是最巧妙设计的提示也可能不够。例如,即使经过大量的提示工程,我们的系统可能仍然难以返回可靠、高质量的输出。如果是这样,那么可能需要为你的特定任务微调模型。

成功案例包括:

  • Honeycomb 的自然语言查询助手:最初,将“编程手册”与上下文学习的 n-shot 示例一起提供在提示中。虽然这效果不错,但微调模型在特定领域语言的语法和规则方面获得了更好的输出。
  • ReChat 的 Lucy:LLM 需要以非常特定的格式生成响应,该格式将结构化数据和非结构化数据组合在一起,以便前端可以正确呈现。微调对于使其始终如一地工作至关重要。

但是,虽然微调可以有效,但它会带来巨大的成本。我们必须标注微调数据、微调和评估模型,最终还要自托管它们。因此,请考虑更高的前期成本是否值得。如果提示可以让你完成 90% 的工作,那么微调可能不值得投资。但是,如果我们确实决定微调,为了降低收集人工标注数据的成本,我们可以生成和在合成数据上进行微调,或者在开源数据上进行引导

评估与监控

评估 LLM 可能是一片雷区。LLM 的输入和输出都是任意的文本,我们为它们设置的任务也多种多样。但是,严格和周到的评估至关重要——OpenAI 的技术领导者 致力于评估,并对个人评估提供反馈 并非偶然。

评估 LLM 应用引入了各种不同的定义和简化:它仅仅是单元测试,或者更像是可观察性,或者也许仅仅是数据科学。我们发现所有这些视角都很有用。在以下部分,我们将分享一些关于构建评估和监控管道的重要性的经验教训。

从真实输入/输出样本中创建一些基于断言的单元测试

创建 单元测试(即断言),其中包含来自生产的输入和输出样本,以及基于至少三个标准对输出的期望。虽然三个标准可能看起来很随意,但这只是一个开始的实际数字;更少的标准可能表明你的任务没有得到充分定义,或者过于开放式,就像一个通用聊天机器人一样。这些单元测试或断言应由任何管道更改触发,无论是编辑提示、通过 RAG 添加新上下文还是其他修改。这个文章 有一个实际用例中基于断言的测试示例。

考虑从断言开始,指定在所有响应中要包含或排除的短语或想法。还要考虑检查以确保单词、项目或句子数量在一定范围内。对于其他类型的生成,断言可能有所不同。执行评估 是一种用于评估代码生成的强大方法,其中你运行生成的代码并确定运行时状态是否足以满足用户请求。

例如,如果用户要求一个名为 foo 的新函数;那么在执行代理生成的代码后,foo 应该可以调用!执行评估的一个挑战是,代理代码经常使运行时处于与目标代码略微不同的形式。可以将断言“放宽”到任何可行答案都应满足的最弱假设。

最后,按照预期的方式使用你的产品(即“狗食”)可以让你洞察现实世界数据中的故障模式。这种方法不仅有助于发现潜在的弱点,而且还提供了一个有用的生产样本来源,可以将其转换为评估。

LLM 作为评判者可以奏效(有点),但它不是万能药

LLM 作为评判者,即我们使用强大的 LLM 来评估其他 LLM 的输出,遭到了一些人的质疑。(我们中的一些人最初对此持怀疑态度。)但是,如果实施得当,LLM 作为评判者可以实现与人类判断相当大的相关性,至少可以帮助构建关于新提示或技术性能的先验知识。具体来说,在进行成对比较(例如,控制组与处理组)时,LLM 作为评判者通常能得到正确的方向,尽管胜负的幅度可能比较嘈杂。

以下是一些关于如何充分利用 LLM 作为评判者的建议:

  • 使用成对比较:与其要求 LLM 在李克特 量表上对单个输出进行评分,不如向它展示两个选项,并要求它选择更好的一个。这往往会导致更稳定的结果。
  • 控制位置偏差:呈现的选项顺序可能会影响 LLM 的决定。为了减轻这种影响,请对每个成对比较进行两次,每次交换对的顺序。请务必在交换后将胜利归因于正确的选项!
  • 允许出现平局:在某些情况下,两个选项可能同样好。因此,允许 LLM 宣告平局,这样它就不必随意选择一个赢家。
  • 使用思维链:要求 LLM 在给出最终偏好之前解释其决定,可以提高评估的可靠性。作为奖励,这使你可以使用更弱但更快的 LLM 并仍然获得类似的结果。因为这个管道的一部分通常是批量模式,所以来自 CoT 的额外延迟不是问题。
  • 控制响应长度:LLM 往往偏向于更长的响应。为了减轻这种影响,请确保响应对的长度相似。

LLM 作为评判者的一个特别强大的应用是检查新提示策略与回归的关系。如果你已经跟踪了一系列生产结果,有时你可以使用新提示策略重新运行这些生产示例,并使用 LLM 作为评判者来快速评估新策略可能出现问题的方面。

以下是一个 简单但有效的方法 来迭代 LLM 作为评判者,其中我们只是记录 LLM 响应、评判者的评论(即 CoT)和最终结果。然后与利益相关者一起审查它们,以确定改进的领域。在三个迭代中,与人类和 LLM 的一致性从 68% 提高到了 94%!

LLM 作为评判者不是万能药。在语言的微妙方面,即使是最强大的模型也无法可靠地进行评估。此外,我们发现 传统的分类器 和奖励模型可以比 LLM 作为评判者实现更高的准确率,并且成本和延迟更低。对于代码生成,LLM 作为评判者可能比执行评估等更直接的评估策略更弱。

评估生成的“实习生测试”

在评估生成内容时,我们喜欢使用以下“实习生测试”:如果你将语言模型的精确输入,包括上下文,作为一个任务交给相关专业领域中的一名普通大学生,他们能成功吗?需要多长时间?

如果答案是否定的,因为 LLM 缺少所需的知识,请考虑如何丰富上下文。

如果答案是否定的,而且我们无法通过改进上下文来解决这个问题,那么我们可能遇到了当代 LLM 难以解决的任务。

如果答案是肯定的,但需要一段时间,我们可以尝试简化任务。它是可分解的吗?任务中是否有可以使之更模板化的方面?

如果答案是肯定的,他们会很快完成,那么就需要深入研究数据。模型错在哪里?我们能找到失败模式吗?尝试要求模型在响应之前或之后解释自己,以帮助你构建一个心智理论。

过度强调某些评估可能会损害整体性能

“当一个指标成为目标时,它就 ceases to be a good measure。”

— 古德哈特法则

“大海捞针”(NIAH)评估就是一个例子。最初的评估有助于量化模型在上下文大小不断增加时的召回率,以及召回率如何受到“针”位置的影响。但是,它被过度强调了,以至于成为 Gemini 1.5 报告的图 1。该评估涉及将一个特定短语(“特殊的魔法 {城市} 数字是:{数字}”)插入到一篇重复了保罗·格雷厄姆文章的冗长文档中,然后提示模型回忆魔法数字。

虽然一些模型实现了接近完美的召回率,但值得怀疑的是,NIAH 是否真正反映了现实世界应用中所需的推理和召回能力。考虑一个更实际的场景:给定一小时会议的记录,LLM 是否能够概括关键决策和后续步骤,并将每个项目正确地归因于相关人员?这项任务更现实,它超越了死记硬背,还考虑了解析复杂讨论、识别相关信息和合成摘要的能力。

以下是一个 实际 NIAH 评估 的例子。使用 医生-病人视频通话的记录,LLM 被询问有关病人用药的信息。它还包括一个更具挑战性的 NIAH,插入随机披萨配料的短语,例如“制作完美披萨所需的秘密配料是:浸泡在浓咖啡中的枣子、柠檬和山羊奶酪”。用药任务的召回率约为 80%,而披萨任务的召回率约为 30%。

顺便说一句,过度强调 NIAH 评估会导致提取和摘要任务的性能下降。因为这些 LLM 经过精细调谐,可以关注每个句子,所以它们可能会开始将不相关的细节和干扰项视为重要内容,从而将它们包含在最终输出中(而实际上不应该包含!)。

这也可能适用于其他评估和用例。例如,摘要。对事实一致性的强调可能会导致更笼统的摘要(因此不太可能出现事实不一致),并且可能不那么相关。相反,对写作风格和流畅性的强调可能会导致更华丽的营销式语言,从而引入事实不一致。

简化标注为二元任务或成对比较

在李克特量表上对模型输出进行开放式反馈或评分在认知上要求很高。因此,收集的数据更加嘈杂——由于人类评分者之间的差异——因此不太有用。更有效的方法是简化任务并减少标注者在认知上的负担。两个行之有效的方法是二元分类和成对比较。

在二元分类中,标注者被要求对模型的输出做出简单的“是”或“否”判断。他们可能会被问到生成的摘要是否与源文档事实一致,或者提出的响应是否相关,或者是否包含有毒内容。与李克特量表相比,二元决策更精确,评分者之间的一致性更高,并且可以提高吞吐量。这就是 Doordash 通过一棵“是-否”问题树来设置他们的菜单项标注队列的方式。

在成对比较中,标注者会看到一对模型响应,并被问到哪个更好。因为人类更容易说“A 比 B 好”,而不是分别对 A 或 B 评分,所以这会导致更快速、更可靠的标注(与李克特量表相比)。在一次 Llama2 会议上,Llama2 论文的作者 Thomas Scialom 证实,成对比较比收集书面响应等监督微调数据更快、更便宜。前者的成本是每单位 3.5 美元,而后者的成本是每单位 25 美元。

如果你要开始编写标注指南,这里有一些来自 Google 和 Bing 搜索的参考指南。

(无参考)评估和护栏可以互换使用

护栏有助于捕获不当或有害内容,而评估有助于衡量模型输出的质量和准确性。对于无参考评估,它们可以被视为同一枚硬币的两个方面。无参考评估是不依赖“黄金”参考(例如人类编写的答案)的评估,并且可以根据输入提示和模型响应来评估输出的质量。

一些例子包括摘要评估,其中我们只需要考虑输入文档就可以根据事实一致性和相关性来评估摘要。如果摘要在这些指标上的得分很低,我们可以选择不将其显示给用户,有效地将评估用作护栏。类似地,无参考翻译评估可以评估翻译的质量,而不需要人类翻译的参考,同样可以将其用作护栏。

LLM 即使不应该也会返回输出

使用 LLM 时面临的一大挑战是,它们经常会生成输出,即使它们不应该这样做。这会导致无害但无意义的响应,或者更严重的缺陷,如毒性或危险内容。例如,当被要求从文档中提取特定属性或元数据时,LLM 可能会自信地返回值,即使这些值实际上并不存在。或者,模型可能会用除英语以外的语言进行响应,因为我们在上下文中提供了非英语文档。

虽然我们可以尝试提示 LLM 返回“不适用”或“未知”响应,但这并不万无一失。即使有对数概率可用,它们也是输出质量的糟糕指标。虽然对数概率表示标记出现在输出中的可能性,但它们并不一定反映生成的文本的正确性。相反,对于经过指令微调的模型,这些模型经过训练可以响应查询并生成连贯的响应,对数概率可能没有得到很好的校准。因此,虽然高对数概率可能表明输出流畅且连贯,但这并不意味着它准确或相关。

虽然谨慎的提示工程在一定程度上有所帮助,但我们应该用健壮的护栏来补充它,这些护栏可以检测和过滤/重新生成不希望出现的输出。例如,OpenAI 提供了一个内容审核 API,可以识别不安全的响应,例如仇恨言论、自残或性内容。类似地,有很多用于检测个人可识别信息 (PII) 的软件包。一个好处是,护栏在很大程度上与用例无关,因此可以广泛应用于给定语言的所有输出。此外,通过精确的检索,我们的系统可以确定性地响应“我不知道”,如果不存在相关文档。

这里的一个推论是,LLM 可能会在需要生成输出时无法生成输出。这可能是由于各种原因造成的,从 API 提供商的简单问题(例如长尾延迟)到更复杂的问题(例如输出被内容审核过滤器阻止)。因此,始终记录输入和(可能缺乏的)输出以进行调试和监控非常重要。

幻觉是一个顽固的问题。

与内容安全或 PII 缺陷(这些缺陷受到了很多关注,因此很少出现)不同,事实不一致具有顽固的持久性,更难检测。它们更常见,基线比率为 5-10%,根据我们从 LLM 提供商那里了解到的情况,即使在简单的任务(如摘要)中,将其降至 2% 以下也具有挑战性。

为了解决这个问题,我们可以结合提示工程(生成的上游)和事实不一致护栏(生成的下游)。对于提示工程,CoT 之类的技术有助于通过让 LLM 在最终返回输出之前解释其推理来减少幻觉。然后,我们可以应用一个事实不一致护栏来评估摘要的事实性,并过滤或重新生成幻觉。在某些情况下,可以确定性地检测到幻觉。当使用 RAG 检索中的资源时,如果输出是结构化的,并且标识了资源是什么,你应该能够手动验证它们是否来自输入上下文。

关于作者

Eugene Yan 设计、构建和运营为客户提供大规模服务的机器学习系统。他目前是亚马逊的高级应用科学家,在那里他构建了为全球数百万客户提供服务的 RecSys(RecSys 2022 主题演讲)并将 LLM 应用于为客户提供更好的服务(AI Eng Summit 2023 主题演讲)。此前,他曾在 Lazada(被阿里巴巴收购)和一家 Healthtech Series A 公司领导机器学习工作。他在 eugeneyan.com 和 ApplyingML.com 上撰写并发表有关机器学习、推荐系统、LLM 和工程方面的文章。

Bryan Bischof 是 Hex 的 AI 主管,在那里他领导着工程师团队构建 Magic——数据科学和分析副驾驶。Bryan 在整个数据栈中工作,领导着分析、机器学习工程、数据平台工程和 AI 工程团队。他创建了 Blue Bottle Coffee 的数据团队,领导了 Stitch Fix 的多个项目,并在 Weights and Biases 构建了数据团队。Bryan 之前与 O’Reilly 合著了《构建生产推荐系统》一书,并在罗格斯大学的

好了,关于的分享介绍就到这里,有什么疑问或者问题,可以留言交流哦~ 关注我公众号(设计小站):sjxz00,获取更多AI辅助设计和设计灵感趋势。

标签