定义
LLM只提供了最通用的功能,如果想要一些更专业化的功能,比如数学运算、网页搜索等,就需要调用相应的Tool。包装了Tool的LLM会用Agent来进行封装,也就是代理。
代理的类型
一共9种,只列出了4种:
名称 | 描述 |
---|---|
zero-shot-react-description(默认) | 这种代理类型在没有任何先前信息的情况下,直接生成对问题的反应和回答。它依赖于模型本身的通用知识和理解能力来处理问题 |
react-docstore | 这种代理类型与文档进行交互。它可以访问一个或多个预先定义的文档库,从中提取相关信息来回答问题。这对于需要引用具体文档或数据的任务非常有用 |
self-ask-with-search | 这种代理类型会在回答问题前先进行自我提问,然后使用搜索引擎或其他信息检索工具来寻找答案。这种方法特别适用于需要实时获取信息或处理复杂问题的场景 |
conversational-react-description | 这种代理类型在对话上下文中生成反应和回答。它能够记住对话的历史内容,并根据对话的上下文进行更为连贯和相关的回答。这对于持续对话或需要上下文理解的任务非常有效 |
后四种代理的代码示例如下:
react-docstore
from langchain import OpenAI, Wikipedia
from langchain.agents import initialize_agent, Tool
from langchain.agents import AgentType
from langchain.agents.react.base import DocstoreExplorer
# 以Wikipedia作为文档进行查询
docstore=DocstoreExplorer(Wikipedia())
# 定义工具
tools = [
Tool(
name="Search",
func=docstore.search,
description="useful for when you need to ask with search"
),
Tool(
name="Lookup",
func=docstore.lookup,
description="useful for when you need to ask with lookup"
)
]
# 初始化LLM
llm = OpenAI(temperature=0, model_name="text-davinci-002")
# 初始化agent
react = initialize_agent(tools, llm, agent=AgentType.REACT_DOCSTORE, verbose=True)
# 定义prompt
question = "Author David Chanoff has collaborated with a U.S. Navy admiral who served as the ambassador to the United Kingdom under which President?"
react.run(question)
self-ask-with-search
from langchain import OpenAI, SerpAPIWrapper
from langchain.agents import initialize_agent, Tool
from langchain.agents import AgentType
# 初始化LLM
llm = OpenAI(temperature=0)
# 初始化谷歌搜索的装饰器
search = SerpAPIWrapper()
# 把搜索功能集成到tool中
tools = [
Tool(
name="Intermediate Answer",
func=search.run,
description="useful for when you need to ask with search"
)
]
# 定义并运行代理
self_ask_with_search = initialize_agent(tools, llm, agent=AgentType.SELF_ASK_WITH_SEARCH, verbose=True)
self_ask_with_search.run("What is the hometown of the reigning men's U.S. Open champion?")
conversational-react-description
from langchain.agents import Tool
from langchain.agents import AgentType
from langchain.memory import ConversationBufferMemory
from langchain import OpenAI
from langchain.utilities import SerpAPIWrapper
from langchain.agents import initialize_agent
# 一般会用谷歌搜索缝一个搜索功能,应对更复杂的提问
search = SerpAPIWrapper()
tools = [
Tool(
name = "Current Search",
func=search.run,
description="useful for when you need to answer questions about current events or the current state of the world"
),
]
# 为了节省内存而造的缓冲器
memory = ConversationBufferMemory(memory_key="chat_history")
# 定义LLM
llm=OpenAI(temperature=0)
# 初始化agent
agent_chain = initialize_agent(tools, llm, agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION, verbose=True, memory=memory)
#连续调用agent实现连续对话
agent_chain.run(input="hi, i am bob")
agent_chain.run(input="what's my name?")
自定义代理
自己创建一个代理类CustomAgent(),然后继承代理类模板。有两种模板:
名称 | 描述 |
---|---|
BaseSingleActionAgent | 设计用于只需要执行一个动作的任务;通常只需要实现 plan 和 finish 方法。 |
BaseMultiActionAgent | 设计用于需要多个步骤才能完成的任务;需要实现 plan, react, 和 finish 方法,并且需要在 plan 和 react 之间进行多次循环。 |
代码示例如下:
BaseSingleActionAgent
from langchain.agents import BaseSingleActionAgent
from langchain.schema import AgentAction, AgentFinish
class AdditionAgent(BaseSingleActionAgent):
def plan(self, inputs: dict) -> AgentAction:
num1 = inputs.get('num1')
num2 = inputs.get('num2')
if num1 is None or num2 is None:
raise ValueError("Inputs must include 'num1' and 'num2'.")
action = AgentAction(
action="addition",
action_input={"num1": num1, "num2": num2}
)
return action
def response(self, action: AgentAction) -> AgentFinish:
if action.action != "addition":
raise ValueError("Unsupported action. This agent only supports 'addition' action.")
num1 = action.action_input['num1']
num2 = action.action_input['num2']
result = num1 + num2
return AgentFinish(
return_values={"result": result}
)
# Usage example
agent = AdditionAgent()
# Plan the action
inputs = {'num1': 3, 'num2': 5}
action = agent.plan(inputs)
# Perform the action and get the response
result = agent.response(action)
print(result.return_values) # Output: {'result': 8}
BaseMultiActionAgent
from langchain.agents import BaseMultiActionAgent
from langchain.schema import AgentAction, AgentFinish
class AdditionAgent(BaseMultiActionAgent):
def plan(self, inputs: dict) -> AgentAction:
num1 = inputs.get('num1')
num2 = inputs.get('num2')
if num1 is None or num2 is None:
raise ValueError("Inputs must include 'num1' and 'num2'.")
action = AgentAction(
action="addition",
action_input={"num1": num1, "num2": num2}
)
return action
def response(self, action: AgentAction) -> AgentFinish:
if action.action != "addition":
raise ValueError("Unsupported action. This agent only supports 'addition' action.")
num1 = action.action_input['num1']
num2 = action.action_input['num2']
result = num1 + num2
return AgentFinish(
return_values={"result": result}
)
def react(self, inputs: dict) -> AgentFinish:
"""
React to inputs by planning and executing an action.
Args:
inputs (dict): The inputs should include two keys: 'num1' and 'num2'.
Returns:
AgentFinish: The result of the addition.
"""
action = self.plan(inputs)
result = self.response(action)
return result
# Usage example
agent = AdditionAgent()
# React to inputs
inputs = {'num1': 3, 'num2': 5}
result = agent.react(inputs)
print(result.return_values) # Output: {'result': 8}
工具和工具包
每个工具包含一个单独的功能,工具包中有一堆工具。两者都可以丢进agent中,使用时按需选择。
工具类可以自定义,只需要继承BaseTool类