原文:https://a16z.com/2023/06/20/emerging-architectures-for-llm-applications/

大型语言模型是一种强大的新原语,用于构建软件。但是由于它们如此新颖——并且与普通计算资源的行为方式如此不同——我们并不总是明确知道如何使用它们。

在这篇文章中,我们分享了一种新兴的LLM应用栈的参考架构。它展示了我们在AI创业公司和先进技术公司中最常见的系统、工具和设计模式。这个栈还处在非常早期的阶段,并可能随着底层技术的进步而发生重大变化,但我们希望它对现在正在使用LLM的开发者来说会是一个有用的参考。

这项工作是基于我们与AI创业公司创始人和工程师的对话。我们特别依赖于以下人士的输入: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进行构建,包括从头开始训练模型,微调开源模型,或使用托管的API。我们在这里展示的堆栈是基于情境学习,这是我们看到的大多数开发者开始使用的设计模式(只有在有基础模型的情况下才可能)。

下一部分将简要解释这种模式;有经验的LLM开发者可以跳过这一部分。

设计模式:情境学习情境学习的核心思想是直接使用LLM(即,不进行任何微调),然后通过巧妙的提示和依赖于私有的“情境”数据的条件来控制它们的行为。

例如,假设你正在构建一个关于一组法律文件的问题的聊天机器人。采取一种天真的方法,你可以将所有的文件粘贴到ChatGPT或GPT-4的提示中,然后在最后提出一个关于它们的问题。这可能对非常小的数据集有效,但是并不能扩展。最大的GPT-4模型只能处理约50页的输入文本,并且随着你接近这个限制(称为上下文窗口),性能(以推理时间和准确性来衡量)会严重下降。

情境学习用一个巧妙的技巧解决了这个问题:它不是在每个LLM提示中发送所有的文件,而是只发送几个最相关的文件。而最相关的文件是由……你猜到了……LLM帮助确定的。

在非常高的层次上,工作流程可以分为三个阶段:

数据预处理/嵌入:这个阶段涉及存储私有数据(在我们的例子中是法律文件)以供稍后检索。通常,这些文件被分解成块,通过嵌入模型传递,然后存储在一个专门的数据库中,称为向量数据库。提示构造/检索:当用户提交一个查询(在这个案例中,是一个法律问题)时,应用程序构造一系列提交给语言模型的提示。编译后的提示通常结合了开发者硬编码的提示模板;称为少量样例的有效输出示例;从外部API检索的任何必要信息;以及从向量数据库检索的一组相关文件。提示执行/推理:一旦提示被编译,它们被提交给一个预训练的LLM进行推理——包括专有的模型API和开源或自我训练的模型。一些开发者在这个阶段还增加了操作系统,如日志记录,缓存和验证。这看起来像很多工作,但通常比替代方案更简单:训练或微调LLM本身。你不需要一个专门的ML工程师团队来进行情境学习。你也不需要托管你自己的基础设施或从OpenAI购买昂贵的专用实例。这种模式有效地将一个AI问题简化为大多数创业公司和大公司已经知道如何解决的数据工程问题。它也倾向于对相对较小的数据集表现更好——因为在LLM通过微调记住一个特定的信息之前,该信息需要在训练集中出现至少大约10次——并且可以近乎实时地包含新数据。

围绕情境学习的一个最大的问题是:如果我们只是改变底层的模型来增加上下文窗口会发生什么?这确实是可能的,这是一个活跃的研究领域(例如,参见Hyena论文或这篇最近的文章)。但是这带来了一些权衡——主要是推理的成本和时间随着提示的长度呈二次方增长。今天,即使是线性扩展(最好的理论结果)也会对许多应用程序造成过高的成本。当前的API价格,一次GPT-4查询超过10,000页的成本可能会达到数百美元。所以,我们不期望基于扩展的上下文窗口对堆栈进行大规模的变化,但我们将在正文中对此进行更多的评论。

如果你想深入了解情境学习,AI典籍中有很多优秀的资源(特别是“用LLM构建实用指南”部分)。在这篇文章的其余部分,我们将使用上面的工作流程作为指导,讲解参考栈。

LLM应用的上下文数据包括文本文档,PDF,甚至像CSV或SQL表这样的结构化格式。我们访谈的开发者对这些数据的数据加载和转换解决方案差异很大。大多数人使用传统的ETL工具,如Databricks或Airflow。一些人也使用内置在编排框架中的文档加载器,如LangChain(由Unstructured提供支持)和LlamaIndex(由Llama Hub提供支持)。我们认为这部分的技术栈相对未发展,有机会为LLM应用开发专用的数据复制解决方案。

对于嵌入,大多数开发者使用OpenAI API,特别是text-embedding-ada-002模型。它易于使用(尤其是如果你已经使用了其他OpenAI API),提供相当好的结果,并且价格越来越便宜。一些大型企业也在探索Cohere,它将产品开发的重点更狭窄地放在嵌入上,并在某些情况下有更好的性能。对于喜欢开源的开发者,Hugging Face的Sentence Transformers库是一个标准。也可以为不同的使用场景创建不同类型的嵌入;这是目前的一种小众实践,但是是一个有前景的研究领域。

