MrArray22 commited on
Commit
080e815
·
verified ·
1 Parent(s): 637c891

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +275 -26
app.py CHANGED
@@ -2,35 +2,281 @@ import os
2
  import gradio as gr
3
  import requests
4
  import pandas as pd
5
- from smolagents import CodeAgent, DuckDuckGoSearchTool, OpenAIServerModel,HfApiModel
6
- # (Keep Constants as is)
7
  # --- Constants ---
8
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  # --- Basic Agent Definition ---
12
- # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
13
  class BasicAgent:
14
  def __init__(self):
15
  print("BasicAgent initialized.")
16
  # Initialize the model
17
- #model = HfApiModel()
18
- model = HfApiModel(model_id="Qwen/Qwen2.5-Coder-32B-Instruct",api_key=os.environ['HF_TOKEN'])
19
- # model = OpenAIServerModel(model_id="openai/gpt-4o",api_key=os.environ["API_KEY"],api_base="https://models.github.ai/inference")
20
- # Initialize the search tool
21
- search_tool = DuckDuckGoSearchTool()
 
 
 
 
 
 
 
22
  # Initialize Agent
23
  self.agent = CodeAgent(
24
- model = model,
25
- tools=[search_tool]
 
26
  )
 
27
  def __call__(self, question: str) -> str:
28
  print(f"Agent received question (first 50 chars): {question[:50]}...")
29
- fixed_answer =self.agent.run(question)
30
- print(f"Agent returning fixed answer: {fixed_answer}")
31
- return fixed_answer
 
 
 
 
 
32
 
33
- def run_and_submit_all( profile: gr.OAuthProfile | None):
34
  """
35
  Fetches all questions, runs the BasicAgent on them, submits all answers,
36
  and displays the results.
@@ -39,7 +285,7 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
39
  space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
40
 
41
  if profile:
42
- username= f"{profile.username}"
43
  print(f"User logged in: {username}")
44
  else:
45
  print("User not logged in.")
@@ -49,13 +295,14 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
49
  questions_url = f"{api_url}/questions"
50
  submit_url = f"{api_url}/submit"
51
 
52
- # 1. Instantiate Agent ( modify this part to create your agent)
53
  try:
54
  agent = BasicAgent()
55
  except Exception as e:
56
  print(f"Error instantiating agent: {e}")
57
  return f"Error initializing agent: {e}", None
58
- # In the case of an app running as a hugging Face space, this link points toward your codebase ( usefull for others so please keep it public)
 
59
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
60
  print(agent_code)
61
 
@@ -91,9 +338,11 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
91
  print(f"Skipping item with missing task_id or question: {item}")
92
  continue
93
  try:
 
94
  submitted_answer = agent(question_text)
95
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
96
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
 
97
  except Exception as e:
98
  print(f"Error running agent on task {task_id}: {e}")
99
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
@@ -153,17 +402,18 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
153
 
154
  # --- Build Gradio Interface using Blocks ---
155
  with gr.Blocks() as demo:
156
- gr.Markdown("# Basic Agent Evaluation Runner")
157
  gr.Markdown(
158
  """
159
  **Instructions:**
160
- 1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
161
- 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
162
- 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
 
163
  ---
