Press "Enter" to skip to content

将现有的LLM项目适应使用LangChain

使用LangChain将OpenAI调用重构为更强大的功能

照片由JJ Ying在Unsplash上提供

恭喜你,你有一个工作中的LLM概念验证,你为之感到自豪并准备向世界展示!也许你直接使用了OpenAI库,或者你使用了不同的基础模型和HuggingFace transformers。无论哪种方式,你都付出了辛勤的努力,现在正在寻找下一步。这可能意味着代码重构,为多个基础模型添加支持,或者添加更高级的功能,如agents或vector db。这就是LangChain的用武之地。

LangChain是一个用于处理LLM和开发基于它们的应用程序的开源框架。它有Python和JavaScript两个版本,并支持多个基础模型和LLM提供商。它还提供了许多实用函数来处理常见任务,例如文档分块或与向量数据库的交互。你相信这是值得一看的东西吗?看看这篇优秀的文章,它是开始了解可能性的好地方:

开始使用LangChain:构建LLM驱动应用程序的入门指南

使用Python构建任何东西的LangChain教程

towardsdatascience.com

本文将不专注于全新的开发,而是专注于重构现有应用程序。它也假设你对LangChain有一些基本了解,但会提供相关文档的链接。具体而言,我将研究重构一个我写过的项目,名为AdventureGPT,这是一个用于玩1977年的巨大洞穴冒险游戏的自主代理。如果你对了解更多关于该项目的信息感兴趣,请查看我之前写的关于它的文章:

AdventureGPT:使用LLM支持的代理玩文本冒险游戏

betterprogramming.pub

我对重构的几个方面最感兴趣:

  1. 使用链代替直接的OpenAI调用
  2. 替换专用的文档工具,使用LangChain的文档/数据处理

接下来将分别讨论这些方面。

让我们从链是什么开始。链是将几种提示操作技术组合在一起形成一个单一单元,从而得到一个单一基础模型调用的方法。一旦有了一个工作中的链,可以将链组合在一起并一起使用,以实现更复杂的任务。

LangChain提供了几种不同类型的链,本文重点介绍LLMChain和ConversationChain。LLMChain是最简单的链类型,它将提示模板与LangChain支持的LLM对象结合起来。ConversationChain提供了一个经验定制的对话式工作流,如聊天机器人。ConversationChain的一个主要特点是它能够包含记忆并将过去的对话部分轻松地存储到提示中。

提示模板是LangChain最强大的功能之一,允许你在提示中包含变量。当手动完成这个任务时,你可能会使用f-strings结合字符串连接和谨慎使用自定义__repr__方法,将数据插入到基础模型的提示中。使用提示模板,你可以通过在变量周围加上大括号来格式化字符串。就是这么简单。

根据你创建的链的类型,有些变量会被默认设置,例如对话历史记录或用户输入。这可能会增加相当多的复杂性。在传统的对话提示中,会有来自系统、AI助手、用户或人类的消息。当手动编写提示时,你使用“系统”、“人类”和“AI”等标签为每个消息标记提示。LangChain可以为你处理这些,允许你使用ChatPromptTemplate方法的from_messages来将每个消息指定为对象列表,从而实现更高级的抽象和自动的历史记录包含和格式化。

所有这些功能都是以复杂性为代价的。与简单地调整文本的提示相比,需要阅读广泛的文档并可能扩展现有代码以适应特定的用例。例如,对话提示通常只包含用户的输入和对话历史记录作为变量。然而,我想在我的PlayerAgent的提示中包含额外的游戏上下文,PlayerAgent负责与游戏世界进行交互。在将额外的变量添加到我的提示后,我看到了以下错误:

遇到了意外的提示输入变量。提示期望的是['completed_tasks', 'input', 'history', 'objective'],但从内存中获取的输入是['history'],并且输入作为正常输入的键。(type=value_error)

我进行了一些调查,并找到了一个现有的GitHub问题,描述了我遇到的确切问题,但没有明确的解决方案。尽管如此,我查看了ConversationChain类的源代码,并发现有一种特定的方法用于验证只有预期的变量作为输入传递。我创建了一个子类来继承原始类,并重写了这个方法。拥有自定义的CustomConversationChain类之后,我需要指定哪个变量应该被会话内存缓冲区用于用户(或在我的情况下,游戏)的输入,因为存在多个输入变量。通过input_key实例变量很简单,一切就都解决了。

完成将我的OpenAI调用转换为链式调用后,就是处理文档摄取的方式了。作为游戏循环的一部分,我接受了一个包含游戏任务的步骤说明文本的路径。当我第一次添加这个功能时,我只是将整个步骤说明传递给提示,并希望一切顺利。但随着我发现更复杂的步骤说明,这已经不再可能,因为步骤说明的长度超过了OpenAI ChatGPT允许的上下文窗口。因此,我将文本切成了500个标记的块,并多次运行提示将步骤说明转换为游戏任务。

当我说我将文本切成大约500个标记的块时,我是非常粗略地这样做的,依靠Python的字符串的split方法来标记化文本(这是一个非常粗略的近似,不符合大多数LLM标记化文本的方式),然后通过join方法将令牌数组转换回字符串,再次使用String类的方法。虽然这样可以工作,但LangChain提供了更好的解决方案。

LangChain能够以多种不同的方式拆分文本。对于大多数人来说,最相关的方式是按标记拆分,因为它保留了文档的流程。这里有一个专门介绍按标记拆分文本的页面的文档。支持多种NLP库进行标记化,但我选择了LLM原生解决方案tiktoken,这是第一种方法。只需要几行代码就可以轻松而且更有效地拆分文本,同时保留空格。

这只是LangChain能够处理的文档准备工作的冰山一角。它还能将文本块转换为适当的文本嵌入,以便存储在向量数据库中,并在以后检索和包含在提示中。我计划在我的项目的未来中这样做,将提供的步骤说明的相关部分作为PlayerAgent的输入。

LangChain是一个功能强大的开源框架,提供了一系列功能和实用函数,用于处理LLM并在其上开发应用程序。无论您使用的是OpenAI库还是其他基础模型,LangChain都支持多个基础模型和LLM提供商,使其成为您项目的多功能选择。

与原始提示管理相比,LangChain可能会引入一些复杂性,但它提供了许多好处,并简化了与LLM的交互。它标准化了处理过程,并提供了有用的工具来增强您的提示并最大限度地发挥您选择的LLM的潜力。

如果您有兴趣了解如何在一个真实项目中实现LangChain,可以查看AdventureGPT的更新代码库,该代码库利用LangChain对现有应用进行了重构和改进。

GitHub – oaguy1/AdventureGPT at langchain

通过在GitHub上创建一个帐户,为oaguy1/AdventureGPT做出贡献。

github.com

总的来说,LangChain对于与LLM一起工作的开发人员来说是一个宝贵的资源,提供了一个全面的框架和广泛的功能,以增强LLM驱动的应用程序。探索LangChain,并发挥您的LLM项目的全部潜力!

Leave a Reply

Your email address will not be published. Required fields are marked *