-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathreact.py
More file actions
181 lines (136 loc) · 6.39 KB
/
react.py
File metadata and controls
181 lines (136 loc) · 6.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# ============================================================================
# Stock Advisor Agent Tutorial
# ============================================================================
# This tutorial demonstrates how to build a financial analyst agent that uses
# ReAct (Reasoning + Action) methodology to provide investment recommendations
# The agent follows a structured thought process and can access external data
import re
from datetime import datetime
# Import necessary libraries
import pixeltable as pxt # Database for AI agent memory
import yfinance as yf # Financial data API
from pixelagent.anthropic import Agent # Agent framework
# ============================================================================
# SECTION 1: DEFINE TOOLS
# ============================================================================
# The agent needs access to external tools to gather financial information
# Here we create a UDF (User-Defined Function) that fetches stock information
@pxt.udf
def stock_info(ticker: str) -> dict:
"""
Retrieve comprehensive stock information for a given ticker symbol.
Args:
ticker (str): Stock ticker symbol (e.g., 'AAPL' for Apple)
Returns:
dict: Dictionary containing stock information and metrics
"""
stock = yf.Ticker(ticker)
return stock.info
# List of tools available to the agent
react_tools = ["stock_info"]
# ============================================================================
# SECTION 2: DEFINE THE REACT SYSTEM PROMPT
# ============================================================================
# The ReAct methodology requires a specific prompt structure to guide the agent
# through alternating reasoning and action steps
REACT_SYSTEM_PROMPT = """
Today is {date}
IMPORTANT: You have {max_steps} maximum steps. You are on step {step}.
Follow this EXACT step-by-step reasoning and action pattern:
1. THOUGHT: Think about what information you need to answer the user's question.
2. ACTION: Either use a tool OR write "FINAL" if you're ready to give your final answer.
Available tools:
{tools}
Always structure your response with these exact headings:
THOUGHT: [your reasoning]
ACTION: [tool_name] OR simply write "FINAL"
Your memory will automatically update with the tool calling results. Use those results to inform your next action.
"""
# ============================================================================
# SECTION 3: HELPER FUNCTIONS
# ============================================================================
# Utility function to parse agent responses and extract specific sections
def extract_section(text, section_name):
"""
Extract a specific section from the agent's response text.
Args:
text (str): The full text response from the agent
section_name (str): The section to extract (e.g., 'THOUGHT', 'ACTION')
Returns:
str: The extracted section content or empty string if not found
"""
pattern = rf"{section_name}:?\s*(.*?)(?=\n\s*(?:THOUGHT|ACTION):|$)"
match = re.search(pattern, text, re.DOTALL | re.IGNORECASE)
return match.group(1).strip() if match else ""
# ============================================================================
# SECTION 4: MAIN EXECUTION LOOP
# ============================================================================
# Initialize variables for the ReAct loop
step = 1
max_steps = 10 # Maximum steps before forced termination
question = "Create a detailed investment recommendation for Apple Inc. (AAPL) based on current market conditions."
# Clear previous agent history before starting
pxt.drop_dir("financial_analyst_react", force=True)
# Start the ReAct loop - the agent will alternate between thinking and acting
print("Starting Financial Analyst Agent with ReAct methodology...")
while step <= max_steps:
print(f"Step {step}:\n")
# Generate the dynamic system prompt with current step information
react_system_prompt = REACT_SYSTEM_PROMPT.format(
date=datetime.now().strftime("%Y-%m-%d"),
tools="\n".join(react_tools),
step=step,
max_steps=max_steps,
)
print("React System Prompt:\n")
print(react_system_prompt)
# Initialize the ReAct agent with persistent memory (reset=False)
agent = Agent(
name="financial_analyst_react",
system_prompt=react_system_prompt, # Dynamic React System Prompt
reset=False, # Maintains persistent memory across steps
# n_latest_messages=10, # Optional: Define N rolling memory window
)
# Get the agent's response for the current step
response = agent.chat(question)
print("Response:")
print(response)
# Extract the ACTION section to determine next steps
action = extract_section(response, "ACTION")
# Check if the agent is ready to finalize its answer
if "FINAL" in action.upper():
print("Agent has decided to finalize answer.")
break
# Determine which tool to call based on the agent's action
call_tool = [tool for tool in react_tools if tool.lower() in action.lower()]
if call_tool:
print(f"Agent has decided to use tool: {call_tool[0]}")
# Create a tool-specific agent to handle the tool call
tool_agent = Agent(
name="financial_analyst_react",
system_prompt="Use your tools to answer the user's question.",
tools=pxt.tools(stock_info), # Register the stock_info tool
)
# Execute the tool call and get results
tool_call_result = tool_agent.tool_call(question)
print("Tool Call Result:\n")
print(tool_call_result)
# Increment the step counter
step += 1
# Safety check to prevent infinite loops
if step > max_steps:
print("Reached maximum steps. Forcing termination.")
break
# ============================================================================
# SECTION 5: GENERATE FINAL ANSWER
# ============================================================================
# Create a final summary agent that accesses the conversation history
print("Generating final investment recommendation...")
summary_agent = Agent(
name="financial_analyst_react", # Same agent name to access history
system_prompt="Answer the user's question. Use your previous chat history to answer the question.",
)
# Generate the final comprehensive answer
final_answer = summary_agent.chat(question)
print("Final Investment Recommendation:")
print(final_answer)