wishmi1234 commited on
Commit
3082c30
·
verified ·
1 Parent(s): 9c5d52d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +276 -59
app.py CHANGED
@@ -1,87 +1,304 @@
1
- import gradio as gr
2
- import json
3
  import pandas as pd
4
- from smolagents import CodeAgent
5
- from smolagents.models import InferenceClientModel
6
- from smolagents.tools import (
7
- DuckDuckGoSearchTool,
8
- WikipediaSearchTool,
9
- PythonInterpreterTool,
10
- UserInputTool,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  )
12
 
13
- # Define the model
14
- model = InferenceClientModel(
15
- model_id="Qwen/Qwen1.5-1.8B-Chat", # Ensure this is a model that supports system_message
16
- system_message="You are a helpful academic assistant tasked with solving student questions accurately.",
17
- max_tokens=512,
18
- )
19
 
20
- # Define tools
21
- tools = [
22
- DuckDuckGoSearchTool(),
23
- WikipediaSearchTool(),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  PythonInterpreterTool(),
25
  UserInputTool(),
 
26
  ]
27
 
28
- # Initialize agent
29
- agent = CodeAgent(model=model, tools=tools)
30
 
31
- # Run agent on uploaded question set
32
- def run_agent(file):
33
- results_log = []
34
- answers_payload = []
 
 
 
 
 
 
 
 
 
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  try:
37
- with open(file.name, "r", encoding="utf-8") as f:
38
- questions_data = json.load(f)
 
39
  except Exception as e:
40
- return f"Error reading JSON file: {e}", pd.DataFrame()
 
 
 
41
 
42
- print(f"Running agent on {len(questions_data)} questions...")
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  for item in questions_data:
45
  task_id = item.get("task_id")
46
- question = item.get("question")
47
-
48
- if not task_id or question is None:
49
- results_log.append({
50
- "Task ID": task_id if task_id else "MISSING",
51
- "Question": question if question else "MISSING",
52
- "Submitted Answer": "Invalid entry",
53
- })
54
  continue
55
-
56
  try:
57
- answer = agent(question)
58
- answers_payload.append({"task_id": task_id, "submitted_answer": answer})
59
- results_log.append({"Task ID": task_id, "Question": question, "Submitted Answer": answer})
 
 
 
 
 
 
 
 
 
 
 
60
  except Exception as e:
61
- error_msg = f"AGENT ERROR: {e}"
62
- print(error_msg)
63
- results_log.append({"Task ID": task_id, "Question": question, "Submitted Answer": error_msg})
64
 
65
  if not answers_payload:
 
66
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
67
 
68
- return "Success! Answers submitted.", pd.DataFrame(results_log)
69
-
70
- # Create Gradio UI
71
- demo = gr.Interface(
72
- fn=run_agent,
73
- inputs=gr.File(label="Upload your questions.json"),
74
- outputs=[
75
- gr.Textbox(label="Status"),
76
- gr.Dataframe(label="Submitted Answers")
77
- ],
78
- title="Academic Assistant Agent",
79
- description="Upload a .json file with questions and task_ids to run the agent.",
80
- )
81
 
82
- if __name__ == "__main__":
83
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  # import os
86
  # import pandas as pd
87
  # import requests
 
1
+ import os
 
2
  import pandas as pd
3
+ import requests
4
+ import smolagents
5
+ print("SmolAgents version:", smolagents.__version__)
6
+ from smolagents import Tool, CodeAgent, InferenceClientModel, load_tool
7
+ from smolagents import DuckDuckGoSearchTool, WikipediaSearchTool, PythonInterpreterTool, UserInputTool
8
+ import gradio as gr
9
+ from PIL import Image
10
+ from io import BytesIO
11
+ import base64
12
+
13
+
14
+
15
+ model = InferenceClientModel("qwen/Qwen2.5-0.5B-Instruct",
16
+ max_tokens=512,
17
+ system_message="""
18
+ You are a highly capable AI assistant designed to solve real-world, multi-step reasoning tasks in the GAIA benchmark.
19
+ Your job is to:
20
+ - Search the web or Wikipedia if needed
21
+ - Perform Python calculations or date arithmetic
22
+ Instructions:
23
+ 1. Think step-by-step and use tools wisely.
24
+ 2. Always return a short, direct answer — no explanation or formatting.
25
+ Examples:
26
+ - Q: What is the capital of France?
27
+ - A: Paris
28
+ Your output must be: a single clean answer string only.
29
+ """
30
  )
31
 
 
 
 
 
 
 
32
 
