leofltt commited on
Commit
830c198
·
1 Parent(s): 3dd74bd
Files changed (1) hide show
  1. app.py +54 -27
app.py CHANGED
@@ -4,6 +4,7 @@ import gradio as gr
4
  import requests
5
  import pandas as pd
6
  import torch
 
7
  from transformers import pipeline
8
  from langchain_community.tools import DuckDuckGoSearchRun
9
  from langchain_core.prompts import ChatPromptTemplate
@@ -50,7 +51,7 @@ image_to_text_pipeline = None
50
  @tool
51
  def web_search(query: str):
52
  """Searches the web using DuckDuckGo."""
53
- print(f"--- Calling Web Search Tool with query: {query} ---")
54
  search = DuckDuckGoSearchRun()
55
  return search.run(query)
56
 
@@ -58,12 +59,13 @@ def web_search(query: str):
58
  @tool
59
  def math_calculator(expression: str):
60
  """Calculates the result of a mathematical expression."""
61
- print(f"--- Calling Math Calculator Tool with expression: {expression} ---")
62
  try:
63
  # Use numexpr for safe evaluation
64
  result = numexpr.evaluate(expression).item()
65
  return result
66
  except Exception as e:
 
67
  return f"Error evaluating expression: {e}"
68
 
69
 
@@ -71,26 +73,31 @@ def math_calculator(expression: str):
71
  def image_analyzer(image_url: str):
72
  """Analyzes an image and returns a description. Loads the model on first use."""
73
  global image_to_text_pipeline
74
- print(f"--- Calling Image Analyzer Tool with URL: {image_url} ---")
75
  try:
76
  if image_to_text_pipeline is None:
77
- print("--- Initializing Image Analyzer pipeline for the first time... ---")
 
 
78
  # Lazy-load the pipeline to conserve memory on startup
79
  image_to_text_pipeline = pipeline(
80
  "image-to-text", model="Salesforce/blip-image-captioning-base"
81
  )
82
- print("--- Image Analyzer pipeline initialized. ---")
83
 
84
  description = image_to_text_pipeline(image_url)[0]["generated_text"]
85
  return description
86
  except Exception as e:
 
87
  return f"Error analyzing image: {e}"
88
 
89
 
90
  @tool
91
  def youtube_transcript_reader(youtube_url: str):
92
  """Reads the transcript of a YouTube video."""
93
- print(f"--- Calling YouTube Transcript Reader Tool with URL: {youtube_url} ---")
 
 
94
  try:
95
  loader = YoutubeLoader.from_youtube_url(youtube_url, add_video_info=False)
96
  docs = loader.load()
@@ -98,6 +105,7 @@ def youtube_transcript_reader(youtube_url: str):
98
  # Return a manageable chunk of the transcript
99
  return transcript[:4000]
100
  except Exception as e:
 
101
  return f"Error reading YouTube transcript: {e}"
102
 
103
 
@@ -111,7 +119,7 @@ class AgentState(TypedDict):
111
  # --- LangGraph Agent Definition ---
112
  class GaiaAgent:
113
  def __init__(self):
114
- print("Initializing GaiaAgent...")
115
  self.tools = [
116
  web_search,
117
  math_calculator,
@@ -120,7 +128,7 @@ class GaiaAgent:
120
  ]
121
 
122
  # Initialize the LLM
123
- print("Loading LLM... This may take a few minutes on first startup.")
124
  # Using a smaller, CPU-friendly model to avoid memory issues on Hugging Face Spaces
125
  llm = HuggingFacePipeline.from_model_id(
126
  model_id="microsoft/Phi-3-mini-4k-instruct",
@@ -135,7 +143,7 @@ class GaiaAgent:
135
  trust_remote_code=True, # Required for Phi-3
136
  device_map="auto",
137
  )
138
- print("LLM loaded successfully.")
139
 
140
  # Create the agent graph
