wlchee commited on
Commit
07c9494
·
verified ·
1 Parent(s): 3aa2c24

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +199 -126
app.py CHANGED
@@ -1,148 +1,221 @@
1
  import os
2
  import gradio as gr
3
  import requests
 
4
  import pandas as pd
5
- from datetime import datetime
6
- from transformers import pipeline, Tool
7
- from transformers.agents import Agent
8
 
 
 
 
 
 
 
 
 
 
 
9
  # --- Constants ---
10
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
11
 
12
- # --- Custom Tools ---
13
- class CalculatorTool(Tool):
14
- name = "calculator"
15
- description = "Performs mathematical calculations"
16
- inputs = {"expression": {"type": "text"}}
17
- outputs = {"result": {"type": "text"}}
18
- output_type = "text" # Added required attribute
19
-
20
- def __call__(self, expression: str) -> str:
21
- try:
22
- return str(eval(expression))
23
- except:
24
- return "Error: Could not evaluate the expression"
25
-
26
- class TimeTool(Tool):
27
- name = "current_time"
28
- description = "Gets current UTC time"
29
- inputs = {}
30
- outputs = {"time": {"type": "text"}}
31
- output_type = "text" # Added required attribute
32
-
33
- def __call__(self) -> str:
34
- return datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC")
35
-
36
- # --- Enhanced Agent ---
37
- class HFLocalAgent:
38
  def __init__(self):
39
- print("Initializing local Hugging Face agent...")
40
- self.tools = {
41
- "calculator": CalculatorTool(),
42
- "time": TimeTool()
43
- }
44
-
45
- # Load local model (small but efficient)
46
- self.llm = pipeline(
47
- "text-generation",
48
- model="HuggingFaceH4/zephyr-7b-beta",
49
- device="cpu" # Change to "cuda" if GPU available
50
  )
51
-
 
 
 
 
 
 
 
 
 
 
52
  def __call__(self, question: str) -> str:
53
- print(f"Processing: {question[:100]}...")
54
- question_lower = question.lower()
55
-
56
- # Math questions
57
- if any(word in question_lower for word in ["calculate", "what is", "how much is", "+", "-", "*", "/"]):
58
- return self.tools["calculator"](question.replace("?", ""))
59
-
60
- # Time questions
61
- if any(word in question_lower for word in ["time", "current time"]):
62
- return self.tools["time"]()
63
-
64
- # Fallback to local LLM
65
- try:
66
- response = self.llm(
67
- f"Answer concisely: {question}",
68
- max_new_tokens=100,
69
- temperature=0.7
70
- )
71
- return response[0]['generated_text'].split(":")[-1].strip()
72
- except Exception as e:
73
- print(f"LLM error: {e}")
74
- return "I couldn't process this question."
75
-
76
- # --- Evaluation Runner ---
77
- def run_and_submit_all(profile: gr.OAuthProfile | None):
78
- if not profile:
79
- return "Please login first", None
80
-
81
- space_id = os.getenv("SPACE_ID", "local-test")
82
- api_url = os.getenv("API_URL", DEFAULT_API_URL)
83
-
84
  try:
85
- agent = HFLocalAgent()
86
- response = requests.get(f"{api_url}/questions", timeout=15)
 
 
 
 
 
 
 
 
 
 
87
  response.raise_for_status()
88
- questions = response.json()
89
-
90
- results = []
91
- answers = []
92
- for q in questions:
93
- try:
94
- answer = agent(q["question"])
95
- answers.append({
96
- "task_id": q["task_id"],
97
- "submitted_answer": answer
98
- })
99
- results.append({
100
- "Task ID": q["task_id"],
101
- "Question": q["question"],
102
- "Answer": answer
103
- })
104
- except Exception as e:
105
- results.append({
106
- "Task ID": q["task_id"],
107
- "Question": q["question"],
108
- "Answer": f"Error: {e}"
109
- })
110
-
111
- submission = {
112
- "username": profile.username,
113
- "agent_code": f"https://huggingface.co/spaces/{space_id}",
114
- "answers": answers
115
- }
 
 
 
 
 
116
 
117
- response = requests.post(f"{api_url}/submit", json=submission, timeout=60)
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  response.raise_for_status()
119
- result = response.json()
120
-
121
- return (
122
- f"Success! Score: {result.get('score', 'N/A')}%\n"
123
- f"Correct: {result.get('correct_count', '?')}/{result.get('total_attempted', '?')}",
124
- pd.DataFrame(results)
 
125
  )