33
+ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
34
+
35
+
36
+ class ImageCaptioningTool(Tool):
37
+ name = "image_captioner"
38
+ description = "Generate a caption for an image."
39
+ inputs = {"image": "image"}
40
+ output_type = "text"
41
+
42
+ def run(self, inputs: dict) -> str:
43
+ image = inputs.get("image")
44
+ if not image:
45
+ return "No image provided."
46
+ # You could run your model here instead
47
+ return "This is a placeholder caption for the uploaded image."
48
+
49
+
50
+ # ---------------------- TOOL CONFIGURATION ---------------------- #
51
+ tools=[
52
+ DuckDuckGoSearchTool(max_results=5, rate_limit=2.0),
53
+ WikipediaSearchTool(user_agent="my-agent", language="en"),
54
  PythonInterpreterTool(),
55
  UserInputTool(),
56
+ ImageCaptioningTool(),
57
  ]
58
 
 
 
59
 
60
+ # # ---------------------- AGENT SETUP ---------------------- #
61
+ # agent = CodeAgent(
62
+ # model = model,
63
+ # tools = tools,
64
+ # )
65
+
66
+ # ---------------------- MAIN LOGIC ---------------------- #
67
+
68
+ class BasicAgent:
69
+ def __init__(self):
70
+ model = InferenceClientModel(
71
+ "qwen/Qwen2.5-0.5B-Instruct",
72
+ max_tokens=512
73
 
74
+ )
75
+ self.agent = CodeAgent(
76
+ tools = tools,
77
+ model=model
78
+
79
+ )
80
+ print("BasicAgent initialized.")
81
+ # print("Available tools:", [tool.name for tool in self.agent.tools])
82
+ def __call__(self, question):
83
+ if isinstance(question, dict):
84
+ text = question.get("question", "")
85
+ # ignoring image context for now since agent.run doesn't support it
86
+ else:
87
+ text = question
88
+
89
+ print(f"Agent received question (first 50 chars): {text[:50]}...")
90
+ answer = self.agent.run(text)
91
+ return answer.strip()
92
+
93
+
94
+
95
+
96
+ def run_agent_on_image(image):
97
  try:
98
+ # Wrap image as expected by the agent tool
99
+ response = agent("Describe this image", inputs={"image": image})
100
+ return response
101
  except Exception as e:
102
+ return f"Error: {e}"
103
+
104
+ # iface = gr.Interface(fn=run_agent_on_image, inputs=gr.Image(type="pil"), outputs="text")
105
+ # iface.launch()
106
 
 
107
 
108
+
109
+ def run_and_submit_all( profile: gr.OAuthProfile | None):
110
+ """
111
+ Fetches all questions, runs the BasicAgent on them, submits all answers,
112
+ and displays the results.
113
+ """
114
+ # --- Determine HF Space Runtime URL and Repo URL ---
115
+ space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
116
+
117
+ if profile:
118
+ username= f"{profile.username}"
119
+ print(f"User logged in: {username}")
120
+ else:
121
+ print("User not logged in.")
122
+ return "Please Login to Hugging Face with the button.", None
123
+
124
+ api_url = DEFAULT_API_URL
125
+ questions_url = f"{api_url}/questions"
126
+ submit_url = f"{api_url}/submit"
127
+
128
+ # 1. Instantiate Agent ( modify this part to create your agent)
129
+ try:
130
+ agent = BasicAgent()
131
+ except Exception as e:
132
+ print(f"Error instantiating agent: {e}")
133
+ return f"Error initializing agent: {e}", None
134
+ # 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)
135
+ agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
136
+ print(agent_code)
137
+
138
+ # 2. Fetch Questions
139
+ print(f"Fetching questions from: {questions_url}")
140
+ try:
141
+ response = requests.get(questions_url, timeout=15)
142
+ response.raise_for_status()
143
+ questions_data = response.json()
144
+ if not questions_data:
145
+ print("Fetched questions list is empty.")
146
+ return "Fetched questions list is empty or invalid format.", None
147
+ print(f"Fetched {len(questions_data)} questions.")
148
+ except requests.exceptions.RequestException as e:
149
+ print(f"Error fetching questions: {e}")
150
+ return f"Error fetching questions: {e}", None
151
+ except requests.exceptions.JSONDecodeError as e:
152
+ print(f"Error decoding JSON response from questions endpoint: {e}")
153
+ print(f"Response text: {response.text[:500]}")
154
+ return f"Error decoding server response for questions: {e}", None
155
+ except Exception as e:
156
+ print(f"An unexpected error occurred fetching questions: {e}")
157
+ return f"An unexpected error occurred fetching questions: {e}", None
158
+
159
+
160
+ # question_text = item.get("question")
161
+ # question_input = {"question": question_text}
162
+ # if "image" in item:
163
+ # question_input["image"] = item["image"]
164
+ # submitted_answer = agent(question_input)
165
+ # 3. Run your Agent
166
+ results_log = []
167
+ answers_payload = []
168
+ print(f"Running agent on {len(questions_data)} questions...")
169
  for item in questions_data:
170
  task_id = item.get("task_id")
