Towards LangChain 0.1: LangChain-Core and LangChain-Community

迈向 LangChain 0.1:LangChain-Core 和 LangChain-Community

14 分钟阅读

LangChain 的目标始终是尽可能轻松地使用 LLM 开发上下文感知推理应用程序。LangChain 最初是一个副项目,纯粹是一个 Python 包。在过去一年中,它取得了巨大的增长。这种增长迫使人们重新思考该软件包的架构。我们一直在倾听社区的意见,并宣布将该软件包重新架构为多个软件包(以完全向后兼容的方式完成),朝着稳定的 0.1 版本迈进,并借此机会强调围绕 LangChain 涌现的生态系统。

TL;DR (太长不看)

为了改善开发者体验,我们已将旧的 langchain 包拆分为三个独立的包

langchain-core 包含已成为标准的简单核心抽象,以及 LangChain 表达式语言,作为将这些组件组合在一起的方式。此包现在为 0.1 版本,所有重大更改都将伴随次要版本号的提升。

langchain-community 包含所有第三方集成。我们将在下个月与合作伙伴合作,将关键集成拆分为独立的软件包。

langchain 包含更高级别和特定用例的链、代理和检索算法,这些算法是您的应用程序认知架构的核心。我们的目标是在 1 月初发布 langchain 的稳定 0.1 版本。

这样做是为了支持围绕 langchain 蓬勃发展的生态系统:LangChain 模板、LangServe、LangSmith 以及构建在其之上的其他软件包。

所有操作均以向后兼容的方式完成。

LangChain 生态系统概述。

LangChain SDK

LangChain Python 和 JavaScript SDK 包含三个主要部分

  • 构建 LLM 应用程序所需的通用组件的基本接口集,以及将这些组件连接在一起的方法
  • 这些组件的集成和/或实现
  • 将这些组件组合在一起以完成特定用例的预配置方法

以前,这三个部分都属于同一个库。虽然这在开始时有效,但随着集成和用例数量的增长,复杂性已变得不可持续。重新架构的主要部分是将这些部分分离到不同的软件包中:langchain-corelangchain-communitylangchain。与此同时,我们希望考虑到庞大的 LangChain 用户群,并尝试以向后兼容的方式进行操作。

💡
我们的两个主要考虑因素是长期稳定性和可扩展性,以及短期向后兼容性。

LangChain Core

langchain-core 由核心抽象和一个运行时组成,用于将这些组件连接在一起 (LangChain 表达式语言)。

简单且模块化的抽象

LangChain 的基本抽象旨在尽可能模块化和简单。这些抽象的示例包括语言模型、文档加载器、嵌入模型、向量存储、检索器等等。拥有这些抽象的好处是,任何提供商都可以实现所需的接口,然后轻松地在 LangChain 的其余部分中使用。

这些不是高级或端到端的抽象。它们只是代表必要组件的通用接口。例如:LLM 只是文本输入,文本输出。检索器是文本输入,文档输出。

💡
这些低级且灵活的抽象使 LangChain 成为提供商和合作伙伴向整个 GenAI 生态系统公开其服务的标准,迄今为止已促成 700 多个不同的集成。

许多框架和应用程序要么构建在这些抽象之上,要么与这些抽象互操作。这包括像 funcchainlangchain-decoratorsgpt-researchergpt-engineerllama-indexpandas-aiCrewAI 这样的框架。拥有 LangChain 集成是确保您的工具与生态系统的很大一部分兼容的最有效方法。此外,超过 3 万个应用程序构建在 LangChain 之上。其中一些需要实现自定义组件。通过使我们的抽象简单且模块化,我们使这项工作变得轻松而无痛。

LangChain 表达式语言

最初的 LangChain 版本实际上并没有一种通用的方法来将这些基本组件连接在一起。尽管标语是“通过可组合性构建 LLM 应用程序”,但最初的 LangChain 实际上并没有那么可组合。

💡
在过去的五个月里,我们努力添加了一个组合的运行时:LangChain 表达式语言

