A16Z:大模型应用的新兴架构
编者按:生成式人工智能的爆发有可能颠覆很多行业,其中之一就是软件业。大语言模型(LLM)的兴起让相关应用也迎来了爆发,科技巨头与初创企业纷纷推出了各种 LLM 应用,那么这些应用都使用了什么样的工具,采取了什么样的设计模式呢?本文进行了总结。文章来自编译。
图片来源:由无界 AI 生成
大型语言模型(LLM)是开发软件的强大的新原语。但由于 LLM 实在是太新了,并且行为与普通的计算资源实在是太不一样了,所以怎么使用 LLM 未必总是一目了然。
在这篇文章里,我们将分享新兴 LLM 应用栈的参考架构。该架构将展示我们见过的人工智能初创企业与顶尖科技公司使用的最常见的系统、工具以及设计模式。这个技术栈还比较原始,可能会随着底层技术的进步而出现重大变化,但我们希望它能为现在从事 LLM 开发的开发者提供有用的参考。
这项工作基于与人工智能初创企业的创始人以及工程师的对话。我们特别有赖于以下人员的意见:包括 Ted Benson、Harrison Chase、Ben Firshman 、Ali Ghodsi 、Raza Habib、Andrej Karpathy 、Greg Kogan、Jerry Liu、 Moin Nadeem、Diego Oppenheimer、Shreya Rajpal、Ion Stoica 、Dennis Xu、 Matei Zaharia 以及 Jared Zoneraich。感谢你们的帮助!
LLM技术栈
LLM 应用技术栈的当前版是这样的:
灰色框是关键组件,带箭头的代表不同的数据流:黑色虚线为应用开发者提供的用于限定输出的上下文数据,黑色实线为传给LLM的提示既少样本例子,蓝色实线为用户查询,红色实线为返回给用户的输出
以下是每个项目的链接列表,可供快速参考:
、应用栈各关键组件的常用工具/系统
用 LLM 进行开发的方法有很多种,包括从零开始训练模型、微调开源模型或利用托管 API。我们在这里展示的技术栈是基于上下文学习(in-context learning),我们观察到大多数开发者都开始利用的这种设计模式(并且目前只能通过基础模型实现)。
下一节将简要解释一下这种设计模式。
设计模式:上下文学习
上下文学习的核心思想是利用现成的 LLM(也就是不需要任何的微调),然后通过巧妙的提示和对私有“上下文”数据的调节来控制其行为。
比方说,假设你正在开发一个聊天机器人来回答有关一系列法律文件的问题。简单的做法呢,你可以把所有文档都粘贴到 ChatGPT 或 GPT-4 提示里面,然后再询问相关问题。这对于规模非常小的数据集也许适用,但没法扩展。最大的 GPT-4 模型只能处理约 50 页的输入文本,当接近这个所谓的上下文窗口限制时,性能(通过推理时间和准确性来衡量)会严重下降。
上下文学习用一个巧妙的技巧解决了这个问题:它不是每次输入 LLM 提示的时候都发送所有的文档过去,而是只发送少数最相关的文档。谁来帮助决定哪些是最相关的文档?你猜对了……LLM。
从非常高的层面而言,这个工作流可以分为三个阶段:
- 数据预处理/嵌入:该阶段要将私有数据(在这里的例子中也就是法律文档)存储起来以供稍后检索。一般而言,文档会被分成块,传送给嵌入模型,然后存储在所谓的向量数据库的专用数据库之中。
- 提示构造/检索:当用户提交查询(在本例中为法律问题)时,应用会构造一系列的提示,然后提交给该语言模型。编译过的提示通常会与开发者硬编码的提示模板结合;有效输出的示例叫做少样本示例;任何必要信息均通过外部 API 检索获取;以及从向量数据库检索到的一组相关文档获取。
- 提示执行/推理:一旦提示被编译过之后,将会被提交给预训练的 LLM 进行推理,其中包括了专有模型 API 以及开源或自训练的模型。在此阶段,部分开发者还会增加日志记录、缓存以及验证等运营性的系统。
这些看似工作量很大,但其实通常比其他替代方案更容易实现:训练 LLM 或微调 LLM 本身其实更难。你不需要专门的机器学习工程师团队来进行上下文学习。你也不需要托管自己的基础设施或从 OpenAI 购买昂贵的专用实例。这种模式有效地将人工智能问题简化为大多数初创企业以及大公司都已经知道如何解决的数据工程问题。对于相对较小的数据集,其性能也往往优于微调,因为在 LLM 通过微调记住特定信息之前,这些信息需要在训练集至少出现过大概 10 次,并且上下文学习还可以近乎实时地合并新数据。
上下文学习其中一个最大问题是:如果我们只是改变底层模型来增加上下文窗口的话,会发生什么?这确实是可能的,并且这是一个活跃的研究领域。但这需要一些权衡——主要是推理的成本和时间与提示的长度呈二次方关系。如今,即便是线性缩放(最好的理论结果)对于许多应用来说成本也过高。按照当前的 API 费率,超过 10000 个页面的单次 GPT-4 查询将花费数百美元。因此,我们预计对基于扩展的上下文窗口的技术栈不会进行大规模地更改,但我们会在后面对此进行进一步阐述。
在本文的其余部分中,我们将使用上面的工作流作为指导来过一遍这个技术栈。
数据处理/嵌入
数据处理/嵌入部分:通过数据管道将数据交给嵌入模型进行向量化,然后存放到向量数据库
LLM 应用的上下文数据 包括文本文档、PDF,甚至是 CSV 或 SQL 表等结构化格式。我们访谈过的开发者各自采用的数据加载和转换(ETL)解决方案差异很大。大多数采用传统的 ETL 工具,比方说 Databricks 或 Airflow。有些还利用了编排框架内置的文档加载器,比方说 LangChain (由 Unstructed 提供支持)以及 LlamaIndex (由 Llama Hub 提供支持)。不过,我们认为这个技术栈的这一部分发展相对还不够,并且有机会专门为 LLM 应用开发数据复制解决方案。
至于嵌入 ,大多数开发者使用 OpenAI API,尤其是 text-embedding-ada-002 模型。这个模型很容易使用(特别是如果你已经在使用其他的 OpenAI API 的话),可以提供相当好的结果,而且价格也越来越便宜了。有些大一点的企业也在探索 Cohere,其产品工作更加聚焦于嵌入,并且在某些场景下具有更好的性能。对于喜欢开源的开发人员来说,Hugging Face 的 Sentence Transformers 库是一个标准。还可以根据不同的用例创建不同类型的嵌入;这是当今一种比较小众的做法,但却是一个很有前途的研究领域。
从系统的角度来看,预处理管道里面最重要的部分是向量数据库 。向量数据库要负责高效存储、比较和检索多达数十亿的嵌入(也就是向量)。我们在市场上看到的最常见的选择是 Pinecone。它是默认设置的,因为完全是由云托管的,因此很容易上手,并且具备大型企业在生产当中所需的许多功能(比方说,良好的规模性能、单点登录以及正常运行时间服务等级协议)。
不过,还有大量可用的向量数据库。值得注意的包括:
- Weaviate 、Vespa 以及 Qdrant 等开源系统 :这些系统通常具有出色的单节点性能,并且可以针对特定应用进行定制,因此受到喜欢开发定制平台的经验丰富的人工智能团队的欢迎。
- Faiss 等本地向量管理库 :这些库拥有丰富的开发者经验,并且对于小型应用和开发实验来说很容易启动。但这些未必能大规模替代完整的数据库。
- pgvector 之类的 OLTP 扩展 :对于看到每一个数据库形态的漏洞并尝试插入 Postgres 的开发者,或从单个云提供商购买大部分数据基础设施的企业来说,这是一个很好的向量支持解决方案。从长远来看,尚不清楚紧耦合向量与标量工作负载是否有意义。
展望未来,大多数开源向量数据库公司都在开发云产品。我们的研究表明,在可能用例的广泛设计空间里,在云端实现强大的性能是一个非常困难的问题。因此,选项集在短期内可能不会发生巨大变化,但从长远来看可能会发生变化。关键问题是向量数据库是否会跟 OLTP 和 OLAP 数据库类似,围绕着一两个流行系统进行整合。
还有一个问题悬而未决,随着大多数模型可用上下文窗口的扩大,嵌入和向量数据库将会如何演变。你很容易会说嵌入会变得不那么重要,因为上下文数据可以直接放进提示里面。不过,专家对这个主题的反馈表明情况恰恰相反——随着时间的推移,嵌入管道可能会变得更加重要。大上下文窗口确实是强大工具,但也需要大量的计算成本。因此,有效利用这个窗口成为当务之急。我们可能会开始看到不同类型的嵌入模型变得流行,会直接针对模型相关性进行训练,还会出现旨在实现和利用这一点的向量数据库。
提示构建与获取
提示构建与获取
提示 LLM 并整合上下文数据的策略变得越来越复杂,而且也被用作产品差异化的来源,其作用也越来越重要。大多数开发者通过实验简单提示来开始新项目,这些提示包括直接指令(零样本提示)或可能含部分示例的输出(少样本提示)。这些提示通常能生成好的结果,但达不到生产部署所需的准确性水平。
下一级别的提示技巧旨在让模型响应是基于某些事实来源的,并提供模型未受训练过的外部上下文。 《提示工程指南》列出了不少于 12 (!) 种更高级的提示策略,包括思维链、自洽、生成知识、思维树、方向性刺激等等。可以结合使用这些策略,从而支持不同的 LLM 用例,比方说文档问答、聊天机器人等。
这就是类似 LangChain 以及 LlamaIndex 这样的编排框架的用武之地。这些框架把提示链的许多细节都给抽象出来;与外部 API 进行交互(包括确定何时需要 API 调用);从向量数据库检索上下文数据;并在跨多个 LLM 的调用过程中维护好记忆。它们还为上述许多常见应用提供模板。其输出是提交给语言模型的一个提示或一系列提示。这些框架获得了业余爱好者以及希望开发应用的初创企业的广泛使用,其中 LangChain 是领先者。
LangChain 仍然是一个相对较新的项目(目前版本为 0.0.201),但我们已经开始看到用它开发的应用投入生产了。部分开发者,尤其是 LLM 的早期采用者,更喜欢在生产环境下切换成原始 Python,以消除额外的依赖性。但我们预计,对于大多数用例来说,这种 DIY 的做法会逐步减少,就像传统的 Web 应用技术栈一样。
眼尖的读者会注意到编排框里面有一个看似奇怪的条目:ChatGPT。在正常情况下,ChatGPT 属于一个应用,而不是开发者工具。但它也可以作为 API 加以访问。而且,如果你仔细观察,它会执行一些与其他编排框架相同的功能,比方说:抽象出对定制提示的需求;维护状态;通过插件、API 或其他来源检索上下文数据。虽然 ChatGPT 不是此处列出的其他工具的直接竞争对手,但可以将其视为替代解决方案,并且最终可能成为提示构建可行、简单的替代方案。
提示执行/推理
提示执行/推理
如今,OpenAI 已成为语言模型领域的领导者。几乎我们采访过的每一位开发者都用 OpenAI API 推出过新的 LLM 应用,通常它们用的是 gpt-4 或 gpt-4-32k 模型。这为应用性能提供了最佳用例场景,并且易于使用,因为它可以使用广泛的输入域,并且通常不需要微调或自托管。
一旦项目投入生产并开始规模化时,更广泛的一系列选项就可以发挥作用。我们听到的一些常见问题包括:
- 切换到 gpt-3.5-turbo:这个要比 GPT-4 便宜约 50 倍,而且速度明显更快。许多应用并不需要 GPT-4 级别的准确性,但对于低延迟推理以及为免费用户提供经济有效的支持确实刚需。
- 用其他专有供应商(尤其是 Anthropic 的 Claude 模型)做实验:Claude 提供了快速推理、GPT-3.5 级别的准确性、针对大客户提供更多定制选项,还有高达 100k 的上下文窗口(尽管我们发现准确性会随输入长度的增加而降低)。
- 对开源模型的部分请求进行分类:这对于搜索或聊天等大容量 B2C 用例尤其有效,因为这些用例的查询复杂性存在很大差异,并且需要以低廉的成本为免费用户提供服务:
1)这个通常跟对开源基础模型进行微调结合起来是最有意义的。我们不会在本文深入探讨这个工具栈,但有越来越多的工程团队正在使用 Databricks、 Anyscale 、Mosaic、Modal 以及 RunPod 等平台。
2)开源模型可以使用多个推理选项,包括 Hugging Face 与 Replicate 的简单 API 接口;来自主要云提供商的原始计算资源;以及像上面列举的有更明确偏好的云产品(opinionated cloud)。
目前,开源模型 落后于专有产品,但差距正在开始缩小。Meta 的 LLaMa 模型为开源的准确性设定了新的标准,并催生了一系列的变体。由于 LLaMa 只被授权用于研究用途,许多新的提供商已经开始训练替代的基础模型(比方说 Together、Mosaic、Falcon、Mistral)。Meta 还在讨论要不要推出 LLaMa 2 的真正开源版。
当(不是如果)开源 LLM 达到与 GPT-3.5 相当的准确度水平时,我们预计会看到文本也会出现自己的 Stable Diffusion 时刻,会有大规模实验、共享以及微调模型的投入生产。像 Replicate 这样的托管公司已经开始添加工具,好让软件开发人员更容易使用这些模型。开发人员越来越相信,更小的、经过微调的模型可以在范围很窄的用例中达到最先进的精度。
我们采访过的大多数开发者还没有深入了解 LLM 的操作工具 。缓存相对常见(通常基于 Redis),因为这可以缩短应用响应时间并降低成本。 Weights & Biases 与 MLflow (从传统机器学习移植过来)或 PromptLayer 与 Helicone (专为LLM构建)等工具也得到相当广泛的使用。这些工具可以记录、跟踪和评估 LLM 的输出,通常是为了改进提示构造、调整管道或选择模型的目的。还有许多用于验证 LLM 输出(比方说 Guardrails)或检测提示注入攻击(比方说 Rebuff)的新工具正在开发中。大多数这些操作工具都鼓励使用自己的 Python 客户端来执行 LLM 调用,因此了解这些解决方案会如何随着时间推移而共存将会很有趣。
最后,LLM 应用的静态部分(也就是模型以外的所有其他内容)也需要托管在某个地方。到目前为止,我们看到的最常见的解决方案是 Vercel 或主要云提供商等标准选项。然而,正在出现两个新的类别。像 Steamship 这样的初创企业为 LLM 应用提供了端到端的托管,包括编排 ( LangChain )、多租户数据上下文、异步任务、向量存储以及密钥管理等。Anyscale 与 Modal 等公司可让开发者将模型和 Python 代码托管在一个地方。
代理呢?
这个参考架构里面缺少了一个最重要的组件,那就是人工智能代理框架。 大家对 AutoGPT 的评价是“一个让 GPT-4 完全自动化的实验性开源尝试”,今年春天,它成为史上增长最快的 Github 库,当今几乎每个人工智能项目或初创企业都会纳入某种形式的代理进去。
跟我们交谈过的大多数开发者对代理的潜力都感到非常兴奋。我们在这篇文章中描述的上下文学习模式可以有效解决幻觉和数据新鲜度问题,从而更好地支持内容生成任务。另一方面,代理为人工智能应用提供了一系列的全新功能:解决复杂问题,对外部世界采取行动,以及从部署后的经验中学习。这是通过将高级推理/规划、工具使用以及记忆/递归/自我反思想结合来做到这一点的。
因此,代理有潜力成为 LLM 应用架构的核心部分(或者甚至接管整个技术栈,如果你相信递归自我改进的话)。像 LangChain 这样的现有框架已经融入了部分代理概念。只有一个问题:代理还没有真正发挥作用。现如今,大多数代理框架都还处在概念验证阶段,虽然能够提供令人难以置信的演示,但还不能够可靠地、可重复地执行任务。我们正在密切关注代理在不久的将来如何发展。
展望未来
预训练的人工智能模型是自互联网以来最重要的软件架构变化的体现。它们让个人开发者能够在几天内开发出令人难以置信的人工智能应用,其能力甚至超越了过去大型团队需要数月才能开发出来的有监督机器学习项目。
我们在这里列出的工具和模式可能是整合 LLM 的起点,而不是最终状态。在发生了重大变化(比方说,向模型训练转变)时,我们还会进行更新,并在有意义的地方发布新的参考架构。