JPM34 commited on
Commit
4d89d4a
·
1 Parent(s): 9505e38

Added gemini agent

Browse files
Files changed (2) hide show
  1. agent_gemini.py +193 -0
  2. app.py +250 -143
agent_gemini.py ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import os
3
+
4
+ import tempfile
5
+
6
+ from langchain.agents import AgentExecutor, create_tool_calling_agent
7
+ from langchain_google_community import GoogleSearchResults
8
+ from langchain_google_community import GoogleSearchAPIWrapper
9
+ from langchain_core.prompts import ChatPromptTemplate
10
+ from langchain_core.tools import Tool
11
+ from langchain_google_genai import ChatGoogleGenerativeAI
12
+ from langchain_experimental.utilities import PythonREPL
13
+
14
+ from tools_audio import transcribe_audio
15
+
16
+ from tools_doc import (
17
+ analyze_csv_file,
18
+ analyze_excel_file,
19
+ download_file_from_url,
20
+ extract_text_from_image,
21
+ read_file,
22
+ )
23
+ from tools_video import (
24
+ review_youtube_video,
25
+ use_vision_model,
26
+ transcribe_youtube,
27
+ video_frames_to_images,
28
+ )
29
+
30
+ from tools_browser import website_scrape, web_search
31
+
32
+ from answers import create_final_answer_graph, validate_answer
33
+
34
+ logger = logging.getLogger(__name__)
35
+
36
+
37
+ class BasicAgent:
38
+ def __init__(self):
39
+ try:
40
+ logger.info("Initializing BasicAgent")
41
+
42
+ # Create the prompt template
43
+ prompt = ChatPromptTemplate.from_messages(
44
+ [
45
+ (
46
+ "system",
47
+ """You are a general AI assistant. I will ask you a question. Report your thoughts, and finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER]. YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string.
48
+ """,
49
+ ),
50
+ ("placeholder", "{chat_history}"),
51
+ ("human", "{input}"),
52
+ ("placeholder", "{agent_scratchpad}"),
53
+ ]
54
+ )
55
+ logger.info("Created prompt template")
56
+
57
+ # Initialize Gemini model
58
+ logger.info("Creating Gemini model...")
59
+ llm = ChatGoogleGenerativeAI(
60
+ model="models/gemini-2.5-pro-preview-03-25",
61
+ google_api_key=os.getenv("GEMINI_KEY"),
62
+ temperature=0.2,
63
+ )
64
+ logger.info("Created Gemini model successfully")
65
+
66
+ # Define available tools
67
+ tools = [
68
+ # GoogleSearchResults(
69
+ # api_wrapper=GoogleSearchAPIWrapper(
70
+ # google_api_key=os.getenv("GOOGLE_SEARCH_API_KEY"),
71
+ # google_cse_id=os.getenv("GOOGLE_CSE_ID"),
72
+ # k=5, # Number of results to return
73
+ # )
74
+ # ),
75
+ web_search,
76
+ analyze_csv_file,
77
+ analyze_excel_file,
78
+ download_file_from_url,
79
+ extract_text_from_image,
80
+ read_file,
81
+ review_youtube_video,
82
+ transcribe_audio,
83
+ transcribe_youtube,
84
+ use_vision_model,
85
+ video_frames_to_images,
86
+ website_scrape,
87
+ Tool(
88
+ name="python_repl",
89
+ description="A Python shell. Use this to execute python commands. Input # should be a valid python command. If you want to see the output of a value, # you should print it out with `print(...)`.",
90
+ func=PythonREPL().run,
91
+ ),
92
+ ]
93
+ logger.info("Tools: %s", tools)
94
+
95
+ # Create the agent
96
+ agent = create_tool_calling_agent(llm, tools, prompt)
97
+ logger.info("Created tool calling agent")
98
+
99
+ # Create the agent executor
100
+ self.agent_executor = AgentExecutor(
101
+ agent=agent,
102
+ tools=tools,
103
+ return_intermediate_steps=True,
104
+ verbose=True,
105
+ )
106
+ logger.info("Created agent executor")
107
+
108
+ # Create the graph
109
+ self.validation_graph = create_final_answer_graph()
110
+
111
+ except Exception as e:
112
+ logger.error("Error initializing agent: %s", e, exc_info=True)
113
+ raise
114
+
115
+ def __call__(self, question: str, task_id: str) -> str:
116
+ """Execute the agent with the given question and optional file.
117
+ Args:
118
+ question (str): The question to answer
119
+ task_id (str): The task ID to fetch the file
120
+ """
121
+ max_retries = 3
122
+ attempt = 0
123
+
124
+ # Create a temporary directory that will be automatically cleaned up
125
+ with tempfile.TemporaryDirectory() as temp_dir:
126
+ while attempt < max_retries:
127
+ default_api_url = os.getenv("DEFAULT_API_URL")
128
+ file_url = f"{default_api_url}/files/{task_id}"
129
+
130
+ try:
131
+ # Download file to temporary directory
132
+ file = download_file_from_url.invoke(
133
+ {
134
+ "url": file_url,
135
+ "directory": temp_dir,
136
+ }
137
+ )
138
+ except Exception as e:
139
+ logger.error(f"Error downloading file: {e}")
140
+ file = None
141
+
142
+ try:
143
+ attempt += 1
144
+ logger.info(f"Attempt {attempt} of {max_retries}")
145
+
146
+ # Prepare input with file information
147
+ if file and file.get("type") != "error":
148
+ input_data = {
149
+ "input": question
150
+ + f" [File: type={file.get('type', 'None')}, path={file.get('path', 'None')}]",
151
+ }
152
+ else:
153
+ input_data = {
154
+ "input": question,
155
+ }
156
+
157
+ # Run the agent to get the answer
158
+ result = self.agent_executor.invoke(input_data)
159
+ answer = result.get("output", "")
160
+
161
+ logger.info(f"Attempt {attempt} result: {result}")
162
+
163
+ # Run validation
164
+ validation_result = validate_answer(
165
+ self.validation_graph,
166
+ answer,
167
+ [result.get("intermediate_steps", [])],
168
+ )
169
+
170
+ valid_answer = validation_result.get("valid_answer", False)
171
+ final_answer = validation_result.get("final_answer", "")
172
+
173
+ if valid_answer:
174
+ logger.info(f"Valid answer found on attempt {attempt}")
175
+ return final_answer
176
+
177
+ logger.warning(
178
+ f"Validation failed on attempt {attempt}: {final_answer}"
179
+ )
180
+ if attempt >= max_retries:
181
+ raise Exception(
182
+ f"Failed to get valid answer after {max_retries} attempts. Last error: {final_answer}"
183
+ )
184
+
185
+ except Exception as e:
186
+ logger.error(
187
+ f"Error in attempt {attempt}: {e}", exc_info=True
188
+ )
189
+ if attempt >= max_retries:
190
+ raise Exception(
191
+ f"Failed after {max_retries} attempts. Last error: {str(e)}"
192
+ )
193
+ continue
app.py CHANGED
@@ -1,24 +1,30 @@
 
 
1
  import os
 
 
 