从系统角度来看,预处理管道中最重要的部分是向量数据库。它负责有效地存储,比较和检索多达数十亿的嵌入(即,向量)。我们在市场上看到的最常见的选择是Pinecone。它是默认的选择,因为它完全托管在云上——所以很容易开始使用——并且拥有大型企业在生产中需要的许多功能(例如,大规模的良好性能,SSO和正常运行时间的服务级别协议)。

然而,可供选择的向量数据库范围非常广泛。值得注意的是:

开源系统,如Weaviate,Vespa和Qdrant:它们通常提供出色的单节点性能,并且可以为特定的应用定制,所以它们受到喜欢构建定制平台的有经验的AI团队的欢迎。本地向量管理库,如Chroma和Faiss:它们提供了很好的开发者体验,并且易于为小型应用和开发实验启动。它们不一定能替代大规模的完整数据库。OLTP扩展,如pgvector:对于看到每一个数据库形状的孔并试图插入Postgres的开发者,或者购买了大部分数据基础设施的企业,这是一个支持向量的好解决方案。从长远来看,将向量和标量工作负载紧密耦合是否合理还不清楚。展望未来,大多数开源向量数据库公司正在开发云服务。我们的研究表明,在云中实现强大的性能,在可能的使用案例的广阔设计空间中,是一个非常困难的问题。因此,短期内选项集可能不会大幅改变,但长期来看可能会改变。关键问题是向量数据库是否会像其OLTP和OLAP的同行一样,围绕一个或两个流行的系统进行整合。

另一个未解的问题是,随着大多数模型可用的上下文窗口增长,嵌入和向量数据库将如何演变。人们可能会认为嵌入会变得不那么相关,因为上下文数据可以直接插入提示中。然而,对这个话题的专家反馈表明相反——嵌入管道可能会随着时间的推移变得更重要。大型上下文窗口是一个强大的工具,但它们也带来了显著的计算成本。因此,高效利用它们成为了优先事项。我们可能开始看到不同类型的嵌入模型变得流行,直接为模型的相关性进行训练,并设计向量数据库来实现和利用这一点。

LLM的提示策略和上下文数据的整合正在变得越来越复杂,并且作为产品差异化的来源越来越重要。大多数开发者通过实验简单的提示来开始新项目,这些提示包括直接指令(零射击提示)或可能的一些示例输出(少射击提示)。这些提示通常会给出良好的结果,但未达到生产部署所需的准确性水平。

下一级的提示策略是设计来使模型的响应基于某种真实源并提供模型未经过训练的外部上下文。Prompt Engineering Guide目录列出了不少于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用例,如搜索或聊天中,这可以特别有效,因为查询的复杂性有广泛的变化,并且需要以低成本为免费用户提供服务。 通常与微调开源基础模型结合使用最有意义。我们在这篇文章中没有深入研究那个工具栈,但像Databricks、Anyscale、Mosaic、Modal和RunPod这样的平台正在被越来越多的工程团队使用。对于开源模型,有各种推断选项可用,包括Hugging Face和Replicate提供的简单API接口;主要云提供商的原始计算资源;以及上述列出的更有意见的云服务。 开源模型目前落后于专有产品,但差距开始缩小。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代码。

关于智能代理怎么说呢?这个参考架构中最重要的缺失部分是AI代理框架。AutoGPT被描述为“一种试验性的开源尝试,旨在使GPT-4完全自主”,它在今年春季成为了历史上增长最快的Github仓库,现在几乎所有的AI项目或创业公司都以某种形式包含了代理。

我们与之交谈的大多数开发者对代理的潜力感到非常兴奋。我们在这篇文章中描述的在上下文中学习的模式,有效地解决了错觉和数据新鲜度问题,以更好地支持内容生成任务。另一方面,代理赋予AI应用一套基本新的能力:解决复杂问题,对外部世界采取行动,以及在部署后从经验中学习。他们通过一种先进的推理/规划,工具使用,以及记忆/递归/自我反思的组合来实现这一点。

因此,代理有可能成为LLM应用架构的核心部分(或者如果你相信递归的自我改进,它们甚至可以接管整个堆栈)。并且像LangChain这样的现有框架已经融入了一些代理的概念。只有一个问题:代理还真的没有实现。现在大多数代理框架都处于概念验证阶段——能够完成令人难以置信的演示,但还不能完成可靠、可重复的任务。我们将关注他们在不久的将来如何发展。

展望未来预训练的AI模型代表了自互联网以来软件架构中最重要的变化。他们使得个人开发者能够在几天内构建出令人难以置信的AI应用,这些应用超越了由大团队花费数月构建的有监督机器学习项目。

我们在这里列出的工具和模式可能是整合LLM的起点,而不是终点。我们将在发生重大变化(例如,转向模型训练)时更新这些内容,并在有意义的地方发布新的参考架构。如果你有任何反馈或建议,请随时联系我们。