164
- **Disclaimers:**
165
- Once clicking on the "submit button, it can take quite some time ( this is the time for the agent to go through all the questions).
166
- This space provides a basic setup and is intentionally sub-optimal to encourage you to develop your own, more robust solution. For instance for the delay process of the submit button, a solution could be to cache the answers and submit in a seperate action or even to answer the questions in async.
167
  """
168
  )
169
 
@@ -172,7 +422,6 @@ with gr.Blocks() as demo:
172
  run_button = gr.Button("Run Evaluation & Submit All Answers")
173
 
174
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
175
- # Removed max_rows=10 from DataFrame constructor
176
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
177
 
178
  run_button.click(
@@ -201,5 +450,5 @@ if __name__ == "__main__":
201
 
202
  print("-"*(60 + len(" App Starting ")) + "\n")
203
 
204
- print("Launching Gradio Interface for Basic Agent Evaluation...")
205
  demo.launch(debug=True, share=False)
 
2
  import gradio as gr
3
  import requests
4
  import pandas as pd
5
+ from smolagents import CodeAgent, DuckDuckGoSearchTool, OpenAIServerModel, Tool, PythonInterpreterTool
6
+
7
  # --- Constants ---
8
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
9
 
10
+ # Custom file reading tool
11
+ class FileReadTool(Tool):
12
+ name = "file_reader"
13
+ description = """
14
+ This tool reads the content of text files.
15
+ It's useful for processing plain text files (.txt, .csv, .json, etc).
16
+ """
17
+ inputs = {
18
+ "file_path": {
19
+ "type": "string",
20
+ "description": "The path to the file to read",
21
+ }
22
+ }
23
+ output_type = "string"
24
+
25
+ def forward(self, file_path: str) -> str:
26
+ """
27
+ Reads the content of the given file.
28
+ """
29
+ try:
30
+ # Check if the file exists
31
+ if not os.path.exists(file_path):
32
+ return f"Error: File not found at {file_path}"
33
+
34
+ # Read the file
35
+ with open(file_path, 'r', encoding='utf-8') as file:
36
+ content = file.read()
37
+
38
+ # If the content is too long, truncate it
39
+ if len(content) > 10000:
40
+ content = content[:10000] + "...\n[Text truncated due to length]"
41
+
42
+ return content or "File is empty."
43
+
44
+ except Exception as e:
45
+ return f"Error reading file: {str(e)}"
46
+
47
+ class PDFReaderTool(Tool):
48
+ name = "pdf_reader"
49
+ description = """
50
+ This tool extracts text content from PDF files.
51
+ It's useful for reading research papers, reports, or other document types.
52
+ """
53
+ inputs = {
54
+ "pdf_path": {
55
+ "type": "string",
56
+ "description": "The path to the PDF file to read",
57
+ }
58
+ }
59
+ output_type = "string"
60
+
61
+ def forward(self, pdf_path: str) -> str:
62
+ """
63
+ Extracts text from the given PDF file.
64
+ """
65
+ try:
66
+ # Check if the file exists
67
+ if not os.path.exists(pdf_path):
68
+ return f"Error: PDF file not found at {pdf_path}"
69
+
70
+ import PyPDF2
71
+
72
+ # Open the PDF file
73
+ with open(pdf_path, 'rb') as file:
74
+ # Create a PDF reader object
75
+ pdf_reader = PyPDF2.PdfReader(file)
76
+
77
+ # Get the number of pages
78
+ num_pages = len(pdf_reader.pages)
79
+
80
+ # Extract text from all pages
81
+ text = ""
82
+ for page_num in range(num_pages):
83
+ page = pdf_reader.pages[page_num]
84
+ text += page.extract_text() + "\n\n"
85
+
86
+ # If the text is too long, truncate it
87
+ if len(text) > 10000:
88
+ text = text[:10000] + "...\n[Text truncated due to length]"
89
+
90
+ return text or "No text could be extracted from the PDF."
91
+
92
+ except Exception as e:
93
+ return f"Error reading PDF: {str(e)}"
94
+
95
+ class ExcelReaderTool(Tool):
96
+ name = "excel_reader"
97
+ description = """
98
+ This tool reads and processes Excel files (.xlsx, .xls).
99
+ It can extract data, calculate statistics, and perform data analysis on spreadsheets.
100
+ """
101
+ inputs = {
102
+ "excel_path": {
103
+ "type": "string",
104
+ "description": "The path to the Excel file to read",
105
+ },
106
+ "sheet_name": {
107
+ "type": "string",
108
+ "description": "The name of the sheet to read (optional, defaults to first sheet)",
109
+ "nullable": True
110
+ }
111
+ }
112
+ output_type = "string"
113
+
114
+ def forward(self, excel_path: str, sheet_name: str = None) -> str:
115
+ """
116
+ Reads and processes the given Excel file.
117
+ """
118
+ try:
119
+ # Check if the file exists
120
+ if not os.path.exists(excel_path):
121
+ return f"Error: Excel file not found at {excel_path}"
122
+
123
+ import pandas as pd
124
+
125
+ # Read the Excel file
126
+ if sheet_name:
127
+ df = pd.read_excel(excel_path, sheet_name=sheet_name)
128
+ else:
129
+ df = pd.read_excel(excel_path)
130
+
131
+ # Get basic info about the data
132
+ info = {
133
+ "shape": df.shape,
134
+ "columns": list(df.columns),
135
+ "dtypes": df.dtypes.to_dict(),
136
+ "head": df.head(5).to_dict()
137
+ }
138
+
139
+ # Return formatted info
140
+ result = f"Excel file: {excel_path}\n"
141
+ result += f"Shape: {info['shape'][0]} rows × {info['shape'][1]} columns\n\n"
142
+ result += "Columns:\n"
143
+ for col in info['columns']:
144
+ result += f"- {col} ({info['dtypes'].get(col)})\n"
145
+
146
+ result += "\nPreview (first 5 rows):\n"
147
+ result += df.head(5).to_string()
148
+
149
+ return result
150
+
151
+ except Exception as e:
152
+ return f"Error reading Excel file: {str(e)}"
153
+
154
+ class ImageAnalysisTool(Tool):
155
+ name = "image_analysis"
156
+ description = """
157
+ This tool analyzes an image and extracts relevant information from it.
158
+ It can describe image content, extract text from images, identify objects, etc.
159
+ """
160
+ inputs = {
161
+ "image_path": {
162
+ "type": "string",
163
+ "description": "The path to the image file to analyze",
164
+ }
165
+ }
166
+ output_type = "string"
167
+
168
+ def forward(self, image_path: str) -> str:
169
+ """
170
+ Analyzes the given image and returns relevant information using OpenAI's ChatGPT API.
171
+ """
172
+ try:
173
+ # Check if the file exists
174
+ if not os.path.exists(image_path):
175
+ return f"Error: Image file not found at {image_path}"
176
+
177
+ import requests
178
+ import base64
179
+ import json
180
+ from PIL import Image
181
+
182
+ # Load the image
183
+ with open(image_path, "rb") as image_file:
184
+ image_bytes = image_file.read()
185
+
186
+ # Convert to base64 for OpenAI API
187
+ encoded_image = base64.b64encode(image_bytes).decode('utf-8')
188
+
189
+ # Get API key from environment
190
+ api_key = os.getenv('OPENAI_API_KEY', '')
191
+ if not api_key:
192
+ return "OpenAI API key not configured. Please add the OPENAI_API_KEY to your environment variables."
193
+
194
+ # Prepare the API request for ChatGPT with vision capabilities
195
+ api_url = "https://api.openai.com/v1/chat/completions"
196
+ headers = {
197
+ "Content-Type": "application/json",
198
+ "Authorization": f"Bearer {api_key}"
199
+ }
200
+
201
+ payload = {
202
+ "model": "gpt-4o-mini-2024-07-18", # Vision-capable model
203
+ "messages": [
204
+ {
205
+ "role": "user",
206
+ "content": [
207
+ {
208
+ "type": "text",
209
+ "text": "Analyze this image in detail. Describe what you see, including main subjects, activities, background elements, colors, and any text visible in the image. If there's text in the image, please extract it."
210
+ },
211
+ {
212
+ "type": "image_url",
213
+ "image_url": {
214
+ "url": f"data:image/jpeg;base64,{encoded_image}"
215
+ }
216
+ }
217
+ ]
218
+ }
219
+ ],
220
+ "max_tokens": 500
221
+ }
222
+
223
+ response = requests.post(
224
+ api_url,
225
+ headers=headers,
226
+ json=payload
227
+ )
228
+
229
+ if response.status_code != 200:
230
+ return f"Error: OpenAI API returned status code {response.status_code}. Details: {response.text}"
231
+
232
+ result = response.json()
233
+
234
+ # Extract the response content
235
+ if "choices" in result and len(result["choices"]) > 0:
236
+ analysis = result["choices"][0]["message"]["content"]
237
+ return f"Image analysis result: {analysis}"
238
+ else:
239
+ return f"Error: Unexpected response format from OpenAI API: {result}"
240
+
241
+ except Exception as e:
242
+ return f"Error analyzing image: {str(e)}"
243
 
244
  # --- Basic Agent Definition ---
 
245
  class BasicAgent:
246
  def __init__(self):
247
  print("BasicAgent initialized.")
248
  # Initialize the model
249
+ model = OpenAIServerModel(model_id="openai/gpt-4o-mini",api_key=os.environ["API_KEY"],api_base="https://models.github.ai/inference")
250
+
251
+ # Initialize tools
252
+ self.tools = [
253
+ DuckDuckGoSearchTool(), # Built-in web search tool
254
+ FileReadTool(), # Custom file reader
255
+ PDFReaderTool(), # PDF reader
256
+ ExcelReaderTool(), # Excel reader
257
+ ImageAnalysisTool(), # Image analysis
258
+ # Code execution
259
+ ]
260
+
261
  # Initialize Agent
262
  self.agent = CodeAgent(
263
+ model=model,
264
+ tools=self.tools,
265
+ add_base_tools=True # Add basic tools like math
266
  )
267
+
268
  def __call__(self, question: str) -> str:
269
  print(f"Agent received question (first 50 chars): {question[:50]}...")
270
+ try:
271
+ answer = self.agent.run(question)
272
+ print(f"Agent returned answer (first 50 chars): {answer[:50]}...")
273
+ return answer
274
+ except Exception as e:
275
+ error_msg = f"Error running agent: {str(e)}"
276
+ print(error_msg)
277
+ return f"I encountered an issue while processing your question: {str(e)}"
278
 
279
+ def run_and_submit_all(profile: gr.OAuthProfile | None):
280
  """