2
  import gradio as gr
3
- import requests
4
- import inspect
5
  import pandas as pd
6
- from agent import BasicAgent
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  # (Keep Constants as is)
9
  # --- Constants ---
10
- DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
11
-
12
- # --- Basic Agent Definition ---
13
- # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
14
- # class BasicAgent:
15
- # def __init__(self):
16
- # print("BasicAgent initialized.")
17
- # def __call__(self, question: str) -> str:
18
- # print(f"Agent received question (first 50 chars): {question[:50]}...")
19
- # fixed_answer = "This is a default answer."
20
- # print(f"Agent returning fixed answer: {fixed_answer}")
21
- # return fixed_answer
22
 
23
 
24
  def run_and_submit_all(profile: gr.OAuthProfile | None):
@@ -26,146 +32,249 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
26
  Fetches all questions, runs the BasicAgent on them, submits all answers,
27
  and displays the results.
28
  """
29
- # --- Determine HF Space Runtime URL and Repo URL ---
30
- space_id = os.getenv(
31
- "SPACE_ID"
32
- ) # Get the SPACE_ID for sending link to the code
33
-
34
- if profile:
35
- username = f"{profile.username}"
36
- print(f"User logged in: {username}")
37
- else:
38
- print("User not logged in.")
39
- return "Please Login to Hugging Face with the button.", None
40
 
41
- api_url = DEFAULT_API_URL
42
- questions_url = f"{api_url}/questions"
43
- submit_url = f"{api_url}/submit"
 
 
 
44
 
45
- # 1. Instantiate Agent ( modify this part to create your agent)
46
- try:
47
- agent = BasicAgent()
48
- except Exception as e:
49
- print(f"Error instantiating agent: {e}")
50
- return f"Error initializing agent: {e}", None
51
- # 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)
52
- agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
53
- print(agent_code)
54
-
55
- # 2. Fetch Questions
56
- print(f"Fetching questions from: {questions_url}")
57
- try:
58
- response = requests.get(questions_url, timeout=15)
59
- response.raise_for_status()
60
- questions_data = response.json()
61
- if not questions_data:
62
- print("Fetched questions list is empty.")
63
- return "Fetched questions list is empty or invalid format.", None
64
- print(f"Fetched {len(questions_data)} questions.")
65
- except requests.exceptions.RequestException as e:
66
- print(f"Error fetching questions: {e}")
67
- return f"Error fetching questions: {e}", None
68
- except requests.exceptions.JSONDecodeError as e:
69
- print(f"Error decoding JSON response from questions endpoint: {e}")
70
- print(f"Response text: {response.text[:500]}")
71
- return f"Error decoding server response for questions: {e}", None
72
- except Exception as e:
73
- print(f"An unexpected error occurred fetching questions: {e}")
74
- return f"An unexpected error occurred fetching questions: {e}", None
75
-
76
- # 3. Run your Agent
77
- results_log = []
78
- answers_payload = []
79
- print(f"Running agent on {len(questions_data)} questions...")
80
- for item in questions_data:
81
- task_id = item.get("task_id")
82
- question_text = item.get("question")
83
- if not task_id or question_text is None:
84
- print(f"Skipping item with missing task_id or question: {item}")
85
- continue
86
  try:
87
- submitted_answer = agent(question_text)
88
- answers_payload.append(
89
- {"task_id": task_id, "submitted_answer": submitted_answer}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  )
91
- results_log.append(
92
- {
93
- "Task ID": task_id,
94
- "Question": question_text,
95
- "Submitted Answer": submitted_answer,
96
- }
97
  )
98
  except Exception as e:
99
- print(f"Error running agent on task {task_id}: {e}")
100
- results_log.append(
101
- {
102
- "Task ID": task_id,
103
- "Question": question_text,
104
- "Submitted Answer": f"AGENT ERROR: {e}",
105
- }
106
  )
107
 
108
- if not answers_payload:
109
- print("Agent did not produce any answers to submit.")
110
- return "Agent did not produce any answers to submit.", pd.DataFrame(
111
- results_log
112
- )
113
 
114
- # 4. Prepare Submission
115
- submission_data = {
116
- "username": username.strip(),
117
- "agent_code": agent_code,
118
- "answers": answers_payload,
119
- }
120
- status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
121
- print(status_update)
122
-
123
- # 5. Submit
124
- print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
125
- try:
126
- response = requests.post(submit_url, json=submission_data, timeout=60)
127
- response.raise_for_status()
128
- result_data = response.json()
129
- final_status = (
130
- f"Submission Successful!\n"
131
- f"User: {result_data.get('username')}\n"
132
- f"Overall Score: {result_data.get('score', 'N/A')}% "
133
- f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
134
- f"Message: {result_data.get('message', 'No message received.')}"
 
 
135
  )
136
- print("Submission successful.")
137
- results_df = pd.DataFrame(results_log)
138
- return final_status, results_df
139
- except requests.exceptions.HTTPError as e:
140
- error_detail = (
141
- f"Server responded with status {e.response.status_code}."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  )
143
  try:
144
- error_json = e.response.json()
145
- error_detail += (
146
- f" Detail: {error_json.get('detail', e.response.text)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  )
148
- except requests.exceptions.JSONDecodeError:
149
- error_detail += f" Response: {e.response.text[:500]}"
150
- status_message = f"Submission Failed: {error_detail}"
151
- print(status_message)
152
- results_df = pd.DataFrame(results_log)
153
- return status_message, results_df
154
- except requests.exceptions.Timeout:
155
- status_message = "Submission Failed: The request timed out."
156
- print(status_message)
157
- results_df = pd.DataFrame(results_log)
158
- return status_message, results_df
159
- except requests.exceptions.RequestException as e:
160
- status_message = f"Submission Failed: Network error - {e}"
161
- print(status_message)
162
- results_df = pd.DataFrame(results_log)
163
- return status_message, results_df
 
 
 
 
 
 
 
 
 
 
 
 
164
  except Exception as e:
165
- status_message = f"An unexpected error occurred during submission: {e}"
166
- print(status_message)
167
- results_df = pd.DataFrame(results_log)
168
- return status_message, results_df
169
 
170
 
171
  # --- Build Gradio Interface using Blocks ---
@@ -174,11 +283,9 @@ with gr.Blocks() as demo:
174
  gr.Markdown(
175
  """
