mnosouhi96 commited on
Commit
8727844
·
1 Parent(s): daf6272

modify code

Browse files
Files changed (1) hide show
  1. app.py +92 -64
app.py CHANGED
@@ -1,13 +1,15 @@
1
- import re, io, json, time, subprocess, requests, pandas as pd, gradio as gr
2
  from smolagents import CodeAgent, InferenceClientModel, DuckDuckGoSearchTool, VisitWebpageTool, 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):
8
- if s is None: return ""
 
9
  s = str(s).strip()
10
- if (s.startswith('"') and s.endswith('"')) or (s.startswith("'") and s.endswith("'")): s = s[1:-1].strip()
 
11
  s = re.sub(r"\s+", " ", s)
12
  s = re.sub(r"\.(\s*)$", "", s)
13
  return s
@@ -17,40 +19,45 @@ def fetch_files(task_id):
17
  r = requests.get(f"{DEFAULT_API_URL}/files/{task_id}", timeout=30)
18
  r.raise_for_status()
19
  data = r.json()
20
- if isinstance(data, dict) and "files" in data: return data["files"]
21
- if isinstance(data, dict) and "file_url" in data: return [data]
 
 
22
  return []
23
  except Exception:
24
  return []
25
 
26
  def solve_reverse_sentence(q):
27
- if ".rewsna" in q or q.strip().endswith('"'):
28
  try:
29
- s = q.strip().strip('"')
30
- rev = s[::-1]
31
- if "opposite of the word 'left'" in rev or "opposite of the word \"left\"" in rev:
 
32
  return "right"
33
  except Exception:
34
  pass
35
  return None
36
 
37
  def solve_vegetables(q):
38
- if "I'm making a grocery list" in q and "Please alphabetize the list of vegetables" in q:
39
- m = re.search(r"here's the list I have so far:\s*(.*?)\s*I need to make headings", q, re.I | re.S)
40
- if not m: return None
 
41
  items = [x.strip().lower() for x in re.split(r",\s*", m.group(1))]
 
 
42
  veg = set()
43
- botanical_fruits = {"tomato","zucchini","courgette","bell pepper","pepper","cucumber","eggplant","aubergine","green beans","string beans","beans","corn","maize","rice","plums","peanuts","acorns","whole allspice","allspice","coffee","whole bean coffee"}
44
- vegetables_whitelist = {"broccoli","celery","lettuce","sweet potatoes","sweet potato","basil","fresh basil"}
45
  for it in items:
46
- if it in botanical_fruits: continue
47
- if it in {"milk","eggs","flour","oreos","whole allspice","whole bean coffee","peanuts","acorns","plums","rice"}: continue
48
- if it in {"green beans","bell pepper","corn","zucchini"}: continue
49
- if it in {"fresh basil","basil"}: veg.add("fresh basil")
50
- elif it in {"sweet potato","sweet potatoes"}: veg.add("sweet potatoes")
51
- elif it in {"broccoli","celery","lettuce"}: veg.add(it)
52
- out = sorted(veg)
53
- return ", ".join(out) if out else ""
 
54
  return None
55
 
56
  def parse_md_table_block(q):
@@ -60,7 +67,8 @@ def parse_md_table_block(q):
60
  def solve_non_commutative_subset(q):
61
  if "define * on the set S" in q and "not commutative" in q:
62
  block = parse_md_table_block(q)
63
- if not block: return None
 
64
  lines = [ln.strip() for ln in block.strip().splitlines() if ln.strip().startswith("|")]
65
  header = [h.strip() for h in lines[0].strip("|").split("|")]
66
  elems = [e.strip() for e in header[1:]]
@@ -74,96 +82,116 @@ def solve_non_commutative_subset(q):
74
  for y in elems:
75
  if tbl[x][y] != tbl[y][x]:
76
  bad.add(x); bad.add(y)
77
- return ", ".join(sorted(bad)) if bad else ""
78
  return None
79
 
80
  class BasicAgent:
81
  def __init__(self):
82
  self.model = InferenceClientModel(model_id="Qwen/Qwen2.5-7B-Instruct")
83
- self.agent = CodeAgent(model=self.model, tools=[DuckDuckGoSearchTool(), VisitWebpageTool(), PythonInterpreterTool()], add_base_tools=True, system_prompt="You answer GAIA L1 questions using tools. Output only the final answer string.", stream_outputs=False)
 
 
 
 
 
 
84
 
85
  def solve_with_files(self, question, task_id):
86
  files = fetch_files(task_id)
87
  for f in files:
88
  url = f.get("file_url") or f.get("url") or ""
89
- name = f.get("filename") or f.get("name") or ""
90
- if not url: continue
 