126
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  except Exception as e:
128
- return f"Evaluation failed: {str(e)}", pd.DataFrame(results if 'results' in locals() else [])
129
-
130
- # --- Gradio Interface ---
131
- with gr.Blocks(title="Local HF Agent Evaluator") as app:
132
- gr.Markdown("""
133
- ## Local Hugging Face Agent Evaluation
134
- Uses completely free/local models - no API keys required
135
- """)
136
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  gr.LoginButton()
138
- run_btn = gr.Button("Start Evaluation")
139
- output = gr.Textbox(label="Results")
140
- results = gr.DataFrame(label="Details")
141
-
142
- run_btn.click(
 
 
 
143
  fn=run_and_submit_all,
144
- outputs=[output, results]
145
  )
146
 
147
  if __name__ == "__main__":
148
- app.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import gradio as gr
3
  import requests
4
+ import inspect
5
  import pandas as pd
 
 
 
6
 
7
+ from smolagents import (
8
+ ToolCallingAgent,
9
+ CodeAgent,
10
+ DuckDuckGoSearchTool,
11
+ InferenceClientModel,
12
+ HfApiModel,
13
+ OpenAIServerModel
14
+ )
15
+
16
+ # (Keep Constants as is)
17
  # --- Constants ---
18
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
19
 
20
+ # --- Basic Agent Definition ---
21
+ # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
22
+ class BasicAgent:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  def __init__(self):
24
+ self.model = OpenAIServerModel(
25
+ model_id='o4-mini',
26
+ api_base="HuggingFaceH4/zephyr-7b-beta",
27
+ #api_key=os.environ["OPENAI_API_KEY"],
 
 
 
 
 
 
 
28
  )
29
+ self.agent = ToolCallingAgent(
30
+ tools=[DuckDuckGoSearchTool()],
31
+ model=self.model,
32
+ add_base_tools=True
33
+ )
34
+ #self.agent.prompt_templates['system_prompt'] = """
35
+
36
+ #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.
37
+
38
+ #"""
39
+ print("BasicAgent initialized.")
40
  def __call__(self, question: str) -> str:
41
+ print(f"Agent received question (first 50 chars): {question[:50]}...")
42
+ fixed_answer = self.agent.run(question)
43
+ print(f"Agent returning fixed answer: {fixed_answer}")
44
+ return fixed_answer
45
+
46
+ def run_and_submit_all( profile: gr.OAuthProfile | None):
47
+ """
48
+ Fetches all questions, runs the BasicAgent on them, submits all answers,
49
+ and displays the results.
50
+ """
51
+ # --- Determine HF Space Runtime URL and Repo URL ---
52
+ space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
53
+
54
+ if profile:
55
+ username= f"{profile.username}"
56
+ print(f"User logged in: {username}")
57
+ else:
58
+ print("User not logged in.")
59
+ return "Please Login to Hugging Face with the button.", None
60
+
61
+ api_url = DEFAULT_API_URL
62
+ questions_url = f"{api_url}/questions"
63
+ submit_url = f"{api_url}/submit"
64
+
65
+ # 1. Instantiate Agent ( modify this part to create your agent)
 
 
 
 
 
 
66
  try:
67
+ agent = BasicAgent()
68
+ except Exception as e:
69
+ print(f"Error instantiating agent: {e}")
70
+ return f"Error initializing agent: {e}", None
71
+ # 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)
72
+ agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
73
+ print(agent_code)
74
+
75
+ # 2. Fetch Questions
76
+ print(f"Fetching questions from: {questions_url}")
77
+ try:
78
+ response = requests.get(questions_url, timeout=15)
79
  response.raise_for_status()
80
+ questions_data = response.json()
81
+ if not questions_data:
82
+ print("Fetched questions list is empty.")
83
+ return "Fetched questions list is empty or invalid format.", None
84
+ print(f"Fetched {len(questions_data)} questions.")
85
+ except requests.exceptions.RequestException as e:
86
+ print(f"Error fetching questions: {e}")
87
+ return f"Error fetching questions: {e}", None
88
+ except requests.exceptions.JSONDecodeError as e:
89
+ print(f"Error decoding JSON response from questions endpoint: {e}")
90
+ print(f"Response text: {response.text[:500]}")
91
+ return f"Error decoding server response for questions: {e}", None
92
+ except Exception as e:
93
+ print(f"An unexpected error occurred fetching questions: {e}")
94
+ return f"An unexpected error occurred fetching questions: {e}", None
95
+
96
+ # 3. Run your Agent
97
+ results_log = []
98
+ answers_payload = []
99
+ print(f"Running agent on {len(questions_data)} questions...")
100
+ for i, item in enumerate(questions_data):
101
+ task_id = item.get("task_id")
102
+ question_text = item.get("question")
103
+ if not task_id or question_text is None:
104
+ print(f"Skipping item with missing task_id or question: {item}")
105
+ continue
106
+ try:
107
+ submitted_answer = agent(question_text)
108
+ answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
109
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
110
+ except Exception as e:
111
+ print(f"Error running agent on task {task_id}: {e}")
112
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
113
 