176
  **Instructions:**
177
-
178
  1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
179
  2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
180
  3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
181
-
182
  ---
183
  **Disclaimers:**
184
  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).
 
1
+ import concurrent.futures
2
+ import logging
3
  import os
4
+ import sys
5
+ import traceback
6
+
7
  import gradio as gr
 
 
8
  import pandas as pd
9
+ import requests
10
+ from dotenv import load_dotenv
11
+
12
+ from agent_gemini import BasicAgent
13
+
14
+ # Load environment variables from .env file
15
+ load_dotenv()
16
+
17
+
18
+ # Configure logging
19
+ logging.basicConfig(
20
+ level=logging.DEBUG,
21
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
22
+ handlers=[logging.StreamHandler(sys.stdout)],
23
+ )
24
+ logger = logging.getLogger(__name__)
25
 
26
  # (Keep Constants as is)
27
  # --- Constants ---
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
 
30
  def run_and_submit_all(profile: gr.OAuthProfile | None):
 
32
  Fetches all questions, runs the BasicAgent on them, submits all answers,
33
  and displays the results.
34
  """
35
+ try:
36
+ # --- Determine HF Space Runtime URL and Repo URL ---
37
+ space_id = os.getenv(
38
+ "SPACE_ID"
39
+ ) # Get the SPACE_ID for sending link to the code
 
 
 
 
 
 
40
 
41
+ if profile:
42
+ username = f"{profile.username}"
43
+ logger.info(f"User logged in: {username}")
44
+ else:
45
+ logger.warning("User not logged in.")
46
+ return "Please Login to Hugging Face with the button.", None
47
 
48
+ api_url = os.getenv("DEFAULT_API_URL")
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
+ logger.info("Instantiating agent...")
55
+ agent = BasicAgent()
56
+ logger.info("Agent instantiated successfully")
57
+ except Exception as e:
58
+ logger.error(f"Error instantiating agent: {e}", exc_info=True)
59
+ return (
60
+ f"Error initializing agent: {str(e)}\n{traceback.format_exc()}",
61
+ None,
62
+ )
63
+
64
+ # In the case of an app running as a hugging Face space, this link points toward your codebase
65
+ agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
66
+ logger.info(f"Agent code: {agent_code}")
67
+
68
+ # 2. Fetch Questions
69
+ logger.info(f"Fetching questions from: {questions_url}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  try:
71
+ response = requests.get(questions_url, timeout=15)
72
+ response.raise_for_status()
73
+ questions_data = response.json()
74
+ if not questions_data:
75
+ logger.warning("Fetched questions list is empty.")
76
+ return (
77
+ "Fetched questions list is empty or invalid format.",
78
+ None,
79
+ )
80
+ logger.info(f"Fetched {len(questions_data)} questions.")
81
+ except requests.exceptions.RequestException as e:
82
+ logger.error(f"Error fetching questions: {e}", exc_info=True)
83
+ return f"Error fetching questions: {str(e)}", None
84
+ except requests.exceptions.JSONDecodeError as e:
85
+ logger.error(
86
+ f"Error decoding JSON response from questions endpoint: {e}",
87
+ exc_info=True,
88
  )
89
+ logger.error(f"Response text: {response.text[:500]}")
90
+ return (
91
+ f"Error decoding server response for questions: {str(e)}",
92
+ None,
 
 
93
  )
94
  except Exception as e:
95
+ logger.error(
96
+ f"An unexpected error occurred fetching questions: {e}",
97
+ exc_info=True,
98
+ )
99
+ return (
100
+ f"An unexpected error occurred fetching questions: {str(e)}",
101
+ None,
102
  )
103
 
104
+ # 3. Run your Agent
105
+ results_log = []
106
+ answers_payload = []
107
+ logger.info(f"Running agent on {len(questions_data)} questions...")
 
108
 
109
+ # Limit the number of questions to process to avoid timeouts
110
+ max_questions = 20 # Process only 20 questions at a time
111
+
112
+ tasks_to_process = [
113
+ # "99c9cc74-fdc8-46c6-8f8d-3ce2d3bfeea3",
114
+ # "1f975693-876d-457b-a649-393859e79bf3",
115
+ # "840bfca7-4f7b-481a-8794-c560c340185d",
116
+ # "7bd855d8-463d-4ed5-93ca-5fe35145f733",
117
+ ]
118
+
119
+ # questions_to_process = questions_data[:max_questions]
120
+
121
+ if tasks_to_process:
122
+ questions_to_process = [
123
+ x
124
+ for x in questions_data
125
+ if x.get("task_id") in tasks_to_process
126
+ ]
127
+ else:
128
+ questions_to_process = questions_data[:max_questions]
129
+
130
+ logger.info(
131
+ f"Processing {len(questions_to_process)} out of {len(questions_data)} questions"
132
  )
133
+
134
+ for item in questions_to_process:
135
+ task_id = item.get("task_id")
136
+ question_text = item.get("question")
137
+ if not task_id or question_text is None:
138
+ logger.warning(
139
+ f"Skipping item with missing task_id or question: {item}"
140
+ )
141
+ continue
142
+ try:
143
+ logger.info(f"Processing task {task_id}: {question_text}")
144
+
145
+ # Use concurrent.futures for thread-safe timeout
146
+ with concurrent.futures.ThreadPoolExecutor() as executor:
147
+ try:
148
+ future = executor.submit(agent, question_text, task_id)
149
+ try:
150
+ submitted_answer = future.result(
151
+ timeout=180
152
+ ) # 60 second timeout
153
+ logger.info(
154
+ f"Answer for task {task_id}: {submitted_answer}"
155
+ )
156
+
157
+ answers_payload.append(
158
+ {
159
+ "task_id": task_id,
160
+ "submitted_answer": submitted_answer,
161
+ }
162
+ )
163
+ results_log.append(
164
+ {
165
+ "Task ID": task_id,
166
+ "Question": question_text,
167
+ "Submitted Answer": submitted_answer,
168
+ }
169
+ )
170
+ except concurrent.futures.TimeoutError:
171
+ logger.error(f"Timeout processing task {task_id}")
172
+ results_log.append(
173
+ {
174
+ "Task ID": task_id,
175
+ "Question": question_text,
176
+ "Submitted Answer": "TIMEOUT ERROR: Question processing timed out after 60 seconds",
177
+ }
178
+ )
179
+ finally:
180
+ # Clean up temporary directory after processing
181
+ try:
182
+ import shutil
183
+
184
+ # shutil.rmtree(temp_dir) ## TBD
185
+ logger.info(
186
+ f"Cleaned up temporary directory for task {task_id}"
187
+ )
188
+ except Exception as e:
189
+ logger.error(
190
+ f"Error cleaning up temporary directory for task {task_id}: {e}"
191
+ )
192
+ except Exception as e:
193
+ logger.error(
194
+ f"Error running agent on task {task_id}: {e}",
195
+ exc_info=True,
196
+ )
197
+ results_log.append(
198
+ {
199
+ "Task ID": task_id,
200
+ "Question": question_text,
201
+ "Submitted Answer": f"AGENT ERROR: {str(e)}",
202
+ }
203
+ )
204
+
205
+ if not answers_payload:
206
+ logger.warning("Agent did not produce any answers to submit.")
207
+ return (
208
+ "Agent did not produce any answers to submit.",
209
+ pd.DataFrame(results_log),
210
+ )
211
+
212
+ # 4. Prepare Submission
213
+ submission_data = {
214
+ "username": username.strip(),
215
+ "agent_code": agent_code,
216
+ "answers": answers_payload,
217
+ }
218
+ status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
219
+ logger.info(status_update)
220
+
221
+ # 5. Submit
222
+ logger.info(
223
+ f"Submitting {len(answers_payload)} answers to: {submit_url}"
224
  )
225
  try:
226
+ response = requests.post(
227
+ submit_url, json=submission_data, timeout=60
228
+ )
229
+ response.raise_for_status()
230
+ result_data = response.json()
231
+ final_status = (
232
+ f"Submission Successful!\n"
233
+ f"User: {result_data.get('username')}\n"
234
+ f"Overall Score: {result_data.get('score', 'N/A')}% "
235
+ f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
236
+ f"Message: {result_data.get('message', 'No message received.')}"
237
+ )
238
+ logger.info("Submission successful.")
239
+ results_df = pd.DataFrame(results_log)
240
+ return final_status, results_df
241
+ except requests.exceptions.HTTPError as e:
242
+ error_detail = (
243
+ f"Server responded with status {e.response.status_code}."
244
  )
245
+ try:
246
+ error_json = e.response.json()
247
+ error_detail += (
248
+ f" Detail: {error_json.get('detail', e.response.text)}"
249
+ )
250
+ except requests.exceptions.JSONDecodeError:
251
+ error_detail += f" Response: {e.response.text[:500]}"
252
+ status_message = f"Submission Failed: {error_detail}"
253
+ logger.error(status_message, exc_info=True)
254
+ results_df = pd.DataFrame(results_log)
255
+ return status_message, results_df
256
+ except requests.exceptions.Timeout:
257
+ status_message = "Submission Failed: The request timed out."
258
+ logger.error(status_message, exc_info=True)
259
+ results_df = pd.DataFrame(results_log)
260
+ return status_message, results_df
261
+ except requests.exceptions.RequestException as e:
262
+ status_message = f"Submission Failed: Network error - {e}"
263
+ logger.error(status_message, exc_info=True)
264
+ results_df = pd.DataFrame(results_log)
265
+ return status_message, results_df
266
+ except Exception as e:
267
+ status_message = (
268
+ f"An unexpected error occurred during submission: {e}"
269
+ )
270
+ logger.error(status_message, exc_info=True)
271
+ results_df = pd.DataFrame(results_log)
272
+ return status_message, results_df
273
  except Exception as e:
274
+ logger.error(
275
+ f"Unhandled exception in run_and_submit_all: {e}", exc_info=True
276
+ )
277
+ return f"Critical error: {str(e)}\n{traceback.format_exc()}", None
278
 
279
 
280
  # --- Build Gradio Interface using Blocks ---
 
283
  gr.Markdown(
284
  """
285
  **Instructions:**
 
286
  1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
287
  2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
288
  3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
 
289
  ---
290
  **Disclaimers:**
291
  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).