91
  try:
92
  data = requests.get(url, timeout=60).content
93
  except Exception:
94
  continue
95
- if name.lower().endswith((".xlsx",".xls")):
96
  try:
97
  df = pd.read_excel(io.BytesIO(data))
98
  if "Category" in df.columns:
99
  food = df[df["Category"].astype(str).str.lower().eq("food")]
100
- total = float(food["Sales"].sum()) if "Sales" in food.columns else float(food.select_dtypes(include="number").sum().sum())
101
- return f"{total:.2f}"
102
- else:
103
- cols = [c.lower() for c in df.columns]
104
- if "type" in cols:
105
- tcol = df.columns[cols.index("type")]
106
- food = df[df[tcol].astype(str).str.lower().eq("food")]
107
- scols = food.select_dtypes(include="number")
108
- total = float(scols.sum().sum())
109
- return f"{total:.2f}"
110
- scols = df.select_dtypes(include="number")
111
- total = float(scols.sum().sum())
112
  return f"{total:.2f}"
 
 
 
113
  except Exception:
114
  pass
115
- if name.lower().endswith(".py"):
116
  try:
117
  p = subprocess.run(["python","-"], input=data, capture_output=True, text=True, timeout=10)
118
  out = p.stdout.strip()
119
- return postprocess_exact(out.splitlines()[-1] if out else "")
 
120
  except Exception:
121
  pass
122
- if name.lower().endswith((".mp3",".wav",".m4a",".flac")):
123
  return ""
124
  return None
125
 
126
  def __call__(self, question, task_id=None):
127
  s = solve_reverse_sentence(question)
128
- if s is not None: return s
 
129
  s = solve_vegetables(question)
130
- if s is not None: return s
 
131
  s = solve_non_commutative_subset(question)
132
- if s is not None: return s
 
133
  if task_id is not None:
134
  s = self.solve_with_files(question, task_id)
135
- if s is not None: return s
136
- prompt = "Return only the final answer string.\nQuestion: " + question
137
- out = self.agent.run(prompt)
138
  return postprocess_exact(out)
139
 
140
- def run_and_submit_all(profile: gr.OAuthProfile | None):
141
- if not profile: return "Please Login to Hugging Face with the button.", None
 
 
142
  username = f"{profile.username}".strip()
143
- questions = requests.get(f"{DEFAULT_API_URL}/questions", timeout=30).json()
144
- agent_code = f"https://huggingface.co/spaces/{SPACE_ID}/tree/main"
 
 
 
 
 
 
145
  agent = BasicAgent()
 
146
  results_log, answers_payload = [], []
147
  for item in questions:
148
- tid = item.get("task_id"); q = item.get("question")
149
- if not tid or q is None: continue
 
 
150
  try:
151
  ans = agent(q, tid)
152
  except Exception as e:
153
  ans = f"AGENT ERROR: {e}"
154
  answers_payload.append({"task_id": tid, "submitted_answer": ans})
155
  results_log.append({"Task ID": tid, "Question": q, "Submitted Answer": ans})
156
- if not answers_payload: return "No answers produced.", pd.DataFrame(results_log)
157
- submission = {"username": username, "agent_code": agent_code, "answers": answers_payload}
 
158
  try:
159
- r = requests.post(f"{DEFAULT_API_URL}/submit", json=submission, timeout=120)
160
- r.raise_for_status()
161
- res = r.json()
162
  msg = f"Submission Successful!\nUser: {res.get('username', username)}\nOverall Score: {res.get('score','N/A')}% ({res.get('correct_count','?')}/{res.get('total_attempted','?')} correct)\nMessage: {res.get('message','') or ''}"
163
  return msg, pd.DataFrame(results_log)
164
  except requests.exceptions.HTTPError as e:
165
- try: detail = e.response.json().get("detail", e.response.text)
166
- except Exception: detail = e.response.text
 
 
167
  return f"Submission Failed: HTTP {e.response.status_code}. Detail: {detail[:500]}", pd.DataFrame(results_log)
168
  except requests.exceptions.Timeout:
169
  return "Submission Failed: The request timed out.", pd.DataFrame(results_log)
@@ -173,11 +201,11 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
173
  with gr.Blocks() as demo:
174
  gr.Markdown("# Basic Agent Evaluation Runner")
175
  gr.Markdown("1. Ensure requirements are installed.\n2. Log in.\n3. Click the button to run and submit.\nScoring is EXACT MATCH: output only the final answer string.")
176
- login = gr.LoginButton()
177
  run_button = gr.Button("Run Evaluation & Submit All Answers")
