jisubae commited on
Commit
cd13f52
ยท
1 Parent(s): 5e8f045

fix: HF login error and future warning

Browse files
README.md CHANGED
@@ -7,6 +7,7 @@ sdk: gradio
7
  app_file: app.py
8
  pinned: false
9
  license: apache-2.0
 
10
  ---
11
 
12
  ## Ko-FreshQA Leaderboard
 
7
  app_file: app.py
8
  pinned: false
9
  license: apache-2.0
10
+ hf_oauth: true
11
  ---
12
 
13
  ## Ko-FreshQA Leaderboard
freshqa/fresheval_parallel.py CHANGED
@@ -85,7 +85,7 @@ class FreshEvalParallel:
85
  progress_queue.put(1)
86
 
87
  total_time = time.time() - start_time
88
- print(f"โœ… {mode} ๋ชจ๋“œ ํ‰๊ฐ€ ์™„๋ฃŒ: {total_time:.1f}์ดˆ ์†Œ์š”")
89
 
90
  return pd.DataFrame(results)
91
 
 
85
  progress_queue.put(1)
86
 
87
  total_time = time.time() - start_time
88
+ # print(f"โœ… {mode} ๋ชจ๋“œ ํ‰๊ฐ€ ์™„๋ฃŒ: {total_time:.1f}์ดˆ ์†Œ์š”")
89
 
90
  return pd.DataFrame(results)
91
 
freshqa/freshqa_acc.py CHANGED
@@ -50,7 +50,7 @@ def process_freshqa_dataframe(df):
50
  processed_df = df.copy()
51
  processed_df['rating'] = 0 # ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ 0 ์„ค์ •
52
 
53
- print(f"FreshQA ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์™„๋ฃŒ: {len(processed_df)}๊ฐœ ์ƒ˜ํ”Œ")
54
  return processed_df
55
  except Exception as e:
56
  print(f"๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {e}")
 
50
  processed_df = df.copy()
51
  processed_df['rating'] = 0 # ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ 0 ์„ค์ •
52
 
53
+ # print(f"FreshQA ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์™„๋ฃŒ: {len(processed_df)}๊ฐœ ์ƒ˜ํ”Œ")
54
  return processed_df
55
  except Exception as e:
56
  print(f"๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {e}")
requirements.txt CHANGED
@@ -1,5 +1,5 @@
1
  # Core dependencies for Hugging Face Spaces
2
- gradio>=5.0.0
3
  huggingface_hub<1.0.0
4
  pandas>=2.0.0
5
  numpy>=1.24.0
 
1
  # Core dependencies for Hugging Face Spaces
2
+ gradio[oauth]>=5.0.0
3
  huggingface_hub<1.0.0
4
  pandas>=2.0.0
5
  numpy>=1.24.0
src/leaderboard_manager.py CHANGED
@@ -126,7 +126,20 @@ def append_to_leaderboard_data(new_data_list):
126
  # ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€
127
  new_df = pd.DataFrame(new_data_list)
128
 
