大型语言模型是构建软件的强大新工具。但由于它们是如此之新,而且行为方式与普通计算资源如此不同,因此如何使用它们并不总是显而易见的。

在这篇文章中,我们将分享新兴 LLM 应用程序栈的参考架构。它展示了我们所见过的人工智能初创公司和尖端科技公司所使用的最常见的系统、工具和设计模式。这个堆栈仍处于早期阶段,可能会随着底层技术的发展而发生重大变化,但我们希望它能为现在使用 LLM 的开发人员提供有用的参考。

1、LLM App技术栈

这是我们当前的 LLM 应用程序栈视图:

以下是每个项目的链接列表,以供快速参考:

Data pipelines Embedding model Vector database Playground Orchestration APIs/plugins LLM cache
Databricks OpenAI Pinecone OpenAI Langchain Serp Redis
Airflow Cohere Weaviate nat.dev LlamaIndex Wolfram SQLite
Unstructured Hugging Face ChromaDB Humanloop ChatGPT Zapier GPTCache
pgvector
Logging / LLMops Validation App hosting LLM APIs (proprietary) LLM APIs (open) Cloud providers Opinionated clouds
Weights & Biases Guardrails Vercel OpenAI Hugging Face AWS Databricks
MLflow Rebuff Steamship Anthropic Replicate GCP Anyscale
PromptLayer Microsoft Guidance Streamlit Azure Mosaic
Helicone LMQL Modal CoreWeave Modal
RunPod

使用 LLM 进行构建的方法有很多种,包括从头开始训练模型、微调开源模型或使用托管 API。 我们在这里展示的技术栈基于上下文学习(in-context learning),这是我们看到大多数开发人员开始使用的设计模式(并且现在只能通过基础模型实现)。

下一节将简要解释此模式; 有经验的 LLM 开发人员可以跳过此部分。

2、LLM App设计模式:上下文学习

上下文学习(in-context learning)的核心思想是使用现成的LLM(即无需任何微调),然后通过巧妙的提示和对私人“情境”数据的调节来控制他们的行为。

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

上下文学习通过一个巧妙的技巧解决了这个问题:它不是在每个 LLM 提示时发送所有文档,而是只发送少数最相关的文档。 最相关的文档是在 … 的帮助下确定的… 你猜到了 …LLM。

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

  • 数据预处理/嵌入:此阶段涉及存储私有数据(在我们的示例中为法律文档)以便稍后检索。 通常,文档被分成块,通过嵌入模型,然后存储在称为矢量数据库的专用数据库中。
  • 提示构造/检索:当用户提交查询(在本例中为法律问题)时,应用程序会构造一系列提示以提交给语言模型。 编译的提示通常结合了开发人员硬编码的提示模板; 有效输出的示例称为少样本示例; 从外部 API 检索的任何必要信息; 以及从矢量数据库检索到的一组相关文档。
  • 提示执行/推理:编译提示后,它们将被提交给预先训练的 LLM 进行推理,包括专有模型 API 和开源或自训练模型。 一些开发人员还在这个阶段添加了日志记录、缓存和验证等操作系统。

这看起来工作量很大,但通常比其他选择更容易:培训或微调LLM本身。 你不需要专门的 ML 工程师团队来进行上下文学习,也不需要托管自己的基础设施或从 OpenAI 购买昂贵的专用实例。 这种模式有效地将人工智能问题简化为大多数初创公司和大公司已经知道如何解决的数据工程问题。 对于相对较小的数据集,它的表现也往往优于微调——因为在LLM通过微调记住它之前,一条特定的信息需要在训练集中出现至少约 10 次——并且可以近乎真实地合并新数据 时间。

上下文学习的最大问题之一是:如果我们只是改变底层模型来增加上下文窗口,会发生什么? 这确实是可能的,并且这是一个活跃的研究领域(例如,参见Heyna论文或最近的这篇文章)。 但这需要一些权衡——主要是推理的成本和时间与提示的长度呈二次方关系。 如今,即使是线性缩放(最好的理论结果)对于许多应用来说成本也过高。 按照当前的 API 费率,超过 10,000 个页面的单个 GPT-4 查询将花费数百美元。 因此,我们预计不会基于扩展的上下文窗口对技术栈进行大规模更改,但我们将在帖子正文中对此进行更多评论。

如果你想更深入地了解情境学习,人工智能经典中有许多很棒的资源(尤其是“LLM构建实用指南”部分)。 在本文的其余部分中,我们将使用上面的工作流程作为指导来浏览参考堆栈。

LLM 应用程序的上下文数据包括文本文档、PDF,甚至是 CSV 或 SQL 表等结构化格式。 我们采访的开发人员之间的数据加载和转换解决方案差异很大。 大多数使用传统的 ETL 工具,例如 Databricks 或 Airflow。 有些还使用编排框架中内置的文档加载器,例如 LangChain(由 Unstructed 提供支持)和 LlamaIndex(由 Llama Hub 提供支持)。 不过,我们认为技术栈栈的这一部分相对不发达,并且有机会专门为 LLM 应用程序构建数据复制解决方案。