141
  prompt = PromptTemplate(
@@ -151,7 +159,7 @@ Question: {question}
151
 
152
  self.agent = prompt | llm | StrOutputParser()
153
  self.graph = self._create_graph()
154
- print("GaiaAgent initialized successfully.")
155
 
156
  def _create_graph(self):
157
  graph = StateGraph(AgentState)
@@ -165,7 +173,7 @@ Question: {question}
165
  return graph.compile()
166
 
167
  def _call_agent(self, state: AgentState):
168
- print("--- Calling Agent ---")
169
  message_history = "\n".join(state["messages"])
170
  response = self.agent.invoke(
171
  {"messages": message_history, "question": state["question"]}
@@ -173,7 +181,7 @@ Question: {question}
173
  return {"messages": [response], "sender": "agent"}
174
 
175
  def _decide_action(self, state: AgentState):
176
- print("--- Deciding Action ---")
177
  response = state["messages"][-1]
178
  if "FINAL ANSWER:" in response:
179
  return END
@@ -181,12 +189,13 @@ Question: {question}
181
  return "tools"
182
 
183
  def _call_tools(self, state: AgentState):
184
- print("--- Calling Tools ---")
185
  raw_tool_call = state["messages"][-1]
186
 
187
  # Simple regex to find tool calls like tool_name("argument") or tool_name(argument)
188
  tool_call_match = re.search(r"(\w+)\s*\((.*?)\)", raw_tool_call, re.DOTALL)
189
  if not tool_call_match:
 
190
  return {"messages": ["No valid tool call found."], "sender": "tools"}
191
 
192
  tool_name = tool_call_match.group(1).strip()
@@ -207,15 +216,17 @@ Question: {question}
207
  result = tool_to_call.run(tool_input)
208
  return {"messages": [str(result)], "sender": "tools"}
209
  except Exception as e:
 
210
  return {
211
  "messages": [f"Error executing tool {tool_name}: {e}"],
212
  "sender": "tools",
213
  }
214
  else:
 
215
  return {"messages": [f"Tool '{tool_name}' not found."], "sender": "tools"}
216
 
217
  def __call__(self, question: str) -> str:
218
- print(f"Agent received question: {question[:100]}...")
219
 
220
  initial_state = {"question": question, "messages": [], "sender": "user"}
221
 
@@ -229,10 +240,12 @@ Question: {question}
229
  )
230
  if match:
231
  extracted_answer = match.group(1).strip()
232
- print(f"Agent returning final answer: {extracted_answer}")
233
  return extracted_answer
234
  else:
235
- print("Agent could not find a final answer in the required format.")
 
 
236
  # Return a fallback answer if parsing fails
237
  return "Could not determine the final answer."
238
 
@@ -243,14 +256,15 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
243
  and displays the results.
244
  """
245
  if not profile:
246
- print("User not logged in.")
247
  return "Please Login to Hugging Face with the button.", None
248
 
249
  username = profile.username
250
- print(f"User logged in: {username}")
251
 
252
  space_id = os.getenv("SPACE_ID")
253
  if not space_id:
 
254
  return "SPACE_ID environment variable is not set. Cannot proceed.", None
255
 
256
  api_url = DEFAULT_API_URL
@@ -261,28 +275,30 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
261
  try:
262
  agent = GaiaAgent()
263
  except Exception as e:
264
- print(f"Error instantiating agent: {e}")
265
  return f"Error initializing agent: {e}", None
266
 
267
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
268
- print(f"Agent code URL: {agent_code}")
269
 
270
  # 2. Fetch Questions
271
- print(f"Fetching questions from: {questions_url}")
272
  try:
273
  response = requests.get(questions_url, timeout=20)
274
  response.raise_for_status()
275
  questions_data = response.json()
276
  if not questions_data:
 
277
  return "Fetched questions list is empty.", None
278
- print(f"Fetched {len(questions_data)} questions.")
279
  except requests.exceptions.RequestException as e:
 
280
  return f"Error fetching questions: {e}", None
281
 
282
  # 3. Run your Agent
283
  results_log = []
284
  answers_payload = []
285
- print(f"Running agent on {len(questions_data)} questions...")
286
  for item in questions_data:
287
  task_id = item.get("task_id")
288
  question_text = item.get("question")
@@ -302,7 +318,7 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
302
  }
303
  )
304
  except Exception as e:
305
- print(f"Error running agent on task {task_id}: {e}")
306
  results_log.append(
307
  {
308
  "Task ID": task_id,
@@ -312,6 +328,7 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
312
  )
313
 
314
  if not answers_payload:
 
315
  return "Agent did not produce any answers.", pd.DataFrame(results_log)
316
 
317
  # 4. Prepare and Submit
@@ -320,7 +337,7 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
320
  "agent_code": agent_code,
321
  "answers": answers_payload,
322
  }
323
- print(f"Submitting {len(answers_payload)} answers for user '{username}'...")
324
  try:
325
  response = requests.post(submit_url, json=submission_data, timeout=60)
326
  response.raise_for_status()
@@ -332,12 +349,16 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
332
  f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
333
  f"Message: {result_data.get('message', 'No message received.')}"
334
  )
335
- print("Submission successful.")
336
  return final_status, pd.DataFrame(results_log)
337
  except requests.exceptions.HTTPError as e:
338
  error_detail = f"Server responded with status {e.response.status_code}. Detail: {e.response.text}"
 
339
  return f"Submission Failed: {error_detail}", pd.DataFrame(results_log)
340
  except Exception as e:
 
 
 
341
  return f"An unexpected error occurred during submission: {e}", pd.DataFrame(
342
  results_log
343
  )
@@ -373,5 +394,11 @@ with gr.Blocks() as demo:
373
  )
374
 
375
  if __name__ == "__main__":
376
- print("\n" + "-" * 30 + " App Starting " + "-" * 30)
 
 
 
 
 
 
377
  demo.launch(debug=True, share=False)
 
4
  import requests
5
  import pandas as pd
6
  import torch
7
+ import logging
8
  from transformers import pipeline
9
  from langchain_community.tools import DuckDuckGoSearchRun
10
  from langchain_core.prompts import ChatPromptTemplate
 
51
  @tool
52
  def web_search(query: str):
53
  """Searches the web using DuckDuckGo."""
54
+ logging.info(f"--- Calling Web Search Tool with query: {query} ---")
55
  search = DuckDuckGoSearchRun()
56
  return search.run(query)
57
 
 
59
  @tool
60
  def math_calculator(expression: str):
61
  """Calculates the result of a mathematical expression."""
62
+ logging.info(f"--- Calling Math Calculator Tool with expression: {expression} ---")
63
  try:
64
  # Use numexpr for safe evaluation
65
  result = numexpr.evaluate(expression).item()
66
  return result
67
  except Exception as e:
68
+ logging.error(f"Error evaluating expression: {e}")
69
  return f"Error evaluating expression: {e}"
70
 
71
 
 
73
  def image_analyzer(image_url: str):
74
  """Analyzes an image and returns a description. Loads the model on first use."""
75
  global image_to_text_pipeline
76
+ logging.info(f"--- Calling Image Analyzer Tool with URL: {image_url} ---")
77
  try:
78
  if image_to_text_pipeline is None:
79
+ logging.info(
80
+ "--- Initializing Image Analyzer pipeline for the first time... ---"
81
+ )
82
  # Lazy-load the pipeline to conserve memory on startup
83
  image_to_text_pipeline = pipeline(
84
  "image-to-text", model="Salesforce/blip-image-captioning-base"
85
  )
86
+ logging.info("--- Image Analyzer pipeline initialized. ---")
87
 
88
  description = image_to_text_pipeline(image_url)[0]["generated_text"]
89
  return description
90
  except Exception as e:
91
+ logging.error(f"Error analyzing image: {e}")
92
  return f"Error analyzing image: {e}"
93
 
94
 
95
  @tool
96
  def youtube_transcript_reader(youtube_url: str):
97
  """Reads the transcript of a YouTube video."""
98
+ logging.info(
99
+ f"--- Calling YouTube Transcript Reader Tool with URL: {youtube_url} ---"
100
+ )
101
  try:
102
  loader = YoutubeLoader.from_youtube_url(youtube_url, add_video_info=False)
103
  docs = loader.load()
 
105
  # Return a manageable chunk of the transcript
106
  return transcript[:4000]
107
  except Exception as e:
108
+ logging.error(f"Error reading YouTube transcript: {e}")
109
  return f"Error reading YouTube transcript: {e}"
110
 
111
 
 
119
  # --- LangGraph Agent Definition ---
120
  class GaiaAgent:
121
  def __init__(self):
122
+ logging.info("Initializing GaiaAgent...")
123
  self.tools = [
124
  web_search,
125
  math_calculator,
 
128
  ]
129
 
130
  # Initialize the LLM
131
+ logging.info("Loading LLM... This may take a few minutes on first startup.")
132
  # Using a smaller, CPU-friendly model to avoid memory issues on Hugging Face Spaces
133
  llm = HuggingFacePipeline.from_model_id(
134
  model_id="microsoft/Phi-3-mini-4k-instruct",
 
143
  trust_remote_code=True, # Required for Phi-3
144
  device_map="auto",
145
  )
146
+ logging.info("LLM loaded successfully.")
147
 
148
  # Create the agent graph
149
  prompt = PromptTemplate(
 
159
 
160
  self.agent = prompt | llm | StrOutputParser()
161
  self.graph = self._create_graph()
162
+ logging.info("GaiaAgent initialized successfully.")
163
 
164
  def _create_graph(self):
165
  graph = StateGraph(AgentState)
 
173
  return graph.compile()
174
 
175
  def _call_agent(self, state: AgentState):
176
+ logging.info("--- Calling Agent ---")
177
  message_history = "\n".join(state["messages"])
178
  response = self.agent.invoke(
179
  {"messages": message_history, "question": state["question"]}
 
181
  return {"messages": [response], "sender": "agent"}
182
 
183
  def _decide_action(self, state: AgentState):
184
+ logging.info("--- Deciding Action ---")
185
  response = state["messages"][-1]
186
  if "FINAL ANSWER:" in response:
187
  return END
 
189
  return "tools"
190
 
191
  def _call_tools(self, state: AgentState):
192
+ logging.info("--- Calling Tools ---")
193
  raw_tool_call = state["messages"][-1]
194
 
195
  # Simple regex to find tool calls like tool_name("argument") or tool_name(argument)
196
  tool_call_match = re.search(r"(\w+)\s*\((.*?)\)", raw_tool_call, re.DOTALL)
197
  if not tool_call_match:
198
+ logging.warning("No valid tool call found in agent response.")
199
  return {"messages": ["No valid tool call found."], "sender": "tools"}
200
 
201
  tool_name = tool_call_match.group(1).strip()
 
216
  result = tool_to_call.run(tool_input)
217
  return {"messages": [str(result)], "sender": "tools"}
218
  except Exception as e:
219
+ logging.error(f"Error executing tool {tool_name}: {e}")
220
  return {
221
  "messages": [f"Error executing tool {tool_name}: {e}"],
222
  "sender": "tools",
223
  }
224
  else:
225
+ logging.warning(f"Tool '{tool_name}' not found.")
226
  return {"messages": [f"Tool '{tool_name}' not found."], "sender": "tools"}
227
 
228
  def __call__(self, question: str) -> str:
229
+ logging.info(f"Agent received question: {question[:100]}...")
230
 
231
  initial_state = {"question": question, "messages": [], "sender": "user"}
232
 
 
240
  )
241
  if match:
242
  extracted_answer = match.group(1).strip()
243
+ logging.info(f"Agent returning final answer: {extracted_answer}")
244
  return extracted_answer
245
  else:
246
+ logging.warning(
247
+ "Agent could not find a final answer in the required format."
248
+ )
249
  # Return a fallback answer if parsing fails
250
  return "Could not determine the final answer."
251
 
 
256
  and displays the results.
257
  """
258
  if not profile:
259
+ logging.warning("User not logged in.")
260
  return "Please Login to Hugging Face with the button.", None
261
 
262
  username = profile.username
263
+ logging.info(f"User logged in: {username}")
264
 
265
  space_id = os.getenv("SPACE_ID")
266
  if not space_id:
267
+ logging.error("SPACE_ID environment variable is not set. Cannot proceed.")
268
  return "SPACE_ID environment variable is not set. Cannot proceed.", None
269
 
270
  api_url = DEFAULT_API_URL
 
275
  try:
276
  agent = GaiaAgent()
277
  except Exception as e:
278
+ logging.critical(f"Error instantiating agent: {e}", exc_info=True)
279
  return f"Error initializing agent: {e}", None
280
 
281
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
282
+ logging.info(f"Agent code URL: {agent_code}")
283
 
284
  # 2. Fetch Questions
285
+ logging.info(f"Fetching questions from: {questions_url}")
286
  try:
287
  response = requests.get(questions_url, timeout=20)
288
  response.raise_for_status()
289
  questions_data = response.json()
290
  if not questions_data:
291
+ logging.warning("Fetched questions list is empty.")
292
  return "Fetched questions list is empty.", None
293
+ logging.info(f"Fetched {len(questions_data)} questions.")
294
  except requests.exceptions.RequestException as e:
295
+ logging.error(f"Error fetching questions: {e}")
296
  return f"Error fetching questions: {e}", None
297
 
298
  # 3. Run your Agent
299
  results_log = []
300
  answers_payload = []
301
+ logging.info(f"Running agent on {len(questions_data)} questions...")
302
  for item in questions_data:
303
  task_id = item.get("task_id")
304
  question_text = item.get("question")
 
318
  }