114
+
115
+ if not answers_payload:
116
+ print("Agent did not produce any answers to submit.")
117
+ return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
118
+
119
+ # 4. Prepare Submission
120
+ submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
121
+ status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
122
+ print(status_update)
123
+
124
+ # 5. Submit
125
+ print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
126
+ try:
127
+ response = requests.post(submit_url, json=submission_data, timeout=60)
128
  response.raise_for_status()
129
+ result_data = response.json()
130
+ final_status = (
131
+ f"Submission Successful!\n"
132
+ f"User: {result_data.get('username')}\n"
133
+ f"Overall Score: {result_data.get('score', 'N/A')}% "
134
+ f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
135
+ f"Message: {result_data.get('message', 'No message received.')}"
136
  )
137
+ print("Submission successful.")
138
+ results_df = pd.DataFrame(results_log)
139
+ return final_status, results_df
140
+ except requests.exceptions.HTTPError as e:
141
+ error_detail = f"Server responded with status {e.response.status_code}."
142
+ try:
143
+ error_json = e.response.json()
144
+ error_detail += f" Detail: {error_json.get('detail', e.response.text)}"
145
+ except requests.exceptions.JSONDecodeError:
146
+ error_detail += f" Response: {e.response.text[:500]}"
147
+ status_message = f"Submission Failed: {error_detail}"
148
+ print(status_message)
149
+ results_df = pd.DataFrame(results_log)
150
+ return status_message, results_df
151
+ except requests.exceptions.Timeout:
152
+ status_message = "Submission Failed: The request timed out."
153
+ print(status_message)
154
+ results_df = pd.DataFrame(results_log)
155
+ return status_message, results_df
156
+ except requests.exceptions.RequestException as e:
157
+ status_message = f"Submission Failed: Network error - {e}"
158
+ print(status_message)
159
+ results_df = pd.DataFrame(results_log)
160
+ return status_message, results_df
161
  except Exception as e:
162
+ status_message = f"An unexpected error occurred during submission: {e}"
163
+ print(status_message)
164
+ results_df = pd.DataFrame(results_log)
165
+ return status_message, results_df
166
+
167
+
168
+ # --- Build Gradio Interface using Blocks ---
169
+ with gr.Blocks() as demo:
170
+ gr.Markdown("# Basic Agent Evaluation Runner")
171
+ gr.Markdown(
172
+ """
173
+ **Instructions:**
174
+
175
+ 1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
176
+ 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
177
+ 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
178
+
179
+ ---
180
+ **Disclaimers:**
181
+ 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).
182
+ 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.
183
+ """
184
+ )
185
+
186
  gr.LoginButton()
187
+
188
+ run_button = gr.Button("Run Evaluation & Submit All Answers")
189
+
190
+ status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
191
+ # Removed max_rows=10 from DataFrame constructor
192
+ results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
193
+
194
+ run_button.click(
195
  fn=run_and_submit_all,
196
+ outputs=[status_output, results_table]
197
  )
198
 
199
  if __name__ == "__main__":
200
+ print("\n" + "-"*30 + " App Starting " + "-"*30)
201
+ # Check for SPACE_HOST and SPACE_ID at startup for information
202
+ space_host_startup = os.getenv("SPACE_HOST")
203
+ space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
204
+
205
+ if space_host_startup:
206
+ print(f"✅ SPACE_HOST found: {space_host_startup}")
207
+ print(f" Runtime URL should be: https://{space_host_startup}.hf.space")
208
+ else:
209
+ print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
210
+
211
+ if space_id_startup: # Print repo URLs if SPACE_ID is found
212
+ print(f"✅ SPACE_ID found: {space_id_startup}")
213
+ print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
214
+ print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
215
+ else:
216
+ print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
217
+
218
+ print("-"*(60 + len(" App Starting ")) + "\n")
219
+
220
+ print("Launching Gradio Interface for Basic Agent Evaluation...")
221
+ demo.launch(debug=True, share=False)