Scott Cogan commited on
Commit
b78f79e
·
1 Parent(s): 30541b5
Files changed (1) hide show
  1. app.py +63 -11
app.py CHANGED
@@ -18,6 +18,12 @@ from langchain_core.tools import tool
18
  from utilities import get_file
19
  import time
20
  from tenacity import retry, stop_after_attempt, wait_exponential
 
 
 
 
 
 
21
 
22
  # Constants
23
  GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
@@ -104,6 +110,30 @@ def google_search(query: str) -> str:
104
  response = llm.invoke(query, tools=[GenAITool(google_search={})])
105
  return response.content
106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  class BasicAgent:
108
  def __init__(self):
109
  self.llm = ChatGoogleGenerativeAI(
@@ -144,24 +174,32 @@ class BasicAgent:
144
  # Compile the graph
145
  self.app = self.workflow.compile()
146
 
147
- print("BasicAgent initialized.")
148
 
149
  @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=60))
150
  def call_model(self, state: AgentState) -> AgentState:
151
  """Call the model to generate a response with retry logic."""
152
  try:
153
  messages = state["messages"]
 
 
 
 
 
154
  response = self.llm.invoke([self.sys_msg] + messages)
155
 
 
 
 
156
  if not response or not response.content:
157
- print("Empty response from model, retrying...")
158
  raise ValueError("Empty response from model")
159
 
160
  return {"messages": [response], "next": "tools"}
161
  except Exception as e:
162
- print(f"Error in call_model: {str(e)}")
163
  if "429" in str(e):
164
- print("Rate limit hit, waiting before retry...")
165
  time.sleep(60) # Wait for 60 seconds before retry
166
  raise
167
 
@@ -171,6 +209,7 @@ class BasicAgent:
171
  messages = state["messages"]
172
  last_message = messages[-1]
173
 
 
174
  if isinstance(last_message, AIMessage):
175
  # Extract tool calls from the message
176
  tool_calls = last_message.tool_calls
@@ -179,20 +218,29 @@ class BasicAgent:
179
  try:
180
  tool_name = tool_call.name
181
  tool_args = tool_call.args
 
 
 
182
  result = self.tool_executor.invoke(tool_name, tool_args)
 
 
183
  messages.append(AIMessage(content=f"Tool result: {result}"))
184
  except Exception as e:
185
- print(f"Error executing tool {tool_name}: {str(e)}")
186
  messages.append(AIMessage(content=f"Tool error: {str(e)}"))
 
 
187
 
188
  return {"messages": messages, "next": "agent"}
189
  except Exception as e:
190
- print(f"Error in call_tools: {str(e)}")
191
  return {"messages": messages, "next": "agent"}
192
 
193
  async def __call__(self, question: str, task_id: str) -> str:
194
  """Process a question and return the answer with error handling."""
195
- print(f"Agent received question (first 50 chars): {question[:50]}...")
 
 
196
 
197
  try:
198
  # Create initial state
@@ -208,12 +256,16 @@ class BasicAgent:
208
 
209
  while retry_count < max_retries:
210
  try:
 
211
  result = self.app.invoke(initial_state)
212
  final_message = result["messages"][-1]
213
 
214
  if isinstance(final_message, AIMessage) and final_message.content:
 
 
215
  return final_message.content
216
  else:
 
217
  raise ValueError("Empty or invalid response")
218
 
219
  except Exception as e:
@@ -221,17 +273,17 @@ class BasicAgent:
221
  retry_count += 1
222
  if "429" in str(e):
223
  wait_time = 60 * retry_count
224
- print(f"Rate limit hit, waiting {wait_time} seconds before retry {retry_count}/{max_retries}")
225
  await asyncio.sleep(wait_time)
226
  else:
227
- print(f"Error in processing, retry {retry_count}/{max_retries}: {str(e)}")
228
  await asyncio.sleep(5)
229
 
230
- print(f"All retries failed. Last error: {str(last_error)}")
231
  return "Unable to generate answer after multiple attempts"
232
 
233
  except Exception as e:
234
- print(f"Fatal error in agent: {str(e)}")
235
  return f"Error: {str(e)}"
236
 
237
  def run_and_submit_all(profile):
 
18
  from utilities import get_file
19
  import time
20
  from tenacity import retry, stop_after_attempt, wait_exponential
21
+ import json
22
+ import logging
23
+
24
+ # Set up logging
25
+ logging.basicConfig(level=logging.INFO)
26
+ logger = logging.getLogger(__name__)
27
 
28
  # Constants
29
  GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
 
110
  response = llm.invoke(query, tools=[GenAITool(google_search={})])
111
  return response.content
112
 
