mnosouhi96 commited on
Commit
2f74e6e
·
1 Parent(s): d359513

previous codes

Browse files
Files changed (2) hide show
  1. app.py +53 -208
  2. requirements.txt +18 -3
app.py CHANGED
@@ -1,206 +1,64 @@
1
- import os, io, re, json, subprocess, requests, pandas as pd, gradio as gr
2
- from smolagents import CodeAgent, InferenceClientModel, PythonInterpreterTool
 
 
3
 
4
- SPACE_ID = "marjanns/Final_Assignment_Template"
5
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
6
-
7
- def postprocess_exact(s: str | None) -> str:
8
- s = "" if s is None else str(s)
9
- s = s.strip()
10
- if (s.startswith('"') and s.endswith('"')) or (s.startswith("'") and s.endswith("'")):
11
- s = s[1:-1].strip()
12
- s = re.sub(r"\s+", " ", s).strip()
13
- s = re.sub(r"\.(\s*)$", "", s)
14
- return s
15
-
16
- def fetch_files(task_id: str):
17
- try:
18
- r = requests.get(f"{DEFAULT_API_URL}/files/{task_id}", timeout=30)
19
- r.raise_for_status()
20
- data = r.json()
21
- if isinstance(data, dict) and "files" in data:
22
- return data["files"]
23
- if isinstance(data, dict) and "file_url" in data:
24
- return [data]
25
- return []
26
- except Exception:
27
- return []
28
-
29
- def solve_reverse_sentence(q: str) -> str | None:
30
- if ".rewsna" in q:
31
- m = re.search(r'"(.*)"', q, re.S)
32
- src = m.group(1) if m else q
33
- rev = src[::-1]
34
- if "opposite of the word 'left'" in rev or 'opposite of the word "left"' in rev:
35
- return "right"
36
- return None
37
-
38
- def solve_non_commutative_subset(q: str) -> str | None:
39
- if "define * on the set S" in q and "not commutative" in q:
40
- lines = [ln.strip() for ln in q.splitlines() if ln.strip().startswith("|")]
41
- if not lines:
42
- return ""
43
- header = [h.strip() for h in lines[0].strip("|").split("|")]
44
- elems = [e.strip() for e in header[1:]]
45
- tbl = {}
46
- for row in lines[2:]:
47
- cells = [c.strip() for c in row.strip("|").split("|")]
48
- if not cells or len(cells) < len(elems) + 1:
49
- continue
50
- r = cells[0]
51
- tbl[r] = {elems[i]: cells[i+1] for i in range(len(elems))}
52
- bad = set()
53
- for x in elems:
54
- for y in elems:
55
- try:
56
- if tbl[x][y] != tbl[y][x]:
57
- bad.add(x); bad.add(y)
58
- except Exception:
59
- pass
60
- return ", ".join(sorted(bad)) if bad else ""
61
- return None
62
-
63
- def solve_vegetables(q: str) -> str | None:
64
- if "I'm making a grocery list" in q and "alphabetize the list of vegetables" in q:
65
- m = re.search(r"list I have so far:\s*(.*?)\s*I need to make headings", q, re.I | re.S)
66
- if not m:
67
- return ""
68
- items = [x.strip().lower() for x in re.split(r",\s*", m.group(1))]
69
- botanical_fruits = {
70
- "tomato","zucchini","courgette","bell pepper","pepper","cucumber","eggplant","aubergine",
71
- "green beans","beans","corn","maize","rice","plums","peanuts","acorns","whole allspice",
72
- "allspice","coffee","whole bean coffee"
73
- }
74
- non_produce = {"milk","eggs","flour","oreos","whole allspice","whole bean coffee","peanuts","acorns","plums","rice"}
75
- veg = set()
76
- for it in items:
77
- if it in botanical_fruits or it in non_produce:
78
- continue
79
- if it in {"fresh basil","basil"}:
80
- veg.add("fresh basil")
81
- elif it in {"sweet potato","sweet potatoes"}:
82
- veg.add("sweet potatoes")
83
- elif it in {"broccoli","celery","lettuce"}:
84
- veg.add(it)
85
- return ", ".join(sorted(veg))
86
- return None
87
-
88
- def solve_with_files(task_id: str) -> str | None:
89
- files = fetch_files(task_id)
90
- for f in files:
91
- url = f.get("file_url") or f.get("url") or ""
92
- name = (f.get("filename") or f.get("name") or "").lower()
93
- if not url:
94
- continue
95
- try:
96
- data = requests.get(url, timeout=60).content
97
- except Exception:
98
- continue
99
- if name.endswith((".xlsx",".xls")):
100
- try:
101
- df = pd.read_excel(io.BytesIO(data))
102
- if "Category" in df.columns:
103
- food = df[df["Category"].astype(str).str.lower().eq("food")]
104
- if "Sales" in food.columns:
105
- total = float(food["Sales"].sum())
106
- else:
107
- total = float(food.select_dtypes(include="number").sum().sum())
108
- return f"{total:.2f}"
109
- scols = df.select_dtypes(include="number")
110
- total = float(scols.sum().sum())
111
- return f"{total:.2f}"
112
- except Exception:
113
- pass
114
- if name.endswith(".py"):
115
- try:
116
- p = subprocess.run(["python","-"], input=data, capture_output=True, text=True, timeout=10)
117
- out = (p.stdout or "").strip()
118
- if out:
119
- return postprocess_exact(out.splitlines()[-1])
120
- except Exception:
121
- pass
122
- if name.endswith((".mp3",".wav",".m4a",".flac",".png",".jpg",".jpeg",".gif",".webp",".pdf",".txt",".csv",".json")):
123
- return ""
124
- return None
125
-
126
- class QwenAgent:
127
- def __init__(self):
128
- self.model = InferenceClientModel(model_id="Qwen/Qwen2.5-7B-Instruct")
129
- self.agent = CodeAgent(
130
- model=self.model,
131
- tools=[PythonInterpreterTool()],
132
- add_base_tools=False,
133
- system_prompt=(
134
- "You solve short questions. If you are unsure or need web/audio/image access you cannot use, "
135
- "return an empty string. Otherwise return ONLY the final answer string—no extra words."
136
- ),
137
- stream_outputs=False,
138
- )
139
-
140
- def run(self, question: str) -> str:
141
- try:
142
- out = self.agent.run("Return only the final answer string.\nQuestion: " + question)
143
- return postprocess_exact(out)
144
- except Exception as e:
145
- return ""
146
 