129
- combined_df = pd.concat([existing_df, new_df], ignore_index=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
130
 
131
  # ์ •๋ ฌ (accuracy ๊ธฐ์ค€)
132
  if not combined_df.empty and 'accuracy' in combined_df.columns:
 
126
  # ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€
127
  new_df = pd.DataFrame(new_data_list)
128
 
129
+ # FutureWarning ๋ฐฉ์ง€: ๋นˆ DataFrame์€ ์ œ์™ธํ•˜๊ณ  ๊ฒฐํ•ฉ
130
+ frames_to_concat = []
131
+ if isinstance(existing_df, pd.DataFrame) and not existing_df.empty:
132
+ frames_to_concat.append(existing_df)
133
+ if isinstance(new_df, pd.DataFrame) and not new_df.empty:
134
+ frames_to_concat.append(new_df)
135
+
136
+ if len(frames_to_concat) == 0:
137
+ # ๋‘˜ ๋‹ค ๋น„์–ด์žˆ์œผ๋ฉด ๊ธฐ์กด ์Šคํ‚ค๋งˆ ์œ ์ง€
138
+ combined_df = existing_df.copy()
139
+ elif len(frames_to_concat) == 1:
140
+ combined_df = frames_to_concat[0].copy()
141
+ else:
142
+ combined_df = pd.concat(frames_to_concat, ignore_index=True)
143
 
144
  # ์ •๋ ฌ (accuracy ๊ธฐ์ค€)
145
  if not combined_df.empty and 'accuracy' in combined_df.columns:
src/quick_csv_loader.py CHANGED
@@ -90,7 +90,19 @@ def merge_with_leaderboard(new_results_df: pd.DataFrame,
90
  existing_df = pd.read_csv(leaderboard_path)
91
 
92
  # ๋ณ‘ํ•ฉ
93
- merged_df = pd.concat([existing_df, new_results_df], ignore_index=True)
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
  # ์ค‘๋ณต ์ œ๊ฑฐ (๋™์ผํ•œ id์™€ evaluation_date ์กฐํ•ฉ)
96
  if 'id' in merged_df.columns and 'evaluation_date' in merged_df.columns:
 
90
  existing_df = pd.read_csv(leaderboard_path)
91
 
92
  # ๋ณ‘ํ•ฉ
93
+ # FutureWarning ๋ฐฉ์ง€: ๋นˆ DataFrame ์ œ์™ธ ํ›„ ๊ฒฐํ•ฉ
94
+ frames_to_concat = []
95
+ if isinstance(existing_df, pd.DataFrame) and not existing_df.empty:
96
+ frames_to_concat.append(existing_df)
97
+ if isinstance(new_results_df, pd.DataFrame) and not new_results_df.empty:
98
+ frames_to_concat.append(new_results_df)
99
+
100
+ if len(frames_to_concat) == 0:
101
+ merged_df = existing_df.copy()
102
+ elif len(frames_to_concat) == 1:
103
+ merged_df = frames_to_concat[0].copy()
104
+ else:
105
+ merged_df = pd.concat(frames_to_concat, ignore_index=True)
106
 
107
  # ์ค‘๋ณต ์ œ๊ฑฐ (๋™์ผํ•œ id์™€ evaluation_date ์กฐํ•ฉ)
108
  if 'id' in merged_df.columns and 'evaluation_date' in merged_df.columns:
src/submission_handler.py CHANGED
@@ -45,7 +45,6 @@ class SubmissionHandler:
45
  self.tracker = tracker
46
  self.cfg = cfg or Config
47
 
48
- # ๊ธฐ์กด ์ฝ”๋“œ์™€ ํ˜ธํ™˜๋˜๋Š” ์†์„ฑ (Config ์ง์ ‘ ์ฐธ์กฐ ์ œ๊ฑฐ)
49
  self.enable_limit = getattr(self.cfg, "ENABLE_SUBMISSION_LIMIT", False)
50
  self.repo_id = getattr(self.cfg, "FRESHQA_DATA_REPO_ID", None)
51
  self.filename = getattr(self.cfg, "FRESHQA_DATA_FILENAME", None)
@@ -174,11 +173,6 @@ class SubmissionHandler:
174
 
175
  # --------- 6) ์š”์•ฝ ----------
176
  def _build_summary(self, name: str, relaxed_accs: dict, strict_accs: dict) -> str:
177
- """
178
- result_summary๊ฐ€ ๊ธฐ๋Œ€ํ•˜๋Š” ์ด์ „ ๋ฌธ์ž์—ด ํฌ๋งท์„ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
179
- - ํ—ค๋”/์„น์…˜ ์ œ๋ชฉ/์ค„๋ฐ”๊ฟˆ/ํ‘œํ˜„(์†Œ์ˆ˜์  1์ž๋ฆฌ) ๋™์ผ
180
- - ํ…Œ์ŠคํŠธ์…‹ ๊ธฐ์ค€ ์ง€ํ‘œ: acc_test, *_fast_changing, *_two_hop, *_old, *_new, *_vp, *_fp
181
- """
182
  submitter = name if name else "(์ด๋ฆ„ ๋ฏธ์ž…๋ ฅ)"
183
 
184
  lines = []
@@ -224,7 +218,6 @@ class SubmissionHandler:
224
  relaxed_table: pd.DataFrame,
225
  strict_table: pd.DataFrame,
226
  ) -> str:
227
- # ๋ณด๊ธฐ ์ข‹์€ ํฌ๋งท์œผ๋กœ ์™ผ์ชฝ ์ •๋ ฌ/๊ตฌ๋ถ„์„ /์—ฌ๋ฐฑ์„ ์ ์šฉํ•ด ๋ฌธ์ž์—ด ๊ตฌ์„ฑ
228
  display_file = os.path.basename(file_name) if file_name else ""
229
  lines: list[str] = []
230
  lines.append("โœ… ์ œ์ถœ ๋ฐ ํ‰๊ฐ€ ์™„๋ฃŒ")
@@ -404,7 +397,6 @@ class SubmissionHandler:
404
  except Exception as e:
405
  print(f"โš ๏ธ ๋ฆฌ๋”๋ณด๋“œ ์ €์žฅ ์‹คํŒจ: {e}")
406
 
407
-
408
  # --------- 9) ๊ณต๊ฐœ ์—”๋“œํฌ์ธํŠธ(ํ•ต์‹ฌ) ----------
409
  def process_submission(
410
  self,
@@ -412,7 +404,8 @@ class SubmissionHandler:
412
  name: str,
413
  submit_model: str,
414
  submit_description: str,
415
- progress: gr.Progress = gr.Progress()
 
416
  ) -> str:
417
  """
418
  ์ œ์ถœ ํŒŒ์ผ ์ฒ˜๋ฆฌ ๋ฐ ํ‰๊ฐ€
@@ -428,12 +421,17 @@ class SubmissionHandler:
428
  # 1) ์ œ์ถœ ์ œํ•œ ํ™•์ธ
429
  tracker: Optional[SubmissionTracker] = None
430
  if self.enable_limit:
 
 
 
 
431
  tracker = self.tracker or get_submission_tracker()
432
  if tracker is not None:
433
  self.tracker = tracker
 
434
  if self.enable_limit and tracker:
435
  try:
436
- can_submit, message, remaining = tracker.can_submit()
437
  if not can_submit:
438
  return f"โŒ ์ œ์ถœ ์ œํ•œ: {message}"
439
  except Exception as e:
@@ -469,11 +467,12 @@ class SubmissionHandler:
469
  ev = self._evaluate_freshqa(merged_df, on_progress=on_inner_progress)
470
  if not ev.ok:
471
  # ์‹คํŒจ ๊ธฐ๋ก
472
- if self.enable_limit and tracker:
473
  try:
474
  tracker.record_submission(
475
- name,
476
- os.path.basename(file.name),
 
477
  success=False,
478
  error_message=ev.error or "ํ‰๊ฐ€ ์‹คํŒจ",
479
  submit_model=normalized_model,
@@ -489,11 +488,12 @@ class SubmissionHandler:
489
  progress(0.8, desc="ํ‰๊ฐ€ ๊ฒฐ๊ณผ ๋ถ„์„ ์ค‘...")
490
  r = self._calculate_accuracy(relaxed_df)
491
  if not r.ok:
492
- if self.enable_limit and tracker:
493
  try:
494
  tracker.record_submission(
495
- name,
496
- os.path.basename(file.name),
 
497
  success=False,
498
  error_message=r.error or "์ง‘๊ณ„ ์‹คํŒจ",
499
  submit_model=normalized_model,
@@ -505,11 +505,12 @@ class SubmissionHandler:
505
 
506
  s = self._calculate_accuracy(strict_df)
507
  if not s.ok:
508
- if self.enable_limit and tracker:
509
  try:
510
  tracker.record_submission(
511
- name,
512
- os.path.basename(file.name),
 
513
  success=False,
514
  error_message=s.error or "์ง‘๊ณ„ ์‹คํŒจ",
515
  submit_model=normalized_model,
@@ -536,15 +537,17 @@ class SubmissionHandler:
536
  )
537
 
538
  # 8) ์ œ์ถœ ์„ฑ๊ณต ๊ธฐ๋ก ๋ฐ ๋ฆฌ๋”๋ณด๋“œ ์ €์žฅ
539
- if self.enable_limit and tracker:
540
  progress(0.85, desc="์ œ์ถœ ๋‚ด์—ญ ์ €์žฅ ์ค‘...")
541
  save_ok = tracker.record_submission(
542
- name,
543
- os.path.basename(file.name),
 
544
  success=True,
545
  submit_model=normalized_model,
546
  submit_description=normalized_description,
547
  )
 
548
  progress(0.9, desc="๋ฆฌ๋”๋ณด๋“œ ์—…๋ฐ์ดํŠธ ์ค‘...")
549
  self._save_leaderboard(name, normalized_model, normalized_description, relaxed_accs, strict_accs)
550
  else:
@@ -563,7 +566,8 @@ def process_submission(
563
  name: str,
564
  submit_model: str,
565
  submit_description: str,
566
- progress: gr.Progress = gr.Progress()
 
567
  ) -> str:
568
  """
569
  Gradio์—์„œ ์ง์ ‘ ํ˜ธ์ถœํ•˜๋Š” ์—”ํŠธ๋ฆฌํฌ์ธํŠธ.
@@ -577,21 +581,16 @@ def process_submission(
577
  name=name,
578
  submit_model=submit_model,
579
  submit_description=submit_description,
 
580
  progress=progress,
581
  )
582
  except Exception as e:
583
  # ์ตœ์ƒ์œ„ ๋ณดํ˜ธ๋ง‰: ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์˜ˆ์™ธ๋„ ์‚ฌ์šฉ์ž ์นœํ™”์ ์œผ๋กœ ๋ฐ˜ํ™˜
584
  try:
585
- tracking_user_id = None
586
- if handler.enable_limit and handler.tracker:
587
- # ๋ˆ„๊ฐ€ ์ œ์ถœํ–ˆ๋Š”์ง€๋Š” tracker๊ฐ€ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด ๊ธฐ๋ก
588
- try:
589
- tracking_user_id = handler.tracker.get_user_id()
590
- except Exception:
591
- tracking_user_id = None
592
- if handler.enable_limit and handler.tracker:
593
  handler.tracker.record_submission(
594
- name=name,
 
595
  file_name=os.path.basename(file.name) if file else "(unknown)",
596
  success=False,
597
  error_message=str(e),
 
45
  self.tracker = tracker
46
  self.cfg = cfg or Config
47
 
 
48
  self.enable_limit = getattr(self.cfg, "ENABLE_SUBMISSION_LIMIT", False)
49
  self.repo_id = getattr(self.cfg, "FRESHQA_DATA_REPO_ID", None)
50
  self.filename = getattr(self.cfg, "FRESHQA_DATA_FILENAME", None)
 
173
 
174
  # --------- 6) ์š”์•ฝ ----------
175
  def _build_summary(self, name: str, relaxed_accs: dict, strict_accs: dict) -> str:
 
 
 
 
 
176
  submitter = name if name else "(์ด๋ฆ„ ๋ฏธ์ž…๋ ฅ)"
177
 
178
  lines = []
 
218
  relaxed_table: pd.DataFrame,
219
  strict_table: pd.DataFrame,
220
  ) -> str:
 
221
  display_file = os.path.basename(file_name) if file_name else ""
222
  lines: list[str] = []
223
  lines.append("โœ… ์ œ์ถœ ๋ฐ ํ‰๊ฐ€ ์™„๋ฃŒ")
 
397
  except Exception as e:
398
  print(f"โš ๏ธ ๋ฆฌ๋”๋ณด๋“œ ์ €์žฅ ์‹คํŒจ: {e}")
399
 
 
400
  # --------- 9) ๊ณต๊ฐœ ์—”๋“œํฌ์ธํŠธ(ํ•ต์‹ฌ) ----------
401
  def process_submission(
402
  self,
 
404
  name: str,
405
  submit_model: str,
406
  submit_description: str,
407
+ user_id: Optional[str] = None,
408
+ progress: gr.Progress = gr.Progress(),
409
  ) -> str:
410
  """
411
  ์ œ์ถœ ํŒŒ์ผ ์ฒ˜๋ฆฌ ๋ฐ ํ‰๊ฐ€
 
421
  # 1) ์ œ์ถœ ์ œํ•œ ํ™•์ธ
422
  tracker: Optional[SubmissionTracker] = None
423
  if self.enable_limit:
424
+ # ๋กœ๊ทธ์ธ ๊ธฐ๋ฐ˜ ์ œ์ถœ ์ œ์•ฝ: user_id ์—†์œผ๋ฉด ๋ฐ”๋กœ ์—๋Ÿฌ
425
+ if not user_id:
426
+ return "โŒ HuggingFace ๋กœ๊ทธ์ธ ์ƒํƒœ์—์„œ๋งŒ ์ œ์ถœ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋จผ์ € ๋กœ๊ทธ์ธ ํ›„ ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”."
427
+
428
  tracker = self.tracker or get_submission_tracker()
429
  if tracker is not None:
430
  self.tracker = tracker
431
+
432
  if self.enable_limit and tracker:
433
  try:
434
+ can_submit, message, remaining = tracker.can_submit(user_id=user_id)
435
  if not can_submit:
436
  return f"โŒ ์ œ์ถœ ์ œํ•œ: {message}"
437
  except Exception as e:
 
467
  ev = self._evaluate_freshqa(merged_df, on_progress=on_inner_progress)
468
  if not ev.ok:
469
  # ์‹คํŒจ ๊ธฐ๋ก
470
+ if self.enable_limit and tracker and user_id:
471
  try:
472
  tracker.record_submission(
473
+ user_id=user_id,
474
+ submitter_name=name,
475
+ file_name=os.path.basename(file.name),
476
  success=False,
477
  error_message=ev.error or "ํ‰๊ฐ€ ์‹คํŒจ",
478
  submit_model=normalized_model,
 
488
  progress(0.8, desc="ํ‰๊ฐ€ ๊ฒฐ๊ณผ ๋ถ„์„ ์ค‘...")
489
  r = self._calculate_accuracy(relaxed_df)
490
  if not r.ok:
491
+ if self.enable_limit and tracker and user_id:
492
  try:
493
  tracker.record_submission(
494
+ user_id=user_id,
495
+ submitter_name=name,
496
+ file_name=os.path.basename(file.name),
497
  success=False,
498
  error_message=r.error or "์ง‘๊ณ„ ์‹คํŒจ",
499
  submit_model=normalized_model,
 
505
 
506
  s = self._calculate_accuracy(strict_df)
507
  if not s.ok:
508
+ if self.enable_limit and tracker and user_id:
509
  try:
510
  tracker.record_submission(
511
+ user_id=user_id,
512
+ submitter_name=name,
513
+ file_name=os.path.basename(file.name),
514
  success=False,
515
  error_message=s.error or "์ง‘๊ณ„ ์‹คํŒจ",
516
  submit_model=normalized_model,
 
537
  )
538
 
539
  # 8) ์ œ์ถœ ์„ฑ๊ณต ๊ธฐ๋ก ๋ฐ ๋ฆฌ๋”๋ณด๋“œ ์ €์žฅ
540
+ if self.enable_limit and tracker and user_id:
541
  progress(0.85, desc="์ œ์ถœ ๋‚ด์—ญ ์ €์žฅ ์ค‘...")
542
  save_ok = tracker.record_submission(
543
+ user_id=user_id,
544
+ submitter_name=name,
545
+ file_name=os.path.basename(file.name),
546
  success=True,
547
  submit_model=normalized_model,
548
  submit_description=normalized_description,
549
  )
550
+ # save_ok ์‹คํŒจํ•ด๋„ ํ‰๊ฐ€ ๊ฒฐ๊ณผ๋Š” ๋ฆฌ๋”๋ณด๋“œ์— ๋ฐ˜์˜
551
  progress(0.9, desc="๋ฆฌ๋”๋ณด๋“œ ์—…๋ฐ์ดํŠธ ์ค‘...")
552
  self._save_leaderboard(name, normalized_model, normalized_description, relaxed_accs, strict_accs)
553
  else:
 
566
  name: str,
567
  submit_model: str,
568
  submit_description: str,
569
+ user_id: Optional[str] = None,
570
+ progress: gr.Progress = gr.Progress(),
571
  ) -> str:
572
  """
573
  Gradio์—์„œ ์ง์ ‘ ํ˜ธ์ถœํ•˜๋Š” ์—”ํŠธ๋ฆฌํฌ์ธํŠธ.
 
581
  name=name,
582
  submit_model=submit_model,
583
  submit_description=submit_description,
584
+ user_id=user_id,
585
  progress=progress,
586
  )