113
+ def log_message(message: BaseMessage, prefix: str = ""):
114
+ """Helper function to log message details."""
115
+ if isinstance(message, HumanMessage):
116
+ logger.info(f"{prefix}Human Message:")
117
+ if isinstance(message.content, list):
118
+ for item in message.content:
119
+ if isinstance(item, dict):
120
+ if item.get("type") == "media":
121
+ logger.info(f"{prefix} Media content (type: {item.get('mime_type')})")
122
+ else:
123
+ logger.info(f"{prefix} {item.get('type')}: {item.get('text')}")
124
+ else:
125
+ logger.info(f"{prefix} {item}")
126
+ else:
127
+ logger.info(f"{prefix} {message.content}")
128
+ elif isinstance(message, AIMessage):
129
+ logger.info(f"{prefix}AI Message:")
130
+ logger.info(f"{prefix} Content: {message.content}")
131
+ if hasattr(message, 'tool_calls') and message.tool_calls:
132
+ logger.info(f"{prefix} Tool Calls: {json.dumps(message.tool_calls, indent=2)}")
133
+ elif isinstance(message, SystemMessage):
134
+ logger.info(f"{prefix}System Message:")
135
+ logger.info(f"{prefix} {message.content}")
136
+
137
  class BasicAgent:
138
  def __init__(self):
139
  self.llm = ChatGoogleGenerativeAI(
 
174
  # Compile the graph
175
  self.app = self.workflow.compile()
176
 
177
+ logger.info("BasicAgent initialized.")
178
 
179
  @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=60))
180
  def call_model(self, state: AgentState) -> AgentState:
181
  """Call the model to generate a response with retry logic."""
182
  try:
183
  messages = state["messages"]
184
+ logger.info("\n=== Model Input ===")
185
+ log_message(self.sys_msg, " ")
186
+ for msg in messages:
187
+ log_message(msg, " ")
188
+
189
  response = self.llm.invoke([self.sys_msg] + messages)
190
 
191
+ logger.info("\n=== Model Output ===")
192
+ log_message(response, " ")
193
+
194
  if not response or not response.content:
195
+ logger.error("Empty response from model")
196
  raise ValueError("Empty response from model")
197
 
198
  return {"messages": [response], "next": "tools"}
199
  except Exception as e:
200
+ logger.error(f"Error in call_model: {str(e)}")
201
  if "429" in str(e):
202
+ logger.warning("Rate limit hit, waiting before retry...")
203
  time.sleep(60) # Wait for 60 seconds before retry
204
  raise
205
 
 
209
  messages = state["messages"]
210
  last_message = messages[-1]
211
 
212
+ logger.info("\n=== Tool Execution ===")
213
  if isinstance(last_message, AIMessage):
214
  # Extract tool calls from the message
215
  tool_calls = last_message.tool_calls
 
218
  try:
219
  tool_name = tool_call.name
220
  tool_args = tool_call.args
221
+ logger.info(f"Executing tool: {tool_name}")
222
+ logger.info(f"Tool arguments: {json.dumps(tool_args, indent=2)}")
223
+
224
  result = self.tool_executor.invoke(tool_name, tool_args)
225
+ logger.info(f"Tool result: {result}")
226
+
227
  messages.append(AIMessage(content=f"Tool result: {result}"))
228
  except Exception as e:
229
+ logger.error(f"Error executing tool {tool_name}: {str(e)}")
230
  messages.append(AIMessage(content=f"Tool error: {str(e)}"))
231
+ else:
232
+ logger.info("No tool calls found in AI message")
233
 
234
  return {"messages": messages, "next": "agent"}
235
  except Exception as e:
236
+ logger.error(f"Error in call_tools: {str(e)}")
237
  return {"messages": messages, "next": "agent"}
238
 
239
  async def __call__(self, question: str, task_id: str) -> str:
240
  """Process a question and return the answer with error handling."""
241
+ logger.info(f"\n=== Processing Question ===")
242
+ logger.info(f"Task ID: {task_id}")
243
+ logger.info(f"Question: {question}")
244
 
245
  try:
246
  # Create initial state
 
256
 
257
  while retry_count < max_retries:
258
  try:
259
+ logger.info(f"\n=== Attempt {retry_count + 1}/{max_retries} ===")
260
  result = self.app.invoke(initial_state)
261
  final_message = result["messages"][-1]
262
 
263
  if isinstance(final_message, AIMessage) and final_message.content:
264
+ logger.info(f"\n=== Final Answer ===")
265
+ logger.info(f"Answer: {final_message.content}")
266
  return final_message.content
267
  else:
268
+ logger.error("Empty or invalid response")
269
  raise ValueError("Empty or invalid response")
270
 
271
  except Exception as e:
 
273
  retry_count += 1
274
  if "429" in str(e):
275
  wait_time = 60 * retry_count
276
+ logger.warning(f"Rate limit hit, waiting {wait_time} seconds before retry {retry_count}/{max_retries}")
277
  await asyncio.sleep(wait_time)
278
  else:
279
+ logger.error(f"Error in processing, retry {retry_count}/{max_retries}: {str(e)}")
280
  await asyncio.sleep(5)
281
 
282
+ logger.error(f"All retries failed. Last error: {str(last_error)}")
283
  return "Unable to generate answer after multiple attempts"
284
 
285
  except Exception as e:
286
+ logger.error(f"Fatal error in agent: {str(e)}")
287
  return f"Error: {str(e)}"
288
 
289
  def run_and_submit_all(profile):