147
  class BasicAgent:
148
  def __init__(self):
149
- self.llm_agent = QwenAgent()
150
-
151
- def __call__(self, question: str, task_id: str | None = None) -> str:
152
- for solver in (solve_reverse_sentence, solve_non_commutative_subset, solve_vegetables):
153
- s = solver(question)
154
- if s is not None:
155
- return s
156
- if task_id:
157
- s = solve_with_files(task_id)
158
- if s is not None:
159
- return s
160
- return self.llm_agent.run(question)
161
 
162
  def _username_from_profile(p):
163
  if p is None:
164
- return ""
 
165
  u = getattr(p, "username", None)
166
  if u:
167
  return str(u)
 
168
  if isinstance(p, dict):
169
  return str(p.get("username") or "")
170
- return ""
171
-
172
- def store_profile_as_dict(p):
173
- u = _username_from_profile(p)
174
- msg = f"✅ Logged in as **{u}**" if u else "❌ Not logged in"
175
- return ({"username": u} if u else None), msg
176
 
177
- def run_and_submit_all(profile_dict, evt=None, username_fallback=""):
178
- username = (profile_dict or {}).get("username", "").strip() or username_fallback.strip()
 
179
  if not username:
180
- return "Please Login to Hugging Face or type a username.", None
181
 
182
- questions_url = f"{DEFAULT_API_URL}/questions"
183
- submit_url = f"{DEFAULT_API_URL}/submit"
184
- agent_code = f"https://huggingface.co/spaces/{SPACE_ID}/tree/main"
185
 
186
  try:
187
- r = requests.get(questions_url, timeout=20)
188
- r.raise_for_status()
189
- questions = r.json()
190
- if not isinstance(questions, list) or not questions:
 
 
 
 
 
 
 
191
  return "Fetched questions list is empty or invalid format.", None
192
  except Exception as e:
193
  return f"Error fetching questions: {e}", None
194
 
195
- agent = BasicAgent()
196
  results_log, answers_payload = [], []
197
- for item in questions:
198
  tid = item.get("task_id")
199
  q = item.get("question")
200
  if not tid or q is None:
201
  continue
202
  try:
