Back to Llama Index

ReActAgent - A Simple Intro with Calculator Tools

docs/examples/agent/react_agent.ipynb

0.14.215.2 KB
Original Source

<a href="https://colab.research.google.com/github/run-llama/llama_index/blob/main/docs/examples/agent/react_agent.ipynb" target="_parent"></a>

ReActAgent - A Simple Intro with Calculator Tools

This is a notebook that showcases the ReAct agent over very simple calculator tools (no fancy RAG pipelines or API calls).

We show how it can reason step-by-step over different tools to achieve the end goal.

The main advantage of the ReAct agent over a Function Calling agent is that it can work with any LLM regardless of whether it supports function calling.

If you're opening this Notebook on colab, you will probably need to install LlamaIndex 🦙.

python
%pip install llama-index
python
import os

os.environ["OPENAI_API_KEY"] = "sk-..."

Define Function Tools

We setup some trivial multiply and add tools. Note that you can define arbitrary functions and pass it to the FunctionTool (which will process the docstring and parameter signature).

python
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 + b

Run Some Queries

python
from llama_index.llms.openai import OpenAI
from llama_index.core.agent.workflow import ReActAgent
from 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 state
ctx = Context(agent)

Run Some Example Queries

By streaming the result, we can see the full response, including the thought process and tool calls.

If we wanted to stream only the result, we can buffer the stream and start streaming once Answer: is in the response.

python
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 handler
python
print(str(response))
python
print(response.tool_calls)

View Prompts

Let's take a look at the core system prompt powering the ReAct agent!

Within the agent, the current conversation history is dumped below this line.

python
prompt_dict = agent.get_prompts()
for k, v in prompt_dict.items():
    print(f"Prompt: {k}\n\nValue: {v.template}")

Customizing the Prompt

For fun, let's try instructing the agent to output the answer along with reasoning in bullet points. See "## Additional Rules" section.

python
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.

## 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
To answer the question, please use the following format.

Thought: 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.

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:

Observation: tool response


You should keep repeating the above format until you have enough information
to answer the question without using any more tools. At that point, you MUST respond
in the one of the following two formats:

Thought: I can answer without using any more tools. Answer: [your answer here]

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 Conversation
Below is the current conversation consisting of interleaving human and assistant messages.

"""
react_system_prompt = PromptTemplate(react_system_header_str)
python
agent.get_prompts()
python
agent.update_prompts({"react_header": react_system_prompt})
python
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 handler
python
print(response)