587
  except Exception as e:
588
  # ์ตœ์ƒ์œ„ ๋ณดํ˜ธ๋ง‰: ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์˜ˆ์™ธ๋„ ์‚ฌ์šฉ์ž ์นœํ™”์ ์œผ๋กœ ๋ฐ˜ํ™˜
589
  try:
590
+ if handler.enable_limit and handler.tracker and user_id:
 
 
 
 
 
 
 
591
  handler.tracker.record_submission(
592
+ user_id=user_id,
593
+ submitter_name=name,
594
  file_name=os.path.basename(file.name) if file else "(unknown)",
595
  success=False,
596
  error_message=str(e),
src/submission_tracker.py CHANGED
@@ -1,6 +1,6 @@
1
  """
2
  ์‚ฌ์šฉ์ž ์ œ์ถœ ์ถ”์  ๋ชจ๋“ˆ
3
- HuggingFace ์‚ฌ์šฉ์ž ID๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฃจ 3๋ฒˆ ์ œํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
4
  ์ œ์ถœ ์ •๋ณด๋Š” ๋ณ„๋„์˜ HuggingFace repository์—์„œ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
5
  """
6
 
@@ -8,10 +8,11 @@ import os
8
  import json
9
  import pandas as pd
10
  import tempfile
11
- from datetime import datetime, date
12
  from typing import Dict, List, Optional, Tuple
13
- from huggingface_hub import whoami, hf_hub_download, login, HfApi
14
  import pytz
 
15
  from src.utils import file_lock, get_current_date_str, get_current_datetime_str
16
 
17
  # ํ•œ๊ตญ ์‹œ๊ฐ„๋Œ€ ์„ค์ •
@@ -21,50 +22,45 @@ KOREA_TZ = pytz.timezone('Asia/Seoul')
21
  class SubmissionTracker:
22
  """์‚ฌ์šฉ์ž ์ œ์ถœ ์ถ”์  ํด๋ž˜์Šค - HuggingFace Repository ๊ธฐ๋ฐ˜"""
23
 
24
- def __init__(self,
25
- repo_id: Optional[str] = None,
26
- token: Optional[str] = None,
27
- filename: str = "user_submissions.json"):
28
  """
29
  Args:
30
- repo_id: HuggingFace repository ID (์˜ˆ: "username/submission-tracker")
31
- token: HuggingFace API ํ† ํฐ (None์ด๋ฉด ํ™˜๊ฒฝ๋ณ€์ˆ˜์—์„œ ์ž๋™ ๋กœ๋“œ)
32
  filename: ์ œ์ถœ ๊ธฐ๋ก ํŒŒ์ผ๋ช…
33
  """
34
  # ํ™˜๊ฒฝ๋ณ€์ˆ˜์—์„œ ์„ค์ • ๊ฐ€์ ธ์˜ค๊ธฐ
35
- self.repo_id = repo_id or os.getenv('SUBMISSION_TRACKER_REPO_ID')
36
- self.token = token or os.getenv('HF_TOKEN') or os.getenv('HUGGINGFACE_HUB_TOKEN')
37
  self.filename = filename
38
 
39
  if not self.repo_id:
40
  raise ValueError(
41
  "SUBMISSION_TRACKER_REPO_ID ํ™˜๊ฒฝ๋ณ€์ˆ˜๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. "
42
- "๋˜๋Š” repo_id๋ฅผ ์ง์ ‘ ์ „๋‹ฌํ•ด์ฃผ์„ธ์š”."
43
  )
44
 
45
- if not self.token:
46
  raise ValueError(
47
- "HuggingFace ํ† ํฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. "
48
- "ํ† ํฐ์„ ์ง์ ‘ ์ „๋‹ฌํ•˜๊ฑฐ๋‚˜ HF_TOKEN ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜์„ธ์š”."
49
  )
50
 
51
  # HuggingFace API ์ดˆ๊ธฐํ™”
52
  self.api = HfApi()
53
  try:
54
- login(token=self.token)
55
- # โœ… HuggingFace์— ์„ฑ๊ณต์ ์œผ๋กœ ๋กœ๊ทธ์ธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
56
  except Exception as e:
57
  print(f"โŒ HuggingFace ๋กœ๊ทธ์ธ ์‹คํŒจ: {e}")
58
  raise
59
 
60
  # ์ œ์ถœ ๊ธฐ๋ก ๋กœ๋“œ
61
- self.submissions = self.load_submissions()
62
 
63
  def load_submissions(self) -> Dict:
64
  """HuggingFace repository์—์„œ ์ œ์ถœ ๊ธฐ๋ก ๋กœ๋“œ"""
65
  try:
66
- # ๐Ÿ“ฅ HuggingFace repository์—์„œ ์ œ์ถœ ๊ธฐ๋ก ๋กœ๋“œ ์ค‘: {self.repo_id}/{self.filename}
67
-
68
  # ์ž„์‹œ ๋””๋ ‰ํ† ๋ฆฌ์— ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ
69
  with tempfile.TemporaryDirectory() as temp_dir:
70
  file_path = hf_hub_download(
@@ -72,43 +68,47 @@ class SubmissionTracker:
72
  filename=self.filename,
73
  local_dir=temp_dir,
74
  repo_type="dataset",
75
- token=self.token
76
  )
77
 
78
  # JSON ํŒŒ์ผ ๋กœ๋“œ
79
- with open(file_path, 'r', encoding='utf-8') as f:
80
  submissions = json.load(f)
81
 
82
- # โœ… ์ œ์ถœ ๊ธฐ๋ก ๋กœ๋“œ ์™„๋ฃŒ: {len(submissions)}๋ช…์˜ ์‚ฌ์šฉ์ž ๊ธฐ๋ก
83
  return submissions
84
 
85
  except Exception as e:
86
  print(f"โš ๏ธ ์ œ์ถœ ๊ธฐ๋ก ๋กœ๋“œ ์‹คํŒจ (์ƒˆ๋กœ ์‹œ์ž‘): {e}")
87
  return {}
88
-
89
- def get_user_id(self) -> Optional[str]:
90
- """HuggingFace์—์„œ ํ˜„์žฌ ์‚ฌ์šฉ์ž ID ๊ฐ€์ ธ์˜ค๊ธฐ (๊ณ ์œ  ID ์‚ฌ์šฉ)"""
91
- try:
92
- user_info = whoami()
93
- # ๊ณ ์œ  ID ์‚ฌ์šฉ (๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•œ ์‹๋ณ„์ž)
94
- return user_info.get("id", None)
95
- except Exception as e:
96
- print(f"โš ๏ธ ์‚ฌ์šฉ์ž ID ๊ฐ€์ ธ์˜ค๊ธฐ ์‹คํŒจ: {e}")
97
- raise Exception("โŒ ์‚ฌ์šฉ์ž ID๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. HuggingFace์— ๋กœ๊ทธ์ธ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์ฃผ์„ธ์š”.")
98
-
99
  def get_today_submissions(self, user_id: str) -> List[Dict]:
100
  """์˜ค๋Š˜ ์‚ฌ์šฉ์ž์˜ ์ œ์ถœ ๊ธฐ๋ก ๊ฐ€์ ธ์˜ค๊ธฐ"""
 
 
101
  today = get_current_date_str()
102
  user_submissions = self.submissions.get(user_id, {})
103
  return user_submissions.get(today, [])
104
 
105
- def can_submit(self, submissions_data: Optional[Dict] = None) -> Tuple[bool, str, int]:
106
- """์‚ฌ์šฉ์ž๊ฐ€ ์ œ์ถœํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธ"""
107
- user_id = self.get_user_id()
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  data = submissions_data if submissions_data is not None else self.submissions
109
  today = get_current_date_str()
110
  today_submissions = data.get(user_id, {}).get(today, [])
111
- successful_count = len([s for s in today_submissions if s.get('success', False)])
112
 
113
  if successful_count >= 3:
114
  raise Exception("โŒ ์˜ค๋Š˜ ์ œ์ถœ ํ•œ๋„๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด์ผ ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.")
@@ -118,15 +118,22 @@ class SubmissionTracker:
118
 
119
  def record_submission(
120
  self,
 
121
  submitter_name: str,
122
  file_name: str,
123
  success: bool,
124
- error_message: str = None,
125
  submit_model: Optional[str] = None,
126
- submit_description: Optional[str] = None
127
  ) -> bool:
128
- """์ œ์ถœ ๊ธฐ๋ก ์ถ”๊ฐ€ (ํŒŒ์ผ ์ž ๊ธˆ์œผ๋กœ ๋ณดํ˜ธ)"""
129
- user_id = self.get_user_id()
 
 
 
 
 
 
130
 
131
  # ์ž ๊ธˆ ํŒŒ์ผ ๊ฒฝ๋กœ ์ƒ์„ฑ
132
  lock_file_path = tempfile.gettempdir() + f'/{self.repo_id.replace("/", "_")}.lock'
@@ -139,11 +146,14 @@ class SubmissionTracker:
139
 
140
  # Lock ๋‚ด๋ถ€์—์„œ ์ตœ์‹  ๋ฐ์ดํ„ฐ ๊ธฐ์ค€์œผ๋กœ ์ œ์ถœ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ์žฌํ™•์ธ
141
  try:
142
- can_submit, message, _ = self.can_submit(submissions_data=latest_submissions)
 
 
 
143
  except Exception as e:
144
  # ์ œ์ถœ ์ œํ•œ ์ดˆ๊ณผ ์‹œ
145
- # ์ œ์ถœ ์ œํ•œ ์ดˆ๊ณผ ๋ฉ”์‹œ์ง€: {e}
146
- # ๋ฉ”๋ชจ๋ฆฌ๋งŒ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ์ €์žฅํ•˜์ง€ ์•Š์Œ
147
  self.submissions = latest_submissions
148
  return False
149
 
@@ -164,7 +174,7 @@ class SubmissionTracker:
164
  "success": success,
165
  "error_message": error_message,
166
  "submit_model": submit_model,
167
- "submit_description": submit_description
168
  }
