Press "Enter" to skip to content

LangChain:允许LLMs与您的代码互动

Photo by David Clode on Unsplash

学习如何使用工具为您的LLM实现自定义函数

介绍

生成模型引起了大家的关注。许多人工智能应用现在不再需要机器学习专家,而只需要知道如何调用API。

最近,例如,我参加了一个黑客马拉松,我需要实现一个自定义的命名实体识别,但我直接使用了一个LLM,并利用其少样本学习能力获得了我想要的结果,这对于赢得黑客马拉松来说已经足够了!(如果您想要,您可以在此处查看项目)。因此,对于许多实际应用,重点更多地转向如何与这些LLM进行交互和使用,而不是创建模型。LangChain是一个允许您做到这一点的库,我最近写了几篇关于它的文章。

LangChain工具

工具是LLM可以使用的用来增强其能力的实用工具。工具可以在链或代理中实例化。例如,一个LLM可能会在回答之前进行维基百科搜索以确保得到最新的回答。当然,代理可以使用多个工具,所以通常所做的是定义一个工具列表。

现在让我们来看看一个工具的结构。 工具只是由几个字段组成的类

  • name(str):定义工具的唯一名称
  • description(str):工具在自然语言中的实用性描述。LLM将能够阅读这个描述并判断是否需要该工具来回答查询。
  • return_direct(bool):例如,一个工具可能返回一个自定义函数的输出。我们想要将该输出直接呈现给用户(True)还是经过LLM预处理(False)?
  • args_schema(Pydantic BaseModel):例如,该工具可能使用一个自定义函数,其输入参数必须从用户的查询中检索。我们可以提供更多关于每个参数的信息,以便LLM能够更轻松地完成这一步骤。

如何定义一个工具

多种方法来定义一个工具,本文将介绍其中的几种。首先,我们导入所需的库并实例化一个OpenAI模型。为此,您将需要一个令牌,您可以在我以前的文章中了解如何获取它。

!pip install langchain!pip install openaifrom langchain import LLMMathChain, SerpAPIWrapperfrom langchain.agents import AgentType, initialize_agentfrom langchain.chat_models import ChatOpenAIfrom langchain.tools import BaseTool, StructuredTool, Tool, toolimport osos.environ["OPENAI_API_KEY"] = ... # 在这里插入您的API_TOKENllm = ChatOpenAI(temperature=0)

实例化一个工具的第一种方法是使用Tool类。

假设我们希望给工具提供搜索网络信息的能力,为此我们将使用一些名为SerpAPI的Google API,您可以在这里注册并获取API:https://serpapi.com/ 让我们实例化一个SerpAPIWrapper类,并使用from_function方法定义工具。

在func字段中,我们需要放置一个指向我们想要使用此工具启动的方法的指针,即SerpAPI的run方法。正如我们所见,我们给工具命名并描述它。比解释更容易。

search = SerpAPIWrapper()tools = [    Tool.from_function(        func=search.run,        name="搜索",        description="在需要回答有关当前事件的问题时非常有用"    ),]

现在,我们可以将创建的工具列表提供给代理,这里只有一个。

agent = initialize_agent(    tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)agent.run(    "谁是Bob Dylan的女朋友?")

自定义工具

我个人认为创建自定义工具的最清晰方法是继承 BaseTool 类。

class CustomTool(BaseTool):    name = "custom_tool"    description = "当您需要回答有关 VoAGI 文章的问题时很有用"    def _run(        self, query: str, run_manager: Optional[CallbackManagerForToolRun] = None    ) -> str:        """使用该工具。"""        return "我不是 VoAGI 专家,但我知道 Marcello 非常擅长!:I)"    async def _arun(        self, query: str, run_manager: Optional[AsyncCallbackManagerForToolRun] = None    ) -> str:        """异步使用该工具。"""        raise NotImplementedError("custom_search 不支持异步")

您可以看到这是一个自定义工具的实现,当用户提问有关 VoAGI 的问题时将使用该工具。然而,返回的字符串可能不会与我设置的完全相同,因为它将由大型语言模型进一步处理。

如果我们想直接返回某些内容,只需以以下方式添加“return_direct”字段。

class CustomTool(BaseTool):    name = "custom_tool"    description = "当您需要回答有关 VoAGI 文章的问题时很有用"    return_direct=True    def _run(        self, query: str, run_manager: Optional[CallbackManagerForToolRun] = None    ) -> str:        """使用该工具。"""        return "我不是 VoAGI 专家,但我知道 Marcello 非常擅长!:I)"    async def _arun(        self, query: str, run_manager: Optional[AsyncCallbackManagerForToolRun] = None    ) -> str:        """异步使用该工具。"""        raise NotImplementedError("custom_search 不支持异步")

即使我们不使用 _arun 方法(用于异步调用),我们仍然必须实现它,因为 BaseTool 是一个抽象类,如果我们不实现所有的抽象方法,将会出错。

实际例子

有一天,我的一个朋友说:“嘿 Marcello,由于你做 AI 和那种东西,为什么不给我做一个聊天机器人,可以在需要时返回医生的工作时间,并预约?”我解决这个问题的第一件事是使用 LangChain,并让 LLM 与用户进行交互,然后一旦模型理解到用户请求查看工作时间,它将直接返回一个 CSV 文件(或者如果你喜欢,可以返回一个数据帧)。

因此,对于这个用例也可以使用相同的方法。假设我们有一个名为 work_time.csv 的 CSV 文件

import pandas as pdclass WorkingHours(BaseTool):    name = "working_hours"    description = "当您需要回答有关医务人员工作时间的问题时很有用"    return_direct=True+    def _run(        self, query: str, run_manager: Optional[CallbackManagerForToolRun] = None    ) -> str:        """使用该工具。"""        df = pd.read_csv("working_hours.csv") #也许您需要从数据库检索一些实时数据        return df    async def _arun(        self, query: str, run_manager: Optional[AsyncCallbackManagerForToolRun] = None    ) -> str:        """异步使用该工具。"""        raise NotImplementedError("custom_search 不支持异步")

就这样,我的朋友想要的应用程序的原型只需要几行代码就完成了!当然,还要和一个优秀的前端开发人员合作,让它看起来更好!

最后的思考

LangChain 是一个最近的库,它允许我们在不同的上下文中使用 LLM 的强大功能。我发现能够使用 LLM 来理解上下文、了解用户的请求,然后运行自己的自定义函数来实际解决问题非常有用。这将使您能够编写具有灵活性的代码。要为您的应用程序添加功能,您只需要编写一个函数,并告诉模型在它认为需要时使用此函数,然后就完成了!如果您对这篇文章感兴趣,请在 VoAGI 上关注我!

💼 领英 | 🐦 推特 | 💻 网站

Leave a Reply

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