赞
踩
官方文档:代理(Agents)
前面有说到“链”,那么在链的组装过程中,我们还可能遇到几个问题,比如:
from langchain.agents import load_tools
from langchain.llms import OpenAI
llm = OpenAI(temperature=0)
tools = load_tools(["serpapi", "llm-math"], llm=llm)
这个示例代码里,是通过函数load_tools加载了一些langchain包里内置的工具类,其中llm-math这个工具类用到了AI,所以需要将llm参数传递进去。
然后进去这个load_tools函数里看看,发现其实是用名字映射到了各个工具。
_LLM_TOOLS: Dict[str, Callable[[BaseLanguageModel], BaseTool]] = {
"llm-math": _get_llm_math,
"open-meteo-api": _get_open_meteo_api,
}
def _get_llm_math(llm: BaseLanguageModel) -> BaseTool:
return Tool(
name="Calculator",
description="Useful for when you need to answer questions about math.",
func=LLMMathChain.from_llm(llm=llm).run,
coroutine=LLMMathChain.from_llm(llm=llm).arun,
)
到这里,就可以看出工具类的定义和使用方式了:自定义工具
上面还有指定一个coroutine参数,使用的是工具类的异步处理方法,我这边没有试过所以先暂时略过。
代理也分为很多种类,这里使用最简单的一种:
ZERO_SHOT_REACT_DESCRIPTION 仅基于工具的描述来确定要使用的工具
文档:代理类型
- zero-shot-react-description
此代理使用ReAct框架,仅基于工具的描述来确定要使用的工具。可以提供任意数量的工具,需要为每个工具提供描述。- react-docstore
这个代理使用ReAct框架与文档存储进行交互。必须提供两个工具:一个Search工具和一个Lookup工具(它们必须被命名为这样)。Search工具应该搜索文档,而Lookup工具应该查找最近找到的文档中的一个术语。- self-ask-with-search
这个代理使用一个被命名为Intermediate Answer的工具。这个工具应该能够查找问题的事实性答案。- conversational-react-description
这个代理程序旨在用于对话环境中。提示设计旨在使代理程序有助于对话。 它使用ReAct框架来决定使用哪个工具,并使用内存来记忆先前的对话交互。
先用示例的内置计算器工具来实践
import include from langchain.agents import initialize_agent, AgentType, load_tools from langchain.chat_models import ChatOpenAI llm = ChatOpenAI( model="gpt-35-turbo", model_kwargs={"deployment_id": "gpt-35-turbo"}, temperature=0, ) # 加载默认工具 tools = load_tools(["llm-math"], llm=llm) # 创建代理,传入工具、模型、代理类型,开启调试 agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True) # 提问 rs = agent.run("Assume you are 12 years old now, what's your age raised to the 0.43 power?") print(rs)
> Entering new AgentExecutor chain...
I need to use a calculator to raise my age to the 0.43 power.
Action: Calculator
Action Input: 12 ^ 0.43
Observation: Answer: 2.911038409866027
Thought:I now know my age raised to the 0.43 power.
Final Answer: 2.911038409866027
> Finished chain.
2.911038409866027
Process finished with exit code 0
从结果来看,由于这里只定义了一个计算器工具,因此agent也只会使用这一个工具。
为了尝试一下代理Agent的选择功能,这里自定义一个新工具,看是否会自动选择
import include from langchain import LLMMathChain from langchain.agents import initialize_agent, AgentType from langchain.chat_models import ChatOpenAI from langchain.tools import Tool llm = ChatOpenAI( model="gpt-35-turbo", model_kwargs={"deployment_id": "gpt-35-turbo"}, temperature=0, ) # 简单定义函数作为一个工具 def personal_info(name: str): info_list = { "Artorias": { "name": "Artorias", "age": 18, "sex": "Male", }, "Furina": { "name": "Furina", "age": 16, "sex": "Female", }, } if name not in info_list: return None return info_list[name] # 自定义工具字典 tools = ( # 这个就是上面的llm-math工具 Tool( name="Calculator", description="Useful for when you need to answer questions about math.", func=LLMMathChain.from_llm(llm=llm).run, coroutine=LLMMathChain.from_llm(llm=llm).arun, ), # 自定义的信息查询工具,声明要接收用户名字,并会给出用户信息 Tool( name="Personal Assistant", description="Useful for when you need to answer questions about somebody, input person name then you will get name and age info.", func=personal_info, ) ) agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True) # 提问,询问Furina用户的年龄的0.43次方 rs = agent.run("What's the person Furina's age raised to the 0.43 power?") print(rs)
可以看到代理会先思考说,首先需要获取Furina的年龄,因此要先使用能够查询用户信息的工具。
获取了用户信息后,代理发现已经获得了年龄信息,这时候需要使用计算器进行计算,于是调用了Calculator,得出最终结果。
> Entering new AgentExecutor chain... I need to use the Personal Assistant tool to get Furina's age first. Action: Personal Assistant Action Input: Furina Observation: {'name': 'Furina', 'age': 16, 'sex': 'Female'} Thought:Now that I have Furina's age, I can use the calculator to raise it to the 0.43 power. Action: Calculator Action Input: 16^0.43 Observation: Answer: 3.2943640690702924 Thought:I now know the final answer. Final Answer: 3.2943640690702924 > Finished chain. 3.2943640690702924 Process finished with exit code 0
到这里可以基本反映出来,非AI功能操作和AI功能操作可以通过工具+代理抉择的方式进行组装,从而形成一个以LLM为驱动核心的模块化处理应用,其效果的好坏完全取决于提示工程,也就是Prompts的好坏。
例如,如果我在工具描述里描述得模糊一些,不说明接收的参数,我们看看会发生什么
# 这是上面示例的自定义工具,现在我们去掉后面关于输入的描述,看看会发生什么
Tool(
name="Personal Assistant",
description="Useful for when you need to answer questions about somebody, input person name then you will get name and age info.",
func=personal_info,
)
# 改成这样
Tool(
name="Personal Assistant",
description="Useful for when you need to answer questions about somebody.",
func=personal_info,
)
最终发生了报错,这是因为AI不知道工具输入的情况下,它直接对工具进行了提问“What is Furina’s age?”,而我们简易的自定义工具无法处理这种提问,因此没有给出回复,因此进一步的,代理不知道计算器该用什么数值进行计算。
> Entering new AgentExecutor chain... I need to use the Personal Assistant tool to find out Furina's age. Action: Personal Assistant Action Input: "What is Furina's age?" Observation: None Thought:I need to use the Calculator tool to raise Furina's age to the 0.43 power. Action: Calculator Action Input: Furina's age ^ 0.43 Traceback (most recent call last): …………………………………… …………………………………… 各种报错 …………………………………… …………………………………… raise ValueError(f"unknown format from LLM: {llm_output}") ValueError: unknown format from LLM: I'm sorry, but the question is incomplete. Please provide the age of Furina or any other necessary information to form a complete mathematical expression. Process finished with exit code 1
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。