supratipb commited on
Commit
ee32359
·
verified ·
1 Parent(s): 71f52ef

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +217 -157
  2. requirements.txt +4 -6
app.py CHANGED
@@ -1,162 +1,222 @@
1
- import faicons as fa
2
- import plotly.express as px
3
-
4
- # Load data and compute static values
5
- from shared import app_dir, tips
6
- from shinywidgets import render_plotly
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
- from shiny import reactive, render
9
- from shiny.express import input, ui
10
 
11
- bill_rng = (min(tips.total_bill), max(tips.total_bill))
12
 
13
- # Add page title and sidebar
14
- ui.page_opts(title="Restaurant tipping", fillable=True)
 
15
 
16
- with ui.sidebar(open="desktop"):
17
- ui.input_slider(
18
- "total_bill",
19
- "Bill amount",
20
- min=bill_rng[0],
21
- max=bill_rng[1],
22
- value=bill_rng,
23
- pre="$",
24
  )
25
- ui.input_checkbox_group(
26
- "time",
27
- "Food service",
28
- ["Lunch", "Dinner"],
29
- selected=["Lunch", "Dinner"],
30
- inline=True,
31
- )
32
- ui.input_action_button("reset", "Reset filter")
33
-
34
- # Add main content
35
- ICONS = {
36
- "user": fa.icon_svg("user", "regular"),
37
- "wallet": fa.icon_svg("wallet"),
38
- "currency-dollar": fa.icon_svg("dollar-sign"),
39
- "ellipsis": fa.icon_svg("ellipsis"),
40
- }
41
-
42
- with ui.layout_columns(fill=False):
43
- with ui.value_box(showcase=ICONS["user"]):
44
- "Total tippers"
45
-
46
- @render.express
47
- def total_tippers():
48
- tips_data().shape[0]
49
-
50
- with ui.value_box(showcase=ICONS["wallet"]):
51
- "Average tip"
52
-
53
- @render.express
54
- def average_tip():
55
- d = tips_data()
56
- if d.shape[0] > 0:
57
- perc = d.tip / d.total_bill
58
- f"{perc.mean():.1%}"
59
-
60
- with ui.value_box(showcase=ICONS["currency-dollar"]):
61
- "Average bill"
62
-
63
- @render.express
64
- def average_bill():
65
- d = tips_data()
66
- if d.shape[0] > 0:
67
- bill = d.total_bill.mean()
68
- f"${bill:.2f}"
69
-
70
-
71
- with ui.layout_columns(col_widths=[6, 6, 12]):
72
- with ui.card(full_screen=True):
73
- ui.card_header("Tips data")
74
-
75
- @render.data_frame
76
- def table():
77
- return render.DataGrid(tips_data())
78
-
79
- with ui.card(full_screen=True):
80
- with ui.card_header(class_="d-flex justify-content-between align-items-center"):
81
- "Total bill vs tip"
82
- with ui.popover(title="Add a color variable", placement="top"):
83
- ICONS["ellipsis"]
84
- ui.input_radio_buttons(
85
- "scatter_color",
86
- None,
87
- ["none", "sex", "smoker", "day", "time"],
88
- inline=True,
89
- )
90
-
91
- @render_plotly
92
- def scatterplot():
93
- color = input.scatter_color()
94
- return px.scatter(
95
- tips_data(),
96
- x="total_bill",
97
- y="tip",
98
- color=None if color == "none" else color,
99
- trendline="lowess",
100
- )
101
-
102
- with ui.card(full_screen=True):
103
- with ui.card_header(class_="d-flex justify-content-between align-items-center"):
104
- "Tip percentages"
105
- with ui.popover(title="Add a color variable"):
106
- ICONS["ellipsis"]
107
- ui.input_radio_buttons(
108
- "tip_perc_y",
109
- "Split by:",
110
- ["sex", "smoker", "day", "time"],
111
- selected="day",
112
- inline=True,
113
- )
114
-
115
- @render_plotly
116
- def tip_perc():
117
- from ridgeplot import ridgeplot
118
-
119
- dat = tips_data()
120
- dat["percent"] = dat.tip / dat.total_bill
121
- yvar = input.tip_perc_y()
122
- uvals = dat[yvar].unique()
123
-
124
- samples = [[dat.percent[dat[yvar] == val]] for val in uvals]
125
-
126
- plt = ridgeplot(
127
- samples=samples,
128
- labels=uvals,
129
- bandwidth=0.01,
130
- colorscale="viridis",
131
- colormode="row-index",
132
- )
133
-
134
- plt.update_layout(
135
- legend=dict(
136
- orientation="h", yanchor="bottom", y=1.02, xanchor="center", x=0.5
137
- )
138
- )
139
-
140
- return plt
141
-
142
-
143
- ui.include_css(app_dir / "styles.css")
144
-
145
- # --------------------------------------------------------
146
- # Reactive calculations and effects
147
- # --------------------------------------------------------
148
-
149
-
150
- @reactive.calc
151
- def tips_data():
152
- bill = input.total_bill()
153
- idx1 = tips.total_bill.between(bill[0], bill[1])
154
- idx2 = tips.time.isin(input.time())
155
- return tips[idx1 & idx2]
156
-
157
-
158
- @reactive.effect
159
- @reactive.event(input.reset)
160
- def _():
161
- ui.update_slider("total_bill", value=bill_rng)
162
- ui.update_checkbox_group("time", selected=["Lunch", "Dinner"])
 