169
 
170
  latest_submissions[user_id][today].append(submission_record)
@@ -182,10 +192,13 @@ class SubmissionTracker:
182
  def _save_submissions_internal(self, submissions_data: Dict) -> bool:
183
  """๋‚ด๋ถ€ ์ €์žฅ ํ•จ์ˆ˜ (lock์€ ์ด๋ฏธ ํš๋“๋œ ์ƒํƒœ)"""
184
  try:
185
- # ๐Ÿ’พ HuggingFace repository์— ์ œ์ถœ ๊ธฐ๋ก ์ €์žฅ ์ค‘: {self.repo_id}/{self.filename}
186
-
187
  # ์ž„์‹œ ํŒŒ์ผ์— JSON ๋ฐ์ดํ„ฐ ์ €์žฅ
188
- with tempfile.NamedTemporaryFile(mode='w', encoding='utf-8', suffix='.json', delete=False) as temp_file:
 
 
 
 
 
189
  json.dump(submissions_data, temp_file, ensure_ascii=False, indent=2)
190
  temp_file_path = temp_file.name
191
 
@@ -195,14 +208,16 @@ class SubmissionTracker:
195
  path_in_repo=self.filename,
196
  repo_id=self.repo_id,
197
  repo_type="dataset",
198
- token=self.token,
199
- commit_message=f"Update submission records - {datetime.now(KOREA_TZ).strftime('%Y-%m-%d %H:%M:%S')}"
 
 
 
