这是一个激动人心的时代,所有人都能够利用语言大模型(LLM)进行各种各样的产品构建。过去一年里,LLM已经达到了“足够好”的水平,可以应用于现实世界的场景,并且模型每年都在迭代,变得更好、更便宜。伴随着社交媒体上的一系列产品演示,预计到2025年,AI领域的投资将达到2000亿美元。此外,供应商的API使LLM更加易于访问,让每个人(不仅仅是ML工程师和科学家)都能将智能融入到他们的产品中。尽管使用AI构建的门槛降低了,但实际创建有效的产品和系统(不仅仅是demo)仍然很有难度。过去一年里,我们一直在进行构建,并在过程中发现了许多棘手的问题。虽然我们的经验并不代表整个行业,但我们希望分享自己的经验来避免同样的错误并加速迭代。我们将经验总结为以下三个部分:战术层面:一些关于提示、RAG、流程工程、评估和监控的实践建议。无论你是通过LLM进行构建的从业者,还是出于兴趣在周末进行项目开发,这部分内容都具有参考价值。运营层面:发布产品的日常组织和管理问题,以及组建高效团队的方法。这部分适合想要可持续且可靠地部署产品的产品/技术领导者。战略层面:长期、宏观的视角,包括诸如“在产品市场契合(PMF)之前不要使用GPU”和“专注于系统而非模型”等有见解的观点,以及如何进行迭代。这部分为创始人和高管量身定制。准备好深入探讨了吗?让我们开始吧。(本文由OneFlow编译,转载请联系授权。原文:https://applied-llms.org/)在本节中,我们将分享一些关于新兴LLM技术栈核心组件的最佳实践:提升质量和可靠性的提示技巧、评估输出效果的策略、通过检索增强生成(RAG)以改进基础性能等等。我们还将探讨如何设计“人机协作(human-in-the-loop)”的workflow。尽管这项技术仍在快速发展,但我们希望这些经验(来自我们集体进行的大量实验的副产品)能够经受住时间的考验,并助力于构建和发布稳健的LLM应用。1.1 提示
我们建议在开发新应用时从提示(prompting)开始。其重要性既容易被低估,也容易被高估。低估是因为正确的提示技巧如果使用得当,可以带来显著的进步。高估是因为即使是基于提示的应用程序也需要围绕提示进行大量的工程工作才能良好运行。1.1.1 专注于充分利用基本的提示技巧
一些提示技巧在提高各种模型和任务的性能方面总是非常有效:n-shot提示+上下文学习、思维链(Chain-of-Thought)以及提供相关背景资源。通过n次提示进行上下文学习的理念是向LLM提供一些示例,以展示任务并使输出符合我们的预期。以下是一些技巧:如果n值太低,模型可能会过度依赖这些特定示例,影响其泛化能力。一般来说,n应≥5。不要害怕将n值提高到几十次。 示例应代表预期输入的分布。如果你正在构建一个电影摘要生成器,它应该包含不同类型电影的样本,大致比例与你在实践中期望看到的一致。 不一定需要提供完整的输入-输出对。在许多情况下,仅提供期望输出的示例就足够了。 如果使用的LLM支持工具使用,你的n-shot示例也应该使用你希望智能体使用的这些工具。
在思维链(CoT)提示中,我们鼓励LLM在返回最终答案之前解释其思考过程。可以想象成给LLM提供一份草稿板,这样它就不必完全依赖内存。最初的方法是简单地添加短语“Let’s think step-by-step”作为指令的一部分,但我们发现,通过额外的一两句话使CoT更具体,通常可以显著降低幻觉率。 例如,当要求LLM总结会议记录时,我们可以明确步骤,例如:
请注意,最近有些人对这种技术是否如预期那样强大表示怀疑。此外,关于在使用思维链时推理过程中究竟发生了什么,存在相当大的争论。无论如何,如果情况允许,这是一种值得尝试的技术。提供相关背景资源是扩展模型知识库、减少幻觉并增强用户信任的强大机制。通常通过RAG来实现,向模型提供可直接用于回答的文本片段是一个基本技巧。在提供相关资源时,仅仅包含文本片段是不够的;记得告诉模型优先使用这些资源,进行直接引用,有时还要提到资源不足时的情况。这些都有助于将智能体响应“锚定”到资源语料库中。1.1.2 将输入和输出结构化
结构化的输入和输出可以帮助模型更好地理解输入,并返回能够可靠地与下游系统集成的输出。为输入添加序列化格式可以为模型提供更多关于上下文中词元关系的线索,例如为特定词元添加额外的元数据(如数据类型),或者将请求与模型训练数据中的类似示例相关联。例如,互联网上许多关于编写SQL的问题都从指定SQL模式开始。因此,你可能会觉得用于Text-to-SQL的有效提示应该包括结构化的模式定义。结构化输出有类似的作用,但它还简化了与系统下游组件的集成。Instructor和Outline非常适合结构化输出。如果你导入了LLM API SDK,请使用Instructor;如果你导入了Huggingface用于自托管模型,就使用Outlines。)结构化输入能够清晰地表达任务,并且类似于训练数据的格式,从而增加了获得更好输出的概率。使用结构化输入时,注意每个LLM系列都有其偏好。如Claude偏好XML格式,而GPT偏好Markdown和JSON格式。使用XML时,你甚至可以通过提供标签来预填Claude的响应,如下所示:messages=[{"role":"user","content":"""Extractthe<name>,<size>,<price>,and<color>fromthisproductdescriptionintoyour<response>.<description>TheSmartHomeMiniisacompactsmarthomeassistantavailableinblackorwhiteforonly$49.99.Atjust5incheswide,itletsyoucontrollights,thermostats,andotherconnecteddevicesviavoiceorapp—nomatterwhereyouplaceitinyourhome.Thisaffordablelittlehubbringsconvenienthands-freecontroltoyoursmartdevices.</description>"""},{"role":"assistant","content":"<response><name>"}]
1.1.3 编写小而精的提示,只做一件事,并且做好
在软件中,一个常见的反面模式是“God Object”,即一个类或函数包揽了所有事项。在提示也同样适用。一个提示通常从简单的开始:几句指令,几个示例,就可以了。但当我们试图提高性能并处理更多边缘情况时,复杂性就会悄悄增加。更多的指令,多步骤的推理,以及数十个示例。不知不觉间,我们最初的简单提示已经变成了一个两千词元的怪物。而更糟糕的是,它在处理更常见和直接的输入时性能更差!GoDaddy将这一挑战作为他们使用LLM进行构建时学到的头号教训。正如我们努力保持系统和代码的简单,提示也应如此。与其为会议记录摘要生成器构建一个万能提示,不如将其分解成以下几个步骤:提取关键决策、行动项目和负责人并形成结构化格式 检查提取的细节与原始转录的一致性 从结构化细节生成简明摘要
结果是,我们将单一提示分解成了多个简单、专注且易于理解的提示。通过将它们拆分,我们现在可以单独迭代和评估每个提示。精心打造你的上下文词元
1.1.4 精心构建你的上下文词元
重新思考并质疑你对于实际需要发送给智能体的上下文数量的假设。像米开朗基罗一样,不要塑造你的上下文雕塑,而是凿掉多余的材料,直到雕塑显露出来。RAG是一种流行的方式来整理所有可能相关的大理石块,那你需要做什么来提取必要的内容呢?我们发现,将发送给模型的最终提示(包括所有上下文构建、元提示和RAG结果)放在空白页面上,然后仔细阅读,这确实能帮助你重新思考上下文。通过这种方法,我们发现了冗余、自相矛盾的语言和糟糕的格式等问题。另一个关键的优化是你的上下文结构。你的文档集合表示对人类没有帮助,也不要假设它对智能体有任何帮助。仔细考虑如何结构化你的上下文,以突显其各部分之间的关系,并使提取尽可能简单。除提示之外,通过在提示中提供知识来引导LLM的另一种有效方法是将其作为上下文提供给LLM,这样可以让LLM在提供的上下文中找到立足点,然后用于上下文学习。这被称为检索增强生成(RAG)。从业者发现,RAG在提供知识和改善输出方面非常有效,同时所需的努力和成本要少得多。1.2.1 RAG的质量取决于检索到的文档的相关性、密度和详细程度RAG的输出质量取决于检索到的文档质量,而这又取决于以下几个因素。
首先是最明显也是最重要的指标:相关性。这通常通过排名指标来量化,如平均倒数排名(Mean Reciprocal Rank, MRR)或归一化折扣累积增益(Normalized Discounted Cumulative Gain, NDCG)。MRR评估系统将第一个相关结果排在排名列表中的能力,而NDCG考虑所有结果的相关性及其位置。它们衡量系统将相关文档排名更高,将不相关文档排名更低的能力。例如,如果我们检索用户摘要以生成电影评论摘要,就会想将特定电影的评论排名更高,同时排除其他电影的评论。与传统的推荐系统类似,检索到的项目的排名将对LLM在下游任务中的表现产生重大影响。要评估影响,运行一个基于RAG的任务,但将检索到的项目进行打乱排列——RAG输出的表现如何?其次,我们还要考虑信息密度。如果两个文档相关度相等,我们会偏向更简洁、附带较少冗余细节的文档。回到我们的电影示例,从广义上讲,我们可能认为电影剧本和所有用户评论都是相关的。尽管如此,排名靠前的评论和编辑评论可能在信息密度上更高。最后,我们还要考虑文档中提供的详细程度。想象一下,我们正在构建一个从自然语言生成SQL查询的RAG系统。可以简单地提供包含列名的表模式作为上下文。但是,如果我们包含列描述和一些示例值呢?这些额外的细节可以帮助LLM更好地理解表的语义,从而生成更正确的SQL。1.2.2 不要忘记关键词搜索;将其作为baseline,并在混合搜索中使用
鉴于基于嵌入的RAG演示非常普遍,人们很容易忘记或忽视信息检索领域数十年来的研究和解决方案。嵌入无疑是一种强大的工具,但它并非万能。首先,尽管它们擅长捕捉高层语义相似性,但它们可能会在更具体的基于关键词的查询方面遇到困难,比如当用户搜索名称(例如,Ilya)、首字母缩略词(例如,RAG)或ID(例如,claude-3-sonnet)时。基于关键词的搜索,例如BM25就专门为此设计。经过多年的基于关键词的搜索,用户可能已经习以为常,如果他们期望检索的文档没有被返回,可能会感到沮丧。向量嵌入并不能奇迹般地解决搜索问题。事实上,在你使用语义相似性搜索重新排序之前的步骤才是关键。要真正改进BM25或全文搜索是很难的。——Perplexity.ai 首席执行官 Aravind Srinivas 我们已经向客户和合作伙伴传达这个观点好几个月了。使用简单嵌入的最近邻搜索会产生非常嘈杂的结果,你最好从基于关键词的方法开始。——ourcegraph 首席技术官 Beyang Liu 其次,通过关键词搜索更容易理解为什么会检索到某个文档——我们可以查看与查询匹配的关键词。相比之下,基于嵌入的检索不太具有可解释性。最后,由于诸如Lucene和OpenSearch等系统经过数十年的优化和考验,关键词搜索通常在计算上更加高效。在大多数情况下,混合方法效果最好:关键词匹配用于明显匹配,嵌入则用于同义词、上下位词和拼写错误,以及多模态(例如,图像和文本)。Shortwave分享了他们如何构建其RAG pipeline,包括查询重写、关键词+嵌入检索以及排名(https://www.shortwave.com/blog/deep-dive-into-worlds-smartest-email-ai/)。RAG和微调都可以用来将新信息整合到LLM中,并提高特定任务的性能。那么,我们应该先尝试哪种方法呢?最近的研究表明(https://arxiv.org/abs/2312.05934),RAG可能更具优势。一项研究将RAG与无监督微调(即持续预训练)进行了比较,在MMLU的一个子集和当前事件上对两者进行了评估。他们发现,无论是在训练期间遇到的知识点还是全新的知识点,RAG始终优于微调。在另一篇论文中(https://arxiv.org/abs/2401.08406),他们将RAG与农业数据集上的监督微调进行了比较。同样,RAG的性能提升大于微调,尤其是对于GPT-4(见论文表20)。除了提高性能外,RAG还带来了几个实际优势。首先,与持续预训练或微调相比,更容易保持检索索引的最新状态,也更便宜!其次,如果我们的检索索引中包含有毒或偏见内容的问题文档,简单地删除或修改这些有问题的文档即可。此外,RAG中的“R”为我们检索文档提供了更细粒度的控制。例如,如果我们为多个组织托管一个RAG系统,通过对检索索引进行分区,我们可以确保每个组织只能从自己的索引中检索文档。这确保了我们不会无意中将一个组织的信息暴露给另一个组织。随着Gemini 1.5提供高达1000万词元大小的上下文窗口,一些人开始质疑RAG的未来。我倾向于认为,Gemini 1.5被严重低估了。一个1000万词元的上下文窗口实际上使大多数现有的RAG框架变得不必要。你只需将数据放入上下文中,然后像平常一样与模型对话。想象一下,这对所有专注于RAG的初创公司/智能体/langchain项目的影响。或者用一句话说:1000万上下文杀死了RAG。Gemini干得好。——Yao Fu
虽然长上下文在分析多个文档或与PDF对话等用例上将会带来变革,但关于RAG消亡的传言被远远夸大了。首先,即使有1000万词元的上下文窗口,我们仍然需要一种方法来选择要输入模型的信息。其次,除了狭窄的“大海捞针(needle-in-a-haystack)”评估之外,我们还没有看到令人信服的数据,表明模型能够有效地对如此大的上下文进行推理。因此,如果没有良好的检索(和排名),我们有可能让模型被干扰信息淹没,或者甚至可能用完全无关的信息填满上下文窗口。最后,还有成本问题。Transformer的推理成本随着上下文长度的增加呈二次方(或空间和时间上的线性)增长。即使存在一个模型,它可能在回答每个问题之前读取整个组织的Google Drive内容,也并不意味着这是个好主意。就像我们使用RAM的方式:即使存在运行数十TB RAM的计算实例,我们仍然从磁盘读取和写入数据。所以,不要急于把你们的RAG扔进垃圾桶。即使上下文窗口的大小增加,这种模式仍将是有用的。为LLM设计提示只是个开始。要充分发挥它们的潜力,我们需要超越单一提示并采用workflow。例如,我们如何将一个复杂的任务分解为多个更简单的任务?微调或缓存何时有助于提高性能并减少时延/成本?在本节中,我们会分享一些行之有效的策略和真实世界的例子,以帮助你优化并构建可靠的LLMworkflow。1.3.1 逐步、多轮“flows”可以带来大幅提升
我们已经知道,通过将单个大提示分解为多个小提示,可以获得更好的结果。例如,AlphaCodium通过从单一提示切换到多步骤workflow,使GPT-4在CodeContests上的准确率(pass@5)从19%提升到了44%。workflow包括:反思问题 对公共测试进行推理 生成可能的解决方案 对可能的解决方案进行排名 生成合成测试 在公共和合成测试上迭代解决方案。
小任务具有明确目标,最适合作为智能体或流程提示。不要求每个智能体提示都请求结构化输出,但结构化输出对与系统交互非常有帮助。一些可尝试的方法:一个尽可能详细的明确计划步骤。考虑使用预定义的计划供选择。 将原始用户提示重写为智能体提示。注意,这一过程有信息丢失的风险! 智能体行为可以是线性链、DAG(有向无环图)和状态机;不同的依赖关系和逻辑关系在不同规模下可能更适用或更不适用。你能从不同的任务架构中挤出性能优化吗? 计划验证;你的计划可以包括如何评估其他智能体响应的指示,以确保最终组装协同工作良好。 具有固定上游状态的提示工程——确保你的智能体提示针对可能发生的各种情况进行评估。
虽然AI智能体可以动态响应用户请求和环境,但它们的不确定性使得部署变得具有挑战性。智能体的每一步都有失败的可能,而从错误中恢复的几率较低。因此,智能体成功完成多步骤任务的可能性随着步骤数量的增加而呈指数级下降。结果是,构建智能体的团队发现难以部署可靠的智能体。一种比较有前景的方法是让智能体系统生成确定性的计划,然后以结构化、可复制的方式执行。在第一步中,智能体根据高层次目标或提示生成一个计划。然后,按确定性地执行该计划。这使每一步都更可预测和可靠。其好处包括:
最成功的智能体构建者可能是那些在管理初级工程师方面具有丰富经验的人,因为生成计划的过程类似于我们指导和管理初级工程师。我们给初级工程师明确的目标和具体的计划,而不是模糊的开放式指示,我们对智能体也应该这样做。最终,构建可靠的工作智能体的关键可能在于采用更结构化、确定性的方法,并收集数据来优化提示和微调模型。如果没有这些,我们构建的智能体可能有时表现非常好,但平均而言,会令用户失望,导致用户留存率低下。假设你的任务需要LLM输出多样化的结果。也许你正在编写一个LLM pipeline,根据用户之前购买的产品列表推荐购买的新产品。当你多次运行提示时,可能会发现结果推荐过于相似,所以你可能会增加LLM请求中的温度参数。简而言之,增加温度参数会使LLM的响应更加多样化。在采样时,下一个词元的概率分布变得更平坦,这意味着通常不太可能的词元被选择的频率更高。然而,当增加温度时,你可能会注意到一些与输出多样性相关的失败模式。例如,目录中非常合适的某些产品可能永远不会被LLM输出。如果这些产品基于LLM在训练时学到的知识,很可能跟随提示出现,那么它们可能会在输出中过度呈现。如果温度太高,你可能会得到引用不存在的产品(或胡言乱语!)的输出。换句话说,提高温度并不能保证LLM就会从预期的概率分布(如均匀随机)中采样输出。不过,我们还有其他方法来提升输出的多样性。最简单的方法是调整提示中的元素。例如,如果提示模板中包含一个项目列表,如历史购买记录,每次将这些项目插入提示时打乱它们的顺序,就可以产生显著的效果。此外,保留一个近期输出的简短列表可以防止冗余。以我们推荐产品的例子为例,通过指示LLM以避免从这个近期列表中推荐项目,或者通过拒绝和重新采样与近期建议相似的输出,我们可以使模型的回答更加多样化。另一个有效策略是改变提示的措辞。例如,加入“选择一个用户经常会喜欢使用的项目”或“选择一个用户可能会推荐给朋友的产品”这样的短语,可以改变焦点,从而影响推荐产品的多样性。缓存可以节省成本并消除生成时延,因为不需要为相同的输入重新生成回答。此外,如果某个回答之前已经经过审查,我们便可以提供这些经过验证的回答,减少提供有害或不适当内容的风险。一种简单的缓存方法是为正在处理的项目使用唯一的ID,例如,假设我们正在总结新的文章或产品评论,当有请求进入时,我们可以检查缓存中是否已有摘要。如果有,我们可以立即回答;如果没有,我们便生成、审查并提供答案,然后将其存储在缓存中以供未来请求使用。对于更加开放式的查询,我们可以借鉴搜索领域的技术,该领域也利用缓存来处理开放式输入。自动补全和拼写校正等功能也有助于规范用户输入,提高缓存命中率。1.3.5 何时微调
我们可能会遇到一些更棘手的任务,即使绞尽脑汁地设计提问,模型也无法给出好的回答。例如,即使经过大量提示设计和优化,系统可能仍然无法给出可靠的高质量输出。如果是这样,那么可能有必要为特定的任务对模型进行微调。
尽管微调可能有效,但成本也很高。我们需要给微调数据、微调和评估模型加注释,最终让他们能自行托管。因此,需要考虑较高的前期成本是否值得。如果提示能做到90%,那么微调可能不值得投资。然而,如果我们决定进行微调,为降低收集人工注释数据的成本,我们可以在合成数据上进行生成与微调,或者利用开源数据来启动这一过程。1.4 评估与监控
评估LLM可能会充满挑战。模型输入和输出的是任意文本,我们给它们设定的任务也是多种多样的。尽管如此,严格且周密的评估至关重要——OpenAI的技术领导者们肯定不是随随便便评估工作并对各个评估给予反馈。评估LLM应用引发了各种相关的定义和方法:只是简单的单元测试,还是对系统内部运行状态和行为的能力进行观察和理解,还是可能只是数据科学。所有这些观点都有其作用。在接下来的部分中,我们提供了一些探索构建评估和监控流程中的重点经验教训。1.4.1 从实际输入/输出样本创建几个基于断言的单元测试
从生产环境中的输入和输出样本中创建一些单元测试(即断言),并以至少三个标准对输出的期望进行验证。虽然三个标准可能看起来有些随意,但这实际上是一个合理的起点;标准更少可能意味着任务定义不够清晰或过于开放,就像通用聊天机器人一样。这些单元测试或断言应该在流程发生任何更改时触发,无论是编辑提示、通过RAG添加新的上下文,还是其他修改。本文提供了一个基于断言的测试实例,适用于实际情况。我们可以考虑包含或排除响应的短语开始构建断言。还要考虑进行检查,确保单词、项或句子数量在一定范围内。对于其他类型的生成任务,断言可能会有所不同。执行评估是评估代码生成的一种强有力方法,我们可以在过程中运行生成的代码,并确定运行时状态是否足够满足用户请求。例如,如果用户请求一个名为foo的新函数;在执行智能体生成的代码后,foo应该是可调用的!执行评估的一个挑战是,智能体的代码会使运行时状态常常与目标代码略有不同。将断言放宽到任何可行答案都能满足最弱假设可能是有效的。最后,按照预期方式使用你的产品(即,“吃自己的狗粮(dogfooding)测试”)可以洞察真实世界上数据的故障模式。这种方法不仅有助于识别潜在的弱点,还提供了一个有用的实际生产样本来源,这样样本可以转化为评估(eval)案例。1.4.2 语言大模型可以作评判者(在某种程度上),但它并非解决所有问题的灵丹妙药
以LLM作评判者(LLM-as-Judge),即利用强大的LLM来评估其他模型的输出,一直受到一些人的怀疑(我们中的一些人最初也是极为怀疑的。)然而,当实施得当时,LLM作为评判者能够与人类判断产生良好的相关性,至少可以帮助建立关于新提示或技术表现的先验知识。具体来说,当进行成对比较(例如,对照组与实验组)时,LLM作为评判者可能会正确地选出哪个选项更好,但在判断胜利或失败的程度时可能会出现一些噪音。以下是一些帮助我们充分利用LLM作为评判者的价值的建议:使用成对比较:与其要求LLM对单一输出进行Likert(https://en.wikipedia.org/wiki/Likert_scale)量表评分,不如向其呈现两个选项,并要求其选择更好的一个。这往往会导致更稳定的结果。 控制位置偏差:呈现选项的顺序可能会影响LLM的决策。为了减轻这种影响,每次进行成对比较时都要交换顺序。只是在交换后一定要确保将胜利归因给正确的选项! 允许平局:在某些情况下,两个选项可能同样好。因此,允许LLM宣布平局,这样它就不必任意选择一个赢家了。 使用思维链:在给出最终偏好之前,要求LLM解释其决策可以提高评估的可靠性。而额外的好处是,我们可以使用较弱但更快的LLM,并且仍能获得类似的结果。因为这部分在流程中通常处于批处理模式,思维链的额外时延并不是问题。 控制回答长度:LLM倾向于更长的回答。为了减轻这种影响,确保回答对在长度上类似。
LLM作为评判者的一个十分强大的应用是检查新的提示策略是否与回归相符。如果已经追踪了一系列生产结果,有时可以使用新的提示策略重新运行这些生产示例,并使用LLM作为评判者快速评估新策略可能出现问题的地方。下列示例是一个简单但有效的LLM作为评判者迭代的方法,我们只需记录LLM的回答、评判的评论(即思维链)和最终结果。然后与利益相关者一起审查,以确定改进的方向。经过三次迭代,人类和LLM的一致性从68%提高到了94%!LLM作评判者并非万能之策。即使是最强大的模型在评估语言的微妙之处时也可能失败。此外,我们发现,与LLM作评判者相比,传统的分类器和奖励模型可以实现更高的准确性,并且成本和时延更低。对于代码生成,LLM作为评判者可能比执行评估等更直接的评估策略要弱。1.4.3 评估生成结果的“实习生测试”
在评估生成结果时,我们喜欢使用以下的“实习生测试”:如果将完全相同的输入给予语言模型,包括上下文,并将其作为一个任务交给相关专业的普通大学生,他们能够成功吗?需要多长时间?- 如果因为LLM缺乏必要的知识而失败,那么要考虑丰富上下文。
- 如果无法完成,并且我们无法通过改进上下文来解决问题,那么我们可能遇到了对于当代LLM来说过于困难的任务。
- 如果可以完成,但可能需要一段时间,我们可以尝试减少任务的复杂性。是否可以分解?任务的某些方面是否可以更模板化?
- 如果可以完成,他们可以很快理解,那么是时候深入数据了。模型出了什么问题?我们能否找到失败的模式?尝试在模型回答之前或之后要求其解释,以帮助建立对模型内部机制的理解。
1.4.4 过分强调某些评估可能会损害整体性能
“当一个衡量指标成为目标时,它就不再是一个好的衡量指标。” — 古德哈特定律。 其中一个例子是“大海捞针”(Needle-in-a-Haystack,简称NIAH)评估。最初的评估有助于量化模型在上下文大小增加情况下的召回率,以及召回率如何受到“针”的位置影响。然而,这一评估已经被过分强调,以至于在Gemini 1.5的报告中被列出(https://arxiv.org/abs/2403.05530)。该评估涉及将特定短语(“特殊的魔法{城市}数字是:{数字}”)插入到重复Paul Graham散文的长文档中,然后提示模型回忆魔法数字。虽然一些模型实现了几乎完美的召回率,但值得质疑的是NIAH是否真正反映了现实世界应用中所需的推理和回忆能力。我们可以考虑一个更实际的场景:给定一个时长为一小时的会议记录,LLM是否能够总结关键决策和下一步行动,并正确地将每一项归因给相关的人员?这个任务更为现实,超越了死记硬背,还考虑了解析复杂讨论、识别相关信息和综合摘要的能力。以下是一个实际的NIAH评估示例。使用医生和患者视频通话的记录,我们询问LLM关于患者用药的情况。它还包括一个更具挑战性的NIAH测试,例如随即插入一个短语,描述制作完美披萨的秘密配料,例如:“制作完美披萨所需的秘密配料是:浸泡过浓缩咖啡的枣、柠檬和羊奶酪。”在药物信息的识别任务上,召回率大约为80%,而在披萨配料识别的非相关任务上,召回率则约为30%。另外,过分强调NIAH评估可能会降低提取和总结任务的效果。因为这些模型被精细微调过,以注意到每个句子,它们可能将无关紧要的细节和干扰因素视为重要内容,并将其包含在最终输出中(尽管不应该如此)!这也可能适用于其他评估和用例,例如,文本总结。对事实的一致性的强调可能导致总结内容变得不够具体(因此可能导致事实层面的不一致),可能也不够相关。相反,对写作风格和修辞的强调可能会导致更花哨、更具市场性的语言,这可能会导致事实上的不一致性。1.4.5 将注释简化为二元任务或成对比较
在Likert量表上为模型输出提供开放式反馈或评级是一项认知负担较重的任务,因此,由于人类评分者之间的差异性,收集的数据更加繁杂,并且数据的实用性较低。更有效的方法是简化任务,并减轻注释者的认知负担。二元分类和成对比较是两个效果良好的任务。在二元分类中,注释者被要求对模型的输出进行简单的肯定或否定判断。他们可能会被要求判断生成的摘要是否与源文档在事实上一致,或者所提出的回复是否相关,是否包含有害内容。与Likert量表相比,二元决策更加精确,评分者之间的一致性和通过率更高。这就是Doordash设置他们的标记队列的方法,通过一系列是-否问题来标记菜单项。在成对比较中,注释者会收到一对模型回答,并从中选择更好的回答。因为人类更容易说“A比B更好”而不是给A或B分配一个单独的评分,所以这导致了更快速和更可靠的注释(相比于Likert量表)。在Llama2的一次聚会上,Llama2论文的作者之一Thomas Scialom确认,成对比较比收集监督微调数据(如书面回复)更快速、更便宜。前者的成本是每个单位3.5美元,而后者的成本是每个单位25美元。如果你打算编写标注指南,以下是一些来自谷歌和必应搜索的参考指南。1.4.6 (无参考)评估和防护措施可以互相替代使用
防护措施有助于捕捉不适当或有害的内容,而评估则有助于衡量模型输出的质量和准确性。在无参考评估的情况下,它们是密切相关的。无参考评估是一种评估方法,它不依赖于“黄金”参考,比如人类编写的答案,而是仅根据输入提示和模型的回答来评估输出的质量。这其中有一些例子是总结评估,我们只需考虑输入文档,以评估摘要的事实一致性和相关性。如果摘要在这些指标上得分较低,我们可以选择不将其展示给用户,实际上将评估用作防护措施。同样,无参考翻译评估可以评估翻译质量,而无需人工翻译的参考,使我们能够将其用作防护措施。与LLM合作的一个关键挑战是,它们经常会生成输出,即使这样做并不合适。这可能导致无害但毫无意义的回答,或者更严重的缺陷,如有害或危险的内容。例如,当要求从文档中提取特定属性或元数据时,LLM可能会自信地返回值,即使这些值实际上并不存在。另外,当我们提供非英语文档的情况下,模型可能会以非英语的语言给出回答。虽然我们可以尝试提示LLM给出“不适用”或“未知”的回答,但这并不是万无一失的。即使对数概率可用,它们也是输出质量的一个很差的指标。尽管对数概率表明了在输出中出现一个词元的可能性,但它们并不一定能反映生成文本的正确性。相反,对于经过指令微调的模型,它们是经过训练以回答查询并生成连贯回答的,对数概率可能不太准确。因此,尽管高的对数概率可能表示输出流畅且连贯,但这并不意味着它是准确或相关的。虽然精心设计的提示设计和优化可以在一定程度上有所帮助,但我们应该将其与强大的防护措施相结合,以检测和过滤/重新生成不希望的输出。例如,OpenAI提供了一个内容审核API,可以识别不安全的回答,如仇恨言论、自残或性内容。同样,也有许多用于检测个人可识别信息(PII)的软件包。这样做的其中一个好处是,防护措施在很大程度上与用例无关,因此,可以广泛应用于给定语言的所有输出。此外,通过精确检索,我们的系统可以确定性地在没有相关文档的情况下回复“我不知道”。一个相关的问题是,LLM可能在我们预期其输出时未能产生输出。这可能是各种原因导致的,无论是API提供商的长尾时延还是输出被内容审核过滤器阻止等。因此,对于调试和监控,始终记录输入和(可能缺乏的)输出是非常重要的。不同于广受关注且很少发生的内容安全或PII缺陷,事实不一致现象一直都存在,并且更难以检测。它们更常见,在基线率为5 - 10%的情况下发生。根据我们从LLM提供商那里了解到的情况,即使在简单的任务(如总结)中,要将其降至2%以下也很具挑战性。为了解决这个问题,我们可以结合提示设计与优化(生成前)和事实不一致的防护措施(生成后)。对于提示设计优化,诸如CoT之类的技术通过要求LLM在最终返回输出之前解释其推理过程来减少幻觉。然后,我们可以应用事实不一致的防护措施来评估摘要的事实性,并过滤或重新生成幻觉。在某些情况下,幻觉可以被确定地检测到。当使用来自RAG检索的资源时,如果输出是结构化的并且识别了资源是什么,你应该能够手动验证它们是否来自输入的上下文。2运营:日常关注与组织关注
2.1 数据
就像食材的质量决定了菜肴的味道一样,输入数据的质量限制了机器学习系统的性能。此外,输出数据是判断产品是否有效的唯一途径。所有创作者都要紧密关注数据,每周花费数小时查看输入和输出,以更好地了解数据分布:其模式、边缘案例以及模型的局限性。传统机器学习流水线中常见的错误是训练-服务(serve)偏差。这种情况发生在训练中使用的数据与模型在生产中遇到的数据不同的情况下。虽然我们可以在没有训练或微调的情况下使用LLM而没有训练集,但开发-生产数据偏差也会出现类似的问题。基本上,在开发过程中测试系统的数据应该反映出系统在生产中将要面对的情况。如果不是这样,我们可能会发现我们的生产准确性受到影响。LLM的开发-生产偏差可以分为两种类型:结构性偏差和内容性偏差。结构性偏差包括格式不一致的问题,例如JSON字典与列表类型值之间的差异、大小写不一致以及拼写错误或句子片段等。这些错误可能导致模型性能不可预测,因为不同的LLM是针对特定数据格式进行训练的,而提示可能对细微变化非常敏感。内容性或“语义性”偏差指的是数据的意义或上下文的差异。与传统机器学习一样,定期测量LLM输入/输出对之间的偏差是很有用的。简单的度量标准,如输入和输出的长度或特定格式要求(例如JSON或XML),是跟踪变化的简单方法。对于更“高级”的漂移检测(drift detection),我们可以考虑将输入/输出对的嵌入进行聚类,以检测语义漂移,例如用户讨论主题的变化,这可能表明他们正在探索模型之前没有接触过的领域。在测试更改(例如提示设计优化)时,确保保留数据集是最新的,并反映了最近的用户交互类型。例如,如果生产输入中常见拼写错误,则在保留数据中也应该存在。除了数值偏差测量之外,对输出进行定性评估也是很有用的。定期审查模型的输出,也就是“氛围检查(vibe checks)”,可以确保结果与期望一致,并保持与用户需求相关。最后,将非确定性纳入偏差检查也很有用——通过对测试数据集中对每个输入多次运行pipeline并分析所有输出,我们更有可能捕获偶尔发生的异常情况。2.1.2 每天查看LLM输入和输出的样本
LLM是动态的,不断发展的。尽管它们具有惊人的0-shot能力,能输出优秀的内容,但它们的故障模式可能非常难以预测。对于自定义任务,定期检查数据样本对于直观理解LLM的表现至关重要。来自生产环境的输入-输出对是LLM应用的“真实事物、真实场景”(genchi genbutsu),它们是无法替代的。最近的研究强调,随着开发人员与更多数据进行交互,他们对于什么构成“好”的和“坏”的输出的认识会发生变化(即标准漂移)。虽然开发人员可以提前确定一些用于评估LLM输出的标准,但这些预定义的标准通常是不完整的。例如,在开发过程中,我们可能会更新提示以增加获得优质回答的概率并减少获得欠优回答的概率。评估、重新评估和标准更新的迭代过程是必要的,因为在没有直接观察到输出的情况下,预测LLM行为或人类偏好是十分困难的。为了有效管理这一点,我们应该记录LLM的输入和输出。通过每天检查这些日志的样本,我们可以快速识别并适应新的模式或故障模式。当我们发现新问题时,我们可以立即撰写一个相关的断言或评估。与此类似,对故障模式定义的任何更新都应该反映在评估标准中。这些“氛围检查”是欠优回答的信号;代码和断言对其进行操作。最后,这种方法态度应该被更多的社群或团队接受、采纳,例如将对输入和输出的审核或注释添加到值班轮换的任务中。借助语言大模型的API,我们可以从几家供应商那里获取智能支持。这无疑是一大优势,但同时也意味着需要在性能、时延、吞吐量和成本方面做出权衡。此外,鉴于过去一年几乎每个月都有更先进、更强大的模型推出,我们应当随时准备随着旧模型的淘汰和新模型的迁移来更新我们的产品。在本节中,我们分享了使用无法完全控制的技术的经验教训,这些模型无法自行托管和管理。2.2.1 生成结构化输出以简化后续集成
在大多数实际应用场景中,LLM的输出需要以某种机器可读的格式被下游应用程序所使用,例如,房地产客户关系管理系统ReChat,它需要结构化的响应来在前端渲染小部件,Boba是一个用于生成产品策略创意的工具,需要具有标题、摘要、可信度评分和时间范围等字段的结构化输出。LinkedIn也分享了他们如何限制LLM生成YAML格式的数据,这些数据随后用于决定使用哪种技能,以及提供调用技能所需的参数。这种应用模式是对Postel原则的极致演绎:在接受输入时应该宽容(接受任意的自然语言),在发送输出时应该保守(发送类型化、机器可读的对象)。我们预期这种模式将非常持久。目前,Instructor(https://github.com/jxnl/instructor)和Outlines(https://github.com/outlines-dev/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 确定并固定模型版本
在机器学习流程中,任何变更都可能影响整个系统(changing anything changes everything)。这一点在我们依赖于外部训练的语言大模型时尤其重要,因为这些模型可能会未知的情况下发生变化。幸运的是,许多模型供应商允许用户“固定”特定版本的模型(如gpt-4-turbo-1106),确保模型权重保持不变。在生产环境中固定模型版本有助于避免因模型更换而导致的意外行为变化,这可能会引起客户对输出过于冗长或其他不可预见问题的关注。此外,建议维护一个与生产环境设置相同但使用最新模型版本的shadow pipeline。这有助于安全地进行新版本的实验和测试。一旦验证了新模型的稳定性和输出质量后,就可以自信地在生产环境中更新模型版本。开发新应用时,人们往往会倾向于使用最大、最强的模型,但一旦确定任务在技术上是可行的,就值得尝试是否能用更小的模型达到相似的结果。较小模型的优势在于更低的时延和成本,尽管其性能可能较弱,但通过思维链(chain-of-thought)、n次提示和上下文学习等技术,可以帮助小型模型发挥更大的作用。除LLM API之外,针对特定任务进行微调也能提高性能。综合考虑,通过精心设计的workflow,较小的模型通常可以匹配甚至超越单一大型模型的输出质量,同时速度更快、成本更低。例如,这条推文(https://twitter.com/mattshumer_/status/1770823530394833242)分享了Haiku加10次提示的性能超过了零次提示的Opus和GPT-4的案例。长远来看,我们期望看到更多以小模型为输出质量、时延和成本优化平衡的流工程(flow-engineering)实例。以分类任务为例,DistilBERT(6700万参数)等轻量级模型是一个令人惊讶的强大基准。参数为4000万的DistilBART也是一个极好的选择,在开源数据上进行微调后,它能够以0.84的ROC-AUC识别幻觉,性能超过大多数LLM,而时延和成本却不到它们的5%。关键是,不要忽视小型模型。虽然用庞大的模型解决每个问题很容易,但通过一些创造性实验,我们通常可以找到更高效的解决方案。2.3 产品
尽管新技术带来了新机遇,但创造卓越产品的原则始终不变。因此,即便我们首次面对新问题,也无需在产品设计上从头开始。将LLM应用开发建立在坚实的产品原则上,就可以确保我们为用户提供真正的价值。2.3.1 尽早持续设计
设计师的参与将促使你深入思考如何向用户构建和呈现产品。我们有时会错误地认为设计师只是对事物进行美化,但实际上除用户界面之外,他们还重新思考了如何改善用户体验,即使这意味着打破现有规则和范式。设计师十分擅长将用户需求转化为多种形式,其中一些形式可能更容易解决,从而为AI解决方案提供了更多的可能性。与开发其他产品一样,AI产品的开发也应以用户需求为中心,而非单纯依赖驱动它们的技术。要始终自问:“用户希望产品为他们完成什么任务?聊天机器人是否适合完成这项任务?自动补全功能怎样?或者有其他更合适的解决方案?”同时,要考虑现有的设计模式与用户需求之间的关系。这些是设计师为团队能力带来的宝贵资产。2.3.2 为人类参与循环设计用户体验
获取高质量标注的一种方式是将人类参与循环(Human-in-the-Loop, HITL)整合到用户体验(UX)中。通过让用户轻松提供反馈和更正,我们可以提升即时输出,并收集宝贵数据来改进模型。假设有一个电子商务平台,用户可以上传并分类他们的产品。设计用户体验的方式如下:
尽管这三种方法都涉及LLM,但它们提供了非常不同的用户体验。第一种方法将初始负担放在用户身上,并将LLM作为后处理检查。第二种方法不需要用户的任何努力,但不提供透明度或控制权。第三种方法找到了正确的平衡点,通过让LLM提前建议类别,我们减轻了用户的认知负担,他们不必学习我们的分类体系以分类产品!同时,通过允许用户审查和编辑建议,他们对产品如何分类有最终决定权,将控制权牢牢掌握在用户手中。作为额外收益,第三种方法为模型改进创造了自然的反馈循环。好的建议被接受(正标签),不好的建议被更新(先标记为负标签,随后再正标签以示改进)。建议、用户验证和数据收集的这种模式在以下几个应用中十分常见:编码助手:用户可以接受建议(强正反馈)、接受并微调建议(正反馈),或忽略建议(负反馈)。 Midjourney:用户可以选择放大并下载图片(强正反馈)、变更图片(正反馈),或生成一组新图片(负反馈)。 聊天机器人:用户可以对回答点赞(正反馈)或点踩(负反馈),或者如果回答非常糟糕,选择重新生成回答(强负反馈)。
反馈可以是显式的或隐式的。显式反馈是用户对我们产品请求的响应所提供的信息;隐式反馈是我们从用户互动中学到的信息,无需用户特意提供反馈。编码助手和Midjourney是隐式反馈的例子,显式反馈的例子是点赞和点踩。如果我们像编码助手和Midjourney那样设计好用户体验,就可以收集大量隐式反馈来改进我们的产品和模型。2.3.3 严格确定需求优先级
在考虑将demo转化为实际应用时,我们必须思考以下需求:
如果我们试图一次性解决所有需求,将永远无法推出产品。因此,我们需要进行严格的需求优先级排序。这意味着要明确什么是不可妥协的(例如,可靠性和安全性),没有这些,我们的产品将无法正常运作或不具备可行性。关键在于识别出最小可行产品。我们必须认识到第一版产品不可能是完美的,应该先发布产品,然后通过迭代来不断完善。在选择语言模型和确定应用审查的严格程度时,要考虑应用场景和目标受众。对于面向客户的聊天机器人,如果提供医疗或财务咨询,我们需要设定极高的安全和准确度标准,错误或不良输出可能导致实际伤害并损害信任。然而,对于不那么关键的应用,例如推荐系统,或者面向内部的应用如内容分类或摘要,过于严格的要求只会拖慢进度而不会带来太多额外价值。这与a16z最近的一份报告(https://a16z.com/generative-ai-enterprise-2024/)相符,该报告显示许多公司在内部LLM应用方面比外部应用发展得更快。通过在内部生产力提升上实验AI,组织可以在更受控的环境中开始捕获价值,并学习如何管理风险。随着信心的增强,他们可以逐步扩展到面向客户的用例。企业在内外部应用场景中使用语言大模型的比例(来源:a16z report)。在这个新领域中,工作职能往往难以界定,但编写职位描述尤具挑战性。我们将不采用职位名称的交集图,也不提供职位描述建议。然而,我们将提出一个新的角色——AI工程师——并讨论其角色定位。重要的是,我们将讨论团队的其他成员以及职责应如何分配。2.4.1 关注流程而非工具
面对LLM等新范式,软件工程师往往倾向于关注工具。因此,我们可能会忽略工具本应解决的问题和流程,这样会导致许多工程师无意中接受了额外的复杂性,这对团队的长期生产力产生了负面影响。例如,这篇文章(https://hamel.dev/blog/posts/prompt/)讨论了某些工具如何自动为LLM创建提示。它认为(我个人认为正确)工程师如果不先理解解决问题的方法或流程,就使用这些工具,最终会承担不必要的技术债务。除偶然的复杂性,工具的规格也通常不明确。例如,有一个不断增长的LLM评估工具行业,提供“即插即用的LLM评估”解决方案,包含针对有害性、简洁性、语气等的通用评估器。我们看到许多团队在没有批判性思考其领域特定故障模式的情况下采用了这些工具。与此相反的是EvalGen,它专注于通过让用户深入参与每一步(从指定标准到标记数据,再到检查评估)来教用户创建领域特定评估的过程。软件引导用户完成如下的workflow:引自“Shankar, S., et al. (2024). Who Validates the Validators? Aligning LLM-Assisted Evaluation of LLM Outputs with Human Preferences”,https://arxiv.org/abs/2404.12272EvalGen引导用户遵循制作LLM评估的最佳实践,即:定义领域特定的测试(从提示自动引导生成)。这些定义为代码断言或以LLM作为评判者。 对齐测试与人类判断的重要性,以便用户可以检查测试是否捕捉到指定的标准。 随着系统(提示等)的变化,对测试进行迭代。
EvalGen为用户提供了一个评估构建流程的心理模型,而不是将他们锚定在特定工具上。我们发现,在为AI工程师提供了这种上下文之后,他们通常会选择更简洁的工具或自行构建。LLM的组成部分远不止提示编写和评估,这里无法一一详尽列出。然而,重要的是在采用工具之前,AI工程师需要寻求理解流程。2.4.2 持续实验
机器学习产品与实验是密不可分的。这不仅包括A/B测试、随机对照试验等方法,还包括频繁地对系统最小单元的修改尝试以及进行离线评估。人们之所以如此重视评估,并不是因为它们关乎信任和信心,而是因为它们能够支持实验的进行!评估系统越完善,实验迭代的速度就越快,从而能够更快地找到系统的最佳版本。现在尝试用不同方法解决同一问题变得很常见,因为实验的成本已经大大降低。收集数据和训练模型的高昂成本被降至最低——提示工程的成本主要就是人力时间。确保团队中的每个人都了解提示工程的基础知识,这可以鼓励大家进行实验,并从组织的不同部门带来多样化的想法。此外,实验不仅仅是为了探索,也要利用它们进行开发!如果已经有了新任务的工作版本,建议让团队中的其他人采用不同的方法来处理,尝试寻找更快的解决方案。探索使用思维链(Chain-of-Thought)或少样本(Few-Shot)等提示技术来提升质量。不要让现有工具阻碍实验的进行;如果存在阻碍,就应该重新构建,或者购买更好的工具来提升实验效率。最后,在进行产品/项目规划时,要为构建评估系统和运行多个实验预留时间。在制定工程产品规格时,除了产品特性,还应该明确评估标准。在制定发展蓝图时,不要低估实验所需的时间——在产品获得生产许可之前,预计要经过多轮开发和评估迭代。2.4.3 让团队成员都能掌握并运用人工智能新技术随着生成式人工智能技术的广泛应用,我们期望团队中的每一位成员——而不仅仅是技术专家——都能够理解并有信心使用这项新兴技术。要培养对语言大模型工作机制的直观理解,例如它们的时延、故障模式和用户体验,最好的方法就是亲自实践。LLM的使用门槛相对较低:你无需编程技能即可改进流程性能,每个人都可以通过提示工程和评估工作贡献自己的力量。教育是实现这一目标的关键。可以简单到从提示工程的基础知识开始,如n-shot提示和思维链(CoT)等技术,这些技术有助于引导模型产生期望的输出。懂行的人还可以进一步教授技术性更强的内容,比如LLM本质上是自回归的。换句话说,尽管输入词元是并行处理的,但输出词元是顺序生成的。因此,在设计用户体验和设定性能预期时,需要认识到时延更多地取决于输出长度而非输入长度。我们还可以通过提供实践实验和探索机会来进一步促进学习,比如举办黑客马拉松。虽然看似让整个团队在探索性项目上花几天时间的成本较为高昂,但却可能带来意外之喜。通过黑客马拉松,有一个团队大约在一年的时间内,完成了未来三年的工作规划。另一个团队通过黑客马拉松实现了用户体验的范式转变,现在因为LLM这些体验成为了可能,其优势将持续到未来几年。2.4.4 避免过度依赖AI工程
随着新职位的出现,人们往往会过分夸大这些职位的能力。随着这些职位的实际工作范围变得清晰,公司常常会经历一个痛苦的纠正过程。无论是新入行者还是招聘经理,都可能对这些职位提出过高的要求或抱有不切实际的期望。过去十年的典型案例如下:
最初,许多人认为数据科学家足以单独承担数据驱动项目。然而,事实很快就证明,数据科学家必须与软件和数据工程师协作,才能有效开发和部署数据产品。这种误解在AI工程师这一职位上再次出现,有些团队误以为只要有了AI工程师就万事大吉,但实际上,构建机器学习或AI产品需要多种专业角色的共同努力。在咨询了十多家AI产品公司后,我们发现他们经常陷入“AI工程师即所需的一切”这一误区。因此,它们的产品往往难以从demo阶段过渡到更大规模的应用,因为公司忽视了构建产品的关键要素。例如,为了将产品规模化,评估和测量至关重要,而这正是机器学习工程师擅长的领域,如果团队仅由AI工程师组成,那么很可能缺乏这方面的技能。共同作者Hamel Husain在他最近关于检测数据漂移和设计特定领域评估方法的研究中,强调了这些技能的重要性。以下是在构建AI产品过程中,你需要的各类角色及时间顺序:- 首先,集中精力构建产品。这可能需要AI工程师,但并非必须。AI工程师在产品原型设计和快速迭代(如用户体验和基础架构)方面非常有价值。
接下来,通过构建系统和数据收集来打好基础。根据数据的类型和规模,可能需要平台工程师或数据工程师。同时,必须有系统能够查询和分析这些数据,以便于调试问题。 最后一步是优化AI系统。这不一定意味着要训练模型。基本工作包括设计指标、构建评估系统、运行实验、优化RAG检索、调试随机系统等。机器学习工程师在这方面非常擅长,不过AI工程师也可以学会这些技能。通常,在完成上述步骤之前,雇佣机器学习工程师是没有意义的。
除此之外,整个过程都需要领域专家的参与。在小公司,理想情况下是创始团队;在大公司,产品经理可以扮演这一角色。了解角色的发展和时机非常关键。错误的时间招聘错误的人(例如,过早招聘机器学习工程师)或以错误的顺序构建产品是在浪费时间和金钱,并会导致团队动荡。此外,在第1-2阶段定期咨询机器学习工程师(而不是全职雇佣)可以帮助公司正确地打好基础。3策略:利用LLM构建产品,而不是被操纵
成功的产品需要深思熟虑的规划以及优先排序,而不是无休止的原型开发或追随最新的模型发布或趋势。在最后一节中,我们将展望未来,探讨构建出色AI产品的战略考量。我们还将探讨团队面临的关键权衡,如何时构建、何时购买,并提出了一份早期LLM应用开发策略的“操作手册”。
3.1 在PMF之前不要使用GPU
要成为出色的产品,需要的不仅仅是对其他API的简单包装。但相反方向的错误可能代价更大。过去一年,大量风险投资,包括令人瞠目的60亿美元A轮融资,被用于训练和定制模型,却没有清晰的产品愿景或目标市场。本节我们将解释为什么立即跳到训练自己的模型是错误的行为,并探讨自托管的作用。
3.1.1 从头训练(几乎)从来没有意义
对于大多数组织来说,从头开始预训练一个LLM是不切实际的,它会分散构建产品的注意力。
尽管这听起来很令人兴奋,看起来其他人好像都在做,但开发和维护机器学习基础设施需要大量的资源。其中包括收集数据、训练和评估模型以及部署。如果你仍在验证产品市场契合度,这些将分散开发核心产品的资源。即便你拥有计算能力、数据和技术能力,预训练的LLM也可能在几个月内就过时。
例如BloombergGPT,这是一个专门为金融任务训练的LLM。该模型由四名AI工程师和五名ML产品与研究人员通过预训练3630亿token完成。尽管如此,BloombergGPT在这些任务上仍在一年内被gpt-3.5-turbo和gpt-4超越。
这个故事和其他类似的故事表明,对于大多数实际应用,从头开始预训练一个LLM,即使是在特定领域数据上,也不是资源的最佳利用方式。相反,团队最好是对他们特定需求的最佳开源模型进行微调。
当然也有例外。一个典型的例子是Replit的代码模型,专门为代码生成和理解而训练。通过预训练,Replit能够超越其他更大尺寸的模型,如CodeLlama7b。但随着其他越来越强大的模型发布,维持其实用性需要持续的投资。
3.1.2 在证明必要之前不要微调
对于大多数组织来说,微调更多是出于FOMO(fear of missing out)而不是清晰的战略思考。
组织在微调上投资过早,试图击败“只是另一种套壳”的指责。但实际上,微调是重型机械活,只有在收集了大量示例并确信其他方法不足时才应部署。
一年前,许多团队告诉我们他们对微调很感兴趣。但很少有人找到产品市场契合度(PMF),大多数人后悔他们的决定。如果你要进行微调,最好非常确信已经准备好随着基础模型的改进而不断地微调——参见下面的“模型不是产品”和“构建LLMOps”。
什么时候微调实际上是正确的选择?如果使用案例需要现有模型训练所用的大规模开放网络数据集中没有的数据——并且如果你已经构建了一个MVP,证明现有模型的不足。但要小心:如果模型构建者无法轻松获得优秀的训练数据,你又从哪里获得?
LLM驱动的应用程序并非是科学展览项目。对它们的投资应该与它们对企业战略目标和竞争差异化的贡献相称。
3.1.3 从推理API开始,但不要害怕自托管
有了LLM API,初创公司就比以往更容易采用和集成语言建模功能,而无需从头开始训练自己的模型。像Anthropic和OpenAI这样的供应商提供通用API,只需几行代码就可以将智能融入你的产品。通过使用这些服务,可以减少所花费的精力,转而专注于为客户创造价值——这使你能够更快地验证想法并迭代PMF。
但就像数据库一样,托管服务并不适合所有使用案例,特别是随着规模和需求的增加。事实上,自托管可能是在不将机密/私有数据发送出你的网络的情况下使用模型的唯一方式,如医疗和金融等受监管行业所要求的,或由合同义务或保密要求所需。
此外,自托管规避了推理供应商施加的限制,如速率限制、模型弃用和使用限制。此外,自托管让你能够完全控制模型,使构建差异化的高质量系统变得更容易。最后,自托管,特别是微调,可以大规模降低成本。例如,Buzzfeed分享了他们如何微调开源LLM,降低了80%的成本。
3.2 迭代以至卓越
为了在长期内保持竞争优势,你需要超越模型,考虑什么将使你的产品脱颖而出。尽管执行速度很重要,但它不应该是你唯一的优势。
3.2.1 模型不是产品,其周围的系统才是
对于不构建模型的团队来说,快速的创新步伐是一大优势,因为他们从一个SOTA模型迁移到下一个,追求上下文大小、推理能力和性价比的提升,以构建更好的产品。这种进步既令人兴奋又可预测。总的来说,这意味着模型可能是系统中最不持久的组件。
相反,应该将你的精力集中在提供持久价值的组件上,如:
评估:可靠地测量任务在不同模型上的性能 防护措施:无论如何,防止模型产生不良输出 缓存:通过避免使用模型来减少时延和成本 数据飞轮:推动上述所有内容的迭代改进
这些组件比原始模型功能创建了更厚的产品质量护城河。
但这并不意味着在应用层构建没有风险。不要将你的精力集中在OpenAI或其他模型供应商需要解决的问题上,如果他们想提供可行的企业软件。
例如,一些团队投资于构建自定义工具以验证专有模型的结构化输出;在这里,尽可能少的投资很重要,但深入的投资并不能充分利用时间。OpenAI需要确保当你请求一个函数调用时,会得到一个有效的函数调用——因为这是所有客户都需要的。可以在这里采取一些“战略性拖延”,构建你所绝对需要的内容,并等待提供商能力的明显扩展。
3.2.2 从小处着手建立信任
构建一个试图满足所有人需求的产品是不可能的。为了创造引人注目的产品,公司需要专注于构建能够吸引用户反复使用的粘性体验。
例如一个通用的RAG系统,旨在回答用户可能问的任何问题缺乏专业化意味着系统无法优先处理最新信息、解析特定领域的格式或理解特定任务的细微差别。结果,用户得到了一次浅薄、不可靠的体验,无法满足他们的需求,导致用户流失。
为了解决这个问题,需要专注于特定领域和使用案例。通过深入而不是宽泛来缩小范围。这将创建与用户产生共鸣的特定领域工具。专业化还可以让你公开自己系统的能力和限制。清晰地说明系统能做什么、不能做什么,这显示出自我意识,帮助用户理解它在哪些方面可以增加最多的价值,从而建立对输出的信任和信心。
3.2.3 更快的迭代是构建LLMOps的正确动因
DevOps的根本目的并不是可复现的工作流程、左移策略(即尽早进行测试和安全检查)或给两个小团队赋能——更不是为了编写YAML文件。
DevOps的真正目的是缩短工作与其结果之间的反馈周期,不断改进而不是不断犯错。其根源可以追溯到精益创业运动,通过精益制造和丰田生产系统,强调单分钟换模(Single Minute Exchange of Die,SMED)和持续改进(Kaizen)。
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机器学习是一种基于人类专家确保ML模型按预期行为的范式。虽然有关联,但这里我们提出的是更微妙的东西。LLM驱动的系统目前不应该是大多数工作流程的主要驱动者,它们只是资源。
通过以人为中心,询问LLM如何支持他们的工作流程,产品和设计决策会有显著的不同。最终,它将推动你开发出不同于竞争对手的产品,这些竞争对手试图将所有责任迅速转移给LLM;而你的产品将更好、更有用和风险更低。
3.3 从提示、评估和数据收集开始
前几节已经提供了很多技术和建议,有很多需要消化的内容。现在让我们考虑一套最低限度的有用建议:如果一个团队想要构建LLM产品,应该从哪里开始?
在过去的一年里,我们已经看到成功的LLM应用遵循一致的轨迹。在本节中,我们将探索这个基本的“入门”手册。核心思想是从简单开始,只在必要时增加复杂性。一个好的经验法则是,每个复杂度级别通常需要比前一个多一个数量级的努力。考虑到这一点…
3.3.1 从提示设计优化开始
提示设计优化是第一步。使用我们在前面战术部分讨论的所有技术。思维链、n-shot示例、结构化输入和输出几乎总是有用的。在尝试从性能较弱的模型中“挤出”性能之前,先使用最强大的模型进行原型设计。
只有当提示设计优化无法达到所需的性能水平时,才应考虑微调。如果存在阻碍使用专有模型并因此需要自托管的非功能性要求(例如,数据隐私、完全控制、成本),这种情况会更频繁地出现。确保这些相同的隐私要求不会阻止你使用用户数据进行微调!
3.3.2 构建评估体系,启动数据飞轮
即便是刚刚起步的团队,评估也是不可或缺的。没有评估,我们就无法判断提示工程是否到位,或者定制模型是否能够取代基础模型。
有效评估应针对具体任务,并与预期使用场景相吻合。我们建议首先进行单元测试,这是一种基础的评估方式。通过这种简单的测试,我们可以发现已知或潜在的失败模式,从而帮助我们做出早期的设计决策。此外,针对分类、摘要等不同任务,还有更多特定的评估方法可供参考。
虽然单元测试和基于模型的评估都非常重要,但它们并不能完全替代人类评估。让真实的用户使用你的模型或产品,并收集他们的反馈,这样不仅能评估模型在现实世界中的表现和缺陷率,还能收集到高质量的标注数据,然后将这些数据用以进一步优化未来的模型。这个过程形成了一个正向的反馈循环,即数据飞轮,它能够随着时间的积累而不断增强:
通过人工评估来衡量模型的性能或发现问题 利用标注数据微调模型或改进提示 重复这一过程
例如,在审核语言大模型生成的摘要时,我们可能会对每个句子进行细致的标注,以识别事实错误、不相关或风格问题。然后,我们可以利用这些事实不一致标注(factual inconsistency annotations)训练幻觉分类器,或使用相关性标注训练相关性奖励模型。再比如,领英在其撰写的文章中分享了他们使用基于模型的评估工具来估计幻觉、负责任的人工智能违规行为、连贯性等方面的成功经验。
通过创建能够随时间增值的资产,我们不仅将评估工作从一项纯粹的运营成本转变为了战略投资,同时也在这个过程中启动了数据飞轮。
3.4 低成本认知的高级发展趋势
1971年,施乐帕洛阿尔托研究中心(Xerox PARC)的科学家们预见了未来:一个利用联网的个人电脑而紧密相连的世界,而这正是我们今天所生活的时代。他们不仅预见了这一未来,更通过在关键技术领域的重要贡献——包括以太网、图形渲染、鼠标以及窗口界面等——直接推动了这一未来的实现。
他们还进行了一项基础练习:审视那些极具价值(如视频显示)但在当时成本过高的应用(例如,获取足够的RAM以驱动视频显示需要花费数千美元)。接着,他们分析了这项技术的历史价格走势(类似于摩尔定律),并预测了这些技术将在何时变得经济实惠。
我们可以对语言大模型技术进行同样的分析,尽管我们没有像晶体管数量与成本比这样直接的指标。使用一个广受欢迎且历史悠久的基准测试(比如大规模多任务语言理解数据集),以及一种持续一致的输入方法(five-shot提示),然后对比不同时间点上,不同性能水平的语言模型在这一基准测试上的运行成本。

图表:对于固定成本,其能力正迅速提升。对于固定能力水平,其成本正迅速降低。图表由共同作者Charles Frye使用2024年5月13日的公开数据绘制而成。
自OpenAI的davinci模型作为API发布四年以来,在一百万词元的任务上(约等于本文档的一百倍)运行同等性能的模型,其成本已从20美元骤降至不到10美分——成本减半的周期为六个月。同样,截至2024年5月,无论是通过API服务还是自行部署,运行Meta的LLaMA 3 8B模型每百万词元的成本仅为20美分,其性能与OpenAI的text-davinci-003模型不相上下,后者正是支撑ChatGPT的模型。2023年11月末发布时,text-davinci-003每百万词元的成本约为20美元。在短短18个月内,成本下降了两个数量级,而按照摩尔定律的预测,这一时期内成本本应只减少一倍。
现在,让我们聚焦于一种极具潜力的LLM应用:视频游戏中的角色生成,正如Park等人的研究所示。尽管这项技术非常有用,但其成本曾高达每小时625美元,尚不具备经济性。然而,自2023年8月论文发布后,其成本已经大幅下降至每小时62.50美元,下降了10倍。根据这一下降趋势,我们预计在未来九个月内,其成本将进一步降至每小时6.25美元,将更具经济可行性。
与此同时,回顾1980年《吃豆人》的问世,以今天的货币价值来衡量,1美元足以让你享受数分钟到数十分钟的游戏乐趣——大致相当于每小时能玩六局,即每小时花费6美元。这一计算表明,这种富有吸引力的由LLM增强的游戏体验,有望在2025年变得具有成本效益。
这些趋势虽然是近几年才出现的,但目前并没有明显的迹象表明其会在未来几年内减缓。尽管我们在算法和数据集方面可能已经充分利用了一些容易实现的改进,例如超越了每参数20个词元的“Chinchilla比率”,但数据中心和硅层面更深层次的创新和投资将继续推动这一趋势向前发展。
这可能是最重要的战略洞见:今天看起来完全不可行或者非常前沿的技术,比如一些复杂的演示或研究论文中提出的理论,在几年之内可能会变成现实。鉴于技术的这种发展趋势,我们在构建系统和组织时,应该考虑到这一点。
4看够了从0到1的演示,是时候推出从1到N的产品了
我们都知道,构建LLM演示非常有趣。只需几行代码、一个向量数据库和一个精心设计的提示,我们就能创造奇迹。在过去的一年里,人们常常将LLM与互联网、智能手机,甚至印刷机相比较。
然而,任何有实际软件发布经验的人都知道,在受控环境中运行的演示和大规模可靠运行的产品存在天壤之别。
世界上有很多容易想象和构建演示的问题,但要将其转化为产品却极其困难,例如,自动驾驶汽车。演示一辆汽车在街区周围自动驾驶很容易,但要将其转变为产品则需要数十年的努力。——安德烈·卡帕西(Andrej Karpathy)
以自动驾驶汽车为例。1988年出现了第一辆由神经网络驱动驾驶的汽车,二十五年后,安德烈·卡帕西在Waymo进行了第一次演示乘坐体验。十年后,该公司获得了无人驾驶许可。从原型到商业产品,自动驾驶汽车经历了三十五年严格的工程、测试、改进和监管导航。
过去一年,工业界和学术界见证了语言大模型应用的起起伏伏,这是LLM应用从演示阶段向产品化转型的第一年。我们在评估、提示设计、安全防护等实操技巧中学到了很多,同时也在运营策略、团队构建以及内部能力建设等策略方面积累了宝贵的经验,希望这些经验教训能在你接下来的旅程中提供指导,因为我们将共同在这个令人振奋的新领域中不断探索前进。 |