我们开发了一年LLMs产品后学到了什么(第一部分)
现在是使用大型语言模型 (LLM) 进行构建的激动人心的时刻。在过去的一年里,LLM 已经变得“足够好”以用于实际应用。LLM 的改进速度,加上社交媒体上的演示游行,将在 2025 年推动对人工智能的 2000 亿美元投资。LLM 也广泛可用,让每个人(而不仅仅是 ML 工程师和科学家)都可以将智能融入他们的产品中。虽然构建人工智能产品的门槛已经降低,但创造超越演示的有效产品仍然是一项看似困难的任务。
我们已经确定了一些至关重要但经常被忽视的机器学习经验和方法,这些经验和方法对于开发基于 LLM 的产品至关重要。了解这些概念可以让您在该领域获得竞争优势,而无需具备 ML 专业知识!在过去的一年里,我们六个人一直在 LLM 的基础上构建现实世界的应用程序。我们意识到有必要将这些经验提炼到一处,以造福社区。
我们的背景各异,担任的角色也不同,但我们都亲身经历了使用这项新技术所带来的挑战。我们中的两位是独立顾问,曾帮助众多客户将 LLM 项目从最初的概念转变为成功的产品,并了解决定成败的模式。我们中的一位是研究员,研究 ML/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 模式开始的。因此,您可能希望有效的 Text-to-SQL 提示应该包括结构化的模式定义;确实如此。
结构化输出具有类似的用途,但它也简化了与系统下游组件的集成。Instructor和Outlines非常适合结构化输出。(如果您要导入 LLM API SDK,请使用 Instructor;如果您要为自托管模型导入 Huggingface,请使用 Outlines。)结构化输入可以清晰地表达任务,并且类似于训练数据的格式,从而增加了获得更好输出的可能性。
使用结构化输入时,请注意每个 LLM 系列都有自己的偏好。Claude 更喜欢xml
Markdown 和 JSON,而 GPT 则更青睐 Markdown 和 JSON。使用 XML,您甚至可以通过提供标签来预填充 Claude 的回复,response
如下所示。
</> 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>" } ]
有一些小提示,只做一件事,很好
软件中常见的反模式/代码异味是“上帝对象”,即我们有一个可以完成所有事情的类或函数。这同样适用于提示。
提示通常从简单开始:几句说明、几个例子,我们就可以开始了。但当我们试图提高性能并处理更多极端情况时,复杂性就会逐渐显现。更多的说明。多步骤推理。几十个例子。不知不觉中,我们最初简单的提示现在变成了一个 2,000 个令牌的怪物。更糟糕的是,它在更常见和更直接的输入上的表现更差!GoDaddy 分享了这一挑战,作为他们从 LLM 建设中获得的第一课。
就像我们努力(读作:奋斗)保持系统和代码简单一样,我们也应该为提示制定简单的规则。我们可以将会议记录摘要器分为几个步骤,而不是使用单一的、包罗万象的提示:
- 将关键决策、行动项目和负责人提取为结构化格式
- 检查提取的细节与原始转录的一致性
- 从结构化细节中生成简洁的摘要
因此,我们将单个提示拆分为多个提示,每个提示都简单、有针对性且易于理解。通过拆分,我们现在可以单独迭代和评估每个提示。
制作上下文标记
重新思考,并质疑你对实际需要向经纪人发送多少背景的假设。像米开朗基罗一样,不要构建你的背景雕塑——凿掉多余的材料,直到雕塑显现出来。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 或全文搜索很难。
几个月来,我们一直在向客户和合作伙伴传达这一信息。使用简单嵌入的最近邻搜索会产生非常嘈杂的结果,您最好从基于关键字的方法开始。
其次,使用关键字搜索可以更直接地了解文档被检索的原因——我们可以查看与查询匹配的关键字。相比之下,基于嵌入的检索不太容易解释。最后,得益于 Lucene 和 OpenSearch 等经过数十年优化和实战考验的系统,关键字搜索通常具有更高的计算效率。
在大多数情况下,混合方法效果最好:关键字匹配用于明显的匹配,而嵌入用于同义词、上位词和拼写错误以及多模态(例如图像和文本)。Shortwave分享了他们如何构建 RAG 管道,包括查询重写、关键字 + 嵌入检索和排名。
对于新知识,更喜欢使用 RAG 而不是微调
RAG 和微调都可用于将新信息纳入 LLM 并提高特定任务的性能。那么,我们应该先尝试哪一个呢?
最近的研究表明,RAG 可能具有优势。一项研究将 RAG 与无监督微调(又称持续预训练)进行了比较,对 MMLU 子集和当前事件进行了评估。他们发现,RAG 在训练期间遇到的知识以及全新知识方面的表现始终优于微调。在另一篇论文中,他们将 RAG 与农业数据集上的监督微调进行了比较。同样,RAG 带来的性能提升大于微调,尤其是对于 GPT-4(参见论文表 20)。
除了提高性能之外,RAG 还具有一些实际优势。首先,与持续预训练或微调相比,保持检索索引最新更简单,而且更便宜!其次,如果我们的检索索引中存在包含有害或有偏见内容的问题文档,我们可以轻松删除或修改有问题的文档。
此外,RAG 中的 R 可以更精细地控制我们检索文档的方式。例如,如果我们为多个组织托管 RAG 系统,则通过对检索索引进行分区,我们可以确保每个组织只能从自己的索引中检索文档。这可确保我们不会无意中将一个组织的信息泄露给另一个组织。
长上下文模型不会让 RAG 过时
由于 Gemini 1.5 提供了高达 10M 个标记大小的上下文窗口,一些人开始质疑 RAG 的未来。
我倾向于认为 Sora 大大夸大了 Gemini 1.5。10M 令牌的上下文窗口有效地使大多数现有的 RAG 框架变得没有必要——您只需将数据放入上下文中,然后像往常一样与模型对话即可。想象一下它对所有初创公司/代理商/LangChain 项目的影响,其中大部分工程工作都投入到了 RAG 😅 或者用一句话来概括:10m 上下文杀死了 RAG。Gemini 做得好。
— Yao Fu
虽然长上下文确实会改变分析多个文档或与 PDF 聊天等用例的游戏规则,但有关 RAG 消亡的谣言被大大夸大了。
首先,即使上下文窗口包含 1000 万个标记,我们仍然需要一种方法来选择要输入到模型中的信息。其次,除了狭隘的大海捞针式评估之外,我们还没有看到令人信服的数据,表明模型可以在如此大的上下文中有效推理。因此,如果没有良好的检索(和排名),我们可能会让模型被干扰项淹没,甚至可能用完全不相关的信息填充上下文窗口。
最后,还有成本。Transformer 的推理成本随上下文长度呈二次方增长(或在空间和时间上呈线性增长)。仅仅因为存在一个模型可以在回答每个问题之前读取您组织的整个 Google Drive 内容并不意味着这是一个好主意。考虑一下我们使用 RAM 的方式:即使存在RAM 运行到数十 TB 的计算实例,我们仍然从磁盘读取和写入。
所以不要急着把你的 RAG 扔进垃圾桶。即使上下文窗口变大,这个模式仍然有用。
调整和优化工作流程
申请 LLM 只是一个开始。为了最大限度地发挥它们的作用,我们需要超越单一的提示并接受工作流程。例如,我们如何将一个复杂的任务拆分为多个更简单的任务?微调或缓存何时有助于提高性能并减少延迟/成本?在本节中,我们将分享经过验证的策略和真实示例,以帮助您优化和构建可靠的 LLM 工作流程。
一步一步、多轮的“流动”可以带来巨大的推动力。
我们已经知道,通过将单个大提示分解为多个较小的提示,我们可以获得更好的结果。AlphaCodium就是一个例子:通过从单个提示切换到多步骤工作流程,他们将 CodeContests 上的 GPT-4 准确率 (pass@5) 从 19% 提高到了 44%。 工作流程包括:
- 反思问题
- 公开测试推理
- 产生可能的解决方案
- 对可能的解决方案进行排序
- 生成综合测试
- 在公共和综合测试中迭代解决方案。
目标明确的小任务是最佳的代理或流程提示。并非要求每个代理提示都请求结构化输出,但结构化输出对于与协调代理与环境交互的任何系统进行交互非常有帮助。
可以尝试以下方法
- 明确的规划步骤,尽可能严格指定。考虑有预定义的计划可供选择(参见 https://youtu.be/hGXhFa3gzBs?si=gNEGYzux6TuB1del)。
- 将原始用户提示重写为代理提示。请注意,此过程是有损的!
- 代理行为有线性链、DAG 和状态机;不同的依赖关系和逻辑关系可能更适合或更不适合不同的规模。您能否从不同的任务架构中挤出性能优化?
- 计划验证;您的计划可以包括如何评估其他代理的响应以确保最终组装顺利进行的说明。
- 使用固定上游状态的提示工程——确保您的代理提示根据之前可能发生的情况的变体集合进行评估。
目前优先考虑确定性工作流程
虽然 AI 代理可以动态地响应用户请求和环境,但其非确定性使其部署起来具有挑战性。代理采取的每个步骤都有失败的可能,并且从错误中恢复的可能性很低。因此,随着步骤数量的增加,代理成功完成多步骤任务的可能性呈指数下降。因此,团队建设代理发现很难部署可靠的代理。
一种有前途的方法是让代理系统生成确定性计划,然后以结构化、可重复的方式执行这些计划。在第一步中,给定一个高级目标或提示,代理会生成一个计划。然后,确定性地执行该计划。这使得每个步骤都更加可预测和可靠。好处包括:
- 生成的计划可以作为小样本来提示或微调代理。
- 确定性执行使系统更加可靠,因此更容易测试和调试。此外,故障可以追溯到计划中的具体步骤。
- 生成的计划可以表示为有向无环图(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-as-Judge可以发挥作用,但并不是灵丹妙药
LLM-as-Judge 系统使用强大的 LLM 来评估其他 LLM 的成果,但这一系统遭到了某些人的质疑。(我们中的一些人最初是持强烈怀疑态度的。)尽管如此,如果实施得当,LLM-as-Judge 系统可以与人类判断实现良好的相关性,并且至少可以帮助建立有关新提示或技术可能如何执行的先验知识。具体而言,在进行成对比较(例如,对照组与治疗组)时,LLM-as-Judge 系统通常会给出正确的方向,尽管胜负的幅度可能不尽相同。
以下是一些关于如何最大程度地利用 LLM-as-Judge 的建议:
- 使用成对比较:不要要求 LLM 在李克特量表上对单个输出进行评分,而是向其提供两个选项并要求其选择更好的一个。这往往会产生更稳定的结果。
- 控制位置偏差:选项的呈现顺序可能会影响 LLM 的决策。为了缓解这种情况,请进行两次成对比较,每次交换成对的顺序。只需确保在交换后将胜利归因于正确的选项!
- 允许平局:在某些情况下,两种选择可能同样好。因此,允许 LLM 宣布平局,这样它就不必任意挑选获胜者。
- 使用思路链:在给出最终偏好之前要求 LLM 解释其决定可以提高评估可靠性。作为额外好处,这允许您使用较弱但速度更快的 LLM 并仍能获得类似的结果。由于管道的这一部分通常处于批处理模式,因此 CoT 的额外延迟不是问题。
- 控制答案长度:LLM 倾向于较长的答案。为了缓解这种情况,请确保答案对的长度相似。
LLM-as-Judge 的一个特别强大的应用是针对回归检查新的提示策略。如果您跟踪了一系列生产结果,有时您可以使用新的提示策略重新运行这些生产示例,并使用 LLM-as-Judge 快速评估新策略可能受到影响的地方。
这是一个简单但有效的 LLM-as-Judge 迭代方法的示例,我们只需记录 LLM 的回应、评委的批评(即 CoT)和最终结果。然后与利益相关者一起审查它们以确定需要改进的地方。经过三次迭代,与人类和 LLM 的一致性从 68% 提高到 94%!
不过,LLM-as-Judge 并非万灵药。语言中存在一些微妙的方面,即使是最强大的模型也无法可靠地进行评估。此外,我们发现传统的分类器和奖励模型可以实现比 LLM-as-Judge 更高的准确率,并且成本和延迟更低。对于代码生成,LLM-as-Judge 可能比更直接的评估策略(如执行评估)更弱。
评估世代的“实习生测试”
在评估代际时,我们喜欢使用以下“实习生测试”:如果你把语言模型的精确输入(包括上下文)交给相关专业的一名普通大学生作为任务,他们能成功吗?需要多长时间?
如果答案是否定的,因为LLM缺乏所需的知识,请考虑丰富背景的方法。
如果答案是否定的,而且我们根本无法改善环境来解决这个问题,那么我们可能遇到了一项对于当代LLM来说太难的任务。
如果答案是肯定的,但需要一段时间,我们可以尝试降低任务的复杂性。它是否可分解?任务的哪些方面可以变得更加模板化?
如果答案是肯定的,他们很快就会明白,然后是时候深入研究数据了。模型做错了什么?我们能找到失败的模式吗?试着让模型在响应之前或之后解释自己,以帮助你建立心智理论。
过分强调某些评估可能会损害整体表现
“当一项措施成为目标时,它就不再是一项好的措施。”
— 古德哈特定律
一个例子是大海捞针 (NIAH) 评估。最初的评估有助于量化随着上下文规模的增加而出现的模型回忆,以及回忆如何受到针头位置的影响。然而,它被过分强调,以至于它被作为Gemini 1.5 报告的图 1展示。评估涉及将一个特定的短语(“特殊的魔法 {city} 数字是:{number}”)插入到重复 Paul Graham 文章的长文档中,然后提示模型回忆这个魔法数字。
虽然有些模型实现了近乎完美的回忆,但 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 A 系列的机器学习。他在eugeneyan.com和ApplyingML.com上撰写和演讲有关 ML、RecSys、LLM 和工程的文章。
Bryan Bischof是 Hex 的 AI 主管,他领导工程师团队开发 Magic — 数据科学和分析副驾驶。Bryan 曾在数据堆栈的各个领域工作,领导分析、机器学习工程、数据平台工程和 AI 工程团队。他创办了 Blue Bottle Coffee 的数据团队,领导了 Stitch Fix 的多个项目,并组建了 Weights and Biases 的数据团队。Bryan 之前曾与 O'Reilly 合著《构建生产推荐系统》一书,并在罗格斯大学研究生院教授数据科学和分析学。他的博士学位是纯数学。
Charles Frye教授人们构建 AI 应用程序。在发表了精神药理学和神经生物学研究成果后,他在加州大学伯克利分校获得了博士学位,论文主题是神经网络优化。他通过在 Weights and Biases、 Full Stack Deep Learning 和 Modal从事教育和咨询工作,教授了数千名学生整个 AI 应用程序开发过程,从线性代数基础到 GPU 奥秘,再到构建可防御的业务。
Hamel Husain是一位拥有超过 25 年经验的机器学习工程师。他曾与 Airbnb 和 GitHub 等创新公司合作,其中包括OpenAI 用于代码理解的早期 LLM 研究。他还领导并为许多流行的,-evaluation%20suite%20where)开源机器学习工具做出了贡献。Hamel 目前是一名独立顾问,帮助公司实施大型语言模型 (LLM),以加速他们的 AI 产品之旅。
Jason Liu是一位杰出的机器学习顾问,因带领团队成功推出 AI 产品而闻名。Jason 的技术专长涵盖个性化算法、搜索优化、合成数据生成和 MLOps 系统。他的经验包括 Stitchfix 等公司,在那里他创建了一个推荐框架和可观察性工具,处理了每天 3.5 亿个请求。其他职位包括 Meta、纽约大学以及 Limitless AI 和 Trunk Tools 等初创公司。
Shreya Shankar是加州大学伯克利分校的 ML 工程师和计算机科学博士生。她是两家初创公司的第一位 ML 工程师,从零开始构建 AI 产品,每天为数千名用户提供服务。作为一名研究员,她的工作重点是通过以人为本的方法解决生产 ML 系统中的数据挑战。她的作品出现在 VLDB、SIGMOD、CIDR 和 CSCW 等顶级数据管理和人机交互场所。
联系我们
我们很乐意听听您对这篇文章的想法。您可以通过contact@applied-llms.org联系我们。我们中的许多人都愿意接受各种形式的咨询和建议。如果合适,我们会在联系后将您转介给合适的专家。
致谢
本系列始于群聊中的对话,布莱恩打趣说他受到启发写了《人工智能工程的一年》。然后,群聊中发生了✨神奇✨,我们都受到启发,纷纷参与进来,分享我们迄今为止学到的东西。
作者要感谢 Eugene 领导了大部分文档集成和整体结构以及大部分课程。此外,还要感谢他承担了主要的编辑职责和文档指导。作者要感谢 Bryan 激发了我们撰写这篇文章,将文章重组为战术、运营和战略部分及其简介,并促使我们更深入地思考如何接触和帮助社区。作者要感谢 Charles 对成本和 LLMOps 的深入研究,以及编织课程以使其更加连贯和紧凑——感谢他让这篇文章只有 30 页而不是 40 页!作者感谢 Hamel 和 Jason 从为客户提供建议和身处第一线的见解、从客户那里获得的广泛可推广的学习以及对工具的深入了解。最后,感谢 Shreya 提醒我们评估和严格的生产实践的重要性,并将她的研究和原创成果带到这篇文章中。
最后,作者要感谢所有团队慷慨地在我们在本系列中引用的文章中分享你们面临的挑战和经验教训,也要感谢人工智能社区对这个小组的积极参与和投入。
原文地址:What We Learned from a Year of Building with LLMs (Part I) – O’Reilly
内容由MiX Copilot基于大语言模型生成,有可能存在错误的风险。