33|三个层次重新审视LangChain
你好,这里是极客头条。
大模型应用开发是一个快速演化的领域,作为应用开发框架的 LangChain 同样也经历着一个快速演化过程。
今天我们邀请了郑晔老师 ,让他带我们重新认识一下LangChain。郑晔老师是极客时间多门课程的作者,也是一位有着 20 多年研发经验的技术老兵。ChatGPT 问世之后,他很快进入到 AI 应用开发领域,积累了丰富的理论和实战经验。他的第五季课程《程序员的AI开发第一课》已经全集上线,如果你感兴趣可以深度学习。
以下是正文:
LangChain是什么?
LangChain是什么?大部分人的理解是,LangChain 是一个开发框架,用来开发各种基于大模型的应用。我们知道,大模型应用开发是一个快速演化的领域,作为应用开发框架的 LangChain 同样也经历着一个快速演化过程。
如果你在 2023 年学过 LangChain 这个框架,再来看 2024 年利用 LangChain 开发的代码,你可能会完全不认识了,因为这期间引入了新的代码表达方式。即便简单如 LangChain 是什么的话题,含义也在不断演化。
站在我写下这段文字的时间点(2024 年),理解 LangChain 有三个层次:
-
开发框架
-
社区生态
-
扩展生态
接下来,我们就从这三个层次来重新认识一下 LangChain。
开发框架
在 LangChain 的自我介绍中,开发框架依然是首要的身份认同。
LangChain is a framework for developing applications powered by large language models (LLMs).
作为一个框架,LangChain 最重要的价值是提供了一些开发应用所需的基础抽象和 LangChain 表达式语言。我们来看一段示例代码:
chain = model | parser
chain.invoke(messages)
这段代码的核心含义就是将一个一个组件组装到一起,形成一条链,然后,调用这条链。LangChain 应用的代码核心就是构建一条这样的链,这也是 LangChain 这个名字里 Chain 的含义。我们后面会看到的各种代码,本质上就是用各种组件组装出一条链来。
在这段代码中,用到的两个组件是模型和输出结果解析器。当我们把消息传给这条链时,它会先调用模型根据消息生成相应的内容,然后,把这个生成的内容传给输出结果解析器,解析成我们需要的格式。
这个例子里的模型(model)和输出结果解析器(parser)都是 LangChain 提供的基础抽象,类似这样的抽象,在 LangChain 框架中还提供了好很多,比如提示词模板、文档加载器、向量存储等。下一讲,我们会花些篇幅讨论核心的抽象,帮助你更好地理解 LangChain 的这些组件。
上面示例还有一个重点,就是这段代码本身的表达方式,也就是:
chain = model | parser
这就是 LangChain 表达式语言(LangChain Expression Language,简称 LCEL)的写法。原本用各种组件组装链是一个非常繁琐的过程,但自从 LangChain 引入了 LCEL 之后,通过管道符,也就是 | 进行组装之后,这个过程就变成了一个声明式的代码,代码的清晰程度一下子上了一个大台阶。
从本质上说,LCEL 就是 LangChain 的一种内部 DSL,引入 DSL 的目的就是要提升代码的表达性。关于 DSL 更多的内容,可以参考我的《软件设计之美》中的《11 | DSL:你也可以设计一门自己的语言》。
社区生态
我们可以把 LangChain 定义的基础抽象理解成一个一个的接口,但只有接口是无法完成任何工作的,我们还需要这些接口具体的实现。为了降低依赖程度,这些实现没有放在 LangChain 的核心框架中,于是我们就需要扩大对于 LangChain 的理解,把这些实现涵盖进来,这就是 LangChain 的社区生态。
社区生态包含了大量的各种实现,我们首先能想到的就是各种大模型,比如,OpenAI 的 GPT、Anthropic 的 Claude 等等,都有对应的实现,国内的很多大模型也有对应的实现,真正去查看一下,你就会发现,原来各种各样的大模型有这么多。
除了大模型,其它基础抽象都有很多实现,比如,向量数据库,有 Milvus、FAISS、Qdrant、Chroma 等等,文档加载既可以加载一个 Web 页面,也可以从诸如 S3、微软 OneDrive 加载,甚至从 Twitter、Telegram 加载内容。总之,针对不同的抽象,都有对应的实现,你可以根据自己的需要在 LangChain 的集成页面上找到对应的内容。
除了直接的代码实现,还有各种提示词模板。相比于其它的代码,提示词模板都是纯文本。LangChain 社区有一个专门的提示词社区。在这里,可以找到各种类别的提示词:实现 Agent 、代码编写、文档问答、内容总结,主流的提示词在这里都可以找到。而在编写代码的过程中,我们只要把它加载过来,就可以形成一个提示词模板:
prompt = hub.pull("hwchase17/react")
runnable = prompt | model
如果说前面提到的都是直接的 LangChain 抽象实现,那还有一批实现就跳出了直接实现接口的范畴,这就是工具。随着 Agent 的兴起,工具成为了扩展 AI 能力的一种重要手段。天下工具如此之多,社区支持就成为了最好的选择:搜索、代码解析、网页浏览、数据库集成等等,各种工具五花八门。
我们对待社区生态应该是照方抓药,用到哪个东西,就到社区里去找相应的实现,完全没有必要一一学习,毕竟数量实在是太多了。
扩展生态
LangChain 社区蓬勃发展,各种扩展层出不穷,但所有这些扩展都围绕着一个目标,如何构建一个链。除了构建链之外,还有什么其它事情可以做呢?
事实上,LangChain 团队确实在探索更多可做的事情,所以,在了解 LangChain 时,你会看到一些与 LangChain 相关的名字。这就是 LangChain 的拓展生态:
-
LangServe,它是把 LangChain 编写的链部署成 REST API 的一个工具。因为我们编写的应用多半是以服务的方式对外提供,LangServe 简化了 LangChain 应用服务化的门槛。不过,它更多地是面向 LangChain 的使用场景设计的,其提供的服务是否适合你的应用,还是需要根据你自己的情况评估。
-
LangSmith,它是 LangChain 团队提供的一个SaaS平台,帮助开发者调试、追踪、测试、评估和监控基于大模型的应用。
-
LangGraph,它提供了又一种构建 Agent 的方式,把 Agent 的状态流转构建成一个图。LangChain 团队甚至构建了一个 IDE:LangGraph Studio,简化这个图的构建过程。
拓展生态我就不做过多的介绍了,因为这个部分在开发社区的接受程度远远不如 LangChain 的开发框架和社区生态。你只要知道它们的存在即可,如果有需要再去深入了解。
如何使用 LangChain?
至此,我们已经对 LangChain 有了一个基础的了解。既然 LangChain 是一个开发框架,我们接下来是不是就是用 LangChain 写代码了,且慢!在开始写代码之前,我们还有些东西值得讨论。
首先,是否选择 LangChain 是一个问题。作为一个框架,LangChain 提供了一些抽象,但这里有一个问题,这些抽象是否合理可谓是见仁见智的一个问题。比如:
-
如果你的应用如果只需要对接 OpenAI 的模型,模型抽象对你来说就是多余的。顺便说一下,兼容 OpenAI API 的模型越来越多,这也降低了模型抽象的价值。
-
如果你的应用做的都是一次性工作,比如,翻译一句话,LangChain 模型中的记忆存储之类的抽象也是多余的。
-
虽然提示词模板不错,但像 Python 这样的语言本身也有字符串模板。
-
……
我看过一些开源项目的代码,他们虽然选择了 LangChain,但并没有选择 LangChain 的基础抽象,而是单纯地利用 LangChain 的代码,此外,它的社区生态很好地提供了各种集成,也降低了开发的难度。
即便是作为开发框架,LangChain 也不是社区里的唯一选择,像 LlamaIndex 这样的框架也可以成为构建大模型应用的选择。
其次,LangChain 是一个很好的学习材料。LangChain 是一个开发框架,而且提供了大量的示例。了解了 LangChain 之后,我们就可以充分利用 LangChain 资源学习如何编写各种大模型应用,无论是 RAG,还是 Agent,亦或是如何利用工具,我们都可以通过 LangChain 来学习。
在学习过程中,很重要的一个组成部分就是如何编写提示词,LangChain 的代码库里就有大量可以学习的提示词。当初我在学习如何利用工具的代码时,从中学到了 ReAct 提示词,也学到了提示工程如何与具体代码结合起来,大大地提升了我对 Agent 实现的理解。
好了,今天的分享就到这里。虽然在很多人眼中,LangChain只是一个开发框架,但实际上,它已经形成了一个完整的生态,有社区生态,也有扩展生态。如果你有兴趣,可以课后看看它的集成页面,了解更多内容。