1
+ import os
2
+ import gradio as gr
3
+ import requests
4
+ import inspect
5
+ import pandas as pd
6
+ import time
7
+ from smolagents import DuckDuckGoSearchTool, CodeAgent, LiteLLMModel
8
+
9
+
10
+ # (Keep Constants as is)
11
+ # --- Constants ---
12
+ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
13
+
14
+ SYSTEM_PROMPT = """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].
15
+ YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings.
16
+ 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.
17
+ 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.
18
+ 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."""
19
+
20
+ # --- Basic Agent Definition ---
21
+ # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
22
+ class BasicAgent:
23
+ def __init__(self):
24
+ print("Initializing BasicAgent.")
25
+ model_id = "gemini/gemini-2.0-flash-lite"
26
+
27
+ self.model = LiteLLMModel(
28
+ model_id=model_id,
29
+ api_key=os.environ.get('GOOGLE_API_KEY'),
30
+ system_prompt=SYSTEM_PROMPT
31
+ )
32
+
33
+ search_tool = DuckDuckGoSearchTool()
34
+
35
+ self.agent = CodeAgent(
36
+ model=self.model,
37
+ tools=[search_tool]
38
+ )
39
+
40
+ print("BasicAgent initialized.")
41
+
42
+ def __call__(self, question: str) -> str:
43
+ print(f"Agent received question (first 50 chars): {question[:50]}...")
44
+ answer = self.agent.run(question)
45
+ print(f"Agent returning the answer: {answer}")
46
+ return answer
47
+
48
+ def run_and_submit_all( profile: gr.OAuthProfile | None):
49
+ """
50
+ Fetches all questions, runs the BasicAgent on them, submits all answers,
51
+ and displays the results.
52
+ """
53
+ # --- Determine HF Space Runtime URL and Repo URL ---
54
+ space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
55
+
56
+ if profile:
57
+ username= f"{profile.username}"
58
+ print(f"User logged in: {username}")
59
+ else:
60
+ print("User not logged in.")
61
+ return "Please Login to Hugging Face with the button.", None
62
+
63
+ api_url = DEFAULT_API_URL
64
+ questions_url = f"{api_url}/questions"
65
+ submit_url = f"{api_url}/submit"
66
+
67
+ # 1. Instantiate Agent ( modify this part to create your agent)
68
+ try:
69
+ agent = BasicAgent()
70
+ except Exception as e:
71
+ print(f"Error instantiating agent: {e}")
72
+ return f"Error initializing agent: {e}", None
73
+ # 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)
74
+ agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
75
+ print(agent_code)
76
+
77
+ # 2. Fetch Questions
78
+ print(f"Fetching questions from: {questions_url}")
79
+ try:
80
+ response = requests.get(questions_url, timeout=15)
81
+ response.raise_for_status()
82
+ questions_data = response.json()
83
+ if not questions_data:
84
+ print("Fetched questions list is empty.")
85
+ return "Fetched questions list is empty or invalid format.", None
86
+ print(f"Fetched {len(questions_data)} questions.")
87
+ except requests.exceptions.RequestException as e:
88
+ print(f"Error fetching questions: {e}")
89
+ return f"Error fetching questions: {e}", None
90
+ except requests.exceptions.JSONDecodeError as e:
91
+ print(f"Error decoding JSON response from questions endpoint: {e}")
92
+ print(f"Response text: {response.text[:500]}")
93
+ return f"Error decoding server response for questions: {e}", None
94
+ except Exception as e:
95
+ print(f"An unexpected error occurred fetching questions: {e}")
96
+ return f"An unexpected error occurred fetching questions: {e}", None
97
+
98
+ # 3. Run your Agent
99
+ results_log = []
100
+ answers_payload = []
101
+ print(f"Running agent on {len(questions_data)} questions...")
102
+ for item in questions_data:
103
+ task_id = item.get("task_id")
104
+ question_text = item.get("question")
105
+ if not task_id or question_text is None:
106
+ print(f"Skipping item with missing task_id or question: {item}")
107
+ continue
108
+ try:
109
+ submitted_answer = agent(question_text)
110
+ answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
111
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
112
+ except Exception as e:
113
+ print(f"Error running agent on task {task_id}: {e}")
114
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
115
+
116
+ if not answers_payload:
117
+ print("Agent did not produce any answers to submit.")
118
+ return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
119
+
120
+ # 4. Prepare Submission
121
+ submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
122
+ status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
123
+ print(status_update)
124
+
125
+ # 5. Submit
126
+ print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
127
+ try:
128
+ response = requests.post(submit_url, json=submission_data, timeout=60)
129
+ response.raise_for_status()
130
+ result_data = response.json()
131
+ final_status = (
132
+ f"Submission Successful!\n"
133
+ f"User: {result_data.get('username')}\n"
134
+ f"Overall Score: {result_data.get('score', 'N/A')}% "
135
+ f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
136
+ f"Message: {result_data.get('message', 'No message received.')}"
137
+ )
138
+ print("Submission successful.")
139
+ results_df = pd.DataFrame(results_log)
140
+ return final_status, results_df
141
+ except requests.exceptions.HTTPError as e:
142
+ error_detail = f"Server responded with status {e.response.status_code}."
143
+ try:
144
+ error_json = e.response.json()
145
+ error_detail += f" Detail: {error_json.get('detail', e.response.text)}"
146
+ except requests.exceptions.JSONDecodeError:
147
+ error_detail += f" Response: {e.response.text[:500]}"
148
+ status_message = f"Submission Failed: {error_detail}"
149
+ print(status_message)
150
+ results_df = pd.DataFrame(results_log)
151
+ return status_message, results_df
152
+ except requests.exceptions.Timeout:
153
+ status_message = "Submission Failed: The request timed out."
154
+ print(status_message)
155
+ results_df = pd.DataFrame(results_log)
156
+ return status_message, results_df
157
+ except requests.exceptions.RequestException as e:
158
+ status_message = f"Submission Failed: Network error - {e}"
159
+ print(status_message)
160
+ results_df = pd.DataFrame(results_log)
161
+ return status_message, results_df
162
+ except Exception as e:
163
+ status_message = f"An unexpected error occurred during submission: {e}"
164
+ print(status_message)
165
+ results_df = pd.DataFrame(results_log)
166
+ return status_message, results_df
167
+
168
+
169
+ # --- Build Gradio Interface using Blocks ---
170
+ with gr.Blocks() as demo:
171
+ gr.Markdown("# Basic Agent Evaluation Runner")
172
+ gr.Markdown(
173
+ """
174
+ **Instructions:**
175
+
176
+ 1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
177
+ 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
178
+ 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
179
+
180
+ ---
181
+ **Disclaimers:**
182
+ 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).
183
+ 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.
184
+ """
185
+ )
186
 