200
  )
201
 
202
  # ์ž„์‹œ ํŒŒ์ผ ์‚ญ์ œ
203
  os.unlink(temp_file_path)
204
 
205
- # โœ… ์ œ์ถœ ๊ธฐ๋ก ์ €์žฅ ์™„๋ฃŒ
206
  return True
207
 
208
  except Exception as e:
@@ -217,10 +232,10 @@ class SubmissionTracker:
217
  user_submissions = self.submissions[user_id]
218
  today = datetime.now(KOREA_TZ).date()
219
 
220
- history = {}
221
  for i in range(days):
222
  check_date = today - pd.Timedelta(days=i)
223
- date_str = check_date.strftime('%Y-%m-%d')
224
 
225
  if date_str in user_submissions:
226
  history[date_str] = user_submissions[date_str]
@@ -233,13 +248,13 @@ class SubmissionTracker:
233
  return {}
234
 
235
  today_submissions = self.get_today_submissions(user_id)
236
- successful_today_count = len([s for s in today_submissions if s.get('success', False)])
237
  history = self.get_user_submission_history(user_id, 7)
238
 
239
  # ํ†ต๊ณ„ ๊ณ„์‚ฐ
240
  total_submissions = sum(len(day_submissions) for day_submissions in history.values())
241
  successful_submissions = sum(
242
- len([s for s in day_submissions if s.get('success', False)])
243
  for day_submissions in history.values()
244
  )
