ReActAgent - 使用计算器工具的简单介绍
这是一个展示ReAct智能体在简单计算器工具上运行的笔记本(没有复杂的RAG流水线或API调用)。
我们展示它如何通过逐步推理使用不同工具来实现最终目标。
ReAct智能体相较于函数调用智能体的主要优势在于,它能与任何大型语言模型协同工作,无论该模型是否支持函数调用功能。
如果您在 Colab 上打开这个笔记本,您可能需要安装 LlamaIndex 🦙。
%pip install llama-indeximport os
os.environ["OPENAI_API_KEY"] = "sk-..."我们设置了一些简单的 multiply 和 add 工具。请注意,您可以定义任意函数并将其传递给 FunctionTool(它将处理文档字符串和参数签名)。
def multiply(a: int, b: int) -> int: """Multiply two integers and returns the result integer""" return a * b
def add(a: int, b: int) -> int: """Add two integers and returns the result integer""" return a + bfrom llama_index.llms.openai import OpenAIfrom llama_index.core.agent.workflow import ReActAgentfrom llama_index.core.workflow import Context
llm = OpenAI(model="gpt-4o-mini")agent = ReActAgent(tools=[multiply, add], llm=llm)
# Create a context to store the conversation history/session statectx = Context(agent)通过流式传输结果,我们可以看到完整的响应,包括思考过程和工具调用。
如果我们只想流式传输结果,可以缓冲数据流,并在响应中出现 Answer: 时开始流式传输。
from llama_index.core.agent.workflow import AgentStream, ToolCallResult
handler = agent.run("What is 20+(2*4)?", ctx=ctx)
async for ev in handler.stream_events(): # if isinstance(ev, ToolCallResult): # print(f"\nCall {ev.tool_name} with {ev.tool_kwargs}\nReturned: {ev.tool_output}") if isinstance(ev, AgentStream): print(f"{ev.delta}", end="", flush=True)
response = await handlerThought: The current language of the user is: English. I need to use a tool to help me answer the question.Action: multiplyAction Input: {"a": 2, "b": 4}Thought: Now I have the result of the multiplication, which is 8. I will add this to 20 to complete the calculation.Action: addAction Input: {'a': 20, 'b': 8}Thought: I can answer without using any more tools. I'll use the user's language to answer.Answer: The result of 20 + (2 * 4) is 28.print(str(response))The result of 20 + (2 * 4) is 28.print(response.tool_calls)[ToolCallResult(tool_name='multiply', tool_kwargs={'a': 2, 'b': 4}, tool_id='a394d807-a9b7-42e0-8bff-f47a432d1530', tool_output=ToolOutput(content='8', tool_name='multiply', raw_input={'args': (), 'kwargs': {'a': 2, 'b': 4}}, raw_output=8, is_error=False), return_direct=False), ToolCallResult(tool_name='add', tool_kwargs={'a': 20, 'b': 8}, tool_id='784ccd85-ae9a-4184-9613-3696742064c7', tool_output=ToolOutput(content='28', tool_name='add', raw_input={'args': (), 'kwargs': {'a': 20, 'b': 8}}, raw_output=28, is_error=False), return_direct=False)]让我们来看看驱动ReAct智能体的核心系统提示!
在智能体内部,当前对话历史记录在此行下方转储。
prompt_dict = agent.get_prompts()for k, v in prompt_dict.items(): print(f"Prompt: {k}\n\nValue: {v.template}")Prompt: react_header
Value: You are designed to help with a variety of tasks, from answering questions to providing summaries to other types of analyses.
## Tools
You have access to a wide variety of tools. You are responsible for using the tools in any sequence you deem appropriate to complete the task at hand.This may require breaking the task into subtasks and using different tools to complete each subtask.
You have access to the following tools:{tool_desc}
## Output Format
Please answer in the same language as the question and use the following format:
```Thought: The current language of the user is: (user's language). I need to use a tool to help me answer the question.Action: tool name (one of {tool_names}) if using a tool.Action Input: the input to the tool, in a JSON format representing the kwargs (e.g. {{"input": "hello world", "num_beams": 5}})```
Please ALWAYS start with a Thought.
NEVER surround your response with markdown code markers. You may use code markers within your response if you need to.
Please use a valid JSON format for the Action Input. Do NOT do this {{'input': 'hello world', 'num_beams': 5}}.
If this format is used, the tool will respond in the following format:
```Observation: tool response```
You should keep repeating the above format till you have enough information to answer the question without using any more tools. At that point, you MUST respond in one of the following two formats:
```Thought: I can answer without using any more tools. I'll use the user's language to answerAnswer: [your answer here (In the same language as the user's question)]```
```Thought: I cannot answer the question with the provided tools.Answer: [your answer here (In the same language as the user's question)]```
## Current Conversation
Below is the current conversation consisting of interleaving human and assistant messages.为了好玩,让我们尝试指导智能体以项目符号形式输出答案及推理过程。请参阅“## 附加规则”部分。
from llama_index.core import PromptTemplate
react_system_header_str = """\
You are designed to help with a variety of tasks, from answering questions \ to providing summaries to other types of analyses.
## ToolsYou have access to a wide variety of tools. You are responsible for usingthe tools in any sequence you deem appropriate to complete the task at hand.This may require breaking the task into subtasks and using different toolsto complete each subtask.
You have access to the following tools:{tool_desc}
## Output FormatTo answer the question, please use the following format.思考:我需要使用一个工具来帮助我回答问题。 行动:工具名称(从{tool_names}中选择一个)如果使用工具。 行动输入:工具的输入,采用表示关键字的JSON格式(例如 {{“input”: “hello world”, “num_beams”: 5}})
Please ALWAYS start with a Thought.
Please use a valid JSON format for the Action Input. Do NOT do this {{'input': 'hello world', 'num_beams': 5}}.
If this format is used, the user will respond in the following format:观察:工具响应
You should keep repeating the above format until you have enough informationto answer the question without using any more tools. At that point, you MUST respondin the one of the following two formats:思考:我可以不使用任何工具来回答。 答案:[在此处填写您的答案]
Thought: I cannot answer the question with the provided tools. Answer: Sorry, I cannot answer your query.
## Additional Rules- The answer MUST contain a sequence of bullet points that explain how you arrived at the answer. This can include aspects of the previous conversation history.- You MUST obey the function signature of each tool. Do NOT pass in no arguments if the function expects arguments.
## Current ConversationBelow is the current conversation consisting of interleaving human and assistant messages.
"""react_system_prompt = PromptTemplate(react_system_header_str)agent.get_prompts(){'react_header': PromptTemplate(metadata={'prompt_type': <PromptType.CUSTOM: 'custom'>}, template_vars=['tool_desc', 'tool_names'], kwargs={}, output_parser=None, template_var_mappings=None, function_mappings=None, template='You are designed to help with a variety of tasks, from answering questions to providing summaries to other types of analyses.\n\n## Tools\n\nYou have access to a wide variety of tools. You are responsible for using the tools in any sequence you deem appropriate to complete the task at hand.\nThis may require breaking the task into subtasks and using different tools to complete each subtask.\n\nYou have access to the following tools:\n{tool_desc}\n\n\n## Output Format\n\nPlease answer in the same language as the question and use the following format:\n\n```\nThought: The current language of the user is: (user\'s language). I need to use a tool to help me answer the question.\nAction: tool name (one of {tool_names}) if using a tool.\nAction Input: the input to the tool, in a JSON format representing the kwargs (e.g. {{"input": "hello world", "num_beams": 5}})\n```\n\nPlease ALWAYS start with a Thought.\n\nNEVER surround your response with markdown code markers. You may use code markers within your response if you need to.\n\nPlease use a valid JSON format for the Action Input. Do NOT do this {{\'input\': \'hello world\', \'num_beams\': 5}}.\n\nIf this format is used, the tool will respond in the following format:\n\n```\nObservation: tool response\n```\n\nYou should keep repeating the above format till you have enough information to answer the question without using any more tools. At that point, you MUST respond in one of the following two formats:\n\n```\nThought: I can answer without using any more tools. I\'ll use the user\'s language to answer\nAnswer: [your answer here (In the same language as the user\'s question)]\n```\n\n```\nThought: I cannot answer the question with the provided tools.\nAnswer: [your answer here (In the same language as the user\'s question)]\n```\n\n## Current Conversation\n\nBelow is the current conversation consisting of interleaving human and assistant messages.\n')}agent.update_prompts({"react_header": react_system_prompt})handler = agent.run("What is 5+3+2")
async for ev in handler.stream_events(): # if isinstance(ev, ToolCallResult): # print(f"\nCall {ev.tool_name} with {ev.tool_kwargs}\nReturned: {ev.tool_output}") if isinstance(ev, AgentStream): print(f"{ev.delta}", end="", flush=True)
response = await handlerThought: The current language of the user is: English. I need to use a tool to help me answer the question.Action: addAction Input: {"a": 5, "b": 3}Thought: I need to add the result (8) to the remaining number (2).Action: addAction Input: {'a': 8, 'b': 2}Thought: I can answer without using any more tools. I'll use the user's language to answer.Answer: The result of 5 + 3 + 2 is 10.print(response)The result of 5 + 3 + 2 is 10.