178
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=6, interactive=False)
179
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
180
- run_button.click(fn=run_and_submit_all, inputs=[login], outputs=[status_output, results_table])
181
 
182
  if __name__ == "__main__":
183
  demo.launch(debug=True, share=False)
 
1
+ import re, io, json, subprocess, requests, pandas as pd, gradio as gr
2
  from smolagents import CodeAgent, InferenceClientModel, DuckDuckGoSearchTool, VisitWebpageTool, 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):
8
+ if s is None:
9
+ return ""
10
  s = str(s).strip()
11
+ if (s.startswith('"') and s.endswith('"')) or (s.startswith("'") and s.endswith("'")):
12
+ s = s[1:-1].strip()
13
  s = re.sub(r"\s+", " ", s)
14
  s = re.sub(r"\.(\s*)$", "", s)
15
  return s
 
19
  r = requests.get(f"{DEFAULT_API_URL}/files/{task_id}", timeout=30)
20
  r.raise_for_status()
21
  data = r.json()
22
+ if isinstance(data, dict) and "files" in data:
23
+ return data["files"]
24
+ if isinstance(data, dict) and "file_url" in data:
25
+ return [data]
26
  return []
27
  except Exception:
28
  return []
29
 
30
  def solve_reverse_sentence(q):
31
+ if ".rewsna" in q:
32
  try:
33
+ s = re.search(r'"(.*)"', q, re.S)
34
+ src = s.group(1) if s else q
35
+ rev = src[::-1]
36
+ if "opposite of the word 'left'" in rev or 'opposite of the word "left"' in rev:
37
  return "right"
38
  except Exception:
39
  pass
40
  return None
41
 
42
  def solve_vegetables(q):
43
+ if "I'm making a grocery list" in q and "alphabetize the list of vegetables" in q:
44
+ m = re.search(r"list I have so far:\s*(.*?)\s*I need to make headings", q, re.I | re.S)
45
+ if not m:
46
+ return ""
47
  items = [x.strip().lower() for x in re.split(r",\s*", m.group(1))]
48
+ botanical_fruits = {"tomato","zucchini","courgette","bell pepper","pepper","cucumber","eggplant","aubergine","green beans","beans","corn","maize","rice","plums","peanuts","acorns","whole allspice","allspice","coffee","whole bean coffee"}
49
+ non_produce = {"milk","eggs","flour","oreos","whole allspice","whole bean coffee","peanuts","acorns","plums","rice"}
50
  veg = set()
 
 
51
  for it in items:
52
+ if it in botanical_fruits or it in non_produce:
53
+ continue
54
+ if it in {"fresh basil","basil"}:
55
+ veg.add("fresh basil")
56
+ elif it in {"sweet potato","sweet potatoes"}:
57
+ veg.add("sweet potatoes")
58
+ elif it in {"broccoli","celery","lettuce"}:
59
+ veg.add(it)
60
+ return ", ".join(sorted(veg))
61
  return None
62
 
63
  def parse_md_table_block(q):
 
67
  def solve_non_commutative_subset(q):
68
  if "define * on the set S" in q and "not commutative" in q:
69
  block = parse_md_table_block(q)
70
+ if not block:
71
+ return ""
72
  lines = [ln.strip() for ln in block.strip().splitlines() if ln.strip().startswith("|")]
73
  header = [h.strip() for h in lines[0].strip("|").split("|")]
74
  elems = [e.strip() for e in header[1:]]
 
82
  for y in elems:
83
  if tbl[x][y] != tbl[y][x]:
84
  bad.add(x); bad.add(y)
85
+ return ", ".join(sorted(bad))
86
  return None
87
 
88
  class BasicAgent:
89
  def __init__(self):
90
  self.model = InferenceClientModel(model_id="Qwen/Qwen2.5-7B-Instruct")
91
+ self.agent = CodeAgent(
92
+ model=self.model,
93
+ tools=[DuckDuckGoSearchTool(), VisitWebpageTool(), PythonInterpreterTool()],
94
+ add_base_tools=True,
95
+ system_prompt="Answer GAIA L1 questions using tools. Output only the final answer string.",
96
+ stream_outputs=False,
97
+ )
98
 
99
  def solve_with_files(self, question, task_id):
100
  files = fetch_files(task_id)
101
  for f in files:
102
  url = f.get("file_url") or f.get("url") or ""
103
+ name = (f.get("filename") or f.get("name") or "").lower()
104
+ if not url:
105
+ continue
106
  try:
107
  data = requests.get(url, timeout=60).content
108
  except Exception:
109
  continue
110
+ if name.endswith((".xlsx",".xls")):
111
  try:
112
  df = pd.read_excel(io.BytesIO(data))
113
  if "Category" in df.columns:
114
  food = df[df["Category"].astype(str).str.lower().eq("food")]
115
+ if "Sales" in food.columns:
116
+ total = float(food["Sales"].sum())
117
+ else:
118
+ total = float(food.select_dtypes(include="number").sum().sum())
 
 
 
 
 
 
 
 
119
  return f"{total:.2f}"
120
+ scols = df.select_dtypes(include="number")
121
+ total = float(scols.sum().sum())
122
+ return f"{total:.2f}"
123
  except Exception:
124
  pass
125
+ if name.endswith(".py"):
126
  try:
127
  p = subprocess.run(["python","-"], input=data, capture_output=True, text=True, timeout=10)
128
  out = p.stdout.strip()
129
+ if out:
130
+ return postprocess_exact(out.splitlines()[-1])
131
  except Exception:
132
  pass
133
+ if name.endswith((".mp3",".wav",".m4a",".flac")):
134
  return ""
135
  return None
136
 
137
  def __call__(self, question, task_id=None):
138
  s = solve_reverse_sentence(question)
139
+ if s is not None:
140
+ return s
141
  s = solve_vegetables(question)
142
+ if s is not None:
143
+ return s
144
  s = solve_non_commutative_subset(question)
145
+ if s is not None:
146
+ return s
147
  if task_id is not None:
148
  s = self.solve_with_files(question, task_id)
149
+ if s is not None:
150
+ return s
151
+ out = self.agent.run("Return only the final answer string.\nQuestion: " + question)
152
  return postprocess_exact(out)
153
 
154
+ def run_and_submit_all(request: gr.Request):
155
+ profile = request.user
156
+ if not profile:
157
+ return "Please Login to Hugging Face with the button.", None
158
  username = f"{profile.username}".strip()
159
+ try:
160
+ qresp = requests.get(f"{DEFAULT_API_URL}/questions", timeout=30)
161
+ qresp.raise_for_status()
162
+ questions = qresp.json()
163
+ if not isinstance(questions, list) or not questions:
164
+ return "Fetched questions list is empty or invalid.", None
165
+ except Exception as e:
166
+ return f"Error fetching questions: {e}", None
167
  agent = BasicAgent()
168
+ agent_code = f"https://huggingface.co/spaces/{SPACE_ID}/tree/main"
169
  results_log, answers_payload = [], []
170
  for item in questions:
171
+ tid = item.get("task_id")
172
+ q = item.get("question")
173
+ if not tid or q is None:
174
+ continue
175
  try:
176
  ans = agent(q, tid)
177
  except Exception as e:
178
  ans = f"AGENT ERROR: {e}"
179
  answers_payload.append({"task_id": tid, "submitted_answer": ans})
180
  results_log.append({"Task ID": tid, "Question": q, "Submitted Answer": ans})
181
+ if not answers_payload:
182
+ return "No answers produced.", pd.DataFrame(results_log)
183
+ payload = {"username": username, "agent_code": agent_code, "answers": answers_payload}
184
  try:
185
+ sresp = requests.post(f"{DEFAULT_API_URL}/submit", json=payload, timeout=120)
186
+ sresp.raise_for_status()
187
+ res = sresp.json()
188
  msg = f"Submission Successful!\nUser: {res.get('username', username)}\nOverall Score: {res.get('score','N/A')}% ({res.get('correct_count','?')}/{res.get('total_attempted','?')} correct)\nMessage: {res.get('message','') or ''}"
189
  return msg, pd.DataFrame(results_log)
190
  except requests.exceptions.HTTPError as e:
191
+ try:
192
+ detail = e.response.json().get("detail", e.response.text)
193
+ except Exception:
194
+ detail = e.response.text
195
  return f"Submission Failed: HTTP {e.response.status_code}. Detail: {detail[:500]}", pd.DataFrame(results_log)
196
  except requests.exceptions.Timeout:
197
  return "Submission Failed: The request timed out.", pd.DataFrame(results_log)
 
201
  with gr.Blocks() as demo:
202
  gr.Markdown("# Basic Agent Evaluation Runner")
203
  gr.Markdown("1. Ensure requirements are installed.\n2. Log in.\n3. Click the button to run and submit.\nScoring is EXACT MATCH: output only the final answer string.")
204
+ gr.LoginButton()
205
  run_button = gr.Button("Run Evaluation & Submit All Answers")
206
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=6, interactive=False)
207
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
208
+ run_button.click(fn=run_and_submit_all, outputs=[status_output, results_table])
209
 
210
  if __name__ == "__main__":
211
  demo.launch(debug=True, share=False)