319
  )
320
  except Exception as e:
321
+ logging.error(f"Error running agent on task {task_id}: {e}", exc_info=True)
322
  results_log.append(
323
  {
324
  "Task ID": task_id,
 
328
  )
329
 
330
  if not answers_payload:
331
+ logging.warning("Agent did not produce any answers.")
332
  return "Agent did not produce any answers.", pd.DataFrame(results_log)
333
 
334
  # 4. Prepare and Submit
 
337
  "agent_code": agent_code,
338
  "answers": answers_payload,
339
  }
340
+ logging.info(f"Submitting {len(answers_payload)} answers for user '{username}'...")
341
  try:
342
  response = requests.post(submit_url, json=submission_data, timeout=60)
343
  response.raise_for_status()
 
349
  f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
350
  f"Message: {result_data.get('message', 'No message received.')}"
351
  )
352
+ logging.info("Submission successful.")
353
  return final_status, pd.DataFrame(results_log)
354
  except requests.exceptions.HTTPError as e:
355
  error_detail = f"Server responded with status {e.response.status_code}. Detail: {e.response.text}"
356
+ logging.error(f"Submission Failed: {error_detail}")
357
  return f"Submission Failed: {error_detail}", pd.DataFrame(results_log)
358
  except Exception as e:
359
+ logging.critical(
360
+ f"An unexpected error occurred during submission: {e}", exc_info=True
361
+ )
362
  return f"An unexpected error occurred during submission: {e}", pd.DataFrame(
363
  results_log
364
  )
 
394
  )
395
 
396
  if __name__ == "__main__":
397
+ # Configure logging
398
+ logging.basicConfig(
399
+ level=logging.INFO,
400
+ format="%(asctime)s - %(levelname)s - %(name)s - %(message)s",
401
+ datefmt="%Y-%m-%d %H:%M:%S",
402
+ )
403
+ logging.info("\n" + "-" * 30 + " App Starting " + "-" * 30)
404
  demo.launch(debug=True, share=False)