245
  failed_submissions = total_submissions - successful_submissions
@@ -250,10 +265,10 @@ class SubmissionTracker:
250
  "week_total": total_submissions,
251
  "week_successful": successful_submissions,
252
  "week_failed": failed_submissions,
253
- "history": history
254
  }
255
 
256
- def cleanup_old_records(self, days_to_keep: int = 30):
257
  """์˜ค๋ž˜๋œ ์ œ์ถœ ๊ธฐ๋ก ์ •๋ฆฌ (ํŒŒ์ผ ์ž ๊ธˆ ์‚ฌ์šฉ)"""
258
  # ์ž ๊ธˆ ํŒŒ์ผ ๊ฒฝ๋กœ ์ƒ์„ฑ
259
  lock_file_path = tempfile.gettempdir() + f'/{self.repo_id.replace("/", "_")}.lock'
@@ -265,11 +280,11 @@ class SubmissionTracker:
265
  latest_submissions = self.load_submissions()
266
 
267
  cutoff_date = datetime.now(KOREA_TZ) - pd.Timedelta(days=days_to_keep)
268
- cutoff_str = cutoff_date.strftime('%Y-%m-%d')
269
 
270
  cleaned_count = 0
271
- for user_id in list(latest_submissions.keys()):
272
- user_submissions = latest_submissions[user_id]
273
  for date_str in list(user_submissions.keys()):
274
  if date_str < cutoff_str:
275
  del user_submissions[date_str]
@@ -277,7 +292,7 @@ class SubmissionTracker:
277
 
278
  # ๋นˆ ์‚ฌ์šฉ์ž ๊ธฐ๋ก ์ œ๊ฑฐ
279
  if not user_submissions:
280
- del latest_submissions[user_id]
281
 
282
  # ๋ฉ”๋ชจ๋ฆฌ ์—…๋ฐ์ดํŠธ
283
  self.submissions = latest_submissions
 
1
  """
2
  ์‚ฌ์šฉ์ž ์ œ์ถœ ์ถ”์  ๋ชจ๋“ˆ
3
+ ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์˜ user_id๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฃจ 3๋ฒˆ ์ œํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
4
  ์ œ์ถœ ์ •๋ณด๋Š” ๋ณ„๋„์˜ HuggingFace repository์—์„œ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
5
  """
6
 
 
8
  import json
9
  import pandas as pd
10
  import tempfile
11
+ from datetime import datetime
12
  from typing import Dict, List, Optional, Tuple
13
+ from huggingface_hub import hf_hub_download, login, HfApi
14
  import pytz
15
+
16
  from src.utils import file_lock, get_current_date_str, get_current_datetime_str
17
 
18
  # ํ•œ๊ตญ ์‹œ๊ฐ„๋Œ€ ์„ค์ •
 
22
  class SubmissionTracker:
23
  """์‚ฌ์šฉ์ž ์ œ์ถœ ์ถ”์  ํด๋ž˜์Šค - HuggingFace Repository ๊ธฐ๋ฐ˜"""
24
 
25
+ def __init__(
26
+ self,
27
+ filename: str = "user_submissions.json",
28
+ ):
29
  """
30
  Args:
 
 
31
  filename: ์ œ์ถœ ๊ธฐ๋ก ํŒŒ์ผ๋ช…
32
  """
33
  # ํ™˜๊ฒฝ๋ณ€์ˆ˜์—์„œ ์„ค์ • ๊ฐ€์ ธ์˜ค๊ธฐ
34
+ self.repo_id = os.getenv("SUBMISSION_TRACKER_REPO_ID")
35
+ self.admin_token = os.getenv("HF_TOKEN")
36
  self.filename = filename
37
 
38
  if not self.repo_id:
39
  raise ValueError(
40
  "SUBMISSION_TRACKER_REPO_ID ํ™˜๊ฒฝ๋ณ€์ˆ˜๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. "
 
41
  )
42
 
43
+ if not self.admin_token:
44
  raise ValueError(
45
+ "HuggingFace Admin ํ† ํฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. "
46
+ "HF_TOKEN ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜์„ธ์š”."
47
  )
48
 
49
  # HuggingFace API ์ดˆ๊ธฐํ™”
50
  self.api = HfApi()
51
  try:
52
+ # ๊ด€๋ฆฌ์ž ํ† ํฐ์œผ๋กœ ๋กœ๊ทธ์ธ (dataset read/write ์šฉ)
53
+ login(token=self.admin_token)
54
  except Exception as e:
55
  print(f"โŒ HuggingFace ๋กœ๊ทธ์ธ ์‹คํŒจ: {e}")
56
  raise
57
 
58
  # ์ œ์ถœ ๊ธฐ๋ก ๋กœ๋“œ
59
+ self.submissions: Dict = self.load_submissions()
60
 
61
  def load_submissions(self) -> Dict:
62
  """HuggingFace repository์—์„œ ์ œ์ถœ ๊ธฐ๋ก ๋กœ๋“œ"""
63
  try:
 
 
64
  # ์ž„์‹œ ๋””๋ ‰ํ† ๋ฆฌ์— ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ
65
  with tempfile.TemporaryDirectory() as temp_dir:
66
  file_path = hf_hub_download(
 
68
  filename=self.filename,
69
  local_dir=temp_dir,
70
  repo_type="dataset",
71
+ token=self.admin_token,
72
  )