187
+ gr.LoginButton()
 
188
 
189
+ run_button = gr.Button("Run Evaluation & Submit All Answers")
190
 
191
+ status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
192
+ # Removed max_rows=10 from DataFrame constructor
193
+ results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
194
 
195
+ run_button.click(
196
+ fn=run_and_submit_all,
197
+ outputs=[status_output, results_table]
 
 
 
 
 
198
  )
199
+
200
+ if __name__ == "__main__":
201
+ print("\n" + "-"*30 + " App Starting " + "-"*30)
202
+ # Check for SPACE_HOST and SPACE_ID at startup for information
203
+ space_host_startup = os.getenv("SPACE_HOST")
204
+ space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
205
+
206
+ if space_host_startup:
207
+ print(f"✅ SPACE_HOST found: {space_host_startup}")
208
+ print(f" Runtime URL should be: https://{space_host_startup}.hf.space")
209
+ else:
210
+ print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
211
+
212
+ if space_id_startup: # Print repo URLs if SPACE_ID is found
213
+ print(f"✅ SPACE_ID found: {space_id_startup}")
214
+ print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
215
+ print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
216
+ else:
217
+ print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
218
+
219
+ print("-"*(60 + len(" App Starting ")) + "\n")
220
+
221
+ print("Launching Gradio Interface for Basic Agent Evaluation...")
222
+ demo.launch(debug=True, share=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
requirements.txt CHANGED
@@ -1,6 +1,4 @@
1
- faicons
2
- shiny
3
- shinywidgets
4
- plotly
5
- pandas
6
- ridgeplot
 
1
+ gradio
2
+ requests
3
+ smolagents
4
+ smolagents[litellm]