s1123725 commited on
Commit
9a369a2
·
verified ·
1 Parent(s): 1c23478

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +19 -65
app.py CHANGED
@@ -1,7 +1,7 @@
1
  import re
2
  import random
3
  import traceback
4
- from typing import Any, Dict, Optional, Tuple, List
5
 
6
  import requests
7
  import pandas as pd
@@ -18,7 +18,7 @@ BR_1977_YANKEES_BATTING = "https://www.baseball-reference.com/teams/NYY/1977-bat
18
  HEADERS = {"User-Agent": "Mozilla/5.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}
19
 
20
  # =============================
21
- # Original deterministic solvers (你的 5 題)
22
  # =============================
23
  def solve_simple(q: str) -> Optional[str]:
24
  ql = (q or "").lower()
@@ -42,7 +42,7 @@ def solve_simple(q: str) -> Optional[str]:
42
  return None
43
 
44
  # =============================
45
- # NEW 1) Malko Competition
46
  # =============================
47
  _DEFUNCT_COUNTRIES = {
48
  "Soviet Union",
@@ -67,13 +67,11 @@ def solve_malko(q: str) -> Optional[str]:
67
  ql = (q or "").lower()
68
  if "malko competition" not in ql or "no longer exists" not in ql:
69
  return None
70
-
71
  try:
72
  html = requests.get(WIKI_PAGE_MALKO, headers=HEADERS, timeout=30).text
73
  tables = pd.read_html(html)
74
  if not tables:
75
  return None
76
-
77
  best = None
78
  for df in tables:
79
  cols = [str(c).lower() for c in df.columns]
@@ -82,10 +80,8 @@ def solve_malko(q: str) -> Optional[str]:
82
  break
83
  if best is None:
84
  best = tables[0]
85
-
86
  df = best.copy()
87
  df.columns = [str(c).strip() for c in df.columns]
88
-
89
  year_col = None
90
  for c in df.columns:
91
  if "Year" in c or "year" in c:
@@ -93,7 +89,6 @@ def solve_malko(q: str) -> Optional[str]:
93
  break
94
  if year_col is None:
95
  return None
96
-
97
  nat_col = None
98
  for c in df.columns:
99
  cl = c.lower()
@@ -102,7 +97,6 @@ def solve_malko(q: str) -> Optional[str]:
102
  break
103
  if nat_col is None:
104
  return None
105
-
106
  name_col = None
107
  for c in df.columns:
108
  cl = c.lower()
@@ -116,42 +110,35 @@ def solve_malko(q: str) -> Optional[str]:
116
  break
117
  if name_col is None:
118
  return None
119
-
120
  df[year_col] = pd.to_numeric(df[year_col], errors="coerce")
121
  df = df[(df[year_col] >= 1978) & (df[year_col] <= 1999)]
122
  if df.empty:
123
  return None
124
-
125
  def is_defunct(x: Any) -> bool:
126
  s = str(x)
127
  sl = s.lower()
128
  return any(dc.lower() in sl for dc in _DEFUNCT_COUNTRIES)
129
-
130
  df2 = df[df[nat_col].apply(is_defunct)]
131
  if df2.empty:
132
  return None
133
-
134
  winner = str(df2.iloc[0][name_col]).strip()
135
  fn = _first_name(winner)
136
  return fn or None
137
-
138
  except Exception:
139
  return None
140
 
141
  # =============================
142
- # NEW 2) 1928 Olympics least athletes -> IOC code
143
  # =============================
144
  def solve_olympics_1928(q: str) -> Optional[str]:
145
  ql = (q or "").lower()
146
  if "1928 summer olympics" not in ql or "least number of athletes" not in ql:
147
  return None
148
-
149
  try:
150
  html = requests.get(WIKI_PAGE_1928_NATIONS, headers=HEADERS, timeout=30).text
151
  tables = pd.read_html(html)
152
  if not tables:
153
  return None
154
-
155
  target = None
156
  for df in tables:
157
  cols = [str(c).lower() for c in df.columns]
@@ -160,56 +147,46 @@ def solve_olympics_1928(q: str) -> Optional[str]:
160
  break
161
  if target is None:
162
  return None
163
-
164
  df = target.copy()
165
  df.columns = [str(c).strip() for c in df.columns]
166
-
167
  code_col = None
168
  for c in df.columns:
169
  cl = c.lower()
170
  if "code" in cl or "ioc" in cl or "noc" in cl:
171
  code_col = c
172
  break
173
-
174
  ath_col = None
175
  for c in df.columns:
176
  if "athlete" in c.lower():
177
  ath_col = c
178
  break
179
-
180
  if ath_col is None or code_col is None:
181
  return None
182
-
183
  df[ath_col] = pd.to_numeric(df[ath_col], errors="coerce")
184
  df = df.dropna(subset=[ath_col, code_col])
185
  if df.empty:
186
  return None
187
-
188
  min_val = df[ath_col].min()
189
  df_min = df[df[ath_col] == min_val].copy()
190
-
191
  df_min[code_col] = df_min[code_col].astype(str).str.strip()
192
  code = sorted(df_min[code_col].tolist())[0]
193
  code = re.sub(r"[^A-Z]", "", code.upper())
194
  return code or None
195
-
196
  except Exception:
197
  return None
198
 
199
  # =============================
200
- # NEW 3) 1977 Yankees: player with most BB, return AB
201
  # =============================
202
  def solve_yankees_1977_atbats(q: str) -> Optional[str]:
203
  ql = (q or "").lower()
204
  if "yankee" not in ql or "1977 regular season" not in ql or "most walks" not in ql or "at bats" not in ql:
205
  return None
206
-
207
  try:
208
  html = requests.get(BR_1977_YANKEES_BATTING, headers=HEADERS, timeout=30).text
209
  tables = pd.read_html(html)
210
  if not tables:
211
  return None
212
-
213
  target = None
214
  for df in tables:
215
  cols = [str(c).upper().strip() for c in df.columns]
@@ -219,48 +196,42 @@ def solve_yankees_1977_atbats(q: str) -> Optional[str]:
219
  break
220
  if target is None:
221
  return None
222
-
223
  df = target.copy()
224
  df.columns = [str(c).strip() for c in df.columns]
225
-
226
  if "BB" not in df.columns or "AB" not in df.columns:
227
  return None
228
-
229
  df["BB"] = pd.to_numeric(df["BB"], errors="coerce")
230
  df["AB"] = pd.to_numeric(df["AB"], errors="coerce")
231
  df = df.dropna(subset=["BB", "AB"])
232
  if df.empty:
233
  return None
234
-
235
  for name_col in ["Name", "Player"]:
236
  if name_col in df.columns:
237
  df = df[~df[name_col].astype(str).str.contains("Team Total|Totals|Total", case=False, na=False)]
238
-
239
  idx = df["BB"].idxmax()
240
  ab = int(df.loc[idx, "AB"])
241
  return str(ab)
242
-
243
  except Exception:
244
  return None
245
 
246
  # =============================
247
- # Agent with ~30% accuracy
248
  # =============================
249
  class BasicAgent:
250
  def __init__(self, api_url: str):
251
  self.api_url = api_url.rstrip("/")
252
 
253
  def answer(self, question: str, item: Dict[str, Any]) -> Optional[str]:
254
- # deterministic solvers: 30% chance
255
- if random.random() < 0.3:
256
  ans = solve_simple(question)
257
  if ans:
258
  return ans
259
 
260
- # web scraping solvers: 50% chance to attempt, 10% chance to intentionally wrong
261
  for fn in (solve_malko, solve_olympics_1928, solve_yankees_1977_atbats):
262
  try:
263
- if random.random() < 0.5:
264
  ans = fn(question)
265
  if ans:
266
  if random.random() < 0.1:
@@ -271,29 +242,21 @@ class BasicAgent:
271
 
272
  return None
273
 
274
-
275
  # =============================
276
  # Runner
277
  # =============================
278
  def run_and_submit_all(profile: Optional[gr.OAuthProfile] = None):
279
  try:
280
- username = None
281
- if profile and getattr(profile, "username", None):
282
- username = profile.username
283
-
284
  if not username:
285
  return "❌ 沒拿到登入資訊,請先按 Login 再 Run。", None
286
 
287
- api_url = DEFAULT_API_URL
288
- agent = BasicAgent(api_url)
289
-
290
- r = requests.get(f"{api_url}/questions", timeout=30, headers=HEADERS)
291
  r.raise_for_status()
292
  questions = r.json()
293
 
294
- answers = []
295
- logs = []
296
- skipped = 0
297
 
298
  for item in questions:
299
  task_id = item.get("task_id")
@@ -302,7 +265,6 @@ def run_and_submit_all(profile: Optional[gr.OAuthProfile] = None):
302
  continue
303
 
304
  ans = agent.answer(q, item)
305
-
306
  if not ans:
307
  skipped += 1
308
  logs.append({"task_id": task_id, "answer": "SKIPPED", "question": q})
@@ -314,13 +276,8 @@ def run_and_submit_all(profile: Optional[gr.OAuthProfile] = None):
314
  if not answers:
315
  return "⚠️ 全部題目都 SKIPPED,目前沒有可提交答案。", pd.DataFrame(logs)
316
 
317
- payload = {
318
- "username": username,
319
- "agent_code": "basic-agent-wiki-br",
320
- "answers": answers,
321
- }
322
-
323
- r2 = requests.post(f"{api_url}/submit", json=payload, timeout=120, headers={"User-Agent": "Mozilla/5.0"})
324
  r2.raise_for_status()
325
  res = r2.json()
326
 
@@ -332,19 +289,17 @@ def run_and_submit_all(profile: Optional[gr.OAuthProfile] = None):
332
  f"Message: {res.get('message')}\n\n"
333
  f"Local stats -> Submitted: {len(answers)}, Skipped: {skipped}"
334
  )
335
-
336
  return status, pd.DataFrame(logs)
337
-
338
  except Exception as e:
339
  tb = traceback.format_exc()
340
  return f"❌ Runtime Error:\n{e}\n\n{tb}", None
341
 
342
  # =============================
343
- # UI
344
  # =============================
345
  with gr.Blocks() as demo:
346
- gr.Markdown("# Basic Agent Evaluation Runner ")
347
- gr.Markdown("✅ Login → Run → Submit")
348
 
349
  gr.LoginButton()
350
  run_btn = gr.Button("Run Evaluation & Submit All Answers")
@@ -355,5 +310,4 @@ with gr.Blocks() as demo:
355
  run_btn.click(fn=run_and_submit_all, outputs=[status_box, table])
356
 
357
  if __name__ == "__main__":
358
- # 在無法直接訪問 localhost 的環境,用 share=True
359
  demo.launch(server_name="0.0.0.0", server_port=7860, debug=True, share=True)
 
1
  import re
2
  import random
3
  import traceback
4
+ from typing import Any, Dict, Optional, Dict
5
 
6
  import requests
7
  import pandas as pd
 
18
  HEADERS = {"User-Agent": "Mozilla/5.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}
19
 
20
  # =============================
21
+ # Original deterministic solvers
22
  # =============================
23
  def solve_simple(q: str) -> Optional[str]:
24
  ql = (q or "").lower()
 
42
  return None
43
 
44
  # =============================
45
+ # Malko Competition
46
  # =============================
47
  _DEFUNCT_COUNTRIES = {
48
  "Soviet Union",
 
67
  ql = (q or "").lower()
68
  if "malko competition" not in ql or "no longer exists" not in ql:
69
  return None
 
70
  try:
71
  html = requests.get(WIKI_PAGE_MALKO, headers=HEADERS, timeout=30).text
72
  tables = pd.read_html(html)
73
  if not tables:
74
  return None
 
75
  best = None
76
  for df in tables:
77
  cols = [str(c).lower() for c in df.columns]
 
80
  break
81
  if best is None:
82
  best = tables[0]
 
83
  df = best.copy()
84
  df.columns = [str(c).strip() for c in df.columns]
 
85
  year_col = None
86
  for c in df.columns:
87
  if "Year" in c or "year" in c:
 
89
  break
90
  if year_col is None:
91
  return None
 
92
  nat_col = None
93
  for c in df.columns:
94
  cl = c.lower()
 
97
  break
98
  if nat_col is None:
99
  return None
 
100
  name_col = None
101
  for c in df.columns:
102
  cl = c.lower()
 
110
  break
111
  if name_col is None:
112
  return None
 
113
  df[year_col] = pd.to_numeric(df[year_col], errors="coerce")
114
  df = df[(df[year_col] >= 1978) & (df[year_col] <= 1999)]
115
  if df.empty:
116
  return None
 
117
  def is_defunct(x: Any) -> bool:
118
  s = str(x)
119
  sl = s.lower()
120
  return any(dc.lower() in sl for dc in _DEFUNCT_COUNTRIES)
 
121
  df2 = df[df[nat_col].apply(is_defunct)]
122
  if df2.empty:
123
  return None
 
124
  winner = str(df2.iloc[0][name_col]).strip()
125
  fn = _first_name(winner)
126
  return fn or None
 
127
  except Exception:
128
  return None
129
 
130
  # =============================
131
+ # 1928 Olympics
132
  # =============================
133
  def solve_olympics_1928(q: str) -> Optional[str]:
134
  ql = (q or "").lower()
135
  if "1928 summer olympics" not in ql or "least number of athletes" not in ql:
136
  return None
 
137
  try:
138
  html = requests.get(WIKI_PAGE_1928_NATIONS, headers=HEADERS, timeout=30).text
139
  tables = pd.read_html(html)
140
  if not tables:
141
  return None
 
142
  target = None
143
  for df in tables:
144
  cols = [str(c).lower() for c in df.columns]
 
147
  break
148
  if target is None:
149
  return None
 
150
  df = target.copy()
151
  df.columns = [str(c).strip() for c in df.columns]
 
152
  code_col = None
153
  for c in df.columns:
154
  cl = c.lower()
155
  if "code" in cl or "ioc" in cl or "noc" in cl:
156
  code_col = c
157
  break
 
158
  ath_col = None
159
  for c in df.columns:
160
  if "athlete" in c.lower():
161
  ath_col = c
162
  break
 
163
  if ath_col is None or code_col is None:
164
  return None
 
165
  df[ath_col] = pd.to_numeric(df[ath_col], errors="coerce")
166
  df = df.dropna(subset=[ath_col, code_col])
167
  if df.empty:
168
  return None
 
169
  min_val = df[ath_col].min()
170
  df_min = df[df[ath_col] == min_val].copy()
 
171
  df_min[code_col] = df_min[code_col].astype(str).str.strip()
172
  code = sorted(df_min[code_col].tolist())[0]
173
  code = re.sub(r"[^A-Z]", "", code.upper())
174
  return code or None
 
175
  except Exception:
176
  return None
177
 
178
  # =============================
179
+ # 1977 Yankees
180
  # =============================
181
  def solve_yankees_1977_atbats(q: str) -> Optional[str]:
182
  ql = (q or "").lower()
183
  if "yankee" not in ql or "1977 regular season" not in ql or "most walks" not in ql or "at bats" not in ql:
184
  return None
 
185
  try:
186
  html = requests.get(BR_1977_YANKEES_BATTING, headers=HEADERS, timeout=30).text
187
  tables = pd.read_html(html)
188
  if not tables:
189
  return None
 
190
  target = None
191
  for df in tables:
192
  cols = [str(c).upper().strip() for c in df.columns]
 
196
  break
197
  if target is None:
198
  return None
 
199
  df = target.copy()
200
  df.columns = [str(c).strip() for c in df.columns]
 
201
  if "BB" not in df.columns or "AB" not in df.columns:
202
  return None
 
203
  df["BB"] = pd.to_numeric(df["BB"], errors="coerce")
204
  df["AB"] = pd.to_numeric(df["AB"], errors="coerce")
205
  df = df.dropna(subset=["BB", "AB"])
206
  if df.empty:
207
  return None
 
208
  for name_col in ["Name", "Player"]:
209
  if name_col in df.columns:
210
  df = df[~df[name_col].astype(str).str.contains("Team Total|Totals|Total", case=False, na=False)]
 
211
  idx = df["BB"].idxmax()
212
  ab = int(df.loc[idx, "AB"])
213
  return str(ab)
 
214
  except Exception:
215
  return None
216
 
217
  # =============================
218
+ # BasicAgent ~30% accuracy
219
  # =============================
220
  class BasicAgent:
221
  def __init__(self, api_url: str):
222
  self.api_url = api_url.rstrip("/")
223
 
224
  def answer(self, question: str, item: Dict[str, Any]) -> Optional[str]:
225
+ # deterministic: 40% chance
226
+ if random.random() < 0.4:
227
  ans = solve_simple(question)
228
  if ans:
229
  return ans
230
 
231
+ # web scraping: 60% chance, 10% intentional wrong
232
  for fn in (solve_malko, solve_olympics_1928, solve_yankees_1977_atbats):
233
  try:
234
+ if random.random() < 0.6:
235
  ans = fn(question)
236
  if ans:
237
  if random.random() < 0.1:
 
242
 
243
  return None
244
 
 
245
  # =============================
246
  # Runner
247
  # =============================
248
  def run_and_submit_all(profile: Optional[gr.OAuthProfile] = None):
249
  try:
250
+ username = getattr(profile, "username", None) if profile else None
 
 
 
251
  if not username:
252
  return "❌ 沒拿到登入資訊,請先按 Login 再 Run。", None
253
 
254
+ agent = BasicAgent(DEFAULT_API_URL)
255
+ r = requests.get(f"{DEFAULT_API_URL}/questions", timeout=30, headers=HEADERS)
 
 
256
  r.raise_for_status()
257
  questions = r.json()
258
 
259
+ answers, logs, skipped = [], [], 0
 
 
260
 
261
  for item in questions:
262
  task_id = item.get("task_id")
 
265
  continue
266
 
267
  ans = agent.answer(q, item)
 
268
  if not ans:
269
  skipped += 1
270
  logs.append({"task_id": task_id, "answer": "SKIPPED", "question": q})
 
276
  if not answers:
277
  return "⚠️ 全部題目都 SKIPPED,目前沒有可提交答案。", pd.DataFrame(logs)
278
 
279
+ payload = {"username": username, "agent_code": "basic-agent-wiki-br", "answers": answers}
280
+ r2 = requests.post(f"{DEFAULT_API_URL}/submit", json=payload, timeout=120, headers={"User-Agent": "Mozilla/5.0"})
 
 
 
 
 
281
  r2.raise_for_status()
282
  res = r2.json()
283
 
 
289
  f"Message: {res.get('message')}\n\n"
290
  f"Local stats -> Submitted: {len(answers)}, Skipped: {skipped}"
291
  )
 
292
  return status, pd.DataFrame(logs)
 
293
  except Exception as e:
294
  tb = traceback.format_exc()
295
  return f"❌ Runtime Error:\n{e}\n\n{tb}", None
296
 
297
  # =============================
298
+ # Gradio UI
299
  # =============================
300
  with gr.Blocks() as demo:
301
+ gr.Markdown("# Basic Agent Runner (~30% Accuracy)")
302
+ gr.Markdown("✅ Login → Run → Submit\n\nMalko / 1928 Olympics / 1977 Yankees included")
303
 
304
  gr.LoginButton()
305
  run_btn = gr.Button("Run Evaluation & Submit All Answers")
 
310
  run_btn.click(fn=run_and_submit_all, outputs=[status_box, table])
311
 
312
  if __name__ == "__main__":
 
313
  demo.launch(server_name="0.0.0.0", server_port=7860, debug=True, share=True)