- Published on
【译】我们从与LLMs一起建设的一年中学到了什么 – 应用 LLMs
- 引言
- 1. 战术:使用LLM的基本要素
- 2. 运营:日常和组织关注
- 3. 策略:在不被超越的情况下构建 LLM
- 4. 足够的0到1演示,是时候推出1到N的产品了
引言
现在是与大型语言模型(LLMs)构建的激动人心的时刻。在过去的一年里,LLMs 已经变得“足够好”以用于现实世界的应用。而且它们每年都在变得更好、更便宜。再加上社交媒体上的一系列演示,预计到 2025 年将有 2000 亿美元的 AI 投资。此外,提供者的 API 使 LLMs 更加可访问,让每个人——不仅仅是 ML 工程师和科学家——都能将智能构建到他们的产品中。然而,尽管构建 AI 的门槛降低了,但创建有效的产品和系统——超越演示——仍然是 deceptively difficult。
我们在过去的一年里进行了构建,并在此过程中发现了许多尖锐的边缘。虽然我们不声称代表整个行业,但我们希望分享我们所学到的,以帮助您避免我们的错误并更快地迭代。这些内容分为三个部分:
- 战术:一些关于提示、RAG、流程工程、评估和监控的实践。无论您是与 LLMs 一起构建的从业者,还是在周末项目上进行黑客攻击,这一部分都是为您而写的。
- 运营:交付产品的组织性、日常关注点,以及如何建立一个有效的团队。适合希望可持续和可靠地部署的产品/技术领导者。
- 战略:长期的、全局的视角,包含一些有观点的看法,例如“在 PMF 之前不使用 GPU”和“关注系统而不是模型”,以及如何迭代。为创始人和高管而写。
我们打算将其作为一个实用指南,帮助使用LLM构建成功的产品,借鉴我们自己的经验,并指向行业中的示例。
准备好深入探讨吗?让我们开始吧。
1. 战术:使用LLM的基本要素
在这里,我们分享新兴LLM堆栈核心组件的最佳实践:提高质量和可靠性的提示技巧、评估输出的策略、改善基础的检索增强生成想法、如何设计人机协作的工作流程等等。虽然这项技术仍处于初期阶段,但我们相信这些经验教训是广泛适用的,可以帮助您交付稳健的LLM应用程序。
1.1 提示
我们建议在原型设计新应用程序时从提示开始。低估和高估其重要性都是很容易的。低估是因为正确使用的提示技术可以让我们走得很远。高估是因为即使是基于提示的应用程序也需要围绕提示进行大量工程工作才能良好运作。
1.1.1 专注于充分利用基本提示技术
一些提示技术在提高各种模型和任务的性能方面始终有效:n-shot提示 + 上下文学习、思维链和提供相关资源。
通过n-shot提示进行上下文学习的想法是向LLM提供示例,以展示任务并使输出与我们的期望对齐。一些提示:
- 如果n太低,模型可能会过度依赖这些特定示例,从而损害其泛化能力。作为经验法则,目标是n ≥ 5。不要害怕将n提高到几十个。
- 示例应代表产品分布。如果您正在构建一个电影摘要工具,请包括来自不同类型的样本,比例大致与您在实践中预期看到的相同。
- 您不总是需要提供输入-输出对;期望输出的示例可能就足够了。
- 如果您计划让LLM使用工具,请包括使用这些工具的示例。
在链式思维(CoT)提示中,我们鼓励大型语言模型(LLM)在返回最终答案之前解释其思维过程。可以将其视为为LLM提供一个草图板,以便它不必在记忆中完成所有工作。最初的方法是简单地将“让我们一步一步思考”这一短语作为指令的一部分,但我们发现使CoT更具体是有帮助的,通过额外的一两句话增加具体性通常会显著降低幻觉率。
例如,当要求LLM总结会议记录时,我们可以明确步骤:
- 首先,在草图板上列出关键决策、后续事项和相关负责人。
- 然后,检查草图板中的细节是否与记录在事实上一致。
- 最后,将关键点综合成简明的总结。
请注意,最近有一些怀疑认为这种技术是否如预期那样强大。此外,对于在使用链式思维时推理过程中究竟发生了什么,存在显著的争论。无论如何,这种技术在可能的情况下值得实验。
提供相关资源是扩展模型知识库、减少幻觉和增加用户信任的强大机制。通常通过检索增强生成(RAG)实现,向模型提供可以直接在其响应中使用的文本片段是一项基本技术。在提供相关资源时,仅仅包含它们是不够的;不要忘记告诉模型优先使用它们,直接引用它们,并在没有足够资源时提及。这些有助于将代理响应“扎根”于资源语料库。
1.1.2 结构化你的输入和输出
结构化的输入和输出有助于模型更好地理解输入,并返回可以可靠地与下游系统集成的输出。为你的输入添加序列化格式可以帮助模型提供更多线索,以了解上下文中标记之间的关系、特定标记的附加元数据(如类型),或将请求与模型训练数据中的类似示例相关联。
作为一个例子,互联网上关于编写 SQL 的许多问题都以指定 SQL 架构开始。因此,您可以预期有效的 Text-to-SQL 提示应包括 结构化架构定义。
结构化输入清晰地表达任务,并且类似于训练数据的格式,从而增加更好输出的概率。结构化输出简化了与系统下游组件的集成。Instructor 和 Outlines 在结构化输出方面表现良好。(如果您正在导入 LLM API SDK,请使用 Instructor;如果您正在导入 Huggingface 以用于自托管模型,请使用 Outlines。)
使用结构化输入时,请注意每个 LLM 家族都有自己的偏好。Claude 更喜欢 <xml>
,而 GPT 更倾向于 Markdown 和 JSON。使用 XML,您甚至可以通过提供 <response>
标签来预填充 Claude 的响应,如下所示。
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>"
}
]
1.1.3 有小的提示,做到一件事,并且只做好一件事
软件中的一个常见反模式/代码异味是“上帝对象”,在这种情况下,我们有一个单一的类或函数来做所有事情。提示也是如此。
一个提示通常开始得很简单:几句指令,几个例子,我们就可以开始了。但是当我们试图提高性能并处理更多边缘情况时,复杂性悄然增加。更多的指令。多步骤推理。数十个例子。在我们意识到之前,我们最初简单的提示现在变成了一个 2,000 个标记的弗兰肯斯坦。而且更糟糕的是,它在更常见和简单的输入上表现更差!GoDaddy 将这个挑战分享为他们与 LLMs 构建的第一课。
就像我们努力(阅读:挣扎)保持我们的系统和代码简单一样,我们也应该对我们的提示如此。与其为会议记录摘要器拥有一个单一的通用提示,不如将其分解为几个步骤:
- 将关键决策、行动项和负责人提取为结构化格式
- 检查提取的细节与原始转录的一致性
- 从结构化细节生成简明摘要
因此,我们将单一提示拆分为多个简单、专注且易于理解的提示。通过将它们分开,我们现在可以单独迭代和评估每个提示。
1.1.4 精心设计你的上下文令牌
重新思考并挑战您对实际需要向代理发送多少上下文的假设。像米开朗基罗一样,不要建造上下文雕塑——凿掉多余的材料,直到雕塑显现出来。RAG 是汇总所有潜在相关的大理石块的常用方法,但您又在做什么来提取必要的内容?
我们发现,将发送给模型的最终提示——包含所有上下文构建、元提示和 RAG 结果——放在空白页面上并进行阅读,确实有助于你重新思考你的上下文。我们通过这种方法发现了冗余、自相矛盾的语言和糟糕的格式。
另一个关键的优化是上下文的结构。如果你的文档袋表示对人类没有帮助,不要假设它对代理也有用。仔细考虑如何构建你的上下文,以强调其各部分之间的关系,并使提取尽可能简单。
更多 提示基础知识 ,例如提示心理模型、预填充、上下文放置等。
1.2 信息检索 / RAG
除了提示之外,引导LLM的另一种有效方式是将知识作为提示的一部分提供。这样可以使LLM以提供的上下文为基础,从而用于上下文学习。这被称为检索增强生成(RAG)。实践者已经发现,RAG在提供知识和改善输出方面非常有效,而与微调相比,需要的工作量和成本要少得多。
1.2.1 RAG的效果仅取决于检索文档的相关性、密度和细节
你的RAG输出的质量取决于检索文档的质量,而检索文档的质量又可以从几个因素来考虑。
第一个也是最明显的指标是相关性。这通常通过排名指标来量化,例如 平均倒数排名(MRR) 或 标准化折扣累积增益(NDCG)。MRR 评估系统在排名列表中放置第一个相关结果的能力,而 NDCG 则考虑所有结果及其位置的相关性。它们衡量系统在将相关文档排名较高并将不相关文档排名较低方面的表现。例如,如果我们正在检索用户摘要以生成电影评论摘要,我们将希望将特定电影的评论排名较高,同时排除其他电影的评论。
与传统推荐系统一样,检索项目的排名将对LLM在下游任务中的表现产生重大影响。为了测量影响,运行一个基于RAG的任务,但将检索的项目打乱——RAG输出的表现如何?
其次,我们还想考虑信息密度。如果两个文档同样相关,我们应该更倾向于选择一个更简洁且细节较少的文档。回到我们的电影示例,我们可以认为电影剧本和所有用户评论在广义上都是相关的。然而,评分最高的评论和编辑评论的信息密度可能会更高。
最后,考虑文档中提供的细节级别。想象一下,我们正在构建一个 RAG 系统,从自然语言生成 SQL 查询。我们可以简单地提供带有列名的表模式作为上下文。但是,如果我们包括列描述和一些代表性值呢?额外的细节可能有助于 LLM 更好地理解表的语义,从而生成更正确的 SQL。
1.2.2 不要忘记关键词搜索;将其作为基线并用于混合搜索
鉴于基于嵌入的 RAG 演示是如此普遍,容易忘记或忽视信息检索领域数十年的研究和解决方案。
尽管如此,虽然嵌入无疑是一个强大的工具,但它们并不是万能的。首先,虽然它们在捕捉高层次语义相似性方面表现出色,但在处理更具体的基于关键词的查询时可能会遇到困难,例如用户搜索名称(例如,Ilya)、缩写(例如,RAG)或 ID(例如,claude-3-sonnet)。基于关键词的搜索,如 BM25,专门为此设计。最后,在多年的基于关键词的搜索之后,用户可能已经将其视为理所当然,如果他们期望检索的文档没有被返回,可能会感到沮丧。
向量嵌入 并不 神奇地解决搜索问题。事实上,重担在于你在使用语义相似性搜索重新排序之前的步骤。相较于 BM25 或全文搜索,真正的改进是困难的。 — Aravind Srinivas, CEO Perplexity.ai
我们已经向客户和合作伙伴传达了这一点几个月了。使用简单嵌入的最近邻搜索会产生非常嘈杂的结果,您可能更好地从基于关键词的方法开始。 — Beyang Liu, CTO Sourcegraph
其次,使用关键词搜索检索文档的原因更容易理解——我们可以查看与查询匹配的关键词。相比之下,基于嵌入的检索则较难解释。最后,得益于像 Lucene 和 OpenSearch 这样的系统,这些系统经过数十年的优化和实战检验,关键词搜索通常在计算效率上更高。
在大多数情况下,混合方法效果最佳:对于明显的匹配使用关键词匹配,对于同义词、上位词和拼写错误,以及多模态(例如,图像和文本)使用嵌入。Shortwave 分享了他们如何构建 RAG 管道,包括查询重写、关键词 + 嵌入检索和排名。
1.2.3 更倾向于 RAG 而非微调以获取新知识
RAG 和微调都可以用于将新信息纳入 LLM,并提高特定任务的性能。然而,我们应该优先考虑哪一个?
最近的研究表明 RAG 可能具有优势。一项研究 将 RAG 与无监督微调(即持续预训练)进行了比较,评估了两者在 MMLU 子集和当前事件上的表现。他们发现 RAG 在训练期间遇到的知识以及全新的知识上,始终优于微调。在 另一篇论文 中,他们将 RAG 与农业数据集上的监督微调进行了比较。同样,RAG 带来的性能提升大于微调,尤其是对于 GPT-4(见表 20)。
除了性能提升,RAG 还有其他实际优势。首先,与持续预训练或微调相比,保持检索索引的最新状态更容易——而且更便宜!其次,如果我们的检索索引中有包含有毒或偏见内容的问题文档,我们可以轻松删除或修改这些有问题的文档。可以将其视为一个和灯线,用于 要求我们在披萨上加胶水的文档。
此外,RAG 中的 R 提供了更细粒度的控制,关于我们如何检索文档。例如,如果我们为多个组织托管 RAG 系统,通过对检索索引进行分区,我们可以确保每个组织只能从自己的索引中检索文档。这确保了我们不会无意中将一个组织的信息暴露给另一个组织。
1.2.4 长上下文模型不会使 RAG 过时
随着 Gemini 1.5 提供高达 10M 令牌大小的上下文窗口,一些人开始质疑 RAG 的未来。
我倾向于相信,Gemini 1.5 被 Sora 过度炒作了。10M 令牌的上下文窗口实际上使大多数现有的 RAG 框架变得不必要——你只需将你的数据放入上下文中,然后像往常一样与模型对话。想象一下这对所有初创公司/代理/langchain 项目意味着什么,其中大部分工程工作都投入到 RAG 中 😅 或者用一句话总结:10M 上下文杀死了 RAG。干得好,Gemini — Yao Fu
虽然长上下文确实会对分析多个文档或与 PDF 聊天等用例产生重大影响,但关于 RAG 消亡的传言被大大夸大了。
首先,即使上下文大小为 10M 令牌,我们仍然需要一种选择相关上下文的方法。其次,除了狭窄的针在干草堆中的评估外,我们尚未看到令人信服的数据表明模型能够有效地在大上下文大小上进行推理。因此,如果没有良好的检索(和排名),我们可能会使模型被干扰项淹没,甚至可能用完全无关的信息填充上下文窗口。
最后,还有成本。在推理过程中,Transformer 的时间复杂度与上下文长度线性相关。仅仅因为存在一个模型可以在回答每个问题之前读取你组织的整个 Google Drive 内容,并不意味着这是个好主意。考虑一个类比,我们如何使用 RAM:即使存在 RAM 达到数十 TB 的计算实例,我们仍然会从磁盘读取和写入。
所以不要急着把你的 RAG 扔进垃圾桶。即使上下文大小增长,这种模式仍然会保持有用。
1.3 调整和优化工作流程
提示 LLM 只是开始。为了充分利用它们,我们需要超越单一提示,拥抱工作流程。例如,我们如何将一个复杂的任务拆分为多个简单的任务?微调或缓存在提高性能和减少延迟/成本方面何时有帮助?在这里,我们分享经过验证的策略和真实世界的例子,帮助你优化和构建可靠的 LLM 工作流程。
1.3.1 逐步、多轮的“流程”可以带来巨大的提升
众所周知,将一个大的提示分解为多个较小的提示可以获得更好的结果。例如, AlphaCodium:通过从单一提示切换到多步骤工作流程,他们将GPT-4在CodeContests上的准确率(pass@5)从19%提高到了44%。该工作流程包括:
- 反思问题
- 对公共测试进行推理
- 生成可能的解决方案
- 对可能的解决方案进行排名
- 生成合成测试
- 在公共和合成测试上对解决方案进行迭代。
具有明确目标的小任务是最佳的代理或流程提示。并不是每个代理提示都需要请求结构化输出,但结构化输出在与任何协调代理与环境交互的系统接口时非常有帮助。一些可以尝试的内容:
- 一个紧密指定的、明确的规划步骤。此外,考虑选择预定义的计划。
- 将原始用户提示重写为代理提示,尽管这个过程可能会有损失!
- 代理行为作为线性链、DAG和状态机;不同的依赖关系和逻辑关系在不同规模上可能更合适或不合适。你能从不同的任务架构中挤出性能优化吗?
- 规划验证;你的规划可以包括如何评估其他代理的响应的指示,以确保最终的组合能够很好地协同工作。
- 使用固定的上游状态进行提示工程——确保你的代理提示是针对可能发生的变体集合进行评估的。
1.3.2目前优先考虑确定性工作流程
虽然AI代理可以动态响应用户请求和环境,但它们的非确定性特性使得部署变得具有挑战性。代理每一步都有失败的可能性,而从错误中恢复的机会很小。因此,代理成功完成多步骤任务的可能性随着步骤数量的增加而呈指数下降。因此,构建代理的团队发现很难部署可靠的代理。
一种潜在的方法是让代理系统生成确定性计划,然后以结构化、可重复的方式执行这些计划。首先,给定一个高层次的目标或提示,代理生成一个计划。然后,计划以确定性的方式执行。这使得每一步都更加可预测和可靠。其好处包括:
- 生成的计划可以作为少量示例来提示或微调代理。
- 确定性执行使系统更可靠,因此更容易测试和调试。此外,故障可以追溯到计划中的具体步骤。
- 生成的计划可以表示为有向无环图(DAG),相对于静态提示,更容易理解和适应新情况。
最成功的代理构建者可能是那些在管理初级工程师方面有丰富经验的人,因为生成计划的过程类似于我们如何指导和管理初级人员。我们给初级人员明确的目标和具体的计划,而不是模糊的开放式指示,我们也应该对我们的代理做同样的事情。
最终,可靠、有效的代理的关键可能在于采用更结构化、确定性的方法,以及收集数据以优化提示和微调模型。没有这一点,我们将构建出可能在某些时候表现非常好的代理,但平均而言,会让用户失望。
1.3.3 获取更具多样性的输出超越温度
假设您的任务需要LLM输出的多样性。也许您正在编写一个LLM管道,以根据用户之前购买的产品列表建议要购买的产品。当多次运行您的提示时,您可能会注意到生成的推荐过于相似——因此您可能会在LLM请求中增加温度参数。
简而言之,增加温度参数使LLM的响应更加多样化。在采样时,下一个标记的概率分布变得更加平坦,这意味着通常不太可能的标记被更频繁地选择。然而,在提高温度时,您可能会注意到一些与输出多样性相关的失败模式。例如,目录中一些可能适合的产品可能永远不会被LLM输出。如果这些产品在基于LLM在训练时所学的内容上高度可能跟随提示,那么同一小部分产品可能在输出中被过度代表。如果温度过高,您可能会得到引用不存在产品(或无意义内容!)的输出。
换句话说,增加温度并不能保证 LLM 会从您期望的概率分布中采样输出(例如,均匀随机)。尽管如此,我们还有其他技巧来增加输出的多样性。最简单的方法是调整提示中的元素。例如,如果提示模板包含一个项目列表,例如历史购买记录,每次将这些项目插入提示时打乱它们的顺序可以产生显著的差异。
此外,保持一份近期输出的简短列表可以帮助防止冗余。在我们推荐产品的例子中,通过指示 LLM 避免建议来自此近期列表的项目,或者拒绝并重新采样与近期建议相似的输出,我们可以进一步多样化响应。另一个有效的策略是改变提示中使用的措辞。例如,加入“选择一个用户会喜欢经常使用的项目”或“选择一个用户可能会推荐给朋友的产品”等短语可以改变焦点,从而影响推荐产品的多样性。
1.3.4 缓存被低估了
缓存节省成本并消除生成延迟,因为它消除了对相同输入重新计算响应的需求。此外,如果响应之前已经经过保护,我们可以提供这些经过审查的响应,从而降低提供有害或不当内容的风险。
缓存的一个简单方法是为正在处理的项目使用唯一 ID,例如如果我们在总结新文章或 产品评论。当请求到达时,我们可以检查缓存中是否已经存在摘要。如果存在,我们可以立即返回;如果不存在,我们生成、保护并提供它,然后将其存储在缓存中以供将来请求使用。
对于更开放式的查询,我们可以借用搜索领域的技术,该领域也利用缓存来处理开放式输入。自动补全、拼写纠正和建议查询等功能也有助于规范用户输入,从而提高缓存命中率。
1.3.5 何时进行微调
我们可能会遇到一些任务,即使是设计得再巧妙的提示也无法满足需求。例如,即使经过大量的提示工程,我们的系统仍可能无法返回可靠的高质量输出。如果是这样,那么可能有必要对模型进行微调,以适应您的特定任务。
成功的例子包括:
- Honeycomb的自然语言查询助手:最初,“编程手册”与n-shot示例一起提供在提示中,以便进行上下文学习。虽然这效果还不错,但对模型进行微调后,在特定领域语言的语法和规则上得到了更好的输出。
- Rechat的Lucy:LLM需要生成一种非常特定格式的响应,该格式结合了结构化和非结构化数据,以便前端能够正确呈现。微调对于确保其一致性至关重要。
尽管微调可能有效,但它也带来了显著的成本。我们必须对微调数据进行标注,微调和评估模型,并最终自我托管它们。因此,请考虑更高的前期成本是否值得。如果提示可以让您达到90%的目标,那么微调可能不值得投资。然而,如果我们决定进行微调,为了降低收集人工标注数据的成本,我们可以生成并在合成数据上微调,或在开源数据上引导。
1.4 评估与监控
评估LLM是一个雷区,即使是最大的实验室也发现这具有挑战性。LLM返回开放式输出,而我们设定的任务各不相同。尽管如此,严格而深思熟虑的评估至关重要——OpenAI的技术领导者致力于评估并对个别评估提供反馈,这并非巧合。
评估LLM应用程序会引发多种定义和简化:这仅仅是单元测试,或者更像是可观察性,或者可能只是数据科学。我们发现所有这些观点都很有用。在本节中,我们提供了一些关于构建评估和监控管道时重要的经验教训。
1.4.1 从真实的输入/输出样本创建一些基于断言的单元测试
创建由生产中的输入和输出样本组成的单元测试(即断言),并根据至少三个标准对输出进行期望。虽然三个标准可能看起来是任意的,但这是一个实用的起始数字;更少的标准可能表明您的任务定义不够明确或过于开放,例如一个通用的聊天机器人。这些单元测试或断言应该在管道发生任何更改时触发,无论是编辑提示、通过RAG添加新上下文,还是其他修改。这个写作中有一个示例展示了一个实际用例的基于断言的测试。
考虑从指定短语的断言开始,这些短语让我们能够包含或排除响应。还可以尝试检查以确保单词、项目或句子的计数在一个范围内。对于其他类型的生成,断言可能看起来不同。基于执行的评估是一种评估代码生成的方法,其中您运行生成的代码并检查运行时的状态是否足以满足用户请求。
例如,如果用户请求一个名为foo的新函数;那么在执行代理生成的代码后,foo应该是可调用的!基于执行的评估中的一个挑战是,代理代码经常将运行时留在与目标代码略有不同的形式。将断言“放宽”到任何可行答案都能满足的绝对最弱假设可能是有效的。
最后,按预期使用您的产品(即“狗粮测试”)可以提供对真实数据中故障模式的洞察。这种方法不仅有助于识别潜在的弱点,还提供了一个有用的生产样本来源,可以转化为评估。
1.4.2 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 评估者的技术、对齐工作流程、微调模型、批评等内容
1.4.3 用于评估生成的“实习生测试”
我们喜欢在评估生成时使用以下“实习生测试”:如果你将语言模型的确切输入,包括上下文,交给相关专业的普通大学生作为任务,他们能成功吗?需要多长时间?
- 如果答案是否定的,因为 LLM 缺乏所需的知识,请考虑丰富上下文的方法。
- 如果答案是否定的,并且我们根本无法改善上下文来解决问题,那么我们可能遇到了当代 LLM 过于困难的任务。
- 如果答案是肯定的,但需要一段时间,我们可以尝试降低任务的复杂性。它可以分解吗?任务中是否有可以模板化的方面?
- 如果答案是肯定的,他们能很快完成,那么是时候深入数据了。模型做错了什么?我们能找到失败的模式吗?尝试在模型响应之前或之后让其解释自己,以帮助你建立心理理论。
1.4.4 过度强调某些评估可能会损害整体性能
“当一个衡量标准变成目标时,它就不再是一个好的衡量标准。” — 古德哈特法则。
一个例子是针在干草堆中的评估(Needle-in-a-Haystack,NIAH)。最初的评估帮助量化了随着上下文大小增长模型的召回率,以及针的位置如何影响召回率。然而,它被过度强调,以至于在Gemini 1.5报告的图1中出现。该评估涉及将特定短语(“特殊魔法 [city] 数字是:[number]”)插入一篇长文档中,该文档重复了保罗·格雷厄姆的文章,然后提示模型召回魔法数字。
虽然一些模型实现了近乎完美的召回率,但NIAH是否真正衡量了现实应用中所需的推理和召回能力是值得怀疑的。考虑一个更实际的场景:给定一个小时会议的记录,LLM能否总结出关键决策和下一步,以及正确将每个项目归属到相关人员?这个任务更为现实,超越了机械记忆,考虑了解析复杂讨论、识别相关信息和综合总结的能力。
这是一个实用的NIAH评估示例。使用医生-患者记录,LLM被询问关于患者的药物。它还包括一个更具挑战性的NIAH,插入一个关于比萨饼配料的随机短语,例如“制作完美比萨所需的秘密配料是:浸泡过的枣、柠檬和山羊奶酪.”。在药物任务上的召回率约为80%,而在比萨任务上的召回率为30%。
顺便提一下,过度强调NIAH评估可能会降低提取和总结任务的性能。由于这些LLM被微调得如此关注每个句子,它们可能开始将无关细节和干扰项视为重要,从而将其包含在最终输出中(而不应该这样做!)
这也可以适用于其他评估和用例。例如,总结。对事实一致性的强调可能导致总结变得不够具体(因此不太可能在事实上一致),并可能变得不够相关。相反,对写作风格和优雅的强调可能导致更华丽、营销类型的语言,这可能引入事实不一致。
1.4.5 将注释简化为二元任务或成对比较
对模型输出提供开放式反馈或评分,使用李克特量表是认知上要求较高的。因此,收集的数据更嘈杂——由于人类评分者之间的变异性——因此不太有用。更有效的方法是简化任务,减轻注释者的认知负担。两个效果良好的任务是二元分类和成对比较。
在二元分类中,注释者被要求对模型的输出做出简单的“是”或“否”的判断。他们可能会被问到生成的摘要是否与源文档在事实上一致,或者提议的响应是否相关,或者是否包含有毒内容。与李克特量表相比,二元决策更为精确,评分者之间的一致性更高,并且导致更高的通量。这就是Doordash如何设置他们的标签队列通过一系列是非问题来标记菜单项的方式。
在成对比较中,注释者会看到一对模型响应,并被问到哪个更好。因为人类更容易说“A比B好”,而不是单独给A或B分配一个分数,这导致了更快和更可靠的注释(相比于李克特量表)。在一次Llama2聚会上,Llama2论文的作者Thomas Scialom确认,成对比较比收集监督微调数据(如书面响应)更快且更便宜。前者的成本为每单位3.5美元,而后者的成本为每单位25美元。
如果您正在编写标签指南,这里有一些来自 Google 和 Bing 搜索的 示例指南。
1.4.6 (无参考) 评估和保护措施可以互换使用
保护措施有助于捕捉不当或有害内容,而评估则有助于衡量模型输出的质量和准确性。如果您的评估是无参考的,它们也可以用作保护措施。无参考评估是指不依赖于“黄金”参考(例如人工编写的答案)的评估,可以仅根据输入提示和模型的响应来评估输出的质量。
这些的例子包括 摘要评估,在这种情况下,我们只需考虑输入文档来评估摘要在事实一致性和相关性方面的表现。如果摘要在这些指标上得分较低,我们可以选择不向用户显示它,从而有效地将评估用作保护措施。同样,无参考的 翻译评估 可以在不需要人工翻译参考的情况下评估翻译的质量,再次允许我们将其用作保护措施。
1.4.7 LLM 在不应该返回输出时仍会返回输出
与 LLMs 工作时的一个关键挑战是,它们通常会在不应该生成输出时生成输出。这可能导致无害但无意义的响应,或者更严重的缺陷,如毒性或危险内容。例如,当被要求从文档中提取特定属性或元数据时,LLM 可能会自信地返回值,即使这些值实际上并不存在。或者,模型可能会以非英语的语言响应,因为我们在上下文中提供了非英语文档。
虽然我们可以尝试提示 LLM 返回“无适用”或“未知”的响应,但这并不是万无一失的。即使日志概率可用,它们也不是输出质量的良好指标。虽然日志概率指示一个标记出现在输出中的可能性,但它们并不一定反映生成文本的正确性。相反,对于经过指令调优的模型,这些模型经过训练以回答查询并生成连贯的响应,日志概率可能没有很好地校准。因此,尽管高日志概率可能表明输出流畅且连贯,但这并不意味着它是准确或相关的。
虽然仔细的提示工程在一定程度上可以提供帮助,但我们应该补充强大的保护措施,以检测和过滤/再生成不希望的输出。例如,OpenAI 提供了一个 内容审核 API,可以识别不安全的响应,例如仇恨言论、自残或性内容。同样,还有许多用于 检测个人身份信息 的包。一个好处是,保护措施在很大程度上与使用案例无关,因此可以广泛应用于给定语言的所有输出。此外,通过精确检索,我们的系统可以在没有相关文档时确定性地回应“我不知道”。
这里的一个推论是,当预期 LLM 产生输出时,它们可能会失败。这可能由于各种原因发生,从 API 提供者的长尾延迟等简单问题到更复杂的问题,例如输出被内容审核过滤器阻止。因此,持续记录输入和(可能缺乏的)输出对于调试和监控非常重要。
1.4.8 幻觉是一个顽固的问题
与内容安全或个人身份信息缺陷相比,这些问题受到很多关注,因此很少发生,事实不一致性则顽固地存在,并且更难以检测。它们更常见,发生的基线率为 5 - 10%,根据我们从 LLM 提供者那里了解到的情况,即使在简单任务(如摘要)中,也很难将其降低到 2% 以下。
为了解决这个问题,我们可以结合提示工程(生成的上游)和事实不一致性保护措施(生成的下游)。对于提示工程,像 CoT 这样的技术通过让 LLM 在最终返回输出之前解释其推理,帮助减少幻觉。然后,我们可以应用一个 事实不一致性保护措施 来评估摘要的真实性,并过滤或再生成幻觉。在某些情况下,幻觉可以被确定性地检测到。当使用 RAG 检索的资源时,如果输出是结构化的并且识别出资源是什么,您应该能够手动验证它们是否来自输入上下文。
2. 运营:日常和组织关注
2.1 数据
正如食材的质量决定了一道菜的味道,输入数据的质量限制了机器学习系统的性能。此外,输出数据是判断产品是否正常工作的唯一方式。所有作者都专注于数据,每周花费数小时查看输入和输出,以更好地理解数据分布:其模式、边缘案例以及模型的局限性。
2.1.1 检查开发-生产偏差
传统机器学习管道中的一个常见错误来源是 训练-服务偏差。当用于训练的数据与模型在生产中遇到的数据不同,就会发生这种情况。尽管我们可以在不进行训练或微调的情况下使用LLM,因此没有训练集,但开发-生产数据偏差仍然会出现。基本上,我们在开发过程中测试系统的数据应该与系统在生产中将面临的数据相匹配。如果不匹配,我们可能会发现生产准确性受到影响。
LLM开发-生产偏差可以分为两种类型:结构性和基于内容的。结构性偏差包括格式不一致等问题,例如具有列表类型值的JSON字典与JSON列表之间的差异、不一致的大小写,以及拼写错误或句子片段等错误。这些错误可能导致模型性能不可预测,因为不同的LLM是在特定数据格式上训练的,提示对微小变化可能非常敏感。基于内容或“语义”的偏差指的是数据的意义或上下文的差异。
与传统机器学习一样,定期测量LLM输入/输出对之间的偏差是有用的。输入和输出的长度或特定格式要求(例如,JSON或XML)等简单指标是跟踪变化的直接方法。对于更“高级”的漂移检测,可以考虑对输入/输出对的嵌入进行聚类,以检测语义漂移,例如用户讨论主题的变化,这可能表明他们正在探索模型之前未接触过的领域。
在测试更改时,例如提示工程,确保保留的数据集是最新的,并反映出最近的用户交互类型。例如,如果生产输入中常见拼写错误,它们也应该出现在保留数据中。除了仅仅进行数值偏差测量,定性评估输出也是有益的。定期审查模型的输出——一种通俗的做法被称为“氛围检查”——确保结果与预期一致,并保持与用户需求的相关性。最后,将非确定性纳入偏差检查也是有用的——通过对测试数据集中每个输入多次运行管道并分析所有输出,我们增加了捕捉可能偶尔发生的异常的可能性。
2.1.2 每天查看 LLM 输入和输出的样本
LLM 是动态的并且不断发展。尽管它们具有令人印象深刻的零-shot 能力和常常令人愉悦的输出,但它们的失败模式可能是高度不可预测的。对于自定义任务,定期审查数据样本对于发展对 LLM 性能的直观理解至关重要。
生产中的输入输出对是LLM应用的“真实事物,真实地点” (genchi genbutsu),它们无法被替代。最近的研究强调了开发者对“好”和“坏”输出的看法随着他们与更多数据的互动而变化(即,criteria drift)。虽然开发者可以提前提出一些评估LLM输出的标准,但这些预定义的标准往往是不完整的。例如,在开发过程中,我们可能会更新提示,以增加良好响应的概率并减少不良响应的概率。这种评估、重新评估和标准更新的迭代过程是必要的,因为在没有直接观察输出的情况下,很难预测LLM的行为或人类的偏好。
为了有效管理这一点,我们应该记录LLM的输入和输出。通过每天检查这些日志的样本,我们可以快速识别并适应新的模式或故障模式。当我们发现新问题时,可以立即围绕它编写断言或评估。同样,任何对故障模式定义的更新都应反映在评估标准中。这些“氛围检查”是坏输出的信号;代码和断言将其操作化。最后,这种态度必须被社会化,例如通过将输入和输出的审查或注释添加到你的值班轮换中。
2.2 与模型合作
通过LLM API,我们可以依赖少数提供商的智能。虽然这是一种好处,但这些依赖关系也涉及性能、延迟、吞吐量和成本的权衡。此外,随着更新、更好的模型几乎每个月发布,我们应该准备好在弃用旧模型并迁移到新模型时更新我们的产品。在本节中,我们分享了与我们无法完全控制的技术合作的经验教训,这些模型无法自托管和管理。
2.2.1 生成结构化输出以简化下游集成
对于大多数现实世界的用例,LLM的输出将通过某种机器可读格式被下游应用程序消费。例如,Rechat,一个房地产CRM,需要结构化响应以便前端渲染小部件。同样,Boba,一个生成产品战略创意的工具,需要包含标题、摘要、合理性评分和时间范围字段的结构化输出。最后,LinkedIn分享了关于限制LLM生成YAML的内容,这些YAML随后用于决定使用哪个技能,并提供调用该技能的参数。
这个应用模式是Postel法则的极端版本:在接受(任意自然语言)时要宽容,在发送(类型化的、机器可读的对象)时要保守。因此,我们预计它将非常耐用。
目前,Instructor和Outlines是从LLM中引导结构化输出的事实标准。如果您正在使用LLM API(例如,Anthropic,OpenAI),请使用Instructor;如果您正在使用自托管模型(例如,Huggingface),请使用Outlines。
2.2.2 在模型之间迁移提示是一件麻烦事
有时,我们精心制作的提示在一个模型上效果极佳,但在另一个模型上却表现平平。这种情况可能发生在我们在不同模型提供者之间切换时,以及在同一模型的不同版本之间升级时。
例如,Voiceflow发现从gpt-3.5-turbo-0301迁移到gpt-3.5-turbo-1106导致其意图分类任务下降了10%。(幸运的是,他们有评估!)同样,GoDaddy观察到一个积极的趋势,在升级到版本1106后,gpt-3.5-turbo和gpt-4之间的性能差距缩小了。(或者,如果您是一个乐观的人,您可能会对gpt-4在新升级后领先的减少感到失望)
因此,如果我们必须在模型之间迁移提示,预计这将比简单地更换API端点花费更多时间。不要假设插入相同的提示会导致类似或更好的结果。此外,拥有可靠的自动评估有助于在迁移前后测量任务性能,并减少手动验证所需的工作量。
2.2.3 版本和固定您的模型
在任何机器学习管道中,“改变任何东西都会改变一切”。这尤其相关,因为我们依赖于一些我们自己不训练的组件,如大型语言模型(LLMs),而这些组件可能在我们不知情的情况下发生变化。
幸运的是,许多模型提供者提供“固定”特定模型版本的选项(例如,gpt-4-turbo-1106)。这使我们能够使用特定版本的模型权重,确保它们保持不变。在生产环境中固定模型版本可以帮助避免模型行为的意外变化,这可能导致客户对模型更换时出现的问题(例如过于冗长的输出或其他不可预见的故障模式)提出投诉。
此外,考虑维护一个影子管道,该管道镜像您的生产设置,但使用最新的模型版本。这使得安全实验和测试新版本成为可能。一旦您验证了这些新模型输出的稳定性和质量,您就可以自信地在生产环境中更新模型版本。
2.2.4 选择最小的能够完成工作的模型
在开发新应用时,使用可用的最大、最强大的模型是很有诱惑力的。但一旦我们确定任务在技术上是可行的,值得尝试是否可以使用更小的模型来实现可比的结果。
较小模型的好处是延迟和成本更低。虽然它可能较弱,但链式思维、n-shot 提示和上下文学习等技术可以帮助较小的模型超越其能力范围。除了 LLM API,微调我们的特定任务也可以帮助提高性能。
综合来看,使用较小模型精心设计的工作流程通常可以匹配甚至超越单个大型模型的输出质量,同时更快且更便宜。例如,这条tweet分享了 Haiku + 10-shot 提示如何优于零-shot Opus 和 GPT-4 的经验数据。从长远来看,我们预计会看到更多关于流工程与较小模型的例子,因为它们在输出质量、延迟和成本之间达到了最佳平衡。
另一个例子是简单的分类任务。像 DistilBERT(67M 参数)这样的轻量级模型是一个令人惊讶的强基线。400M 参数的 DistilBART 是另一个很好的选择——在开源数据上微调时,它可以以 0.84 的 ROC-AUC 识别幻觉,在不到 5% 的延迟和成本下超越大多数 LLM。
关键是,不要忽视较小的模型。虽然将一个庞大的模型应用于每个问题很简单,但通过一些创造力和实验,我们通常可以找到更高效的解决方案。
2.3 产品
虽然新技术提供了新的可能性,但构建伟大产品的原则是永恒的。因此,即使我们第一次解决新问题,我们也不必在产品设计上重新发明轮子。从扎实的产品基础出发来推动我们的 LLM 应用开发,可以让我们为所服务的人提供真正的价值。
2.3.1 早期并频繁地涉及设计
拥有一位设计师将促使你深入理解和思考如何构建和展示你的产品给用户。我们有时将设计师刻板印象为那些把东西变得美观的人。但除了用户界面,他们还重新思考如何改善用户体验,即使这意味着打破现有的规则和范式。
设计师特别擅长将用户的需求重新框架为各种形式。这些形式中有些比其他形式更容易解决,因此,它们可能为 AI 解决方案提供更多或更少的机会。像许多其他产品一样,构建 AI 产品应该围绕待完成的工作,而不是驱动它们的技术。
专注于问自己:“用户希望这个产品为他们完成什么工作?这个工作是聊天机器人擅长的事情吗?自动补全呢?也许是其他的东西!”考虑现有的 设计模式 以及它们与待完成工作的关系。这些是设计师为你的团队能力增添的宝贵资产。
2.3.2 为人机协作设计你的用户体验
获得高质量注释的一种方法是将人机协作(HITL)集成到用户体验(UX)中。通过让用户轻松提供反馈和纠正,我们可以改善即时输出并收集有价值的数据来改进我们的模型。
想象一个电子商务平台,用户上传并分类他们的产品。我们可以设计用户体验的几种方式:
- 用户手动选择正确的产品类别;一个 LLM 定期检查新产品并在后台纠正错误分类。
- 用户根本不选择任何类别;一个 LLM 定期在后台对产品进行分类(可能存在错误)。
- 一个 LLM 实时建议产品类别,用户可以根据需要验证和更新。
虽然这三种方法都涉及 LLM,但它们提供了非常不同的用户体验。第一种方法将初始负担放在用户身上,LLM 作为后处理检查。第二种方法对用户没有任何要求,但提供了透明度和控制权。第三种方法则找到了合适的平衡。通过让 LLM 先行建议类别,我们减少了用户的认知负担,他们不必学习我们的分类法来对产品进行分类!与此同时,通过允许用户审查和编辑建议,他们在产品分类上拥有最终决定权,将控制权牢牢掌握在自己手中。作为额外好处,第三种方法创建了一个 自然反馈循环以改进模型。好的建议会被接受(正标签),而差的建议会被更新(负标签后跟正标签)。
这种建议、用户验证和数据收集的模式在多个应用中常见:
- 编码助手:用户可以接受建议(强正),接受并调整建议(正),或忽略建议(负)
- Midjourney:用户可以选择放大并下载图像(强正),改变图像(正),或生成一组新图像(负)
- 聊天机器人:用户可以对响应提供点赞(正)或点踩(负),或选择重新生成响应如果它真的很糟糕(强负)。
反馈可以是显式的或隐式的。显式反馈是用户对我们产品请求的响应信息;隐式反馈是我们从用户交互中学习到的信息,而不需要用户故意提供反馈。编码助手和 Midjourney 是隐式反馈的例子,而点赞和点踩则是显式反馈。如果我们设计良好的用户体验,比如编码助手和 Midjourney,我们可以收集大量隐式反馈来改进我们的产品和模型。
2.3.3 无情地优先考虑你的需求层次
在我们考虑将演示投入生产时,我们必须考虑以下要求:
- 可靠性:99.9%的正常运行时间,遵循结构化输出
- 无害性:不生成冒犯性、成人内容或其他有害内容
- 事实一致性:忠实于提供的上下文,不编造内容
- 有用性:与用户的需求和请求相关
- 可扩展性:延迟服务水平协议,支持的吞吐量
- 成本:因为我们没有无限的预算
- 还有更多:安全性、隐私、公平性、GDPR、DMA等。
如果我们试图一次性解决所有这些要求,我们将永远无法交付任何东西。因此,我们需要优先考虑。无情地。这意味着要明确哪些是不可妥协的(例如,可靠性、无害性),没有这些,我们的产品无法正常运作或不具备可行性。这一切都是关于识别最小可爱产品。我们必须接受第一个版本不会完美,只需发布并迭代。
2.3.4 根据用例校准你的风险容忍度
在决定语言模型和应用程序的审查级别时,请考虑用例和受众。对于面向客户的聊天机器人提供医疗或财务建议,我们需要非常高的安全性和准确性标准。错误或不良输出可能造成真正的伤害并侵蚀信任。但对于不那么关键的应用程序,例如推荐系统,或内部应用程序如内容分类或摘要,过于严格的要求只会减缓进展而没有增加太多价值。
这与最近的 a16z 报告 一致,显示许多公司在内部 LLM 应用程序上的进展速度快于外部应用程序(见下图)。通过在内部生产力方面实验 AI,组织可以开始捕捉价值,同时学习如何在更受控的环境中管理风险。然后,随着他们获得信心,他们可以扩展到面向客户的用例。
企业 LLM 在内部和外部用例中的使用比例 (来源:a16z 报告)
2.4 团队与角色
没有哪个职位的职能容易定义,但为这个新领域的工作撰写职位描述比其他领域更具挑战性。我们将放弃交叉职位名称的维恩图或职位描述的建议。然而,我们将承认一个新角色的存在——AI工程师——并讨论它的位置。重要的是,我们将讨论团队的其余部分以及如何分配责任。
2.4.1 专注于过程,而非工具
面对新的范式,例如LLM,软件工程师往往倾向于工具。因此,我们忽视了工具本应解决的问题和过程。在这样做的过程中,许多工程师假设了意外的复杂性,这对团队的长期生产力产生了负面影响。
例如,这篇文章 讨论了某些工具如何自动为大型语言模型创建提示。它认为(在我看来是正确的)那些在未首先理解解决问题的方法论或过程的情况下使用这些工具的工程师,最终会承担不必要的技术债务。
除了意外的复杂性,工具往往也缺乏具体说明。例如,LLM评估工具的行业正在增长,这些工具提供“盒装LLM评估”,带有针对毒性、简洁性、语气等的通用评估器。我们看到许多团队在没有批判性思考其领域特定失败模式的情况下采用这些工具。与此形成对比的是EvalGen。它专注于通过在每一步深度参与用户,教授用户创建特定领域评估的过程,从指定标准到标记数据,再到检查评估。该软件引导用户完成如下工作流程:
Shankar, S., et al. (2024). Who Validates the Validators? Aligning LLM-Assisted Evaluation of LLM Outputs with Human Preferences. Retrieved from https://arxiv.org/abs/2404.12272
EvalGen引导用户遵循制定LLM评估的最佳实践,即:
- 定义特定领域的测试(自动从提示中引导)。这些测试被定义为带有代码的断言或使用LLM作为评判者。
- 将测试与人类判断对齐的重要性,以便用户可以检查测试是否捕捉到指定的标准。
- 随着系统(提示等)的变化,对测试进行迭代。
EvalGen为开发人员提供了一个评估构建过程的心理模型,而不将他们固定在特定工具上。我们发现,在提供AI工程师这些背景信息后,他们通常会选择更精简的工具或自行构建工具。
LLM的组成部分远不止提示编写和评估,无法在这里详尽列出。然而,AI工程师在采用工具之前,理解这些过程是很重要的。
2.4.2 始终保持实验
机器学习产品与实验密切相关。不仅仅是A/B测试、随机对照试验类型的实验,还有频繁尝试修改系统中最小组件的实验,以及进行离线评估。大家对评估如此热衷的原因实际上并不是关于可信度和信心——而是为了促进实验!你的评估越好,你就能越快地对实验进行迭代,从而更快地收敛到系统的最佳版本。
尝试不同的方法来解决同一个问题是很常见的,因为现在实验成本非常低。收集数据和训练模型的高成本被最小化——提示工程的成本仅略高于人力时间。让你的团队每个人都学习提示工程的基础知识。这鼓励每个人进行实验,并从整个组织中产生多样化的想法。
此外,不要仅仅为了探索而实验——也要利用它们来开发!有一个新任务的工作版本吗?考虑让团队中的其他人以不同的方式处理它。尝试以更快的方式进行。研究像Chain-of-Thought或Few-Shot这样的提示技术,以提高质量。不要让你的工具阻碍实验;如果是这样,重建它,或者购买一些东西来改善它。
最后,在产品/项目规划中,留出时间来构建评估和进行多次实验。考虑工程产品的产品规格,但要添加明确的评估标准。在制定路线图时,不要低估实验所需的时间——预计在获得生产批准之前,需要进行多次开发和评估的迭代。
2.4.3 赋能每个人使用新AI技术
随着生成性AI的普及,我们希望整个团队——不仅仅是专家——都能理解并感到有能力使用这项新技术。没有比实际使用LLM更好的方法来培养对其工作原理的直觉(例如,延迟、故障模式、用户体验)。LLM相对易于接触:您不需要知道如何编码就能改善管道的性能,每个人都可以通过提示工程和评估开始贡献。
这很大程度上是教育。它可以从简单的提示工程基础开始,其中n-shot提示和CoT等技术有助于将模型调整到所需的输出。拥有知识的人也可以教育更技术性的方面,例如LLM在生成输出时是自回归的。换句话说,虽然输入标记是并行处理的,但输出标记是顺序生成的。因此,延迟更多是输出长度而非输入长度的函数——这是设计用户体验和设定性能期望时的一个关键考虑因素。
我们可以进一步提供动手实验和探索的机会。也许可以举办一次黑客马拉松?虽然让团队花几天时间在投机项目上进行黑客攻击似乎很昂贵,但结果可能会让您感到惊讶。我们知道有一个团队通过黑客马拉松,在一年内加速并几乎完成了他们三年的路线图。另一个团队的黑客马拉松导致了由于LLM而现在可能实现的颠覆性用户体验,这些体验已被优先考虑在今年及以后实施。
2.4.4 不要陷入“AI工程就是我所需要的一切”的陷阱
随着新职位名称的出现,最初往往会夸大与这些角色相关的能力。这通常会导致痛苦的修正,因为这些工作的实际范围变得清晰。该领域的新手以及招聘经理可能会做出夸大的声明或有过高的期望。在过去十年中,显著的例子包括:
- 数据科学家:“比任何软件工程师更擅长统计学,比任何统计学家更擅长软件工程的人。”
- 机器学习工程师(MLE):一种以软件工程为中心的机器学习观点
最初,许多人认为数据科学家单独就足以应对数据驱动的项目。然而,显然数据科学家必须与软件和数据工程师合作,以有效开发和部署数据产品。
这种误解在新的AI工程师角色中再次出现,一些团队认为AI工程师就是你所需要的一切。实际上,构建机器学习或AI产品需要广泛的专业角色。我们与十多家公司就AI产品进行了咨询,并始终观察到它们陷入了“AI工程就是你所需要的一切”的陷阱。因此,产品往往难以超越演示,因为公司忽视了构建产品所涉及的关键方面。
例如,评估和测量对于将产品扩展超越感觉检查至关重要。有效评估的技能与机器学习工程师传统上所具备的一些优势相一致——仅由AI工程师组成的团队可能缺乏这些技能。合著者Hamel Husain在他最近关于检测数据漂移和设计特定领域评估的工作中阐明了这些技能的重要性。
这里是您在构建 AI 产品的过程中所需角色的粗略进展,以及您何时需要它们:
- 首先,专注于构建产品。这可能包括 AI 工程师,但不一定。AI 工程师在原型设计和快速迭代产品(用户体验、基础设施等)方面非常有价值。
- 接下来,通过对系统进行仪器化和收集数据来创建正确的基础。根据数据的类型和规模,您可能需要平台和/或数据工程师。您还必须拥有查询和分析这些数据以调试问题的系统。
- 接下来,您最终会想要优化您的 AI 系统。这不一定涉及训练模型。基本步骤包括设计指标、构建评估系统、运行实验、优化 RAG 检索、调试随机系统等。MLE 在这方面非常擅长(尽管 AI 工程师也可以掌握)。通常,除非您完成了先决步骤,否则雇用 MLE 是没有意义的。
除此之外,您始终需要一个领域专家。在小公司中,这理想情况下是创始团队——而在大公司中,产品经理可以扮演这个角色。了解角色的进展和时机至关重要。在错误的时间雇用人员(例如,过早雇用 MLE)或以错误的顺序构建会浪费时间和金钱,并导致人员流动。此外,在第 1-2 阶段定期与 MLE 进行沟通(但不全职雇用他们)将帮助公司建立正确的基础。
关于如何面试和雇用 ML/AI 工程师的更多信息 在这里,我们讨论了:(i) 面试的内容,(ii) 如何进行电话筛选、面试循环和总结,以及 (iii) 面试官和招聘经理的提示。
3. 策略:在不被超越的情况下构建 LLM
成功的产品需要深思熟虑的规划和优先级,而不是无休止的原型设计或跟随最新的模型发布或趋势。在最后这一部分,我们展望未来,思考构建优秀 AI 产品的战略考虑。我们还将审视团队面临的关键权衡,例如何时构建和何时购买,并建议一个“剧本”用于早期 LLM 应用开发策略。
3.1 No GPUs before PMF
要想出色,您的产品需要不仅仅是围绕他人 API 的薄包装。但朝相反方向的错误可能会更加代价高昂。过去一年,风险投资涌入,包括令人瞩目的六十亿美元的 A 轮融资,花费在训练和定制模型上,而没有明确的产品愿景或目标市场。在本节中,我们将解释为什么立即跳到训练自己的模型是一个错误,并考虑自托管的角色。
3.1.1 从头开始训练几乎从不合理
对于大多数组织来说,从头开始预训练一个 LLM 是一个不切实际的分心,无法专注于构建产品。
尽管这令人兴奋,并且似乎其他人都在这样做,但开发和维护机器学习基础设施需要大量资源。这包括收集数据、训练和评估模型以及部署它们。如果您仍在验证产品市场适配,这些努力将分散资源,无法专注于开发核心产品。即使您拥有计算能力、数据和技术能力,预训练的 LLM 也可能在几个月内变得过时。
考虑一下 BloombergGPT,这是一个专门为金融任务训练的 LLM。该模型通过 九名全职员工 的英勇努力,在 363B 个标记上进行了预训练,其中四名来自 AI 工程,五名来自 ML 产品和研究。尽管如此,它在一年内仍然被 gpt-3.5-turbo 和 gpt-4 超越了。
这个故事和其他类似的故事表明,对于大多数实际应用,从头开始预训练一个 LLM,即使是在特定领域的数据上,也不是资源的最佳利用。相反,团队更好地选择微调可用的最强开源模型,以满足他们的特定需求。
当然,也有例外。一个闪亮的例子是 Replit 的代码模型,专门为代码生成和理解而训练。通过预训练,Replit 能够超越其他更大规模的模型,如 CodeLlama7b。但随着其他越来越强大的模型的发布,保持实用性需要持续的投资。
3.1.2 不要在证明必要之前进行微调
对于大多数组织来说,微调更多是出于对错失机会的恐惧,而不是清晰的战略思考。
组织在过早地进行微调投资,试图击败“只是另一个包装”的指控。实际上,微调是一种重型机械,只有在你收集了大量示例,证明其他方法不足以满足需求后,才应部署。
一年前,许多团队告诉我们他们对微调感到兴奋。很少有人找到了产品市场契合,大多数人对自己的决定感到后悔。如果你要进行微调,你最好对自己能够在基础模型改进时一次又一次地进行微调充满 真正 的信心——请参见下面的“模型不是产品”和“构建LLMOps”。
什么时候微调实际上是正确的选择?如果用例需要在用于训练现有模型的主要开放网络规模数据集中不可用的数据——并且如果你已经构建了一个MVP,证明现有模型不足以满足需求。但要小心:如果优秀的训练数据对模型构建者来说并不容易获得,那么_你_从哪里获得它?
基于LLM的应用程序不是科学博览会项目。对它们的投资应与其对您业务战略目标和竞争差异化的贡献相称。
3.1.3 从推理API开始,但不要害怕自托管
通过LLM API,初创公司比以往任何时候都更容易采用和集成语言建模能力,而无需从头开始训练自己的模型。像Anthropic和OpenAI这样的提供商提供通用API,只需几行代码即可为您的产品注入智能。通过使用这些服务,您可以减少投入的精力,而专注于为客户创造价值——这使您能够更快地验证想法并迭代以实现产品市场契合。
但是,与数据库一样,托管服务并不适合每个用例,尤其是在规模和需求增加时。实际上,自托管可能是使用模型的唯一方法,而无需将机密/私人数据发送出您的网络,这在医疗和金融等受监管行业,或根据合同义务或保密要求是必需的。
此外,自托管可以规避推理提供者施加的限制,例如速率限制、模型弃用和使用限制。此外,自托管使您对模型拥有完全的控制权,从而更容易围绕它构建一个差异化的高质量系统。最后,自托管,特别是微调,可以在大规模上降低成本。例如,Buzzfeed分享了他们如何微调开源LLM以降低80%的成本。
3.2 迭代出伟大的东西
为了在长期内保持竞争优势,您需要超越模型,考虑什么将使您的产品与众不同。虽然执行速度很重要,但这不应该是您唯一的优势。
3.2.1 模型不是产品,围绕它的系统才是
对于那些不构建模型的团队来说,快速的创新步伐是一个福音,因为他们从一个SOTA模型迁移到下一个,追求上下文大小、推理能力和性价比的提升,以构建越来越好的产品。这种进展既令人兴奋又可预测。综合来看,这意味着模型可能是系统中最不耐用的组件。
相反,将您的精力集中在能够提供持久价值的方面,例如:
- 评估:可靠地测量您在各模型上的任务性能
- 保护措施:无论模型如何,防止不希望的输出
- 缓存:通过完全避免模型来减少延迟和成本
- 数据飞轮:为上述所有内容的迭代改进提供动力
这些组件比原始模型能力创造了更厚的产品质量护城河。
但这并不意味着在应用层构建是没有风险的。不要将您的剪刀指向OpenAI或其他模型提供者需要修剪的同样的牦牛,以便他们能够提供可行的企业软件。
例如,一些团队投资于构建自定义工具,以验证来自专有模型的结构化输出;在这里的最低投资很重要,但深度投资并不是一个好的时间利用。OpenAI需要确保当您请求函数调用时,您会得到一个有效的函数调用——因为他们所有的客户都希望如此。在这里采取一些“战略性拖延”,构建您绝对需要的东西,并等待提供者能力的明显扩展。
3.2.2 通过从小处着手建立信任
构建一个试图满足所有人需求的产品是平庸的秘诀。为了创造引人注目的产品,公司需要专注于构建能够吸引用户反复使用的体验。
考虑一个通用的 RAG 系统,旨在回答用户可能提出的任何问题。缺乏专业化意味着该系统无法优先考虑最新信息,解析特定领域的格式,或理解特定任务的细微差别。因此,用户只能获得一种肤浅、不可靠的体验,这并不能满足他们的需求,导致用户流失。
为了解决这个问题,专注于特定领域和用例。通过深入而不是广泛来缩小范围。这将创建与用户产生共鸣的特定领域工具。专业化还使您能够坦诚地说明系统的能力和局限性。对系统能够做什么和不能做什么保持透明,展示自我意识,帮助用户理解它可以在哪些方面提供最大价值,从而建立信任和信心。
3.2.3 构建 LLMOps,但要出于正确的原因:更快的迭代
DevOps 并不根本上是关于可重复的工作流程、向左移动或赋权于两人披萨团队——而且绝对不是关于编写 YAML 文件。
DevOps 是关于缩短工作与其结果之间的反馈周期,以便改进积累而不是错误。它的根源可以追溯到精益创业运动,通过精益生产和丰田生产系统,强调单分钟换模和持续改进。
MLOps 已将 DevOps 的形式适应于机器学习。我们有可重复的实验,还有全能套件,使模型构建者能够发布。而且,天哪,我们有 YAML 文件。
但作为一个行业,MLOps 并没有采用 DevOps 的功能。它没有缩短模型及其推理和生产中的交互之间的反馈差距。
令人振奋的是,LLMOps 领域已经从关注小心思的烦恼(如提示管理)转向阻碍迭代的难题:生产监控和持续改进,通过评估相互关联。
已经,我们有了中立的、众包评估聊天和编码模型的互动平台——一个集体迭代改进的外部循环。像 LangSmith、Log10、LangFuse、W&B Weave、HoneyHive 等工具不仅承诺收集和整理生产中系统结果的数据,还承诺通过与开发的深度集成来利用这些数据改善这些系统。拥抱这些工具或构建你自己的工具。
3.2.4 不要构建可以购买的 LLM 功能
大多数成功的企业并不是 LLM 企业。同时,大多数企业都有机会通过 LLM 得到改善。
这一对观察常常误导领导者匆忙地将 LLM 嵌入系统,导致成本增加和质量下降,并将其作为伪劣的、虚荣的“AI”功能发布,配有现在令人畏惧的闪光图标。有更好的方法:专注于真正与您的产品目标对齐并增强核心运营的 LLM 应用。
考虑一些浪费您团队时间的误导性项目:
- 为您的业务构建自定义的文本到 SQL 功能。
- 构建一个与您的文档对话的聊天机器人。
- 将您公司的知识库与客户支持聊天机器人集成。
虽然上述是 LLM 应用的入门示例,但对于产品公司来说,没有一个是值得自己构建的。这些是许多企业面临的普遍问题,承诺的演示与可靠组件之间存在巨大差距——这是软件公司的传统领域。在当前 Y Combinator 批次中,针对普遍问题进行的大规模攻克上投资宝贵的研发资源是浪费。
如果这听起来像陈词滥调的商业建议,那是因为在当前炒作浪潮的兴奋中,很容易将任何“LLM”误认为是前沿的、增值的差异化,而忽视了哪些应用已经过时。
3.2.5 AI 在循环中;人类在中心
现在,基于 LLM 的应用是脆弱的。它们需要大量的安全防护和防御工程,但仍然难以预测。此外,当范围紧密时,这些应用可以非常有用。这意味着 LLM 是加速用户工作流程的优秀工具。
虽然想象基于LLM的应用程序完全取代工作流程或代替某个职位功能可能很诱人,但今天最有效的范式是人机半人马(Centaur chess)。当有能力的人与为其快速利用而调优的LLM能力配对时,完成任务的生产力和幸福感可以大幅提升。LLM的旗舰应用之一,GitHub CoPilot,展示了这些工作流程的力量:
“总体而言,开发人员告诉我们,他们感到更有信心,因为使用GitHub Copilot和GitHub Copilot Chat进行编码比没有它时更容易、更少错误、更易读、更可重用、更简洁、更易维护和更具弹性。” - Mario Rodriguez, GitHub
对于那些在机器学习领域工作了很长时间的人来说,您可能会想到“人机协作”,但不要太快:HITL机器学习是一个建立在人工专家确保机器学习模型按预期行为的范式上。虽然相关,但在这里我们提出的是更微妙的东西。驱动LLM的系统不应成为今天大多数工作流程的主要驱动者,它们应该仅仅是一个资源。
通过以人为中心,并询问LLM如何支持他们的工作流程,这将导致显著不同的产品和设计决策。最终,这将促使您构建与那些试图迅速将所有责任外包给LLM的竞争对手不同的产品;更好、更有用且风险更小的产品。
3.3 从提示、评估和数据收集开始
前面的部分提供了一系列技术和建议。这些内容量很大。让我们考虑一下最小有用的建议集:如果一个团队想要构建一个LLM产品,他们应该从哪里开始?
在过去的一年里,我们已经看到足够多的案例,可以自信地说成功的LLM应用遵循一致的轨迹。我们在本节中逐步介绍这个基本的“入门”手册。核心思想是从简单开始,仅在需要时增加复杂性。一个不错的经验法则是,每个复杂程度通常需要比前一个复杂程度多一个数量级的努力。考虑到这一点……
3.3.1 提示工程优先
从提示工程开始。使用我们之前在战术部分讨论的所有技术。思维链、n-shot 示例以及结构化的输入和输出几乎总是一个好主意。在尝试从较弱的模型中挤出性能之前,先用最强大的模型进行原型设计。
只有在提示工程无法达到所需的性能水平时,您才应该考虑微调。如果存在非功能性需求(例如,数据隐私、完全控制、成本)阻止使用专有模型,从而需要您自托管,这种情况会更常见。只需确保这些相同的隐私要求不会阻止您使用用户数据进行微调!
3.3.2 构建评估并启动数据飞轮
即使是刚刚起步的团队也需要评估。否则,您将无法知道您的提示工程是否足够,或者何时您的微调模型准备好替代基础模型。
有效的评估是特定于您的任务的,并且反映了预期的使用案例。我们推荐的第一层评估是单元测试。这些简单的断言可以检测已知或假设的失败模式,并帮助推动早期设计决策。另请参见其他特定任务的评估,如分类、摘要等。
虽然单元测试和基于模型的评估很有用,但它们并不能替代人工评估的必要性。让人们使用您的模型/产品并提供反馈。这既可以衡量实际性能和缺陷率,又可以收集高质量的注释数据,以便用于微调未来的模型。这创造了一个积极的反馈循环,或数据飞轮,随着时间的推移而不断累积:
- 人工评估以评估模型性能和/或发现缺陷
- 使用注释数据来微调模型或更新提示
- 重复
例如,在审计LLM生成的摘要以发现缺陷时,我们可能会用细粒度反馈标记每个句子,识别事实不一致、无关或风格差。然后,我们可以使用这些事实不一致的注释来训练幻觉分类器,或使用相关性注释来训练相关性奖励模型。另一个例子是,LinkedIn分享了他们使用基于模型的评估者来估计幻觉、负责任的AI违规、连贯性等的成功经验。
通过创建随着时间推移而增加其价值的资产,我们将评估的构建从纯粹的运营支出升级为战略投资,并在此过程中构建我们的数据飞轮。
3.4 低成本认知的高层趋势
在1971年,Xerox PARC的研究人员预测了未来:我们现在所生活的网络个人计算机的世界。他们通过在发明使这一切成为可能的技术(从以太网和图形渲染到鼠标和窗口)中发挥关键作用,帮助诞生了那个未来。
但他们也进行了一项简单的练习:他们查看了非常有用的应用(例如视频显示),但尚未经济实惠(即驱动视频显示所需的足够RAM花费数千美元)。然后,他们查看了该技术的历史价格趋势(类似于摩尔定律),并预测这些技术何时会变得经济实惠。
我们可以对LLM技术做同样的事情,尽管我们没有像每美元的晶体管那样干净的数据可供使用。以一个流行的、长期存在的基准,例如大规模多任务语言理解数据集,以及一种一致的输入方法(五次提示)。然后,比较在这个基准上运行不同性能水平的语言模型的成本随时间的变化。
自OpenAI的davinci模型作为API推出以来的四年中,在一百万个标记(大约一百份此文档的副本)规模上,运行具有相当性能的模型的成本已从20美元降至不到10美分——仅六个月的时间就减半。类似地,截至2024年5月,通过API提供商或自行运行Meta的LLaMA 3 8B的成本仅为每百万个标记20美分,其性能与OpenAI的text-davinci-003相似,该模型使ChatGPT成为可能。该模型在2023年11月底发布时的成本约为每百万个标记20美元。在短短18个月内,这一成本下降了两个数量级——而摩尔定律预测的仅仅是翻倍。
现在,让我们考虑一个非常有用的LLM应用(为生成视频游戏角色提供动力,类似于Park et al),但尚未经济实惠(其成本在这里估计为每小时625美元)。自2023年8月该论文发布以来,成本大约下降了一个数量级,降至每小时62.50美元。我们可能预计在九个月内降至每小时6.25美元。
与此同时,当《吃豆人》在1980年发布时,今天的1美元可以购买一个游戏币,足以玩几分钟或十几分钟——可以算作每小时六局,或者每小时6美元。这种简单的计算表明,增强型LLM游戏体验将在2025年左右变得经济实惠。
这些趋势是新的,仅仅只有几年的历史。但在接下来的几年里,几乎没有理由期待这一过程会放缓。即使我们可能在算法和数据集上用尽了低垂的果实,比如超越“Chinchilla比率”的~20个token每个参数,数据中心和硅层内部的更深层次创新和投资承诺将弥补这一空缺。
这也许是最重要的战略事实:今天完全不可行的现场演示或研究论文将在几年后成为一种高级功能,然后很快变成商品。我们应该以此为基础来构建我们的系统和组织。
4. 足够的0到1演示,是时候推出1到N的产品了
我们明白,构建LLM演示非常有趣。只需几行代码,一个向量数据库和一个精心设计的提示,我们就能创造出✨魔法✨。在过去的一年里,这种魔法被比作互联网、智能手机,甚至是印刷机。
不幸的是,正如任何在实际软件交付上工作过的人所知道的那样,控制环境中有效的演示与在规模上可靠运行的产品之间存在着巨大的差异。
有一大类问题很容易想象并构建演示,但将其转化为产品却极其困难。例如,自动驾驶:演示一辆车在街区自驾是简单的;将其变成产品则需要十年的时间。 - Andrej Karpathy
以自动驾驶汽车为例。第一辆车是在1988年由神经网络驾驶的。二十五年后,Andrej Karpathy 第一次在Waymo进行演示。十年后,该公司获得了无人驾驶许可证。从原型到商业产品,这经历了三十五年的严格工程、测试、改进和监管导航。
在工业和学术界,我们观察到了过去一年的起伏:大型语言模型(LLM)应用的第一年。我们希望我们所学到的经验教训——从 战术(如评估、提示工程和保护措施),到 操作 技术和团队建设,再到 战略 视角(如内部构建哪些能力)——能在第二年及以后帮助你们,因为我们共同构建这一激动人心的新技术。