281
  Fetches all questions, runs the BasicAgent on them, submits all answers,
282
  and displays the results.
 
285
  space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
286
 
287
  if profile:
288
+ username = f"{profile.username}"
289
  print(f"User logged in: {username}")
290
  else:
291
  print("User not logged in.")
 
295
  questions_url = f"{api_url}/questions"
296
  submit_url = f"{api_url}/submit"
297
 
298
+ # 1. Instantiate Agent
299
  try:
300
  agent = BasicAgent()
301
  except Exception as e:
302
  print(f"Error instantiating agent: {e}")
303
  return f"Error initializing agent: {e}", None
304
+
305
+ # In the case of an app running as a Hugging Face space, this link points toward your codebase
306
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
307
  print(agent_code)
308
 
 
338
  print(f"Skipping item with missing task_id or question: {item}")
339
  continue
340
  try:
341
+ print(f"Processing task {task_id}: {question_text[:50]}...")
342
  submitted_answer = agent(question_text)
343
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
344
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
345
+ print(f"Completed task {task_id}")
346
  except Exception as e:
347
  print(f"Error running agent on task {task_id}: {e}")
348
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
 
402
 
403
  # --- Build Gradio Interface using Blocks ---
404
  with gr.Blocks() as demo:
405
+ gr.Markdown("# Advanced Agent Evaluation Runner")
406
  gr.Markdown(
407
  """
408
  **Instructions:**
409
+
410
+ 1. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
411
+ 2. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
412
+
413
  ---
414
+ **Note:**
415
+ Once you click on the "submit" button, it may take quite some time as the agent processes all the questions.
416
+ The agent is using SmolaAgents with multiple tools including web search, file processing, and code execution.
417
  """
418
  )
419
 
 
422
  run_button = gr.Button("Run Evaluation & Submit All Answers")
423
 
424
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
 
425
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
426
 
427
  run_button.click(
 
450
 
451
  print("-"*(60 + len(" App Starting ")) + "\n")
452
 
453
+ print("Launching Gradio Interface for Advanced Agent Evaluation...")
454
  demo.launch(debug=True, share=False)