此运行时允许用户将任意序列组合在一起,并获得在构建 LLM 应用程序时很重要的几个好处。我们将这些序列称为“可运行对象”。

所有可运行对象都公开相同的接口,包括单次、批量、流式和异步方法。这种设计很有用,因为在构建 LLM 应用程序时,仅仅拥有一个同步接口是不够的。批量处理对于高效处理许多输入是必需的。流式处理(以及中间步骤的流式处理)是向用户展示正在取得进展所必需的。异步接口在进入生产环境时非常有用。LangChain 表达式语言允许您编写一次可运行对象,并以多种不同的方式调用它,而无需为所有这些接口编写多个实现。

我们还编写了可运行对象来编排常见的(但令人讨厌的)任务。所有可运行对象都公开一个 .map 方法,该方法将可运行对象并行应用于列表的所有元素。所有可运行对象还公开一个 .with_fallbacks 方法,该方法允许您在可运行对象出错时定义回退。这些是在构建 LLM 应用程序时常见且有用的编排任务。

这些可运行对象也比以前的“链”更易于检查和自定义。以前的链主要是 langchain 源代码中的自定义类。这使得很难理解它们内部发生了什么(包括使用了哪些提示),并且更难更改更改的行为(而不完全重写它们)。我们已经使用可运行对象重写了几个链(并且将来会重写更多)。可运行对象以声明方式定义,这使得更容易理解逻辑和修改部分。

最后,可运行对象通过与 LangSmith 的无缝集成,拥有一流的可观察性。LLM 应用程序非常难以调试。了解确切的步骤顺序、确切的输入是什么以及确切的输出是什么可以大大提高您的提示速度。我们构建 LangSmith 就是为了极大地促进这一点 - 稍后会详细介绍。

独立软件包的优势

这些抽象和运行时非常稳定,而且每当我们进行更改时,我们基本上都是以向后兼容的方式进行的。尽管如此,由于这些对于 LangChain 生态系统至关重要,我们希望在更改这些抽象时格外小心并进行沟通。截至今天,这些抽象是 langchain-core 的一部分,后者刚刚发布了 0.1 版本。现在 langchain-core0.1 版本,任何未来的重大更改都将伴随次要版本号的提升。这为这些核心抽象创建了稳定性,这将使其他人有信心在其之上构建。

LangChain Community

LangChain 的一个重要组成部分是我们的合作伙伴。我们拥有近 700 个集成,从文档加载器到 LLM,再到向量存储和工具包。在所有情况下,我们都努力使添加集成尽可能容易,并感谢社区和我们的合作伙伴与我们合作。

如此大量的集成对开发者来说是赋能的,但这并非没有缺点。由于集成如此之多,我们使所有依赖项都成为可选的(以使 LangChain 轻量级)。不幸的是,这使得很难知道给定集成需要哪些依赖项。在同一个包中包含如此多的集成也使得几乎不可能正确地对它们进行版本控制。底层集成本身正在快速变化(鉴于该领域的变化速度,这是必要的现实)。这导致了这些集成的不稳定,因为很难知道何时可能发生了更改。由于这些集成与其他 LangChain 组件捆绑在一起,因此它们导致了整个软件包的不稳定性。由于集成如此之多,这些集成的可靠性和稳健性自然存在广泛的范围。如果它们都在一个包中,则开发者无法可靠地知道哪些集成得到了良好的支持和充分的测试。

我们很高兴地宣布 LangChain 架构的一些更改,这些更改将解决这些问题。

首先,在最近的版本中,我们将所有集成移到了一个单独的 langchain-community 包中。这将有助于分离和区分集成代码 - 这通常需要不同的设置、不同的测试实践和不同的维护。同样,这是以完全向后兼容的方式完成的。

特定于集成的软件包