73
 
74
  # JSON ํŒŒ์ผ ๋กœ๋“œ
75
+ with open(file_path, "r", encoding="utf-8") as f:
76
  submissions = json.load(f)
77
 
 
78
  return submissions
79
 
80
  except Exception as e:
81
  print(f"โš ๏ธ ์ œ์ถœ ๊ธฐ๋ก ๋กœ๋“œ ์‹คํŒจ (์ƒˆ๋กœ ์‹œ์ž‘): {e}")
82
  return {}
83
+
 
 
 
 
 
 
 
 
 
 
84
  def get_today_submissions(self, user_id: str) -> List[Dict]:
85
  """์˜ค๋Š˜ ์‚ฌ์šฉ์ž์˜ ์ œ์ถœ ๊ธฐ๋ก ๊ฐ€์ ธ์˜ค๊ธฐ"""
86
+ if not user_id:
87
+ return []
88
  today = get_current_date_str()
89
  user_submissions = self.submissions.get(user_id, {})
90
  return user_submissions.get(today, [])
91
 
92
+ def can_submit(
93
+ self,
94
+ user_id: str,
95
+ submissions_data: Optional[Dict] = None,
96
+ ) -> Tuple[bool, str, int]:
97
+ """
98
+ ์‚ฌ์šฉ์ž๊ฐ€ ์ œ์ถœํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธ.
99
+
100
+ Args:
101
+ user_id: ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์˜ ๊ณ ์œ  ID (HF ๊ณ„์ • ID ๋“ฑ)
102
+ submissions_data: ๊ฒ€์‚ฌ์— ์‚ฌ์šฉํ•  ์ œ์ถœ ๋ฐ์ดํ„ฐ(ํ…Œ์ŠคํŠธ/๋ฝ ๋‚ด๋ถ€ ์žฌ๊ฒ€์‚ฌ์šฉ).
103
+ None์ด๋ฉด self.submissions ์‚ฌ์šฉ.
104
+ """
105
+ if not user_id:
106
+ raise ValueError("โŒ HuggingFace ๋กœ๊ทธ์ธ ์ƒํƒœ์—์„œ๋งŒ ์ œ์ถœ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”.")
107
+
108
  data = submissions_data if submissions_data is not None else self.submissions
109
  today = get_current_date_str()
110
  today_submissions = data.get(user_id, {}).get(today, [])
111
+ successful_count = len([s for s in today_submissions if s.get("success", False)])
112
 
113
  if successful_count >= 3:
114
  raise Exception("โŒ ์˜ค๋Š˜ ์ œ์ถœ ํ•œ๋„๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด์ผ ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.")
 
118
 
119
  def record_submission(
120
  self,
121
+ user_id: str,
122
  submitter_name: str,
123
  file_name: str,
124
  success: bool,
125
+ error_message: Optional[str] = None,
126
  submit_model: Optional[str] = None,
127
+ submit_description: Optional[str] = None,
128
  ) -> bool:
129
+ """
130
+ ์ œ์ถœ ๊ธฐ๋ก ์ถ”๊ฐ€ (ํŒŒ์ผ ์ž ๊ธˆ์œผ๋กœ ๋ณดํ˜ธ)
131
+
132
+ Args:
133
+ user_id: ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์˜ ๊ณ ์œ  ID (HF ๊ณ„์ • ID ๋“ฑ)
134
+ """
135
+ if not user_id:
136
+ raise ValueError("โŒ HuggingFace ๋กœ๊ทธ์ธ ์ƒํƒœ์—์„œ๋งŒ ์ œ์ถœ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”.")
137
 
138
  # ์ž ๊ธˆ ํŒŒ์ผ ๊ฒฝ๋กœ ์ƒ์„ฑ
139
  lock_file_path = tempfile.gettempdir() + f'/{self.repo_id.replace("/", "_")}.lock'
 
146
 
147
  # Lock ๋‚ด๋ถ€์—์„œ ์ตœ์‹  ๋ฐ์ดํ„ฐ ๊ธฐ์ค€์œผ๋กœ ์ œ์ถœ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ์žฌํ™•์ธ
148
  try:
149
+ self.can_submit(
150
+ user_id=user_id,
151
+ submissions_data=latest_submissions,
152
+ )
153
  except Exception as e:
154
  # ์ œ์ถœ ์ œํ•œ ์ดˆ๊ณผ ์‹œ
155
+ print(f"์ œ์ถœ ์ œํ•œ ์ดˆ๊ณผ: {e}")
156
+ # ๋ฉ”๋ชจ๋ฆฌ๋งŒ ์ตœ์‹ ์œผ๋กœ ๋งž์ถ”๊ณ  ์ €์žฅํ•˜์ง€ ์•Š์Œ
157
  self.submissions = latest_submissions
158
  return False
159
 
 
174
  "success": success,
175
  "error_message": error_message,
176
  "submit_model": submit_model,
177
+ "submit_description": submit_description,
178
  }
179
 
180
  latest_submissions[user_id][today].append(submission_record)
 
192
  def _save_submissions_internal(self, submissions_data: Dict) -> bool:
193
  """๋‚ด๋ถ€ ์ €์žฅ ํ•จ์ˆ˜ (lock์€ ์ด๋ฏธ ํš๋“๋œ ์ƒํƒœ)"""
194
  try:
 
 
195
  # ์ž„์‹œ ํŒŒ์ผ์— JSON ๋ฐ์ดํ„ฐ ์ €์žฅ
196
+ with tempfile.NamedTemporaryFile(
197
+ mode="w",
198
+ encoding="utf-8",
199
+ suffix=".json",
200
+ delete=False,
201
+ ) as temp_file:
202
  json.dump(submissions_data, temp_file, ensure_ascii=False, indent=2)
203
  temp_file_path = temp_file.name
204
 
 
208
  path_in_repo=self.filename,
209
  repo_id=self.repo_id,
210
  repo_type="dataset",
211
+ token=self.admin_token,
212
+ commit_message=(
213
+ "Update submission records - "
214
+ f"{datetime.now(KOREA_TZ).strftime('%Y-%m-%d %H:%M:%S')}"
215
+ ),
216
  )
217
 
218
  # ์ž„์‹œ ํŒŒ์ผ ์‚ญ์ œ
219
  os.unlink(temp_file_path)
220
 
 
221
  return True
222
 
223
  except Exception as e:
 
232
  user_submissions = self.submissions[user_id]
