Article
react-promptingllm-agentsreasoningtool-useprompt-engineeringopenai-apipython
Implement ReAct Prompting for LLM Tool Use
Teach an LLM to reason and act to solve multi-step problems. ReAct Prompting guides a model through a Thought-Action-Observation loop, allowing it to use external tools (like search) to find information and arrive at more reliable answers.
intermediate30 min4 steps
The play
- Understand the ReAct FrameworkReAct stands for Reason + Act. It structures problem-solving by having the LLM generate a `Thought` (its reasoning), an `Action` (a tool to use), and then receiving an `Observation` (the tool's output). This loop repeats until a final answer is found.
- Craft the ReAct System PromptInstruct the model to follow the ReAct format. Your prompt must define the rules, the format for thoughts and actions, and list the available tools with their descriptions. This sets the stage for the agentic behavior.
- Define Your Tools in CodeImplement the functions that correspond to the tools you described in the prompt. The agent loop will call these functions based on the LLM's `Action` output. Here, we create a mock `search` tool for demonstration.
- Build the Agentic LoopWrite the main loop that orchestrates the ReAct process. It sends the current state to the LLM, parses the response to find the `Action`, executes the corresponding tool, formats the `Observation`, and appends the results to the prompt for the next turn.
Starter code
import os
import re
from openai import OpenAI
# --- 1. Setup: Add your OpenAI API key to your environment variables ---
# In your terminal: export OPENAI_API_KEY='your-key-here'
# Ensure you have the openai library: pip install openai
if not os.environ.get("OPENAI_API_KEY"):
raise ValueError("OPENAI_API_KEY environment variable not set.")
client = OpenAI()
# --- 2. Define Tools ---
def search(query: str) -> str:
"""A mock search tool that returns predefined answers."""
print(f"\033[94m--> Searching for: {query}\033[0m")
query = query.lower()
if "capital of spain" in query:
return "The capital of Spain is Madrid."
elif "population of madrid" in query:
return "The population of Madrid in 2023 was approximately 3.3 million."
else:
return "Information not found."
TOOLS = {
"search": search
}
# --- 3. Define the ReAct Prompt Template ---
PROMPT_TEMPLATE = """You are a helpful assistant that answers questions by breaking them down into steps. You have access to the following tools:
search[query]: A tool to search for information about places or populations.
finish[answer]: Use this to provide the final answer when you have enough information.
Use the following format:
Question: The input question you must answer.
Thought: You should always think about what to do.
Action: The action to take, which should be one of [search, finish].
Observation: The result of the action.
... (this Thought/Action/Observation can repeat N times)
Thought: I now know the final answer.
Action: finish[The final answer]
Begin!
Question: {question}
"""
# --- 4. The ReAct Agent Loop ---
def run_react_agent(question: str):
prompt = PROMPT_TEMPLATE.format(question=question)
max_turns = 5
for i in range(max_turns):
print(f"\n\033[92m--- Turn {i+1} ---\033[0m")
print(f"\033[90mSending to LLM:\n{prompt}\033[0m")
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
temperature=0,
stop=["Observation:"] # Stop generation once it's time for an observation
)
response_text = response.choices[0].message.content.strip()
print(f"\033[93mLLM Output:\n{response_text}\033[0m")
# Parse the action from the LLM's response
action_match = re.search(r"Action: (\w+)\[(.*?)\]", response_text, re.DOTALL)
if not action_match:
print("\033[91mError: Could not parse action. Halting.\033[0m")
break
tool_name = action_match.group(1).strip()
tool_input = action_match.group(2).strip()
prompt += response_text
# Check for the 'finish' action
if tool_name == "finish":
print(f"\n\033[92mFinal Answer: {tool_input}\033[0m")
break
# Execute the tool and get the observation
if tool_name in TOOLS:
observation = TOOLS[tool_name](tool_input)
print(f"\033[96m<-- Observation: {observation}\033[0m")
prompt += f"\nObservation: {observation}\n"
else:
print(f"\033[91mError: Unknown tool '{tool_name}'. Halting.\033[0m")
break
else:
print("\033[91mAgent stopped after reaching max turns.\033[0m")
# --- 5. Run the agent with a sample question ---
if __name__ == "__main__":
sample_question = "What is the population of the capital of Spain?"
run_react_agent(sample_question)