171
+ question_text = item.get("question")
172
+ image = item.get("image", None)
173
+
174
+ if not task_id or question_text is None:
175
+ print(f"Skipping item with missing task_id or question: {item}")
 
 
 
176
  continue
177
+
178
  try:
179
+ question_input = {"question": question_text}
180
+ if image:
181
+ try:
182
+ image_bytes = base64.b64decode(image)
183
+ pil_image = Image.open(BytesIO(image_bytes))
184
+ question_input["image"] = pil_image
185
+ except Exception as e:
186
+ print(f"Failed to decode image for task {task_id}: {e}")
187
+
188
+ submitted_answer = agent(question_input)
189
+
190
+ answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
191
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
192
+
193
  except Exception as e:
194
+ print(f"Error running agent on task {task_id}: {e}")
195
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
 
196
 
197
  if not answers_payload:
198
+ print("Agent did not produce any answers to submit.")
199
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
200
 
201
+ # 4. Prepare Submission
202
+ submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
203
+ status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
204
+ print(status_update)
 
 
 
 
 
 
 
 
 
205
 
206
+ # 5. Submit
207
+ print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
208
+ try:
209
+ response = requests.post(submit_url, json=submission_data, timeout=60)
210
+ response.raise_for_status()
211
+ result_data = response.json()
212
+ final_status = (
213
+ f"Submission Successful!\n"
214
+ f"User: {result_data.get('username')}\n"
215
+ f"Overall Score: {result_data.get('score', 'N/A')}% "
216
+ f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
217
+ f"Message: {result_data.get('message', 'No message received.')}"
218
+ )
219
+ print("Submission successful.")
220
+ results_df = pd.DataFrame(results_log)
221
+ return final_status, results_df
222
+ except requests.exceptions.HTTPError as e:
223
+ error_detail = f"Server responded with status {e.response.status_code}."
224
+ try:
225
+ error_json = e.response.json()
226
+ error_detail += f" Detail: {error_json.get('detail', e.response.text)}"
227
+ except requests.exceptions.JSONDecodeError:
228
+ error_detail += f" Response: {e.response.text[:500]}"
229
+ status_message = f"Submission Failed: {error_detail}"
230
+ print(status_message)
231
+ results_df = pd.DataFrame(results_log)
232
+ return status_message, results_df
233
+ except requests.exceptions.Timeout:
234
+ status_message = "Submission Failed: The request timed out."
235
+ print(status_message)
236
+ results_df = pd.DataFrame(results_log)
237
+ return status_message, results_df
238
+ except requests.exceptions.RequestException as e:
239
+ status_message = f"Submission Failed: Network error - {e}"
240
+ print(status_message)
241
+ results_df = pd.DataFrame(results_log)
242
+ return status_message, results_df
243
+ except Exception as e:
244
+ status_message = f"An unexpected error occurred during submission: {e}"
245
+ print(status_message)
246
+ results_df = pd.DataFrame(results_log)
247
+ return status_message, results_df
248
+
249
+
250
+ # --- Build Gradio Interface using Blocks ---
251
+ with gr.Blocks() as demo:
252
+ gr.Markdown("# Basic Agent Evaluation Runner")
253
+ gr.Markdown(
254
+ """
255
+ **Instructions:**
256
+ 1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
257
+ 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
258
+ 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
259
+ ---
260
+ **Disclaimers:**
261
+ 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).
262
+ 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.
263
+ """
264
+ )
265
+
266
+ gr.LoginButton()
267
+
268
+ run_button = gr.Button("Run Evaluation & Submit All Answers")
269
+
270
+ status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
271
+ # Removed max_rows=10 from DataFrame constructor
272
+ results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
273
+
274
+ run_button.click(
275
+ fn=run_and_submit_all,
276
+ outputs=[status_output, results_table]
277
+ )
278
 
279
+ if __name__ == "__main__":
280
+ print("\n" + "-"*30 + " App Starting " + "-"*30)
281
+ # Check for SPACE_HOST and SPACE_ID at startup for information
282
+ space_host_startup = os.getenv("SPACE_HOST")
283
+ space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
284
+
285
+ if space_host_startup:
286
+ print(f"✅ SPACE_HOST found: {space_host_startup}")
287
+ print(f" Runtime URL should be: https://{space_host_startup}.hf.space")
288
+ else:
289
+ print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
290
+
291
+ if space_id_startup: # Print repo URLs if SPACE_ID is found
292
+ print(f"✅ SPACE_ID found: {space_id_startup}")
293
+ print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
294
+ print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
295
+ else:
296
+ print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
297
+
298
+ print("-"*(60 + len(" App Starting ")) + "\n")
299
+
300
+ print("Launching Gradio Interface for Basic Agent Evaluation...")
301
+ demo.launch(debug=True, share=False)
302
  # import os
303
  # import pandas as pd
304
  # import requests