203
- ans = agent(q, tid)
204
  except Exception as e:
205
  ans = f"AGENT ERROR: {e}"
206
  answers_payload.append({"task_id": tid, "submitted_answer": ans})
@@ -209,19 +67,19 @@ def run_and_submit_all(profile_dict, evt=None, username_fallback=""):
209
  if not answers_payload:
210
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
211
 
212
- payload = {"username": username, "agent_code": agent_code, "answers": answers_payload}
213
  try:
214
- sresp = requests.post(f"{DEFAULT_API_URL}/submit", json=payload, timeout=120)
215
- sresp.raise_for_status()
216
- res = sresp.json()
217
- msg = (
218
  "Submission Successful!\n"
219
- f"User: {res.get('username', username)}\n"
220
- f"Overall Score: {res.get('score','N/A')}% "
221
- f"({res.get('correct_count','?')}/{res.get('total_attempted','?')} correct)\n"
222
- f"Message: {res.get('message','') or ''}"
223
  )
224
- return msg, pd.DataFrame(results_log)
225
  except requests.exceptions.HTTPError as e:
226
  try:
227
  detail = e.response.json().get("detail", e.response.text)
@@ -233,38 +91,25 @@ def run_and_submit_all(profile_dict, evt=None, username_fallback=""):
233
  except Exception as e:
234
  return f"Submission Failed: {e}", pd.DataFrame(results_log)
235
 
236
- def test_single(question_text, task_id):
237
- agent = BasicAgent()
238
- try:
239
- return agent(question_text, task_id or None)
240
- except Exception as e:
241
- return f"AGENT ERROR: {e}"
242
-
243
  with gr.Blocks() as demo:
244
- gr.Markdown("# Basic Agent Evaluation Runner — Qwen on Hugging Face (no OpenAI/Groq keys)")
245
- gr.Markdown("Log in **or** type your HF username. Use **Quick Test** to try one question. Then submit all.")
246
 
247
  login = gr.LoginButton()
248
  user_state = gr.State()
249
  whoami = gr.Markdown()
250
- login.click(store_profile_as_dict, inputs=login, outputs=[user_state, whoami])
251
 
252
- with gr.Row():
253
- username_box = gr.Textbox(label="HF Username (fallback if login fails)", placeholder="your-username")
 
254
 
255
- gr.Markdown("### Quick Test")
256
- with gr.Row():
257
- q_inp = gr.Textbox(label="Question", lines=4)
258
- tid_inp = gr.Textbox(label="Task ID (optional)")
259
- test_btn = gr.Button("Run Quick Test")
260
- test_out = gr.Textbox(label="Agent Answer", lines=3, interactive=False)
261
- test_btn.click(fn=test_single, inputs=[q_inp, tid_inp], outputs=test_out)
262
 
263
- gr.Markdown("---")
264
  run_button = gr.Button("Run Evaluation & Submit All Answers")
265
- status_output = gr.Textbox(label="Run Status / Submission Result", lines=7, interactive=False)
266
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
267
- run_button.click(fn=run_and_submit_all, inputs=[user_state, run_button, username_box], outputs=[status_output, results_table])
 
268
 
269
  if __name__ == "__main__":
270
- demo.launch(debug=True, share=False)
 
1
+ import os
2
+ import gradio as gr
3
+ import requests
4
+ import pandas as pd
5
 
 
6
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
7
+ SPACE_ID = "marjanns/Final_Assignment_Template"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
  class BasicAgent:
10
  def __init__(self):
11
+ print("BasicAgent initialized.")
12
+ def __call__(self, question: str) -> str:
13
+ print(f"Agent received question (first 50 chars): {question[:50]}...")
14
+ return "This is a default answer."
 
 
 
 
 
 
 
 
15
 
16
  def _username_from_profile(p):
17
  if p is None:
18
+ return None
19
+ # object with attribute
20
  u = getattr(p, "username", None)
21
  if u:
22
  return str(u)
23
+ # dict-style
24
  if isinstance(p, dict):
25
  return str(p.get("username") or "")
26
+ return None
 
 
 
 
 
27
 
28
+ def run_and_submit_all(profile, evt=None):
29
+ space_id = SPACE_ID
30
+ username = _username_from_profile(profile)
31
  if not username:
32
+ return "Please Login to Hugging Face with the button.", None
33
 
