最近一年,LLM(大型语言模型)已经成熟到可以投入实际应用中了。预计到 2025 年,AI 领域的投资会飙升到 2000 亿美元。现在,不只是机器学习专家,任何人都能轻松地把 AI 技术融入自己的产品里。
我们整理了一些关键的机器学习经验和技巧,这些对于开发基于 LLM 的产品特别重要。掌握了这些,即使你不是机器学习专家,也能在竞争中站稳脚跟。
今天这篇文章,是我们结合自己的实践经验和行业案例,希望能帮你打造成功的 LLM 产品。虽然我们的经验可能不是行业标准,但肯定能给你一些有用的建议和教训。
战术要点
提示词设计
我们建议在开发新应用时从提示设计开始。它的作用既容易被低估也容易被高估。被低估是因为正确的提示技术使用得当可以带来显著效果。被高估是因为即使是基于提示的应用也需要大量的工程工作才能运行良好。
充分利用基本提示技巧
一些提示技术在各种模型和任务中都能提高性能:n-shot 提示与上下文学习、链式思维以及提供相关资源。
通过 n-shot 提示进行上下文学习的基本思路是为 LLM 提供一些示例,这些示例展示了任务要求,并引导模型输出符合预期。以下是一些建议:
- 如果 n 值太低,模型可能会过度依赖这些特定示例,影响其泛化能力。通常,n 值应不小于 5,有时甚至可以达到几十个。
- 示例应代表预期的输入分布。例如,如果你正在构建一个电影总结器,应该包括来自不同类型的电影样本,比例大致与实际情况相符。
- 你不一定需要提供完整的输入 - 输出对。在多数情况下,仅提供期望输出的示例就足够了。
- 如果你使用的是支持工具的 LLM,那么你的 n-shot 示例也应该包括你希望 Agent 使用的工具。
在链式思维(CoT)提示中,我们鼓励 LLM 在返回最终答案之前解释其思维过程。可以把它想象成给 LLM 一个草稿本,这样它就不必全都记在脑海中。最初的方法是简单地在指令中添加短语 “让我们一步一步思考”。
但是,我们发现使 CoT 更具体很有帮助,通过添加一两句话的具体说明,通常可以显著降低幻觉率。例如,当要求 LLM 总结会议记录时,我们可以明确步骤,例如:
- 首先,在草稿本中列出关键决策、后续事项和相关负责人。
- 然后,检查草稿本中的细节是否与会议记录一致。
- 最后,将关键点总结成简洁的总结。
提供相关资源是扩展模型知识库、减少幻觉并增加用户信任的强大机制。通常通过检索增强生成(RAG)实现,为模型提供它可以在响应中直接利用的文本片段是一个基本技巧。
在提供相关资源时,光包含它们还不够;不要忘记告诉模型优先使用这些资源,直接引用它们,有时在资源不足时提及它们。这些都有助于将 Agent 的响应 “基于” 资源库。
结构化输入和输出
结构化输入和输出帮助模型更好地理解输入,并返回可以可靠集成到下游系统的输出。为你的输入添加序列化格式可以提供更多线索,指示上下文中 Token 之间的关系,向特定 Token 添加附加元数据(如类型),或将请求与模型训练数据中的类似示例关联。
结构化输出也有类似的作用,但它还简化了与系统下游组件的集成。Instructor 和 Outlines 在结构化输出方面表现良好。(如果你正在导入一个 LLM API SDK,请使用 Instructor;如果你在导入 Huggingface 用于自托管模型,请使用 Outlines。)结构化输入清晰地表达任务,并类似于训练数据的格式,提高了获得更好输出的概率。
使用结构化输入时,请注意每个 LLM 家族都有自己的偏好。Claude 喜欢 XML,而 GPT 更喜欢 Markdown 和 JSON。使用 XML,你甚至可以通过提供 response 标签来预填 Claude 的响应。
代码语言:javascript复制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 个 Token 的庞然大物。但是,处理更常见和简单输入的性能反而变差了!
就像我们在保持系统和代码简洁方面努力一样,我们也应在提示词设计中保持简洁。与其为会议记录总结设计一个包罗万象的提示词,不如将其拆分为几个步骤:
- 提取关键决策、行动项和负责人,形成结构化格式
- 检查提取的细节与原始记录的一致性
- 根据结构化细节生成简洁总结
这样,我们就把一个复杂的提示词拆分成了多个简单、专注且易于理解的提示词。通过拆分提示词,我们可以分别迭代和评估每个提示词。
设计上下文 Token
重新思考并挑战你对代理所需上下文量的传统认知。就像米开朗基罗那样,不是去堆砌,而是要精心雕琢,去除不必要的部分,让作品的真正形态显现出来。RAG 虽然是一种广泛使用的方法,用于收集所有可能相关的信息,但关键在于你如何从中提取出真正需要的部分。
我们发现,将最终提示词放在一个空白页面上阅读,确实有助于重新思考上下文。通过这种方法,我们发现了冗余、自相矛盾的语言和糟糕的格式。
另一个关键优化是上下文的结构。文档堆积对人类无用,对 Agent 也一样无用。仔细考虑如何结构化上下文,突出各部分之间的关系,并尽量简化提取过程。
信息检索/RAG
除了直接提问之外,通过在提示中融入知识也是一种引导 LLM 的有效策略。这为模型提供了一个上下文基础,使其能够进行上下文学习,这种方法被称作检索增强生成(RAG)。
业界人士已经发现,RAG 在提供知识、提升输出质量方面表现出色,而且相比于微调模型,它所需的工作量和成本要低得多。RAG 的效果好坏,关键在于检索到的文档是否具有高度的相关性、信息密度以及详尽的细节。
RAG 输出的质量依赖于检索到的文档的质量,这可以从几个方面考虑。
第一个指标是相关性,通常通过排名指标如平均倒数排名(MRR)或归一化折扣累积增益(NDCG)来量化。MRR 评估系统将第一个相关结果放在排名列表中的位置,而 NDCG 考虑所有结果的相关性及其位置。
它们衡量系统在将相关文档排名靠前和不相关文档排名靠后方面的效果。例如,如果我们检索用户总结以生成电影评论总结,我们会希望为特定电影的评论排名更高,同时排除其他电影的评论。
像传统推荐系统一样,检索到的项目的排名将对 LLM 在下游任务中的表现产生重大影响。为了衡量影响,运行一个基于 RAG 的任务,但将检索到的项目随机打乱 ——RAG 输出的表现如何?
其次,我们还要考虑信息密度。如果两个文档同样相关,我们应该更喜欢更简洁且没有多余细节的那个。回到我们的电影例子,我们可能会认为电影剧本和所有用户评论在广义上都是相关的。然而,顶级评论和编辑评论可能会更密集。
最后,考虑文档提供的细节程度。假设我们正在构建一个 RAG 系统来生成 SQL 查询。我们可以简单地提供表模式和列名作为上下文。但是,如果我们包括列描述和一些代表性值呢?额外的细节可以帮助 LLM 更好地理解表的语义,从而生成更正确的 SQL。
不要忘记关键字搜索:把它作为基线并在混合搜索中使用
嵌入式 RAG 演示的普遍存在使得我们容易忘记信息检索领域几十年的研究和解决方案。
尽管嵌入确实是一个强大的工具,但它们并不是万能的。
首先,虽然它们在捕捉高级语义相似性方面表现出色,但在处理更具体的基于关键字的查询时(如搜索名字、缩写或 ID),可能会表现不佳。关键字搜索(如 BM25)专为此设计。经过多年的关键字搜索,用户可能已经习惯了这一点,如果他们期望检索到的文档没有被返回,可能会感到沮丧。
其次,使用关键字搜索时,更容易理解为什么会检索到某个文档 —— 我们可以查看匹配查询的关键字。相比之下,基于嵌入的检索则不太可解释。最后,感谢经过几十年优化和实际测试的 Lucene 和 OpenSearch 系统,关键字搜索通常在计算上更高效。
在大多数情况下,混合方法效果最好:关键字匹配用于明显的匹配,而嵌入用于同义词、上位词和拼写错误,以及多模态(如图像和文本)。
优先使用 RAG 而不是微调来获取新知识
RAG 和微调都可以用来将新信息整合到 LLM 中并提高特定任务的性能。那么,我们应该首先尝试哪一个?
最近的研究表明 RAG 可能更有优势。一项研究比较了 RAG 与无监督微调(即持续预训练),评估了它们在 MMLU 子集和当前事件中的表现。他们发现,RAG 在训练期间遇到的知识以及全新的知识方面均优于微调。在另一篇论文中,他们比较了 RAG 与在农业数据集上的有监督微调。同样,RAG 的性能提升比微调更大,特别是对于 GPT-4。
除了性能提升外,RAG 还具有几个实际优势。首先,与持续预训练或微调相比,维护检索索引更加容易且便宜。其次,如果我们的检索索引中包含有害或偏见内容的问题文档,我们可以轻松删除或修改这些有问题的文档。
此外,RAG 中的 R 提供了更细粒度的控制。例如,如果我们为多个组织托管一个 RAG 系统,通过分区检索索引,我们可以确保每个组织只能检索他们自己的索引中的文档。这确保了我们不会无意中将一个组织的信息暴露给另一个组织。
长上下文模型不会让 RAG 过时
随着 Gemini 1.5 提供高达 10M Token 大小的上下文窗口,一些人开始质疑 RAG 的未来。
虽然长上下文对于分析多份文档或与 PDF 聊天等用例来说将是一个改变游戏规则的因素,但关于 RAG 的消亡的传言被大大夸大了。
首先,即使有 10M Token 的上下文窗口,我们仍然需要一种方法来选择要传送到模型的信息。其次,除了狭隘的大海捞针式评估之外,我们还没有看到令人信服的数据表明模型可以有效地处理如此大的上下文。因此,如果没有好的检索(和排名),我们冒着用分心的内容淹没模型的风险,甚至可能将完全不相关的信息填充到上下文窗口中。
最后,是成本问题。Transformer 的推理成本随上下文长度呈二次(或线性)增长。仅仅因为存在一个模型可以在回答每个问题之前读取你的组织的整个 Google Drive 内容,并不意味着这是一个好主意。类比一下我们如何使用 RAM:我们仍然从磁盘读写,即使存在具有数十 TB RAM 的计算实例。
所以不要急着扔掉你的 RAG。这种模式即使在上下文窗口扩大后仍将有用。
调整和优化工作流
提示 LLM 只是开始。为了最大限度地利用它们,我们需要超越单个提示并接受工作流。例如,我们如何将一个复杂的任务拆分成多个简单的任务?什么时候微调或缓存有助于提高性能和降低延迟 / 成本?下面,我们分享了一些经过验证的策略和实际的例子,帮助你优化和构建可靠的 LLM 工作流。
逐步、多回合的 “流” 可以带来大幅提升。
我们已经知道,通过将一个大提示分解成多个小提示,可以获得更好的结果。AlphaCodium 就是一个例子:通过从单一提示转变为多步骤工作流,他们将 GPT-4 在 CodeContests 上的准确率(pass@5)从 19% 提高到 44%。该工作流包括:
- 反思问题
- 在公共测试上推理
- 生成可能的解决方案
- 对可能的解决方案进行排名
- 生成合成测试
- 在公共和合成测试上迭代解决方案
目标明确的小任务是最佳的 Agent 或流程提示。不要求每个 Agent 提示都请求结构化输出,但结构化输出有助于与协调 Agent 与环境交互的系统接口。
一些尝试的建议:
- 明确的计划步骤,尽可能具体。
- 将原始用户提示重写为 Agent 提示。小心,这个过程是有损的!
- Agent 行为如线性链、DAG 和状态机;不同的依赖和逻辑关系对于不同的规模可能更或更不合适。你能否从不同的任务架构中挤出性能优化?
- 计划验证;你的计划可以包括如何评估其他智能体响应的指令,以确保最终的组合工作良好。
- 具有固定上游状态的提示工程 —— 确保你的 Agent 提示在可能发生的各种变体中进行评估。
现在优先考虑确定性工作流
虽然 AI Agent 可以动态响应用户请求和环境,但它们的非确定性使其部署成为一个挑战。Agent 采取的每一步都有可能失败,恢复错误的几率很低。因此,Agent 成功完成多步骤任务的可能性随着步骤数量的增加而呈指数下降。结果是,构建 Agent 的团队发现很难部署可靠的 Agent。
一个有效的方法是拥有生成确定性计划的 Agent 系统,然后以结构化、可重复的方式执行这些计划。在第一步中,给定一个高层次的目标或提示,Agent 生成一个计划。然后,按确定性方式执行该计划。这使每一步都更可预测和可靠。其好处包括:
- 生成的计划可以作为少样本示例来提示或微调 Agent。
- 确定性执行使系统更可靠,因此更容易测试和调试。此外,故障可以追溯到计划中的具体步骤。
- 生成的计划可以表示为有向无环图(DAG),相对于静态提示,它们更容易理解和适应新情况。
最成功的 Agent 构建者可能是那些善于管理初级工程师的人,因为生成计划的过程类似于我们如何指导和管理初级工程师。我们给初级工程师明确的目标和具体的计划,而不是模糊的开放式指示,我们也应该对我们的智能体这样做。
最后,构建可靠的、可工作的 Agent 的关键可能在于采用更结构化、确定性的方法,以及收集数据以优化提示和微调模型。否则,我们将构建一些有时可能表现出色的 Agent,但平均而言,会让用户失望,导致用户留存率下降。
超越 temperature 获得更多样化的输出
假设你的任务需要 LLM 的输出具有多样性。也许你正在编写一个 LLM 管道,以根据用户之前购买的产品列表推荐购买目录中的产品。当你多次运行提示时,你可能会注意到结果推荐过于相似 —— 所以你可能会增加 LLM 请求中的 temperature 参数。
简而言之,增加 temperature 参数使 LLM 的响应更加多样化。在采样时,下一个 Token 的概率分布变得更平坦,这意味着通常不太可能的 Token 更有可能被选择。然而,增加 temperature 时,你可能会注意到一些与输出多样性相关的故障模式。例如:
- 目录中一些可能适合的产品可能从未被 LLM 输出。
- 如果某些产品在训练时非常可能跟随提示,它们可能会在输出中过度代表。
- 如果 temperature 过高,你可能会得到引用不存在产品(或胡言乱语)的输出!
换句话说,增加 temperature 并不保证 LLM 会从你期望的概率分布(例如,均匀随机)中采样输出。然而,我们还有其他技巧可以增加输出多样性。最简单的方法是调整提示中的元素。例如,如果提示模板包含一个项目列表,如历史购买记录,每次插入提示时打乱这些项目的顺序会产生显著影响。
此外,保持一个最近输出的短列表可以防止冗余。在我们的推荐产品例子中,通过指示 LLM 避免建议最近列表中的项目,或拒绝和重新采样类似于最近建议的输出,我们可以进一步多样化响应。另一种有效策略是改变提示中使用的措辞。例如,使用 “选择一个用户会经常使用的产品” 或 “选择一个用户可能会推荐给朋友的产品” 这样的短语可以改变重点,从而影响推荐产品的多样性。
缓存被低估了
缓存节省了成本,并通过消除对相同输入重新计算响应的需求来消除生成延迟。此外,如果响应之前已经经过审核,我们可以提供这些经过审核的响应,减少提供有害或不适当内容的风险。
一种简单的缓存方法是使用正在处理的项目的唯一 ID,例如,如果我们正在总结新文章或产品评论。当请求进来时,我们可以检查缓存中是否已经存在摘要。如果有,我们可以立即返回它;如果没有,我们生成、审核并提供它,然后将其存储在缓存中以供将来请求。
对于更开放的查询,我们可以借用搜索领域的技术,该领域也利用缓存处理开放输入。自动补全和拼写校正等功能也有助于规范用户输入,从而提高缓存命中率。
什么时候进行微调
我们可能有一些任务,即使经过精心设计的提示也无法完成。例如,即使经过大量提示工程,我们的系统仍可能无法返回可靠的高质量输出。如果是这样,那么可能需要为你的特定任务微调模型。
尽管微调可以有效,但它成本很高。我们必须注释微调数据、微调和评估模型,并最终自托管它们。因此,考虑是否值得进行高额的前期投资。如果提示能让你达到 90% 的目标,那么微调可能不值得投资。然而,如果我们决定进行微调,为了降低收集人工注释数据的成本,我们可以生成并微调合成数据,或基于开源数据进行启动。
评估和监控
评估 LLM 可能是一个雷区。LLM 的输入和输出是任意文本,我们给它们设置的任务也是多种多样的。然而,严格和深思熟虑的评估至关重要 ——OpenAI 的技术领导者从事评估工作并对各个评估提供反馈并非巧合。
评估 LLM 应用程序需要多样的定义和简化:这只是单元测试,或者更像是可观测性,或者只是数据科学。我们发现所有这些观点都很有用。在以下部分中,我们提供了一些关于构建评估和监控管道的重要经验教训。
从实际输入/输出示例中创建基于断言的单元测试
创建单元测试(即断言),包括生产环境中的输入和输出示例,并基于至少三个标准对输出进行期望。虽然三个标准似乎是任意的,但它是一个实用的起点;更少的标准可能表明你的任务定义不够明确或过于开放,例如一个通用聊天机器人。这些单元测试或断言应该在任何管道更改时触发,无论是编辑提示、通过 RAG 添加新上下文或其他修改。
考虑从指定所有响应中包含或排除的短语或想法的断言开始。还可以考虑检查单词、项目或句子数量是否在范围内。对于其他类型的生成,断言可能看起来不同。执行 - 评估是一种强大的代码生成评估方法,其中你运行生成的代码并确定运行时状态是否满足用户请求。
最后,按客户预期使用你的产品(即 “dogfooding”)可以提供对实际数据中失败模式的见解。这种方法不仅有助于识别潜在的弱点,还提供了可转化为评估的生产样本。
LLM-as-Judge 可以工作(有时),但它不是万能的
LLM-as-Judge,即使用强大的 LLM 来评估其他 LLM 的输出,一直受到一些人的质疑(我们中一些人最初也是极大的怀疑者)。尽管如此,当实施得当时,LLM-as-Judge 与人类判断的相关性相当不错,至少可以帮助建立对新提示或技术性能的先验知识。特别是当进行成对比较时(例如,控制与处理),LLM-as-Judge 通常能正确判断方向,尽管胜负的幅度可能不尽相同。
以下是一些从 LLM-as-Judge 中获得最大收益的建议:
- 使用成对比较:不要让 LLM 在李克特量表上对单个输出评分,而是给它两个选项并让它选择更好的一个。这往往会有更稳定的结果。
- 控制位置偏差:选项的顺序会影响 LLM 的决策。为了减轻这一点,每次成对比较时交换选项顺序两次。只是要确保在交换后将胜利归因于正确的选项!
- 允许平局:在某些情况下,两者可能同样好。因此,允许 LLM 宣布平局,这样它就不必任意选择一个赢家。
- 使用链式思考:让 LLM 在给出最终偏好之前解释其决定,可以提高评估的可靠性。作为额外奖励,这允许你使用较弱但速度更快的 LLM,并仍然取得类似的结果。因为管道的这部分通常是批处理模式,因此链式思考带来的额外延迟不是问题。
- 控制响应长度:LLM 往往偏向更长的响应。为了减轻这一点,确保响应对的长度相似。
LLM-as-Judge 的一个特别强大的应用是检查新的提示策略是否回归。如果你已经跟踪了一组生产结果,有时你可以用新的提示策略重新运行这些生产示例,并使用 LLM-as-Judge 快速评估新策略可能出现的问题。
不过,LLM-as-Judge 并不是万能的。语言的一些微妙方面,即使是最强的模型也难以可靠地评估。此外,我们发现传统的分类器和奖励模型可以比 LLM-as-Judge 达到更高的准确性,并且成本和延迟更低。对于代码生成,LLM-as-Judge 可能比直接的评估策略(如执行 - 评估)要弱。
“实习生测试” 用于评估生成
我们喜欢在评估生成时使用以下 “实习生测试”:如果你将语言模型的确切输入,包括上下文,作为任务交给相关专业的普通大学生,他们能否成功?需要多长时间?
如果答案是否定的,因为 LLM 缺乏所需的知识,考虑丰富上下文的方法。
如果答案是否定的,并且我们无法通过改善上下文来解决它,那么我们可能遇到了一个对于当前 LLM 来说太难的任务。
如果答案是肯定的,但需要一些时间,我们可以尝试减少任务的复杂性。它是否可分解?任务的哪些方面可以模板化?
如果答案是肯定的,他们会很快完成,那么是时候深入研究数据了。模型做错了什么?我们能找到失败模式吗?尝试让模型在响应之前或之后解释自己,帮助你建立一个心智模型。
过分强调某些评估可能会损害整体性能
一个例子是大海捞针(NIAH)评估。最初的评估帮助量化了上下文大小增加时的模型召回率,以及针的位置如何影响召回率。但是,它被过分强调了,评估涉及将一个特定短语(“特殊魔法 {city} 数字是:{number}”)插入到重复 Paul Graham 文章的长文档中,然后提示模型回忆魔法数字。
虽然一些模型实现了近乎完美的召回率,但 NIAH 是否真正反映了现实应用中所需的推理和召回能力值得怀疑。考虑一个更实际的场景:给定一个小时的会议记录,LLM 能否总结关键决策和下一步,并正确归属每项内容给相关人员?这个任务更现实,超越了死记硬背,并且考虑了解析复杂讨论、识别相关信息和合成摘要的能力。
另外,过分强调 NIAH 评估可能会导致提取和总结任务的性能下降。因为这些 LLM 如此微调,以至于关注每句话,它们可能会开始将无关的细节和干扰项视为重要,从而将它们包括在最终输出中(当它们不应该这样做时!)
这也适用于其他评估和用例。例如,总结。一种对事实一致性的强调可能导致总结变得不那么具体(因此不太可能出现事实不一致),可能不那么相关。相反,对写作风格和优雅的强调可能会导致更花哨的、市场类型的语言,这可能会引入事实不一致。
简化注释到二进制任务或成对比较
为模型输出提供开放式反馈或在李克特量表上评分是认知上非常耗费精力的。结果是,收集的数据更具噪音 —— 由于人类评分者之间有差异 —— 因此不太有用。一种更有效的方法是简化任务并减少注释者的认知负担。两种有效的任务是二进制分类和成对比较。
在二进制分类中,注释者被要求对模型的输出做出简单的是或否的判断。他们可能被问及生成的摘要是否与源文档事实一致,或提议的响应是否相关,或是否包含有害内容。与李克特量表相比,二进制决策更精确,评分者之间的一致性更高,产量也更高。Doordash 就是通过一系列是非问题树来设置菜单项目标注队列的。
在成对比较中,注释者会看到一对模型响应,并被要求哪个更好。因为人类更容易说 “甲比乙好” 而不是单独给甲或乙评分,这会导致更快和更可靠的注释(相对于李克特量表)。
(无参考)评估和护栏可以互换使用
护栏有助于捕捉不适当或有害内容,而评估有助于衡量模型输出的质量和准确性。在无参考评估的情况下,它们可以被视为同一枚硬币的两面。无参考评估是不依赖于 “黄金” 参考(如人工编写的答案)的评估,可以仅根据输入提示和模型的响应评估输出的质量。
一些示例是摘要评估,其中我们只需考虑输入文档,以评估摘要的事实一致性和相关性。如果摘要在这些指标上的得分很低,我们可以选择不向用户展示它,有效地将评估用作护栏。同样,无参考翻译评估可以在不需要人工翻译参考的情况下评估翻译的质量,再次允许我们将其用作护栏。
LLM 会返回它们不应该返回的输出
使用 LLM 的一个关键挑战是它们经常会生成不应该生成的输出。这可能导致无害但荒谬的响应,或更严重的问题,如有害或危险的内容。例如,当被要求从文档中提取特定属性或元数据时,LLM 可能自信地返回值,即使这些值实际上并不存在。或者,模型可能会因为我们提供了非英文的文档而以非英文语言响应。
虽然我们可以尝试提示 LLM 返回 “不可用” 或 “未知” 的响应,但这并不是万无一失的。即使日志概率可用,它们也是输出质量的糟糕指标。虽然日志概率指示 Token 出现在输出中的可能性,但它们不一定反映生成文本的正确性。
相反,对于训练以响应查询和生成连贯响应的指令调整模型,日志概率可能不太校准。因此,虽然高日志概率可能表明输出流畅且连贯,但这并不意味着它准确或相关。
虽然谨慎的提示工程在某种程度上有所帮助,但我们应该辅以强大的护栏来检测和过滤/重新生成不需要的输出。例如,OpenAI 提供了一个内容审核 API,可以识别仇恨言论、自残或性内容等不安全响应。
同样,有许多包可以检测个人身份信息(PII)。一个好处是,护栏在很大程度上与用例无关,因此可以广泛应用于给定语言的所有输出。此外,通过精确检索,如果没有相关文档,我们的系统可以确定性地回答 “我不知道”。
这里的一个推论是,LLM 可能在预期输出时未能生成输出。这可能由于各种原因,从 API 提供商的长尾延迟等简单问题到更复杂的问题,如输出被内容审核过滤器阻止。因此,重要的是始终记录输入和(可能缺乏的)输出以进行调试和监控。
幻觉是一个顽固的问题
与内容安全或 PII 缺陷相比,幻觉(即事实不一致)是顽固且更难检测的问题。它们更常见,基线发生率为 5-10%,从我们了解到的 LLM 提供商的情况来看,即使在简单任务(如摘要)上,将其降低到 2%以下也很困难。
为了解决这个问题,我们可以结合提示工程(生成上游)和事实不一致护栏(生成下游)。对于提示工程,链式思考等技术通过让 LLM 解释其推理以减少幻觉。然后,我们可以应用事实不一致护栏评估摘要的事实性,并过滤或重新生成幻觉。
在某些情况下,幻觉可以通过确定性检测到。当使用 RAG 检索的资源时,如果输出是结构化的并识别资源是什么,你应该能够手动验证它们是否来自输入上下文。
操作 LLM 应用程序时,我们会遇到一些与操作传统软件系统相似的问题,但这些问题通常会带来新的挑战,使工作更具活力。同时,LLM 应用程序还会引发全新的问题。我们将这些问题及其答案分为四个部分:数据、模型、产品和人员。
运作:开发和管理 LLM 应用程序以及构建团队
数据
就像食材的质量决定了菜肴的味道一样,输入数据的质量决定了机器学习系统的性能。此外,输出数据是判断产品是否正常工作的唯一标准。所有作者都非常重视数据,每周花费数小时来审查输入和输出数据,以更好地理解数据分布:它的模式、边缘情况以及模型的局限性。
检查开发与生产的偏差
在传统机器学习管道中,常见的错误来源是训练与服务的偏差。这种情况发生在训练数据与模型在生产中遇到的数据不一致时。虽然我们可以在无需训练或微调的情况下使用 LLM,因此不存在训练集,但开发与生产数据的偏差仍然存在。
基本上,我们在开发过程中测试系统的数据应该与系统在生产中面临的数据相似。否则,我们可能会发现生产准确性受到影响。
LLM 的开发与生产偏差可以分为两种类型:结构性和内容性。结构性偏差包括格式不一致的问题,例如 JSON 字典与列表类型值之间的差异,不一致的大小写,以及拼写错误或句子碎片等错误。
这些错误可能导致模型性能不可预测,因为不同的 LLM 训练于特定的数据格式,提示词对细微变化非常敏感。基于内容或 “语义” 的偏差指的是数据的意义或上下文的差异。
与传统机器学习一样,定期衡量 LLM 输入/输出对之间的偏差是有用的。简单的指标如输入和输出的长度或特定的格式要求(例如 JSON 或 XML)是跟踪变化的直接方法。对于更 “高级” 的漂移检测,考虑对输入/输出对的嵌入进行聚类以检测语义漂移,例如用户讨论话题的变化,这可能表明他们正在探索模型之前未接触过的领域。
在测试更改(如提示词工程)时,确保保留的数据集是最新的并反映了最近的用户互动类型。例如,如果生产输入中常见拼写错误,它们也应该出现在保留数据中。除了数值偏差测量外,进行输出的定性评估也很有帮助。
定期审查模型的输出 —— 一种被称为 “氛围检查” 的做法 —— 确保结果符合预期并且仍然与用户需求相关。最后,将不确定性引入偏差检查也是有用的 —— 通过对测试数据集中的每个输入多次运行管道并分析所有输出,我们增加了捕捉偶发异常的可能性。
每天查看 LLM 的输入和输出样本
LLM 是动态的,并且在不断演变。尽管它们具有令人印象深刻的零样本能力和经常令人愉快的输出,但它们的失败模式可能是高度不可预测的。对于定制任务,定期审查数据样本对于发展对 LLM 性能的直观理解至关重要。
来自生产的输入 - 输出对是 LLM 应用程序的 “真实事物、真实地方”(genchi genbutsu),它们是不可替代的。最近的研究指出,开发人员对 “好” 与 “坏” 输出的认知会随着他们与更多数据的互动而发生变化(即标准漂移)。
虽然开发人员可以预先提出一些评估 LLM 输出的标准,但这些预定义标准通常是不完整的。例如,在开发过程中,我们可能会更新提示以增加良好响应的概率并减少不良响应的概率。这种评估、重新评估和标准更新的迭代过程是必要的,因为在不直接观察输出的情况下,很难预测 LLM 的行为或人类的偏好。
为有效管理这一过程,我们应记录 LLM 的输入和输出。通过每天检查这些日志的样本,我们可以快速识别和适应新的模式或故障模式。当我们发现新的问题时,可以立即编写断言或评估来解决它。同样,对故障模式定义的任何更新都应反映在评估标准中。这些 “氛围检查” 是坏输出的信号;代码和断言将其操作化。最后,这种态度必须被社会化,例如通过将输入和输出的审查或注释添加到你的轮值中。
使用模型
使用 LLM API 时,我们可以依赖少数供应商的智能。这是一个好处,但这些依赖关系也带来了性能、延迟、吞吐量和成本上的权衡。此外,随着更好的新模型不断出现(过去一年几乎每月都有),我们应准备好在淘汰旧模型并迁移到新模型时更新我们的产品。在本节中,我们分享了与我们无法完全控制的技术合作的经验,这些技术不能自行托管和管理。
生成结构化输出以简化下游集成
对于大多数实际用例,LLM 的输出将通过某种机器可读格式被下游应用程序消耗。例如,Rechat(一种房地产 CRM)需要结构化响应以便前端渲染小部件。同样,Boba(一种生成产品战略想法的工具)需要结构化输出,包括标题、摘要、可行性评分和时间范围等字段。最后,LinkedIn 分享了如何将 LLM 约束生成 YAML,然后用于决定使用哪些技能以及提供调用技能的参数。
这种应用模式是 Postel 定律的极端版本:在接受方面要宽容(任意自然语言),在发送方面要保守(类型化的机器可读对象)。因此,我们期望它具有极高的耐用性。
目前,Instructor 和 Outlines 是从 LLM 中引导结构化输出的事实标准。如果你使用的是 LLM API(例如 Anthropic,OpenAI),请使用 Instructor;如果你使用的是自托管模型(例如 Hugging Face),请使用 Outlines。
跨模型迁移提示是件苦差事
有时,我们精心制作的提示在一个模型上效果极佳,但在另一个模型上却表现不佳。这种情况可能发生在我们在不同模型供应商之间切换时,也可能发生在我们升级同一模型的不同版本时。
因此,如果我们必须跨模型迁移提示,预计这将比简单地交换 API 端点花费更多时间。不要假设使用相同的提示会产生类似或更好的结果。此外,拥有可靠的自动化评估有助于在迁移前后测量任务性能,并减少手动验证所需的工作量。
版本控制和固定你的模型
在任何机器学习管道中,“改变任何事情都会改变一切”。这在我们依赖的 LLM 等组件上尤为相关,这些组件我们无法自行训练,可能在我们不知情的情况下发生变化。
幸运的是,许多模型提供商提供了 “固定” 特定模型版本的选项(例如 gpt-4-turbo-1106)。这使我们能够使用特定版本的模型权重,确保其保持不变。在生产中固定模型版本可以避免模型行为的意外变化,这些变化可能导致客户投诉,例如输出过于冗长或其他不可预见的故障模式。
此外,考虑维护一个影子管道,模拟你的生产设置,但使用最新的模型版本。这使得能够安全地进行实验和测试新版本。一旦验证了这些新模型输出的稳定性和质量,可以放心地在生产环境中更新模型版本。
选择能够完成工作的最小模型
在开发新应用程序时,使用最大的、最强大的模型是很有诱惑力的。但一旦确定任务在技术上是可行的,就值得尝试是否较小的模型可以实现类似的结果。
较小模型的好处是延迟和成本更低。虽然它可能较弱,但链式思考、n-shot 提示和上下文学习等技术可以帮助较小的模型超越其自身能力。除了 LLM API,微调特定任务也可以帮助提高性能。
总而言之,使用较小模型精心设计的工作流程往往可以匹敌甚至超越单个大型模型的输出质量,同时速度更快且成本更低。从长远来看,我们预计将看到更多小型模型流工程的例子,以实现输出质量、延迟和成本的最佳平衡。
重点是,不要忽视较小的模型。虽然很容易将大型模型用于每个问题,但通过一些创造力和实验,我们通常可以找到更有效的解决方案。
产品
虽然新技术提供了新可能性,但构建优秀产品的原则是永恒的。因此,即使我们是第一次解决新问题,也不必在产品设计上重新发明轮子。将 LLM 应用程序开发基础扎根于坚实的产品基础,可以让我们为服务的人提供真正的价值。
尽早且频繁地让设计参与
拥有设计师将推动你理解和深思如何构建和呈现产品给用户。我们有时将设计师刻板印象化为只负责让事物变得漂亮的人。但不仅限于用户界面,他们还会重新思考如何改进用户体验,即使这意味着打破现有规则和范式。
设计师特别擅长将用户需求重新定义为各种形式。有些形式比其他形式更易于解决,因此,它们可能提供更多或更少的 AI 解决方案机会。与许多其他产品一样,构建 AI 产品应以完成的工作为中心,而不是驱动它们的技术。
专注于问自己:“用户要求这个产品为他们完成什么工作?这个工作是聊天机器人擅长的吗?自动完成怎么样?也许是其他东西!” 考虑现有的设计模式及其与待完成的工作的关系。这些都是设计师为你的团队带来的宝贵资产。
为人机交互设计你的用户体验
获得高质量注释的一种方法是将人机交互(HITL)集成到用户体验(UX)中。通过允许用户轻松提供反馈和修正,我们可以改进即时输出并收集有价值的数据来改进我们的模型。
想象一下一个电子商务平台,用户上传并分类他们的产品。有几种方法可以设计 UX:
- 用户手动选择正确的产品类别;LLM 定期检查新产品并在后台纠正分类错误。
- 用户根本不选择任何类别;LLM 定期在后台分类产品(可能有错误)。
- LLM 实时建议产品类别,用户可以根据需要验证和更新。
虽然所有三种方法都涉及 LLM,但它们提供了非常不同的 UX。第一种方法将初始负担放在用户身上,让 LLM 充当后处理检查。第二种方法要求用户零努力,但不提供透明度或控制。第三种方法找到了正确的平衡。
通过让 LLM 预先建议类别,我们减少了用户的认知负担,他们不必学习我们的分类法来对其产品进行分类!同时,通过允许用户审查和编辑建议,他们对如何分类产品有最终决定权,将控制权牢牢掌握在自己手中。作为奖励,第三种方法为模型改进创建了一个自然的反馈循环。好的建议被接受(正面标签),坏的建议被更新(负面标签然后是正面标签)。
这种建议、用户验证和数据收集的模式在多个应用程序中常见:
- 代码助手:用户可以接受建议(强正面),接受并调整建议(正面)或忽略建议(负面)
- Midjourney:用户可以选择放大并下载图片(强正面),变换图片(正面)或生成新图片集(负面)
- 聊天机器人:用户可以对响应提供点赞(正面)或点踩(负面),如果响应真的很糟糕,可以选择重新生成响应(强负面)
反馈可以是显性的也可以是隐性的。显性反馈是用户响应我们产品请求而提供的信息;隐性反馈是我们从用户交互中学到的信息,而无需用户故意提供反馈。
代码助手和 Midjourney 是隐性反馈的例子,而点赞和点踩是显性反馈。如果我们设计好我们的 UX,就像代码助手和 Midjourney 一样,我们可以收集大量隐性反馈来改进我们的产品和模型。
严格按照需求层次划分优先顺序
当我们考虑将演示投产时,我们需要考虑以下需求:
- 可靠性:99.9% 的正常运行时间,符合结构化输出
- 无害性:不生成冒犯性、NSFW 或其他有害内容
- 事实一致性:忠于提供的上下文,不编造内容
- 有用性:与用户需求和请求相关
- 可扩展性:延迟 SLA,支持的吞吐量
- 成本:因为我们没有无限的预算
- 以及更多:安全性、隐私、公平性、GDPR、DMA 等。
如果我们试图一次性解决所有这些需求,我们将永远不会发布任何东西。因此,我们需要严格地优先考虑。这意味着明确什么是不可协商的(例如,可靠性、无害性),没有这些我们的产品无法运行或不可行。这一切都是关于识别最小可爱的产品。我们必须接受第一个版本不会完美,然后发布和迭代。
根据用例校准风险容忍度
在决定语言模型和应用程序的审查级别时,考虑用例和受众。对于提供医疗或财务建议的面向客户的聊天机器人,我们需要非常高的安全性和准确性标准。错误或不良输出可能会造成实际伤害并侵蚀信任。
但对于不太关键的应用程序,例如推荐系统,或面向内部的应用程序如内容分类或摘要,过于严格的要求只会拖慢进度而不会增加太多价值。
团队与角色
定义任何工作职能都不容易,但在这个新领域撰写职位描述比其他领域更具挑战性。我们将放弃交叉职位标题的维恩图或职位描述建议。我们将承认新角色 ——AI 工程师 —— 的存在并讨论其位置。重要的是,我们将讨论团队的其他成员及其职责应如何分配。
专注于流程而不是工具
面对新范式,如 LLM,软件工程师倾向于偏爱工具。因此,我们忽略了工具应解决的问题和过程。在这样做的过程中,许多工程师承担了意外的复杂性,这对团队的长期生产力产生了负面影响。
除了意外的复杂性外,工具通常还不够完善。LLM 的组件远不止提示编写和评估。重要的是 AI 工程师在采用工具之前要了解流程。
不断进行尝试
ML 产品与实验深度交织。不仅是 A/B、随机对照试验类型,还包括对系统最小可能组件的频繁修改和离线评估。每个人对评估的热情并不是关于信任和信心 —— 而是关于使实验成为可能!评估越好,实验迭代速度越快,从而系统最佳版本的收敛速度越快。
尝试不同方法解决同一问题很常见,因为实验现在很便宜。收集数据和训练模型的高成本最小化 —— 提示工程几乎只需要人力时间。将你的团队定位,使每个人都掌握提示工程的基本知识。这鼓励每个人进行实验,并带来组织内的多样化想法。
此外,不仅仅是探索实验 —— 也利用它们来开发!有一个新任务的工作版本吗?考虑让团队中的其他人用不同的方法解决它。尝试另一种更快的方法。研究链式思考或少样本提示等技术,以提高质量。不要让工具阻碍实验;如果是这样,重建它或购买更好的工具。
最后,在产品/项目规划期间,留出时间来构建评估并进行多次实验。将产品规范视为工程产品,但增加明确的评估标准。在路线图制定期间,不要低估实验所需的时间 —— 预计在获得生产批准之前要进行多次开发和评估迭代。
让每个人都能使用新 AI 技术
随着生成式 AI 的应用增加,我们希望整个团队 —— 不仅仅是专家 —— 理解并能够使用这项新技术。没有比实际使用它更好的方法来培养对 LLM 工作原理(如延迟、故障模式、用户体验)的直觉。LLM 相对容易获取:无需编程即可提高管道性能,每个人都可以通过提示工程和评估开始贡献。
这很大程度上取决于教育。可以从提示工程的基础知识开始,使用 n-shot 提示和链式思考等技术帮助模型朝向期望的输出。了解技术方面的人还可以学习更技术的方面,例如 LLM 是如何自回归的。换句话说,虽然输入 Token 是并行处理的,但输出 Token 是顺序生成的。因此,延迟更多是输出长度的函数而不是输入长度 —— 这是设计 UX 和设置性能期望时的关键考虑因素。
我们还可以进一步提供实践实验和探索的机会。也许是黑客马拉松?虽然整个团队花几天时间进行推测性项目黑客似乎成本高昂,但结果可能会让你惊讶。
不要陷入 “AI 工程是我需要的全部” 陷阱
随着新职位名称的出现,最初往往会夸大与这些角色相关的能力。这通常会导致随着这些工作的实际范围变得清晰而进行的痛苦调整。新进入者以及招聘经理可能会夸大或对期望值过高。在过去十年中值得注意的例子包括:
- 数据科学家:“比任何软件工程师更擅长统计,比任何统计学家更擅长软件工程的人”
- 机器学习工程师(MLE):以软件工程为中心的机器学习观点
最初,许多人认为单靠数据科学家就足以完成数据驱动的项目。然而,事实证明,数据科学家必须与软件和数据工程师合作,才能有效地开发和部署数据产品。
这种误解在新角色 AI 工程师中再次出现,一些团队认为 AI 工程师是唯一需要的角色。实际上,构建机器学习或 AI 产品需要广泛的专业角色。我们与十几家公司就 AI 产品进行了咨询,始终发现他们陷入了 “AI 工程是我需要的全部” 的陷阱。因此,产品往往难以扩展到演示之外,因为公司忽略了构建产品涉及的重要方面。
以下是构建 AI 产品过程中所需角色类型及其所需时间的大致进展:
- 首先,专注于构建产品。这可能包括 AI 工程师,但不一定。AI 工程师在快速原型设计和产品迭代(UX,管道等)方面很有价值。
- 接下来,通过对系统进行检测和收集数据来创建正确的基础。根据数据的类型和规模,你可能需要平台和 / 或数据工程师。你还必须有查询和分析这些数据以调试问题的系统。
- 接下来,你最终希望优化 AI 系统。这不一定涉及训练模型。基本步骤包括设计指标、构建评估系统、运行实验、优化 RAG 检索、调试随机系统等。MLE 在这方面非常擅长(尽管 AI 工程师也可以掌握这些技能)。除非你已经完成了前期步骤,否则通常没有必要雇佣 MLE。
- 除此之外,你随时都需要领域专家。在小公司中,这理想情况下是创始团队 —— 在大公司中,产品经理可以扮演这一角色。了解角色的进展和时间安排至关重要。在错误的时间雇佣人员(例如,过早雇佣 MLE)或以错误的顺序构建是浪费时间和金钱,并导致人员流动。此外,在阶段 1-2 期间定期与 MLE 核对(但不要全职雇佣他们)将帮助公司构建正确的基础。
这样,通过对角色的合理分配和管理,团队可以更高效地开发和部署 LLM 应用程序,从而实现最佳的产品效果。
战略:利用 LLM 打造产品,避免被淘汰
成功的产品需要深思熟虑的规划和严格的优先级排序,而不是无休止的原型设计或追随最新的模型发布或趋势。下面,我们将深入探讨打造优秀 AI 产品的战略考量。我们还将探讨团队将面临的关键权衡,如何时构建、何时购买,并为早期 LLM 应用开发战略提出建议。
在 PMF 之前不使用 GPU
要想成为伟大的产品,你的产品就不能仅仅是对他人应用程序接口的简单包装。但反其道而行之,代价可能会更高。在过去的一年中,风险投资也投入了大量资金,其中包括令人瞠目的 60 亿美元 A 轮融资,都用在了培训和定制没有明确产品愿景或目标市场的模型上。
从头开始培训(几乎)毫无意义
对于大多数企业来说,从头开始预训练 LLM 是一种不切实际的做法。
虽然这很令人兴奋,而且似乎其他人都在这么做,但开发和维护机器学习基础架构需要大量资源。这包括收集数据、训练和评估模型以及部署模型。如果你还在验证产品与市场的契合度,这些工作就会占用开发核心产品的资源。即使你拥有计算、数据和技术能力,经过预培训的 LLM 也可能在几个月后就会过时。
在证明有必要之前不要微调
对于大多数企业来说,微调更多是出于 “望梅止渴”,而非清晰的战略思考。
企业过早地投资微调,试图摆脱:只是另一种包装 “的说法。实际上,微调是一种重型机械,只有在收集了大量实例,证明其他方法无法满足需要时,才能部署微调。
一年前,许多团队告诉我们,他们很想进行微调。但很少有人找到了产品与市场的契合点,大多数人对自己的决定感到后悔。如果你要进行微调,你最好真的确信,随着基础模型的不断改进,你已经做好了反复进行微调的准备。
什么情况下进行微调是正确的?如果用例所需的数据无法从用于训练现有模型的大部分开放式网络规模数据集中获得,而且你已经构建了一个 MVP,证明现有模型是不够的。但要注意:如果模型构建者无法随时获得大量训练数据,那么你从哪里获得这些数据呢?
最后,请记住,由 LLM 驱动的应用不是一个科学展览项目;对它们的投资应与其对企业战略目标和差异化竞争的贡献相称。
从推理 API 开始,但不要害怕自托管
有了 LLM API,初创企业就可以比以往任何时候都更容易地采用和集成语言建模功能,而无需从头开始训练自己的模型。Anthropic 和 OpenAI 等提供商提供通用 API,只需几行代码就能将智能融入你的产品。通过使用这些服务,你可以减少花费的精力,转而专注于为客户创造价值,这让你可以验证想法,并更快地实现产品与市场的契合。
但是,与数据库一样,托管服务并不适合每种使用情况,尤其是随着规模和需求的增加。事实上,自托管可能是使用模型而不将机密 / 私人数据发送出网络的唯一方法,这在医疗保健和金融等受监管行业或合同义务或保密要求中是必需的。
此外,自托管还可以规避推理提供商施加的限制,如费率限制、模型报废和使用限制。此外,自托管使您可以完全控制模型,从而更容易围绕模型构建差异化的高质量系统。最后,自托管,尤其是微调,可以大规模降低成本。
迭代出伟大的产品
要想长期保持竞争优势,就必须跳出模式的束缚,考虑如何让自己的产品与众不同。执行速度固然重要,但它不应该是你唯一的优势。
模型不是产品,围绕它的系统才是
对于没有建立模型的团队来说,快速的创新步伐是一个福音,因为他们可以从一个 SOTA 模型迁移到下一个模型,在上下文大小、推理能力和性价比方面不断追求进步,从而打造出越来越好的产品。
这种进步既令人兴奋,又可以预见。综上所述,这意味着模型很可能是系统中最不耐用的组件。
取而代之的是,将精力集中在能够提供持久价值的方面,例如:
- 评估底盘:可靠地衡量不同模型在任务中的表现
- 护栏:防止在任何模型中出现不希望的输出
- 缓存:通过完全避免模型来减少延迟和成本
- 数据飞轮:为上述各项的迭代改进提供动力
与原始模型能力相比,这些组件为产品质量提供了更坚实的护城河。
但这并不意味着在应用层构建就没有风险。如果 OpenAI 或其他模型提供商想要提供可行的企业软件,就不要把剪子对准他们需要剪掉的牦牛。
例如,一些团队投资构建定制工具,以验证专有模型的结构化输出;在此方面进行最小程度的投资固然重要,但过深的投资并不能很好地利用时间。OpenAI 需要确保当你要求调用函数时,你得到的是有效的函数调用 -- 因为他们的所有客户都希望如此。在此采用一些 “策略性拖延”,构建你绝对需要的功能,等待供应商对功能的明显扩展。
从小事做起,建立信任
试图为所有人提供面面俱到的产品是平庸的秘诀。要想创造出引人注目的产品,公司需要专门打造令人难忘的粘性体验,让用户流连忘返。
考虑一下通用的 RAG 系统,它的目标是回答用户可能提出的任何问题。缺乏专业化意味着该系统无法对近期信息进行优先排序,无法解析特定领域的格式,也无法理解特定任务的细微差别。因此,用户只能获得肤浅、不可靠的体验,无法满足他们的需求。
为解决这一问题,应将重点放在特定领域和使用案例上。通过深入而非广泛的方式缩小范围。这将创建能与用户产生共鸣的特定领域工具。专业化还能让你直面系统的能力和局限性。对系统能做什么和不能做什么保持透明,能体现自我意识,帮助用户了解系统在哪些方面能带来最大价值,从而建立对产出的信任和信心。
构建 LLMOps,但要有正确的理由:更快的迭代
从根本上说,DevOps 与可复制的工作流程、左移或授权两个披萨团队无关,也绝对与编写 YAML 文件无关。
DevOps 是要缩短工作与成果之间的反馈周期,从而不断改进,而不是不断出错。它的根源可以追溯到精益创业运动、精益生产和丰田生产方式,后者强调 “一分钟换模(Single Minute Exchange of Die)” 和 “改善(Kaizen)”。
MLOps 将 DevOps 的形式应用于 ML。我们有可重现的实验,我们有一体式套件,让模型构建者能够进行交付。我们还有 YAML 文件。
但作为一个行业,MLOps 并没有适应 DevOps 的功能。它没有缩短模型与生产中的推论和交互之间的反馈差距。
令人欣慰的是,LLMOps 领域已经从思考诸如及时管理之类的小妖怪,转向了阻碍迭代的难题:生产监控和持续改进,并通过评估进行关联。
不要构建可以购买的 LLM 功能
大多数成功的企业都不是终身学习企业。与此同时,大多数企业都有机会通过终身学习来改进。
这两点往往会误导领导者匆忙地在系统中加装 LLM,从而增加成本、降低质量,并将其作为徒有其表的 “AI” 功能发布,同时附上令人生厌的闪光图标。有一种更好的方法:专注于真正符合产品目标并能增强核心运营的 LLM 应用程序。
考虑一些浪费团队时间的误入歧途的冒险:
- 为你的业务构建自定义文本到 SQL 功能
- 构建一个聊天机器人与你的文档对话
- 将公司的知识库与客户支持聊天机器人整合在一起
虽然以上是 LLM 应用程序的入门级应用,但几乎所有产品公司都不应该自己构建这些应用程序。这些都是许多企业面临的普遍问题,在有前景的演示和可靠的组件之间存在巨大差距,而这正是软件公司的惯常做法。将宝贵的研发资源投入到当前 Y Combinator 批量解决的一般问题上是一种浪费。
如果这听起来像是老生常谈的商业建议,那是因为在当前的炒作浪潮中,人们很容易把任何 “LLM” 都误认为是前沿的增量差异化技术,而忽略了哪些已经过时的应用。
AI 在循环中,人类在中心
目前,由 LLM 驱动的应用非常脆弱。它们需要大量的安全保护和防御工程,而且仍然难以预测。此外,当范围严格限定时,这些应用可能非常有用。这意味着 LLM 是加速用户工作流程的绝佳工具。
虽然想象基于 LLM 的应用完全取代工作流程或替代工作职能可能很有诱惑力,但如今最有效的范例是半人马机器人(例如半人马国际象棋)。当有能力的人类与为快速利用而调整的 LLM 功能配对时,工作效率和完成任务的快乐程度都会大大提高。
对于那些在 ML 领域工作了很长时间的人来说,你可能会想到 “人机协同” 的概念,但没那么快:HITL 机器学习是一种建立在人类专家确保 ML 模型的行为符合预测的基础上的范式。虽然相关,但我们在这里提出的是更微妙的东西。LLM 驱动的系统不应成为当今大多数工作流程的主要驱动力;它们应该只是一种资源。
以人类为中心,询问 LLM 如何支持他们的工作流程,这将带来截然不同的产品和设计决策。最终,这将促使你打造出与那些试图迅速将所有责任外包给 LLM 的竞争对手不同的产品 —— 更好、更有用、风险更低的产品。
从提示、评估和数据收集开始
前面内容提供了大量的技巧和建议。这需要吸收很多东西。让我们考虑一下最有用的建议:如果一个团队想要构建一个 LLM 产品,他们应该从哪里开始?
在过去的一年中,我们已经看到了足够多的例子,开始确信成功的 LLM 应用程序都遵循着一致的轨迹。现在,我们介绍这本基本的 “入门” 手册。核心理念是从简单开始,只在需要时增加复杂性。一个合理的经验法则是,每提高一个复杂度,通常都需要比前一个复杂度多付出至少一个数量级的努力。考虑到这一点……
从提示工程开始
首先进行提示工程。使用我们在战术部分讨论过的所有技巧。思维链、n-shot 示例以及结构化输入和输出几乎总是个好主意。在尝试从性能较弱的模型中榨取性能之前,先用性能最高的模型做原型。
只有在提示工程设计无法达到所需的性能水平时,才应考虑微调。如果有一些非功能性要求(如数据隐私、完全控制和成本)阻碍了专有模型的使用,从而要求您自行托管,那么这种情况就会更多。只要确保同样的隐私要求不会阻止你使用用户数据进行微调即可!
建立评估并启动数据飞轮
即使是刚刚起步的团队也需要评估。否则,你将不知道你的提示工程是否足够好,也不知道你的微调模型何时可以取代原始模型。
有效的 evals 针对你的任务并反映预期用例。我们推荐的第一级 evals 是单元测试。这种简单的测试可以发现潜在的错误,并帮助我们在项目初期做出设计决策。此外,还可查看其他针对特定任务的 evals,如分类、总结等。
虽然单元测试和基于模型的评估很有用,但它们不能取代人工评估。让人们使用你的模型/产品并提供反馈。这样做有两个目的,一是测量真实世界的性能和缺陷率,二是收集高质量的注释数据,用于微调未来的模型。这就形成了一个正反馈循环,或称数据飞轮,并随着时间的推移不断累积:
- 使用人工评估来评估模型性能和/或发现缺陷
- 使用注释数据对模型进行微调或更新提示
- 重复
例如,在审核 LLM 生成的摘要是否存在缺陷时,我们可能会在每个句子上标注细粒度的反馈,以确定事实不一致、不相关或风格不佳。然后,我们可以使用这些事实不一致注释来训练一个幻觉分类器,或者使用相关性注释来训练一个奖励模型,对相关性进行评分。
通过创建资产,使其价值随着时间的推移不断复合,我们将建立 evals 从纯粹的运营支出升级为战略投资,并在此过程中建立我们的数据飞轮。
低成本认知的高级趋势
1971 年,施乐公司 PARC 的研究人员预言了未来:一个充满网络化个人电脑的世界,正是我们今天所处的环境。他们在以太网、图形渲染、鼠标和窗口等技术的发明过程中发挥了关键作用,为这个未来的到来做出了贡献。
但他们也做了一项简单的工作:他们研究了那些非常有用(如视频显示)但还不经济(即足够的 RAM 驱动一个视频显示需要数千美元)的应用。然后,他们研究该技术的历史价格趋势(类似摩尔定律),预测这些技术何时会变得经济实惠。
我们可以对 LLM 技术采取同样的方法,尽管我们没有像每美元晶体管那样简洁的方法。我们可以采用一个流行的、长期使用的基准,比如大规模多任务语言理解数据集,以及一种一致的输入方法(五次提示)。然后,比较不同性能水平的语言模型在该基准上的运行成本。
自 OpenAI 的 Davinci 模型作为 API 推出以来的四年里,在一百万 Token(约 100 份本文档)的规模上运行一个性能相当的模型的成本已从 20 美元降至不到 10 美分 —— 仅用了六个月的时间就减少了一半。
同样,截至 2024 年 5 月,通过 API 提供商或自行运行 Meta 的 LLama 3 8B 的成本仅为每百万 Token 20 美分,其性能与 OpenAI 的 text-davinci-003 相似,后者是让 ChatGPT 震惊世界的模型。
该模型在 2023 年 11 月底发布时的价格也约为每百万 Token 20 美元。这在短短 18 个月内就提升了两个数量级 —— 摩尔定律预测在同一时间段内仅会翻一番。
现在,让我们来考虑一下 LLM 的一个非常有用的应用(生成视频游戏角色,如 Park 等人),但目前还不经济。自该论文于 2023 年 8 月发表以来,成本已经下降了大约一个数量级,降至每小时 62.50 美元。我们可以预计,再过九个月,成本将降至每小时 6.25 美元。
与此同时,1980 年《吃豆人》发行时,今天的 1 美元可以买到一个信用点数,可以玩几分钟或几十分钟 —— 算作每小时 6 个游戏,即每小时 6 美元。根据这一理论计算结果,令人信服的 LLM 增强型游戏体验将在 2025 年的某个时候变得经济实惠。
这些趋势都是新趋势,只有几年的历史。但我们没有理由期待这一进程在未来几年放缓。即使我们可能已经耗尽了算法和数据集中的低垂果实,例如超过了每参数约 20 个 Token 的 “Chinchilla 比率”,数据中心内部和硅层的深度创新和投资仍有望弥补这一不足。
这也许是最重要的战略事实:今天还完全不可行的地面演示或研究论文,几年后就会成为一种高级功能,不久后就会成为一种商品。我们在构建系统和组织时应牢记这一点。
0 到 1 的演示已经够多了,是时候推出 1 到 N 的产品了
我们知道,制作 LLM 演示非常有趣。只需几行代码、一个矢量数据库和一个精心制作的提示,我们就能创造出✨奇迹✨。在过去的一年里,这种魔力被比作互联网、智能手机甚至印刷机。
不幸的是,参与过实际软件交付的人都知道,在受控环境下运行的演示与大规模可靠运行的产品之间存在天壤之别。
以自动驾驶汽车为例。1988 年,第一辆汽车由神经网络驱动。25 年后,Andrej Karpathy 第一次试驾了 Waymo。十年后,该公司获得了无人驾驶许可证。从原型车到商业产品,经过了三十五年的严格工程设计、测试、改进和监管导航。
在工业界和学术界的不同领域,我们敏锐地观察到了过去一年是 LLM 从 1 到 N 的第一年。我们希望我们学到的经验 —— 从建立团队的严格操作技术等战术到内部建设哪些能力等战略视角 —— 能在第二年及以后帮助你们,让我们共同探索这项令人兴奋的新技术。