基于LangChain的LLM应用开发7——代理

君子性非异也,善假于物也。

普通人使用大语言模型,很容易就把大语言模型当作百科全书。的确,使用ChatGPT的时候,很容易让我们有错觉,感觉它已经记忆并且学会了大量从互联网上获取的信息:无论你问任何问题,几乎总能得到一个看似合理的答案 😅 (偶尔会装死说不懂某个问题,其实是程序拦截,由于某些原因不方便回答而已。)

其实就目前大语言模型的水平而言,把大语言模型作为推理引擎更有用:给它提供一些文本或者其他信息来源,大语言模型可能会使用从互联网学习的背景知识,同时也会利用我们提供的新信息来帮助回答问题、推理内容,甚至决定接下来要做什么。LangChain的代理框架会协助我们做这件事。

代理就是一种用大语言模型做出决策、调用工具来执行具体操作的系统。通过设定代理的性格、背景以及工具的描述,你可以定制代理的行为,使其能够根据输入的文本做出理解和推理,从而实现自动化的任务处理。

很多年前,我用过一个流行的工作流开源软件:shark,shark支持WFMC 的 "ToolAgents"接口。ToolAgent和今天要说的代理(Agent)使用Tool的方式很类似,阳光底下无新鲜事,以前是工作流系统要和外部世界打交道,现在是大语言模型和外部世界交流,采用类似的机制很正常。当然,科技是在发展的,以前只会固定调用某个工具,现在会由大语言模型自主选择调用哪个工具。

工具代理(Tool Agent)为 Enhydra Shark 提供了面向不同软件的接口。例如,MailToolAgents、SOAPToolAgent 和 RuntimeApplicationToolAgent 实现了发送和接收邮件、调用网络服务以及启动本地可用应用程序所需的连接性。

如果说链是LangChain的基础功能,代理就是LangChain里最强大的功能。我们今天会深入了解什么是代理,如何创建和使用代理,如何使用不同类型的LangChain内置工具:数学工具、维基百科工具、搜索引擎等,当内置的工具不能满足时,如何创建自己的工具,这样就可以让代理与任何数据存储、接口或者功能进行互动。

代理就像一个多功能的调度总管,它能够接触并使用一套工具。根据用户的输入,代理会决定调用哪些工具。它不仅可以同时使用多种工具,而且可以将一个工具的输出结果作为另一个工具的输入。

准备

同样,先通过.env文件初始化环境变量,记住我们用的是微软Azure的GPT,具体内容参考本专栏的第一篇。

from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())  # read local .env file

deployment = "gpt-4"
# deployment = "gpt-35-turbo"
model = "gpt-4"

需要安装wikipedia库。

!pip install -U wikipedia

我们会用到AzureChatOpenAI类,注意temperature会设置为0以消除任何可能出现的随机性。因为我们会使用LLM作为代理的推理引擎,它会连接到其他数据和计算资源,所以,我们希望这个推理引擎尽可能好、尽可能精确。

AzureChatOpenAI(temperature=0, deployment_name=deployment)

使用Agent

使用工具计算数学题

from langchain.agents import load_tools, initialize_agent
from langchain.agents import AgentType
from langchain.chat_models import AzureChatOpenAI

llm = AzureChatOpenAI(temperature=0, deployment_name=deployment)
tools = load_tools(["llm-math","wikipedia"], llm=llm) #加载工具
agent= initialize_agent(
    tools, 
    llm, 
    agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION,
    handle_parsing_errors=True,
    verbose = True)
agent("What is the 25% of 300?")

llm-math工具实际上是一个链,它结合LLM和计算器来解决数学问题。

wikipedia工具是一个连接到维基百科API的程序,允许你查询维基百科上的内容,并返回查询结果。

我们会使用CHAT_ZERO_SHOT_REACT_DESCRIPTION的代理类型,这种类型用了ReAct来激发更好的推理能力。

这里简单说一下大语言模型的ReAct框架。(注意不要和前端的React混淆)

ReAct 是一种组织Prompt的技术,能最大化语言模型的推理能力。通过 ReAct 框架,大模型将被引导生成一个任务解决轨迹,即观察环境 - 进行思考 - 采取行动。观察和思考阶段被统称为推理(Reasoning),而实施下一步行动的阶段被称为行动(Acting)。每一步推理过程中,都会详细记录,这也改善了大模型解决问题时的可解释性和可信度。

  • 在推理阶段,模型对当前环境和状态进行观察,并生成推理轨迹,从而使模型能够诱导、跟踪和更新操作计划,甚至处理异常情况。
  • 在行动阶段,模型会采取下一步的行动,如与外部源(如知识库或环境)进行交互并收集信息,或给出最终答案。

ReAct 框架的这些优点,使得它在未来的发展中具有巨大的潜力。我们可以期待 ReAct 框架将能够处理更多、更复杂的任务。特别是随着具身智能的发展,ReAct 框架将能够使智能代理在虚拟或实际环境中进行更复杂的交互。例如,智能代理可能会在虚拟环境中进行导航,或者在实际环境中操作物理对象。这将大大扩展 AI 的应用范围,使得它们能够更好地服务于我们的生活和工作。

