WHU1psh commited on
Commit
bc26912
·
verified ·
1 Parent(s): 6f81c69

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +88 -23
app.py CHANGED
@@ -320,6 +320,12 @@ CUSTOM_CSS = """
320
  white-space: pre-wrap;
321
  line-height: 1.6;
322
  }
 
 
 
 
 
 
323
  """
324
 
325
 
@@ -508,7 +514,6 @@ def build_sample_brief_html(sample: Dict[str, Any], index: int, total: int) -> s
508
 
509
  def create_app():
510
  samples = build_pending_samples()
511
- sample_map = {s["anon_id"]: s for s in samples}
512
 
513
  with gr.Blocks(
514
  title="VideoEval Movie-Level Evaluation",
@@ -526,6 +531,7 @@ def create_app():
526
 
527
  current_idx = gr.State(0)
528
  evaluator_state = gr.State("anonymous")
 
529
 
530
  with gr.Row():
531
  with gr.Column(scale=5, elem_classes=["panel"]):
@@ -550,7 +556,7 @@ def create_app():
550
  if not samples else build_sample_brief_html(samples[0], 0, len(samples))
551
  )
552
 
553
- gr.Markdown("## 3) Movie-Level 指标评分(1-5)")
554
  gr.Markdown("<span class='hint'>请先完成 1-5 分评分,未打分无法提交。</span>")
555
 
556
  score_widgets: Dict[str, gr.Radio] = {}
@@ -576,32 +582,34 @@ def create_app():
576
  score_widgets[key] = gr.Radio(choices=[1, 2, 3, 4, 5], label=f"{key} Score")
577
 
578
  final_summary = gr.Textbox(label="Final Summary(可选)", lines=4, placeholder="总结该视频的主要优缺点")
579
- submit_btn = gr.Button("提交当前评分并统计", variant="primary")
580
 
581
- def _sync_sample_from_dropdown(anon_id: str) -> Tuple[str, str, int]:
 
582
  if not anon_id or anon_id not in sample_map:
583
  return None, "<div class='sample-card'><p class='story-body'>未找到样本</p></div>", 0
584
- idx = next(i for i, s in enumerate(samples) if s["anon_id"] == anon_id)
585
- sample = samples[idx]
586
- return sample["video_path"], build_sample_brief_html(sample, idx, len(samples)), idx
587
 
588
- def _go_prev(idx: int) -> Tuple[str, str, str, int]:
589
- if not samples:
590
  return None, "<div class='sample-card'><p class='story-body'>无可用样本</p></div>", None, 0
591
  idx = max(0, idx - 1)
592
- sample = samples[idx]
593
- return sample["video_path"], build_sample_brief_html(sample, idx, len(samples)), sample["anon_id"], idx
594
 
595
- def _go_next(idx: int) -> Tuple[str, str, str, int]:
596
- if not samples:
597
  return None, "<div class='sample-card'><p class='story-body'>无可用样本</p></div>", None, 0
598
- idx = min(len(samples) - 1, idx + 1)
599
- sample = samples[idx]
600
- return sample["video_path"], build_sample_brief_html(sample, idx, len(samples)), sample["anon_id"], idx
601
 
602
- def _submit(evaluator_id: str, anon_id: str, summary: str, *score_vals):
603
- if not samples:
604
  return "❌ 没有可提交样本。"
 
605
  if not anon_id or anon_id not in sample_map:
606
  return "❌ 请先选择样本。"
607
  sample = sample_map[anon_id]
@@ -627,19 +635,76 @@ def create_app():
627
 
628
  return f"✅ 已保存: `{single_path}`\n\n✅ 已更新方法统计: `{agg_path}`"
629
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
630
  sample_dropdown.change(
631
  _sync_sample_from_dropdown,
632
- inputs=[sample_dropdown],
633
  outputs=[movie_video, sample_info, current_idx],
634
  )
