350016z commited on
Commit
52ef8e5
·
verified ·
1 Parent(s): 12de53c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +168 -151
app.py CHANGED
@@ -192,7 +192,7 @@ def get_error_dataframe():
192
  main_cat, sub_cat = cat_str.split("/", 1)
193
  main_cat_zh = category_display_map.get(main_cat, main_cat)
194
  # sub_cat -> e.g. "Mistranslation", "Addition", "Omission", ...
195
- # 這裡可逐一對照,略示如下:
196
  if sub_cat == "Mistranslation":
197
  sub_cat_zh = "誤譯"
198
  elif sub_cat == "Addition":
@@ -293,7 +293,7 @@ def save_and_next(source, target, score, rater_selector, alternative_translation
293
 
294
  if not rater_selector:
295
  return (
296
- source, target, "", # return empty error_span
297
  str(data.loc[current_index, "id"]),
298
  "請先選擇標註人員!",
299
  get_error_dataframe(),
@@ -335,10 +335,10 @@ def save_and_next(source, target, score, rater_selector, alternative_translation
335
 
336
  if current_index >= len(data):
337
  return (
338
- "已完成所有文本標記", # source
339
- "已完成所有文本標記", # target
340
- "", # error_span
341
- "", # current_index_display
342
  f"標記完成並儲存到 {annotations_file.name}!(共 {len(data)} 筆)",
343
  pd.DataFrame(columns=["錯誤文字", "嚴重度", "分類"]),
344
  ""
@@ -402,53 +402,71 @@ def update_index_selection(selected_display):
402
  )
403
 
404
  DEMO_EXPLANATION = """
405
- ## 翻譯標記工具:階段性操作流程
406
-
407
- ### 操作步驟
408
- 1. **先選擇標註人員與檔案**,並在「索引」下拉中挑選要標註的句子。
409
- 2. 在「步驟 1:錯誤標註」中,若翻譯文本有錯,請輸入「錯誤區間」、選擇「錯誤類別/子類別/嚴重度」並點「保存並繼續標記」。
410
- - 多個錯誤可重複此步驟;若無錯誤則可直接點「完全正確」。
411
- 3. 錯誤標完後,在「步驟 2:評分與提交」中,拉動滑桿給分,若有更好譯文,可在「建議翻譯」填入。
412
- 4. 按「保存並顯示下一筆」送出本句標註並進入下一句。
413
  """
414
 
415
  with gr.Blocks(css="""
416
- /* 整體字體與行距 */
417
- * {
418
- font-size: 15px;
419
- line-height: 1.4;
420
- }
421
- /* 按鈕分色 */
422
- #correct_button {
423
- background-color: #4CAF50; /* 綠 */
424
- color: white;
425
- font-size: 14px;
426
- margin-bottom: 5px;
427
- }
428
- #too_many_errors_button {
429
- background-color: #f44336; /* */
430
- color: white;
431
- font-size: 14px;
432
- margin-bottom: 5px;
433
- }
434
- /* 模擬帶框風格 */
435
- #highlight_box_group {
436
- border: 1px solid #aaa;
437
- padding: 10px;
438
- margin-bottom: 10px;
439
- min-height: 80px;
440
- }
441
- /* 讓「步驟區塊」顯示類似面板效果 */
442
- #step1_box, #step2_box {
443
- border: 1px solid #ccc;
444
- padding: 10px;
445
- margin-bottom: 10px;
446
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
  """) as demo:
448
  gr.Markdown(DEMO_EXPLANATION)
449
 
450
- with gr.Tab("標記工具"):
451
- # ------------------- 頂部: 檔案 & 索引控制 -------------------
 
452
  with gr.Row():
453
  with gr.Column(scale=1):
454
  rater_selector = gr.Dropdown(
@@ -472,31 +490,31 @@ with gr.Blocks(css="""
472
  interactive=False
473
  )
474
 
475
- # 左: 原始文本 / 右: 翻譯文本
476
  with gr.Column(scale=4):
477
  source = gr.Textbox(label="原始文本", lines=4, interactive=False)
478
  with gr.Column(scale=4):
479
  target = gr.Textbox(label="翻譯文本", lines=4, interactive=False)
480
 
481
- # ------------------- 螢光標記區(用 Group + elem_id)&錯誤紀錄表 -------------------
482
- with gr.Row():
483
- with gr.Column(scale=5):
484
- with gr.Group(elem_id="highlight_box_group"):
485
- highlighted_target = gr.HTML(value="", label="螢光標示區 (已標註的錯誤)")
486
- with gr.Column(scale=5):
487
- error_table = gr.Dataframe(
488
- headers=["錯誤文字", "嚴重度", "分類"],
489
- label="當前句子錯誤紀錄 (中文顯示)",
490
- datatype=["str", "str", "str"],
491
- interactive=False
492
- )
493
-
494
- # ------------------- 步驟1:錯誤標註 -------------------
495
- with gr.Group(elem_id="step1_box"):
496
- gr.Markdown("### 步驟 1:錯誤標註")
497
-
 
 
498
  with gr.Row():
499
- error_span = gr.Textbox(label="錯誤區間 (可複製『翻譯文本』貼上)", lines=2)
500
  category = gr.Dropdown(
501
  label="錯誤類別",
502
  choices=list(categories_display.keys()),
@@ -507,103 +525,102 @@ with gr.Blocks(css="""
507
  choices=categories_display["正確性"],
508
  value="誤譯"
509
  )
510
- other = gr.Textbox(label="其他子類別(如選『其他』則填寫)")
511
  severity = gr.Dropdown(
512
  label="嚴重度",
513
  choices=severity_choices_display,
514
  value="輕微 (Minor)"
515
  )
 
516
 
517
  with gr.Row():
518
- save_current_button = gr.Button("保存並繼續標記當前資料")
519
  correct_button = gr.Button("✔ 完全正確", elem_id="correct_button")
520
  too_many_errors_button = gr.Button("✖ 過多錯誤", elem_id="too_many_errors_button")
521
 
522
- # ------------------- 步驟2:評分與提交 -------------------
523
- with gr.Group(elem_id="step2_box"):
524
- gr.Markdown("### 步驟 2:評分與提交")
525
- with gr.Row():
526
- alternative_translation = gr.Textbox(
527
- label="建議翻譯(如有更好譯法可填)",
528
- lines=2
529
- )
530
- score = gr.Slider(
531
- label="翻譯評分 (0=最差, 100=最好)",
532
- minimum=0,
533
- maximum=100,
534
- step=1,
535
- value=66
536
- )
537
- save_next_button = gr.Button("保存並顯示下一筆")
538
-
539
- status = gr.Textbox(label="當前狀態", lines=1, interactive=False)
540
-
541
- # ------------------- 邏輯綁定 -------------------
542
- def update_subcats(selected_category):
543
- subcats = categories_display[selected_category]
544
- return gr.update(choices=subcats, value=subcats[0])
545
-
546
- file_selector.change(
547
- update_file_selection,
548
- inputs=[file_selector],
549
- outputs=[
550
- source, target, error_span,
551
- index_selector, current_index_display,
552
- status, error_table, highlighted_target
553
- ]
554
- )
555
- index_selector.change(
556
- update_index_selection,
557
- inputs=[index_selector],
558
- outputs=[
559
- source, target, current_index_display,
560
- status, error_table, highlighted_target
561
- ]
562
- )
563
- category.change(
564
- update_subcats,
565
- inputs=[category],
566
- outputs=[subcategory]
567
- )
568
 
569
- correct_button.click(
570
- mark_as_correct,
571
- outputs=[error_span, status, error_table]
572
- )
573
- too_many_errors_button.click(
574
- mark_as_too_many_errors,
575
- outputs=[error_span, status, error_table]
576
- )
577
 
578
- # 按「保存並繼續標記」 -> 在同一句上加錯誤
579
- save_current_button.click(
580
- save_current,
581
- inputs=[source, target, rater_selector, error_span, category, subcategory, severity, other],
582
- outputs=[error_span, status]
583
- )
584
- # 再更新表格 & 高亮
585
- save_current_button.click(
586
- fn=lambda tgt: (get_error_dataframe(), highlight_errors_in_text(tgt, current_errors)),
587
- inputs=[target],
588
- outputs=[error_table, highlighted_target]
589
- )
590
 
591
- # 按「保存並顯示下一筆」 -> 送出當前整句標註 & 進下一句
592
- save_next_button.click(
593
- save_and_next,
594
- inputs=[source, target, score, rater_selector, alternative_translation],
595
- outputs=[
596
- source, target, error_span,
597
- current_index_display, status,
598
- error_table, highlighted_target
599
- ]
600
- )
601
 
602
- # 初始化介面
603
- init_src, init_tgt = get_current_text()
604
- source.value = init_src
605
- target.value = init_tgt
606
- error_table.value = pd.DataFrame(columns=["錯誤文字","嚴重度","分類"])
607
- highlighted_target.value = highlight_errors_in_text(init_tgt, [])
608
 
609
- demo.launch()
 
192
  main_cat, sub_cat = cat_str.split("/", 1)
193
  main_cat_zh = category_display_map.get(main_cat, main_cat)
194
  # sub_cat -> e.g. "Mistranslation", "Addition", "Omission", ...
195
+ # 這裡可逐一對照
196
  if sub_cat == "Mistranslation":
197
  sub_cat_zh = "誤譯"
198
  elif sub_cat == "Addition":
 
293
 
294
  if not rater_selector:
295
  return (
296
+ source, target, "",
297
  str(data.loc[current_index, "id"]),
298
  "請先選擇標註人員!",
299
  get_error_dataframe(),
 
335
 
336
  if current_index >= len(data):
337
  return (
338
+ "已完成所有文本標記",
339
+ "已完成所有文本標記",
340
+ "",
341
+ "",
342
  f"標記完成並儲存到 {annotations_file.name}!(共 {len(data)} 筆)",
343
  pd.DataFrame(columns=["錯誤文字", "嚴重度", "分類"]),
344
  ""
 
402
  )
403
 
404
  DEMO_EXPLANATION = """
405
+ ## 翻譯標記工具:兩個 Tab
406
+
407
+ **操作步驟:**
408
+ 1. 在「基本設定」中,選擇要標註的檔案、標註人員,以及句子索引。
409
+ 2. 切換到「錯誤標註」標籤頁 (Tab),若發現翻譯有錯,於該頁面中輸入「錯誤區間」並選擇類別/嚴重度等,最後點擊「保存並繼續標記當前資料」。
410
+ - 若整句完全正確,可點擊「完全正確」
411
+ - 若錯誤太多超過五處,可點擊「過多錯誤」
412
+ 3. 切換到「評分與提交」標籤頁,於此頁拉動滑桿給分,若有更好的譯文可在「建議翻譯」中輸入,最後按「保存並顯示下一筆」送出本句並進入下一筆。
413
  """
414
 
415
  with gr.Blocks(css="""
416
+ /* 整體字體與行距 */
417
+ body {
418
+ background-color: #FAFAFA;
419
+ color: #333;
420
+ margin: 0;
421
+ padding: 0;
422
+ }
423
+ * {
424
+ font-size: 15px;
425
+ line-height: 1.4;
426
+ }
427
+ /* 按鈕分色,改用更柔和或深色系 */
428
+ #correct_button {
429
+ background-color: #2E7D32; /* 深綠 */
430
+ color: white;
431
+ font-size: 14px;
432
+ margin-bottom: 5px;
433
+ }
434
+ #too_many_errors_button {
435
+ background-color: #C62828; /* 深紅 */
436
+ color: white;
437
+ font-size: 14px;
438
+ margin-bottom: 5px;
439
+ }
440
+ #save_current_button {
441
+ background-color: #1565C0; /* */
442
+ color: white;
443
+ font-size: 14px;
444
+ margin-bottom: 5px;
445
+ }
446
+ #save_next_button {
447
+ background-color: #6D4C41; /* 棕 */
448
+ color: white;
449
+ font-size: 14px;
450
+ margin-bottom: 5px;
451
+ }
452
+ /* 螢光標示區的外框 */
453
+ #highlight_box_group {
454
+ border: 1px solid #aaa;
455
+ padding: 10px;
456
+ min-height: 80px;
457
+ }
458
+ /* 小面板 */
459
+ .panel {
460
+ border: 1px solid #ccc;
461
+ padding: 10px;
462
+ margin-bottom: 10px;
463
+ }
464
  """) as demo:
465
  gr.Markdown(DEMO_EXPLANATION)
466
 
467
+ # ------------------- 頂部:基本設定 -------------------
468
+ with gr.Box():
469
+ gr.Markdown("### 基本設定")
470
  with gr.Row():
471
  with gr.Column(scale=1):
472
  rater_selector = gr.Dropdown(
 
490
  interactive=False
491
  )
492
 
 
493
  with gr.Column(scale=4):
494
  source = gr.Textbox(label="原始文本", lines=4, interactive=False)
495
  with gr.Column(scale=4):
496
  target = gr.Textbox(label="翻譯文本", lines=4, interactive=False)
497
 
498
+ # ------------------- 顯示螢光標示 錯誤紀錄 -------------------
499
+ with gr.Row():
500
+ with gr.Column(scale=5):
501
+ with gr.Group(elem_id="highlight_box_group"):
502
+ highlighted_target = gr.HTML(label="螢光標示區 (已標註的錯誤)")
503
+ with gr.Column(scale=5):
504
+ error_table = gr.Dataframe(
505
+ headers=["錯誤文字", "嚴重度", "分類"],
506
+ label="當前句子錯誤紀錄 (中文顯示)",
507
+ datatype=["str", "str", "str"],
508
+ interactive=False
509
+ )
510
+
511
+ # ------------------- 分成兩個 Tab -------------------
512
+ with gr.Tabs():
513
+ # ---- Tab 1: 錯誤標註 ----
514
+ with gr.Tab(label="錯誤標註"):
515
+ gr.Markdown("#### 在此頁標註錯誤區間,或按「完全正確」「過多錯誤」")
516
+ error_span = gr.Textbox(label="錯誤區間 (可複製『翻譯文本』貼上)", lines=2)
517
  with gr.Row():
 
518
  category = gr.Dropdown(
519
  label="錯誤類別",
520
  choices=list(categories_display.keys()),
 
525
  choices=categories_display["正確性"],
526
  value="誤譯"
527
  )
 
528
  severity = gr.Dropdown(
529
  label="嚴重度",
530
  choices=severity_choices_display,
531
  value="輕微 (Minor)"
532
  )
533
+ other = gr.Textbox(label="其他子類別(如選『其他』則在此填)")
534
 
535
  with gr.Row():
536
+ save_current_button = gr.Button("保存並繼續標記當前資料", elem_id="save_current_button")
537
  correct_button = gr.Button("✔ 完全正確", elem_id="correct_button")
538
  too_many_errors_button = gr.Button("✖ 過多錯誤", elem_id="too_many_errors_button")
539
 
540
+ # ---- Tab 2: 評分與提交 ----
541
+ with gr.Tab(label="評分與提交"):
542
+ gr.Markdown("#### 在此頁給分,若有更適合的譯文可提供建議,最後點『保存並顯示下一筆』")
543
+ alternative_translation = gr.Textbox(
544
+ label="建議翻譯(如有更好譯法可填)",
545
+ lines=2
546
+ )
547
+ score = gr.Slider(
548
+ label="翻譯評分 (0=最差, 100=最好)",
549
+ minimum=0,
550
+ maximum=100,
551
+ step=1,
552
+ value=66
553
+ )
554
+ save_next_button = gr.Button("保存並顯示下一筆", elem_id="save_next_button")
555
+
556
+ # ------------------- 最下方:狀態顯示 -------------------
557
+ status = gr.Textbox(label="當前狀態", lines=1, interactive=False)
558
+
559
+ # ------------------- 互動邏輯綁定 -------------------
560
+ def update_subcats(selected_category):
561
+ subcats = categories_display[selected_category]
562
+ return gr.update(choices=subcats, value=subcats[0])
563
+
564
+ file_selector.change(
565
+ update_file_selection,
566
+ inputs=[file_selector],
567
+ outputs=[
568
+ source, target, error_span,
569
+ index_selector, current_index_display,
570
+ status, error_table, highlighted_target
571
+ ]
572
+ )
573
+ index_selector.change(
574
+ update_index_selection,
575
+ inputs=[index_selector],
576
+ outputs=[
577
+ source, target, current_index_display,
578
+ status, error_table, highlighted_target
579
+ ]
580
+ )
581
+ category.change(
582
+ update_subcats,
583
+ inputs=[category],
584
+ outputs=[subcategory]
585
+ )
586
 
587
+ correct_button.click(
588
+ mark_as_correct,
589
+ outputs=[error_span, status, error_table]
590
+ )
591
+ too_many_errors_button.click(
592
+ mark_as_too_many_errors,
593
+ outputs=[error_span, status, error_table]
594
+ )
595
 
596
+ # 當「保存並繼續標記當前資料」
597
+ save_current_button.click(
598
+ save_current,
599
+ inputs=[source, target, rater_selector, error_span, category, subcategory, severity, other],
600
+ outputs=[error_span, status]
601
+ )
602
+ save_current_button.click(
603
+ fn=lambda tgt: (get_error_dataframe(), highlight_errors_in_text(tgt, current_errors)),
604
+ inputs=[target],
605
+ outputs=[error_table, highlighted_target]
606
+ )
 
607
 
608
+ # 當「保存並顯示下一筆」
609
+ save_next_button.click(
610
+ save_and_next,
611
+ inputs=[source, target, score, rater_selector, alternative_translation],
612
+ outputs=[
613
+ source, target, error_span,
614
+ current_index_display, status,
615
+ error_table, highlighted_target
616
+ ]
617
+ )
618
 
619
+ # 初始化
620
+ init_src, init_tgt = get_current_text()
621
+ source.value = init_src
622
+ target.value = init_tgt
623
+ error_table.value = pd.DataFrame(columns=["錯誤文字","嚴重度","分類"])
624
+ highlighted_target.value = highlight_errors_in_text(init_tgt, [])
625
 
626
+ demo.launch()