上面的代码很简单,就是调用load_tools来加载工具函数,然后通过initialize_agent初始化代理,最后运行代理计算数学问题:What is the 25% of 300?

这个例子很简单,但是麻雀虽小,五脏俱全,我们刚好可以用来理解ReAct的基本框架。

进入AgentExecutor链,开始思考(Thought)需要做什么,然后开始行动(Action),这里会传入一个json对象:操作(action)和操作(action_input)的输入,action对应的是要使用的工具,action_input就是要使用工具的输入。接下来,就到了观察结果(Observation):观察工具返回的计算结果Answer: 75.0,大模型思考(Thought)之后,认为得到了结果就返回最终答案(Final Answer)。如果思考之后认为还没有得到最终的结果,可能会继续调用其他工具,继续Action、Action Input、Observation、Thought……(Thought/Action/Action Input/Observation can repeat N times)
在这里插入图片描述

调用维基百科接口

接下来,我们来看一个调用维基百科接口的示例。我们会问一个问题:Tom M. Mitchell 写了什么书?为了预防重名的情况,我们加入背景信息:

Tom M. Mitchell is an American computer scientist and the Founders University Professor at Carnegie Mellon University (CMU).

question = "Tom M. Mitchell is an American computer scientist \
and the Founders University Professor at Carnegie Mellon University (CMU).\
what book did he write?"
result = agent(question)

可以看到,代理会调用维基百科工具,并且找到了两个维基百科的页面,LLM结合我们给出的背景信息,找到了正确的页面,并且从页面的摘要返回了我们想要的结果。
在这里插入图片描述

执行Python代码

如果你用过GitHub Copilot/Cursor(如果没用过,赶紧去体验),或者ChatGPT的代码解释器插件,就知道它们最常用的功能就是用LLM写代码,执行生成的代码。我们这里用代理做同样的事情。

from langchain_experimental.agents.agent_toolkits.python.base import create_python_agent
from langchain_experimental.tools.python.tool import PythonREPLTool

agent = create_python_agent(
    llm,
    tool=PythonREPLTool(),
    verbose=True
)
customer_list = [["Harrison", "Chase"], 
                 ["Lang", "Chain"],
                 ["Dolly", "Too"],
                 ["Elle", "Elem"], 
                 ["Geoff","Fusion"], 
                 ["Trance","Former"],
                 ["Jen","Ayai"]
                ]
agent.run(f"""Sort these customers by last name and then first name 
and print the output: {customer_list}""")

首先,要创建一个Python的代理,传入一个工具:PythonREPLTool(REPL是一种与代码互动的方式,类似Jupyter Notebook),代理可以用REPL执行代码,得到代码运行结果,结果回传给代理,代理决定接下来做什么。

我们需要代理解决的问题是让它给一组客户名单customer_list排序。这里很重要的一点是让代理打印输出结果,打印出的内容后面会反馈给LLM,让LLM对代码输出的结果进行推理。

在这里插入图片描述

如果想了解具体的执行过程,可以开启Debug模式:

import langchain
langchain.debug=True
agent.run(f"""Sort these customers by \
last name and then first name \
and print the output: {customer_list}""") 
langchain.debug=False

再次推荐LangChain公司开发的平台:https://smith.langchain.com/ (邀请码去上一篇文章找),有了它,看调用过程就如掌上观纹。

在这里插入图片描述

使用自定义工具

上面都是使用LangChain内置的工具,代理的一大优势是可以连接你自己的信息来源、接口、数据,这时候就需要创建自己的工具。

简单起见,我们定义一个工具来获取当前日期。

需要先安装库:!pip install DateTime

from langchain.agents import tool
from datetime import date
@tool
def time(text: str) -> str:
    """Returns todays date, use this for any 
    questions related to knowing todays date. 
    The input should always be an empty string, 
    and this function will always return todays
    date - any date mathmatics should occur \
    outside this function."""
    return str(date.today())
agent= initialize_agent(
    tools + [time], 
    llm, 
    agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION,
    handle_parsing_errors=True,
    verbose = True)
try:
    result = agent("whats the date today?") 
except: 
    print("exception on external access")

定义tool很简单:导入tool装饰器,将这个装饰器用于任何函数就可以将函数转换为LangChain可以使用的tool。关键是要写好工具函数的注释,那样LLM才清楚什么情况下要调用、如何调用这个tool。

展望

在2023-11-6日的OpenAI开发者大会上,OpenAl放出了一系列Assistants API,方便人们构建类AIAgent的应用(能学习新知识,然后调用模型和工具来执行任务)那么是否没必要使用LangChain的代理机制了?

参考

  1. 短课程:https://learn.deeplearning.ai/langchain/lesson/7/agents
  2. 文档:https://python.langchain.com/docs/modules/agents/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值