635
- prev_btn.click(_go_prev, inputs=[current_idx], outputs=[movie_video, sample_info, sample_dropdown, current_idx])
636
- next_btn.click(_go_next, inputs=[current_idx], outputs=[movie_video, sample_info, sample_dropdown, current_idx])
637
 
638
- submit_inputs = [evaluator_input, sample_dropdown, final_summary]
639
  for key in BASE_METRIC_KEYS:
640
  submit_inputs.append(score_widgets[key])
641
- submit_btn.click(_submit, inputs=submit_inputs, outputs=[status])
 
 
 
 
 
642
 
 
 
 
 
643
  app.load(lambda x: x, inputs=[evaluator_input], outputs=[evaluator_state])
644
 
645
  return app
 
320
  white-space: pre-wrap;
321
  line-height: 1.6;
322
  }
323
+ #submit-btn button {
324
+ min-height: 52px !important;
325
+ font-size: 1.08rem !important;
326
+ font-weight: 700 !important;
327
+ padding: 0.7rem 1.2rem !important;
328
+ }
329
  """
330
 
331
 
 
514
 
515
  def create_app():
516
  samples = build_pending_samples()
 
517
 
518
  with gr.Blocks(
519
  title="VideoEval Movie-Level Evaluation",
 
531
 
532
  current_idx = gr.State(0)
533
  evaluator_state = gr.State("anonymous")
534
+ samples_state = gr.State(samples)
535
 
536
  with gr.Row():
537
  with gr.Column(scale=5, elem_classes=["panel"]):
 
556
  if not samples else build_sample_brief_html(samples[0], 0, len(samples))
557
  )
558
 
559
+ gr.Markdown("## 3) 评分(1-5)")
560
  gr.Markdown("<span class='hint'>请先完成 1-5 分评分,未打分无法提交。</span>")
561
 
562
  score_widgets: Dict[str, gr.Radio] = {}
 
582
  score_widgets[key] = gr.Radio(choices=[1, 2, 3, 4, 5], label=f"{key} Score")
583
 
584
  final_summary = gr.Textbox(label="Final Summary(可选)", lines=4, placeholder="总结该视频的主要优缺点")
585
+ submit_btn = gr.Button("提交", variant="primary", elem_id="submit-btn")
586
 
587
+ def _sync_sample_from_dropdown(anon_id: str, curr_samples: List[Dict[str, Any]]) -> Tuple[str, str, int]:
588
+ sample_map = {s["anon_id"]: s for s in curr_samples}
589
  if not anon_id or anon_id not in sample_map:
590
  return None, "<div class='sample-card'><p class='story-body'>未找到样本</p></div>", 0
591
+ idx = next(i for i, s in enumerate(curr_samples) if s["anon_id"] == anon_id)
592
+ sample = curr_samples[idx]
593
+ return sample["video_path"], build_sample_brief_html(sample, idx, len(curr_samples)), idx
594
 
595
+ def _go_prev(idx: int, curr_samples: List[Dict[str, Any]]) -> Tuple[str, str, str, int]:
596
+ if not curr_samples:
597
  return None, "<div class='sample-card'><p class='story-body'>无可用样本</p></div>", None, 0
598
  idx = max(0, idx - 1)
599
+ sample = curr_samples[idx]
600
+ return sample["video_path"], build_sample_brief_html(sample, idx, len(curr_samples)), sample["anon_id"], idx
601
 
602
+ def _go_next(idx: int, curr_samples: List[Dict[str, Any]]) -> Tuple[str, str, str, int]:
603
+ if not curr_samples:
604
  return None, "<div class='sample-card'><p class='story-body'>无可用样本</p></div>", None, 0
605
+ idx = min(len(curr_samples) - 1, idx + 1)
606
+ sample = curr_samples[idx]
607
+ return sample["video_path"], build_sample_brief_html(sample, idx, len(curr_samples)), sample["anon_id"], idx
608
 
609
+ def _submit(evaluator_id: str, anon_id: str, summary: str, curr_samples: List[Dict[str, Any]], *score_vals):
610
+ if not curr_samples:
611
  return "❌ 没有可提交样本。"
612
+ sample_map = {s["anon_id"]: s for s in curr_samples}
613
  if not anon_id or anon_id not in sample_map:
614
  return "❌ 请先选择样本。"
615
  sample = sample_map[anon_id]
 
635
 
636
  return f"✅ 已保存: `{single_path}`\n\n✅ 已更新方法统计: `{agg_path}`"
637
 
638
+ def _refresh_on_load() -> Tuple[Any, Any, str, int, str, List[Dict[str, Any]]]:
639
+ refreshed_samples = build_pending_samples()
640
+ if not refreshed_samples:
641
+ return (
642
+ gr.update(choices=[], value=None),
643
+ None,
644
+ "<div class='sample-card'><p class='story-body'>无可用样本(可能都已评估)</p></div>",
645
+ 0,
646
+ "当前无待评估样本。",
647
+ refreshed_samples,
648
+ )
649
+
650
+ first = refreshed_samples[0]
651
+ return (
652
+ gr.update(choices=[s["anon_id"] for s in refreshed_samples], value=first["anon_id"]),
653
+ first["video_path"],
654
+ build_sample_brief_html(first, 0, len(refreshed_samples)),
655
+ 0,
656
+ f"已刷新样本池:{len(refreshed_samples)} 个待评估样本。",
657
+ refreshed_samples,
658
+ )
659
+
660
+ def _refresh_after_submit(submit_msg: str) -> Tuple[Any, Any, str, int, str, List[Dict[str, Any]]]:
661
+ refreshed_samples = build_pending_samples()
662
+ submit_msg = (submit_msg or "").strip()
663
+ if not refreshed_samples:
664
+ status_msg = f"{submit_msg}\n\n当前无待评估样本。" if submit_msg else "当前无待评估样本。"
665
+ return (
666
+ gr.update(choices=[], value=None),
667
+ None,
668
+ "<div class='sample-card'><p class='story-body'>无可用样本(可能都已评估)</p></div>",
669
+ 0,
670
+ status_msg,
671
+ refreshed_samples,
672
+ )
673
+
674
+ first = refreshed_samples[0]
675
+ refresh_msg = f"已刷新样本池:{len(refreshed_samples)} 个待评估样本。"
676
+ status_msg = f"{submit_msg}\n\n{refresh_msg}" if submit_msg else refresh_msg
677
+ return (
678
+ gr.update(choices=[s["anon_id"] for s in refreshed_samples], value=first["anon_id"]),
679
+ first["video_path"],
680
+ build_sample_brief_html(first, 0, len(refreshed_samples)),
681
+ 0,
682
+ status_msg,
683
+ refreshed_samples,
684
+ )
685
+
686
  sample_dropdown.change(
687
  _sync_sample_from_dropdown,
688
+ inputs=[sample_dropdown, samples_state],
689
  outputs=[movie_video, sample_info, current_idx],
690
  )
691
+ prev_btn.click(_go_prev, inputs=[current_idx, samples_state], outputs=[movie_video, sample_info, sample_dropdown, current_idx])
692
+ next_btn.click(_go_next, inputs=[current_idx, samples_state], outputs=[movie_video, sample_info, sample_dropdown, current_idx])
693
 
694
+ submit_inputs = [evaluator_input, sample_dropdown, final_summary, samples_state]
695
  for key in BASE_METRIC_KEYS:
696
  submit_inputs.append(score_widgets[key])
697
+ submit_evt = submit_btn.click(_submit, inputs=submit_inputs, outputs=[status])
698
+ submit_evt.then(
699
+ _refresh_after_submit,
700
+ inputs=[status],
701
+ outputs=[sample_dropdown, movie_video, sample_info, current_idx, status, samples_state],
702
+ )
703
 
704
+ app.load(
705
+ _refresh_on_load,
706
+ outputs=[sample_dropdown, movie_video, sample_info, current_idx, status, samples_state],
707
+ )
708
  app.load(lambda x: x, inputs=[evaluator_input], outputs=[evaluator_state])
709
 
710
  return app