在接下来的几周内,我们将致力于拆分一些受众最广、功能最关键的集成。这些集成将存在于其特定集成的独立软件包中。例如:langchain-openailangchain-anthropic 等。这些软件包将位于 LangChain monorepo 中或其各自的独立存储库中(取决于集成合作伙伴的意愿)。这将带来几个好处。它将使我们能够单独对这些软件包进行版本控制,并且如果进行了重大更改,可以通过适当的版本号提升来反映这些更改。它将简化测试过程,提高这些关键集成的测试覆盖率。它将使我们能够使第三方依赖项成为这些软件包的必需项,从而使安装更容易。对于拆分到其自己仓库中的软件包,它将允许其他公司拥有其集成。

💡
LangChain 的最大优势之一是提供了大量的集成。此步骤使围绕它们的开发者体验更加出色。

LangChain

保留在 langchain 包中的将是链、代理、高级检索方法以及构成应用程序认知架构的其他通用编排组件。

其中一些将是旧的遗留链 - 例如 ConversationalRetrievalChain,它是我们最流行的用于执行检索增强生成任务的链之一。我们将继续支持和维护这些类型的链。但是,我们将越来越多地转向使用 LangChain 表达式语言构建的链。

由于上一节中列出的许多原因,我们默认使用 LangChain 表达式语言。最重要的是,易于创建新链、步骤的透明度、易于编辑这些步骤以及易于公开流式、批量和异步接口。

在过去的几个月中,我们主要专注于使 LangChain 表达式语言和 langchain-core 处于稳固的状态。现在我们相信情况就是如此,我们将增加对更高级别抽象和链(全部由 LangChain 表达式语言驱动)的关注。

示例

让我们看一下这在实践中是什么样子的!为此,我们可以查看最近添加的用于回复电子邮件的 模板。让我们看一下导入,看看我们从每个包中导入了什么

from langchain_core.messages import AIMessage, HumanMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.tools import tool

langchain_core 中,我们导入了一些东西。首先,我们导入消息类型,例如 AIMessageHumanMessage,我们将使用它们来抽象出不同模型提供商处理这些对象的方式。接下来,将导入 ChatPromptTemplateMessagesPlaceholder。这些是一种封装逻辑的方法,该逻辑需要用户输入并生成要传递给聊天模型的消息列表。最后,我们将导入 tool。这是一个装饰器,我们可以将其放在任何函数上,以自动将其转换为 LangChain 工具对象。所有这些对象都是使用 LangChain 的核心。

from langchain_community.chat_models import ChatOpenAI
from langchain_community.tools.gmail import (
    GmailCreateDraft,
    GmailGetMessage,
    GmailGetThread,
    GmailSearch,
    GmailSendMessage,
)

langchain_community 中,我们导入第三方集成。首先,与 OpenAI 集成 - 我们将使用他们的聊天模型。接下来,我们导入一堆用于处理 Gmail 的工具。这些分别是基本 LangChain 抽象(ChatModelTool)的特定实例化。

from langchain.agents import AgentExecutor
from langchain.agents.format_scratchpad import format_to_openai_function_messages
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser
from langchain.tools.render import format_tool_to_openai_function

langchain 中,我们导入了一些东西。首先,我们导入 AgentExecutor。这是一种特定的认知架构,用于运行代理和工具。接下来,我们导入用于处理特定类型代理(使用 OpenAI 函数的代理)的实用程序。这包括 (a) 将 agent_scratchpad(代理可能采取的中间步骤)格式化为要传递给聊天模型的消息的逻辑,(b) 将 LLM 的输出解析为代理操作的输出解析器,以及 (c) 将工具列表转换为 OpenAI 函数期望的格式的函数。

以前,所有这些都是从同一个 langchain 包中导入的,即使它们代表三种不同类型的导入(基本逻辑、第三方集成和认知架构)。拆分 langchain 的部分价值在于更清楚地了解如何考虑每种类型的模块。

Python 和 JS 的对等性

我们收到了很多关于 Python 和 JS 包以及它们之间如何关联的问题。以这种方式拆分包(langchain-corelangchain-communitylangchain)可以解释我们围绕此的理念。

langchain-core 在两种语言之间已经非常接近功能对等。保持 Python 和 JavaScript 包的功能对等是我们的首要任务。我们正在开发一种可序列化的语法(我们已经在某些地方使用它);维护核心功能的跨语言支持非常重要。