对于嵌入,大多数开发人员使用 OpenAI API,特别是 text-embedding-ada-002 模型。 它易于使用(特别是如果你已经在使用其他 OpenAI API),可以提供相当不错的结果,并且变得越来越便宜。 一些较大的企业也在探索Cohere,其产品工作更集中于嵌入,并且在某些场景下具有更好的性能。 对于喜欢开源的开发人员来说,Hugging Face 的 Sentence Transformers 库是一个标准。 还可以根据不同的用例创建不同类型的嵌入; 这是当今的一种小众实践,但却是一个有前途的研究领域。

从系统的角度来看,预处理管道中最重要的部分是矢量数据库。 它负责高效存储、比较和检索多达数十亿个嵌入(即向量)。 我们在市场上看到的最常见的选择是Pinecode。 它是默认设置,因为它完全由云托管,因此很容易上手,并且具有大型企业在生产中所需的许多功能(例如,良好的规模性能、SSO 和正常运行时间 SLA)。

不过,有大量可用的矢量数据库。 尤其:

  • Weaviate、Vespa 和 Qdrant 等开源系统:它们通常具有出色的单节点性能,并且可以针对特定应用进行定制,因此受到喜欢构建定制平台的经验丰富的 AI 团队的欢迎。
  • Chroma 和 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 用例中尤其有效,这些用例的查询复杂性存在很大差异,并且需要以低廉的成本为免费用户提供服务。
  • 这通常与微调开源基础模型结合起来最有意义。 我们不会在本文中深入讨论该工具堆栈,但越来越多的工程团队正在使用 Databricks、Anyscale、Mosaic、Modal 和 RunPod 等平台。
  • 开源模型可以使用多种推理选项,包括 Hugging Face 和 Replicate 的简单 API 接口; 来自主要云提供商的原始计算资源; 以及像上面列出的更多固执己见的云产品。

目前,开源模型落后于专有产品,但差距正在开始缩小。 Meta 的 LLaMa 模型为开源准确性设定了新的标准,并引发了一系列变体。 由于 LLaMa 只被授权用于研究用途,许多新的提供商已经介入训练替代基础模型(例如 Together、Mosaic、Falcon、Mistral)。 Meta 还在讨论 LLaMa 2 的真正开源版本。

当(不是如果)开LLM达到与 GPT-3.5 相当的准确度水平时,我们预计会看到文本的稳定扩散时刻,包括大规模实验、共享和微调模型的生产。 像 Replicate 这样的托管公司已经在添加工具,以使软件开发人员更容易使用这些模型。 开发人员越来越相信,更小的、经过微调的模型可以在狭窄的用例中达到最先进的精度。

我们采访过的大多数开发人员还没有深入了解LLM的操作工具。 缓存相对常见(通常基于 Redis),因为它可以缩短应用程序响应时间并降低成本。 Weights & Biases 和 MLflow(从传统机器学习移植)或 PromptLayer 和 Helicone(专为LLM构建)等工具也得到相当广泛的使用。 他们可以记录、跟踪和评估 LLM 输出,通常是为了改进提示构建、调整管道或选择模型。 还有许多新工具正在开发中,用于验证 LLM 输出(例如 Guardrails)或检测即时注入攻击(例如 Rebuff)。 大多数这些操作工具都鼓励使用自己的 Python 客户端进行 LLM 调用,因此了解这些解决方案如何随着时间的推移共存将会很有趣。

最后,LLM 应用程序的静态部分(即模型以外的所有内容)也需要托管在某个地方。 到目前为止,我们看到的最常见的解决方案是 Vercel 或主要云提供商等标准选项。 然而,两个新类别正在出现。 像 Steamship 这样的初创公司为 LLM 应用程序提供端到端托管,包括编排 (LangChain)、多租户数据上下文、异步任务、矢量存储和密钥管理。 Anyscale 和 Modal 等公司允许开发人员将模型和 Python 代码托管在一个地方。

3、关于Agent代理

该参考架构中缺少的最重要组件是人工智能代理框架。 AutoGPT 被描述为“使 GPT-4 完全自治的一项实验性开源尝试”,是今年春天历史上增长最快的 Github 存储库,几乎当今的每个人工智能项目或初创公司都包含某种形式的代理。

与我们交谈的大多数开发人员都对代理的潜力感到非常兴奋。 我们在这篇文章中描述的上下文学习模式可以有效解决幻觉和数据新鲜度问题,以便更好地支持内容生成任务。 另一方面,代理为人工智能应用程序提供了一组全新的功能:解决复杂的问题,对外部世界采取行动,以及从部署后的经验中学习。 他们通过结合高级推理/规划、工具使用和记忆/递归/自我反思来做到这一点。

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

4、展望未来

预训练的人工智能模型代表了自互联网以来最重要的软件架构变化。 它们使个人开发人员能够在几天内构建出令人难以置信的人工智能应用程序,超越大型团队需要数月才能构建的监督机器学习项目。

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