34
+ api_url = DEFAULT_API_URL
35
+ questions_url = f"{api_url}/questions"
36
+ submit_url = f"{api_url}/submit"
37
 
38
  try:
39
+ agent = BasicAgent()
40
+ except Exception as e:
41
+ return f"Error initializing agent: {e}", None
42
+
43
+ agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
44
+
45
+ try:
46
+ response = requests.get(questions_url, timeout=15)
47
+ response.raise_for_status()
48
+ questions_data = response.json()
49
+ if not questions_data:
50
  return "Fetched questions list is empty or invalid format.", None
51
  except Exception as e:
52
  return f"Error fetching questions: {e}", None
53
 
 
54
  results_log, answers_payload = [], []
55
+ for item in questions_data:
56
  tid = item.get("task_id")
57
  q = item.get("question")
58
  if not tid or q is None:
59
  continue
60
  try:
61
+ ans = agent(q)
62
  except Exception as e:
63
  ans = f"AGENT ERROR: {e}"
64
  answers_payload.append({"task_id": tid, "submitted_answer": ans})
 
67
  if not answers_payload:
68
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
69
 
70
+ submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
71
  try:
72
+ resp = requests.post(submit_url, json=submission_data, timeout=60)
73
+ resp.raise_for_status()
74
+ data = resp.json()
75
+ status = (
76
  "Submission Successful!\n"
77
+ f"User: {data.get('username')}\n"
78
+ f"Overall Score: {data.get('score','N/A')}% "
79
+ f"({data.get('correct_count','?')}/{data.get('total_attempted','?')} correct)\n"
80
+ f"Message: {data.get('message','No message received.')}"
81
  )
82
+ return status, pd.DataFrame(results_log)
83
  except requests.exceptions.HTTPError as e:
84
  try:
85
  detail = e.response.json().get("detail", e.response.text)
 
91
  except Exception as e:
92
  return f"Submission Failed: {e}", pd.DataFrame(results_log)
93
 
 
 
 
 
 
 
 
94
  with gr.Blocks() as demo:
95
+ gr.Markdown("# Basic Agent Evaluation Runner")
96
+ gr.Markdown("Click **Log in with Hugging Face** first. After you see your username below, press **Run**.")
97
 
98
  login = gr.LoginButton()
99
  user_state = gr.State()
100
  whoami = gr.Markdown()
 
101
 
102
+ def store_and_echo(p):
103
+ u = _username_from_profile(p) or "(not logged in)"
104
+ return p, f"✅ Logged in as **{u}**" if u and u != "(not logged in)" else "❌ Not logged in"
105
 
106
+ login.click(store_and_echo, inputs=login, outputs=[user_state, whoami])
 
 
 
 
 
 
107
 
 
108
  run_button = gr.Button("Run Evaluation & Submit All Answers")
109
+ status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
110
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
111
+
112
+ run_button.click(fn=run_and_submit_all, inputs=[user_state], outputs=[status_output, results_table])
113
 
114
  if __name__ == "__main__":
115
+ demo.launch(debug=True, share=True)
requirements.txt CHANGED
@@ -34,9 +34,24 @@
34
  # python-dotenv
35
  # protobuf==3.20.*
36
  # chromadb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  gradio[oauth]>=4.44.0
38
  requests>=2.31.0
39
  pandas>=2.2.0
40
- openpyxl>=3.1.2
41
- smolagents>=0.0.23
42
- duckduckgo-search>=6.1.0
 
34
  # python-dotenv
35
  # protobuf==3.20.*
36
  # chromadb
37
+ # gradio[oauth]>=4.44.0
38
+ # requests>=2.31.0
39
+ # pandas>=2.2.0
40
+ # openpyxl>=3.1.2
41
+ # smolagents>=0.0.23
42
+ # duckduckgo-search>=6.1.0
43
+ # gradio[oauth]>=4.44.0
44
+ # requests
45
+ # smolagents>=0.0.23
46
+ # duckduckgo-search>=6.1.0
47
+ # pandas>=2.2.0
48
+ # python-dotenv>=1.0.1
49
+ # gradio
50
+ # requests
51
+ # smolagents
52
+ # smolagents[openai]
53
  gradio[oauth]>=4.44.0
54
  requests>=2.31.0
55
  pandas>=2.2.0
56
+ itsdangerous>=2.1.2
57
+ authlib>=1.3.0