什么是代理(Agent)?
在编程中,代理的核心思想是使用一个大型语言模型(LLM)来选择执行的一系列动作。在传统的链式编程(chains)中,这些动作通常被硬编码在代码中。而在代理模式中,一个语言模型被用作推理引擎,来确定要采取哪些动作以及以何种顺序执行。
代理的关键概念:
AgentAction(代理动作): 这是一个数据类,代表了代理应该执行的动作。它包含一个
tool
属性,表示应该调用的工具的名称,以及一个tool_input
属性,表示该工具的输入。AgentFinish(代理完成): 这是一个数据类,表示代理已经完成任务,应该将结果返回给用户。它具有一个
return_values
参数,是一个要返回的字典。通常,它只包含一个键 -output
- 代表一个字符串,因此通常只返回这个键。Intermediate Steps(中间步骤): 这些代表了先前代理动作和相应的输出,它们会被传递下去。这对于将来的迭代非常重要,因为代理需要知道它已经完成了哪些任务。这个类型被定义为
List[Tuple[AgentAction, Any]]
。需要注意,observation
目前被定义为Any
类型,以确保最大的灵活性。实际上,它通常是一个字符串。
在Langchain中,代理可以根据需求进行自定义,也可以使用官方提供的代理。下面是一个示例代码,演示了如何使用Langchain的代理功能:
# 导入必要的模块和工具
from langchain.agents import initialize_agent, Tool
from langchain.agents import load_tools
from langchain.llms import OpenAI
from langchain.agents import AgentType
from langchain import hub
from langchain.tools.render import render_text_description
# 初始化配置
import os
import config
config.init(os)
# 定义查询
query = "对比下InternLM-123B和gpt4"
# 初始化LLM模型和工具
llm = OpenAI(temperature=0, verbose=True)
tools = load_tools(["serpapi", "llm-math"], llm=llm)
llm_with_stop = llm.bind(stop=["\nObservation"])
prompt = hub.pull("hwchase17/react")
prompt = prompt.partial(
tools=render_text_description(tools),
tool_names=", ".join([t.name for t in tools]),
)
# 定义代理
agent = {
"input": lambda x: x["input"],
"agent_scratchpad": lambda x: format_log_to_str(x['intermediate_steps'])
} | prompt | llm_with_stop | ReActSingleInputOutputParser()
# 初始化代理执行器
agent_executor = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
# 执行查询
agent_executor.invoke({"input": query})
以上代码演示了如何使用Langchain的代理功能,通过LLM的代理增加了数学运算和搜索两种能力。这个例子展示了Langchain代理的灵活性和强大功能。
但是你如果稍微深入点研究会发现agent的Tool只能传入2个,超过了就会崩溃。
而且还有其他问题,我尝试问了他100以内的素数,它居然报错了
ValueError: unknown format from LLM: This cannot be solved using the numexpr library.
我把同样的问题给了gpt3.5他就给出了结果,原因是因为llm-math这个Tool接管这个逻辑分支,名字叫llm-math怎么敢啊?
然后我把这个Tool删除之后它就运行正常了。