233
  today = datetime.now(KOREA_TZ).date()
234
 
235
+ history: Dict[str, List[Dict]] = {}
236
  for i in range(days):
237
  check_date = today - pd.Timedelta(days=i)
238
+ date_str = check_date.strftime("%Y-%m-%d")
239
 
240
  if date_str in user_submissions:
241
  history[date_str] = user_submissions[date_str]
 
248
  return {}
249
 
250
  today_submissions = self.get_today_submissions(user_id)
251
+ successful_today_count = len([s for s in today_submissions if s.get("success", False)])
252
  history = self.get_user_submission_history(user_id, 7)
253
 
254
  # ํ†ต๊ณ„ ๊ณ„์‚ฐ
255
  total_submissions = sum(len(day_submissions) for day_submissions in history.values())
256
  successful_submissions = sum(
257
+ len([s for s in day_submissions if s.get("success", False)])
258
  for day_submissions in history.values()
259
  )
260
  failed_submissions = total_submissions - successful_submissions
 
265
  "week_total": total_submissions,
266
  "week_successful": successful_submissions,
267
  "week_failed": failed_submissions,
268
+ "history": history,
269
  }
270
 
271
+ def cleanup_old_records(self, days_to_keep: int = 30) -> int:
272
  """์˜ค๋ž˜๋œ ์ œ์ถœ ๊ธฐ๋ก ์ •๋ฆฌ (ํŒŒ์ผ ์ž ๊ธˆ ์‚ฌ์šฉ)"""
273
  # ์ž ๊ธˆ ํŒŒ์ผ ๊ฒฝ๋กœ ์ƒ์„ฑ
274
  lock_file_path = tempfile.gettempdir() + f'/{self.repo_id.replace("/", "_")}.lock'
 
280
  latest_submissions = self.load_submissions()
281
 
282
  cutoff_date = datetime.now(KOREA_TZ) - pd.Timedelta(days=days_to_keep)
283
+ cutoff_str = cutoff_date.strftime("%Y-%m-%d")
284
 
285
  cleaned_count = 0
286
+ for uid in list(latest_submissions.keys()):
287
+ user_submissions = latest_submissions[uid]
288
  for date_str in list(user_submissions.keys()):
289
  if date_str < cutoff_str:
290
  del user_submissions[date_str]
 
292
 
293
  # ๋นˆ ์‚ฌ์šฉ์ž ๊ธฐ๋ก ์ œ๊ฑฐ
294
  if not user_submissions:
295
+ del latest_submissions[uid]
296
 
297
  # ๋ฉ”๋ชจ๋ฆฌ ์—…๋ฐ์ดํŠธ
298
  self.submissions = latest_submissions
ui/submission_tab.py CHANGED
@@ -5,9 +5,42 @@
5
  """
6
 
7
  import gradio as gr
 
 
8
  from src.submission_handler import process_submission
9
 
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  def create_submission_tab():
12
  """์ œ์ถœ ๋ฐ ํ‰๊ฐ€ ํƒญ UI ์ƒ์„ฑ"""
13
 
@@ -53,7 +86,8 @@ def create_submission_tab():
53
  <br>
54
  """)
55
 
56
-
 
57
 
58
  submission_file = gr.File(
59
  label="์ •๋‹ต์ด ํฌํ•จ๋œ CSV ํŒŒ์ผ ์—…๋กœ๋“œ",
@@ -91,8 +125,8 @@ def create_submission_tab():
91
 
92
  # ์ œ์ถœ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
93
  submit_btn.click(
94
- fn=process_submission,
95
  inputs=[submission_file, submitter_name, submit_model, submit_description],
96
  outputs=[submission_status],
97
- concurrency_limit=3
98
  )
 
5
  """
6
 
7
  import gradio as gr
8
+ from huggingface_hub import whoami
9
+
10
  from src.submission_handler import process_submission
11
 
12
 
13
+ def _process_submission_with_oauth(
14
+ file,
15
+ name: str,
16
+ submit_model: str,
17
+ submit_description: str,
18
+ oauth_token: gr.OAuthToken | None = None, # ๐Ÿ”ง Gradio๊ฐ€ ์ž๋™์œผ๋กœ ์ฃผ์ž…
19
+ ):
20
+ """
21
+ - hf_oauth: true ๊ฐ€ ์ผœ์ง„ HF Space์—์„œ๋งŒ ์‹ค์ œ ํ† ํฐ์ด ๋“ค์–ด์˜ด
22
+ - ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋Š” oauth_token์ด None ์ด๋ฏ€๋กœ user_id=None ์œผ๋กœ ๋™์ž‘
23
+ """
24
+ user_id = None
25
+
26
+ if oauth_token is not None:
27
+ try:
28
+ info = whoami(oauth_token.token) # ๐Ÿ”ง ๋กœ๊ทธ์ธํ•œ ์œ ์ € ํ† ํฐ์œผ๋กœ whoami ํ˜ธ์ถœ
29
+ user_id = info.get("id")
30
+ except Exception as e:
31
+ print(f"๐Ÿšจ whoami ์‹คํŒจ, user_id๋ฅผ ๊ฐ€์ ธ์˜ค์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค: {e}")
32
+ user_id = None
33
+
34
+ # submission_handler.process_submission ์— user_id ๋„˜๊ฒจ์คŒ
35
+ return process_submission(
36
+ file=file,
37
+ name=name,
38
+ submit_model=submit_model,
39
+ submit_description=submit_description,
40
+ user_id=user_id,
41
+ )
42
+
43
+
44
  def create_submission_tab():
45
  """์ œ์ถœ ๋ฐ ํ‰๊ฐ€ ํƒญ UI ์ƒ์„ฑ"""
46
 
 
86
  <br>
87
  """)
88
 
89
+ # ๐Ÿ”ง HF OAuth ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ (Space์—์„œ๋งŒ ์‹ค์ œ๋กœ ๋™์ž‘, ๋กœ์ปฌ์—์„œ๋Š” ๊ทธ๋ƒฅ ํ‘œ์‹œ๋งŒ)
90
+ gr.LoginButton()
91
 
92
  submission_file = gr.File(
93
  label="์ •๋‹ต์ด ํฌํ•จ๋œ CSV ํŒŒ์ผ ์—…๋กœ๋“œ",
 
125
 
126
  # ์ œ์ถœ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
127
  submit_btn.click(
128
+ fn=_process_submission_with_oauth,
129
  inputs=[submission_file, submitter_name, submit_model, submit_description],
130
  outputs=[submission_status],
131
+ concurrency_limit=3,
132
  )