关于 langchain-community 中的集成(及其自己的包),其中大多数将由任何一种语言自行决定,并且预计并非所有集成都将被移植过来。我们对实现功能对等的少数关键集成(目前主要是 LLM 提供商)感兴趣。

langchain 介于两者之间 - 它不像 langchain-core 那样接近功能对等,但将其实现为目标比 langchain-community 更重要。

LangChain Experimental

langchain-experimental 将保留作为放置更多实验性工具、链和代理的地方。“实验性”可能意味着几件事。目前,langchain-experimental 中的大多数实现要么是 (1) 更新、更“超前”的想法,我们希望鼓励人们使用和试用,但不确定它们是否是合适的抽象,要么是 (2) 可能有风险并可能引入 CVE(Python REPL,编写和执行 SQL)。我们分离这些工具、链和代理是为了向最终用户传达其实验性质。

LangChain 模板

两个月前,我们推出了 LangChain 模板,作为开始构建 GenAI 应用程序的最简单方法。这些是可以使用 LangServe 轻松部署的端到端应用程序。这些在几个方面与 langchain 库中的链和代理不同。

首先,它们不是 Python 库的一部分,而是已下载并成为您的应用程序一部分的代码。这具有巨大的优势,因为它们易于修改。随着时间的推移,我们观察到的主要事情之一是,当用户将 LangChain 应用程序投入生产时,他们必须对他们开始使用的链或代理进行一些自定义。他们至少必须编辑使用的提示,并且通常他们必须修改链的内部结构、数据如何流动。通过将此逻辑(提示和编排)作为应用程序的一部分 - 而不是作为库的源代码的一部分 - 它更易于修改。

第二个主要区别是这些模板预配置了各种集成。虽然链和代理通常需要您传入 LLM 或 VectorStore 才能使其工作,但模板已经预置了这些。由于不同的 LLM 可能需要不同的提示策略,并且不同的向量存储可能具有不同的参数,这使我们有可能与集成合作伙伴合作,以交付最能利用其特定技术的模板。

💡
我们已经添加了 50 多个不同的模板 - 在 这里 查看它们。

LangServe

三个月前,我们推出了 LangServe,作为部署 LangChain 应用程序的最佳方式。LangServe 是一个开源 Python 库,它本质上包装了 FastAPI,以自动为您的 LangChain 对象添加端点。它自动添加多个端点(流式处理、批量处理),并自动推断这些端点的输入/输出 - 这都是因为我们非常了解底层 LangChain 对象。这也使我们能够自动为这些链和代理启动简单的 UI。这使得向最终用户公开特定链以进行试用变得容易。

💡
我们发现,最好的团队可以快速迭代其 LLM 应用程序。这意味着尽快向最终用户公开,收集反馈,然后进行相应的调整。LangServe 旨在使所有团队都能轻松做到这一点。此外,它与 LangSmith(见下文)无缝集成,使反馈收集和迭代过程更加容易。

(我们还在开发 LangServe 的托管版本,允许一键部署 LangChain 应用程序 - 在 此处 注册候补名单)

LangSmith

LangChain 生态系统的最后一块拼图是 LangSmith - 您 LLM 应用程序的控制中心。

💡
LangSmith 是一个平台,可在整个旅程的各个步骤中补充 GenAI 开发体验。它与 LangChain 无缝集成,但也很容易单独使用。它仍处于私有 Beta 版(我们正在朝着 GA 努力),您可以在 此处 加入候补名单。

LangSmith 在一流的调试体验中派上用场。通过记录链和代理的所有步骤,您可以轻松地

  • 准确查看采取了哪些步骤以及按什么顺序
  • 查看这些步骤的确切输入是什么
  • 查看这些步骤的确切输出是什么
  • 进入给定步骤的 Playground,您可以在其中修改输入并查看这如何更改输出

当您构建这些复杂的链和代理时,其中主要部分是非确定性语言模型,这种类型的可观察性至关重要。从您开始构建的那一刻起,LangSmith 将大大提高您的迭代速度。

LangSmith 还包含一套额外的工具,旨在将您的应用程序从原型推向生产环境。这包括

  • 反馈收集 - 对于了解用户如何与您的产品互动非常重要
  • 数据集和测试 - 请参阅我们 最近的 工作 关于评估 的工作,其中使用了此功能
  • 监控 - 使用情况、反馈评分、延迟、令牌
  • 数据注释队列 - 用于快速标记数据
  • Hub - 用于协作处理提示

有关所有这些功能的更多信息,请查看我们最近发布的 YouTube 亮点系列

路线图

我们已经思考、研究和讨论此路线图一个多月了。以下是我们已采取的步骤以及未来要做的事情的摘要

[11/8 - 完成] 拆分出 langchain-core

[12/11 - 完成] 将所有集成拆分到 langchain-community 中,发布 langchain-core v0.1

[12/11-1/5] 将主要集成拆分到独立软件包中

[1/9] 发布 langchain v0.1

langchain v0.1 版本预计与今天存在的内容完全兼容。我们今天不发布 0.1 版本的原因是我们知道还有一些我们想要添加的功能,并且我们还想评估 langchain 中的一些逻辑是否适合移动到 langchain-core 中。

这实现了什么

这实现的主要事情是一个蓬勃发展的 GenAI 生态系统。LLM 的用例似乎是无限的。我们需要的是更多地探索和优化这些用例,而减少对必须支持流式处理、多个模型、跟踪等的担忧。

软件包的这种架构更强烈地为不仅应用程序,而且其他库和框架构建在 LangChain 之上或与之集成铺平了道路。我们已经看到这种情况发生在 GPT Researcher、CrewAI、LlamaIndex、PandasAI 等框架中。

这也为集成合作伙伴更全面地拥有不仅他们的集成,而且围绕其集成的框架铺平了道路。Datastax 团队及其 RAGStack 框架就是一个很好的例子。这建立在 LangChain 之上,但侧重于 (1) 一流的 AstraDB 和 CassandraDB 集成,以及 (2) 关于什么最适合 CassandraDB 的更主观的看法。这使 Datastax 能够为其软件用户提供最佳体验,但也与 LangChain 生态系统的其余部分无缝集成,因此他们不必重新发明 LLM 集成、文档加载器、跟踪等。

结论

我们对 GenAI 领域的看法是,它仍然处于非常早期且变化非常快的阶段。随着空间的发展,整个 LangChain 生态系统也将随之发展。LangChain 与一年前甚至三个月前的 LangChain 完全不同。我们相信,最近的更改以及 langchain-corelangchain-community 的引入对于为推动我们所有人前进奠定坚实的基础至关重要。我们期待看到您构建的内容 🙂

常见问题解答

问:我应该从哪个软件包开始?

答:如果您希望从头开始,LangChain 可能仍然是最好的入门软件包。它在后台使用 langchain-corelangchain-community,因此公开了最广泛的功能集合。

问:这三个软件包之间是否存在兼容性考虑,或者版本是否可互操作?

答:目前,我们当前版本的 LangChain 依赖于 langchain-core>=0.1,<0.2

问:LangChain 的链和代理会发生什么变化,例如 ConversationalRetrievalQA 链?

答:它们将继续存在,作为开始使用特定用例的简单方法!我们将越来越多地将它们转换为在后台使用 LCEL(或创建 LCEL 等效项),以获得 LCEL 的好处,但这些更高级别的接口将始终存在(并且是我们下个月关注的重点)。

问:我应该升级到哪个版本?

答:langchain>=0.0.350 具有所有更新!

问:我需要升级吗?

答:您不需要!所有这些更改都是以向后兼容的方式完成的,因此如果您选择忽略,则可以安全地忽略。

问:我是 LangChain 集成的贡献者,并且想要创建一个单独的软件包。我该如何做?

答:我们将在未来几天内添加说明和一个 CLI 以帮助您完成此操作 - 请密切关注 GitHub 讨论。