#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Data-Viewer Side-by-Side tab for ICBCBench.
"""
import gradio as gr
import random
import re
from tabs.shared_data import get_entries_for_task, get_index
def make_user_task_markdown(item_id, prompt):
return f"""### User Task 🎯
**Task ID:** {item_id}
**Description:** {prompt}"""
def make_article_markdown(article: str) -> str:
if article and isinstance(article, str):
processed_article = re.sub(r'\n{2,}', '\n\n', article)
table_pattern = r'(\|[^\n]*\n(?:[\|\s\-:]+\n)?(?:\|[^\n]*\n)*)'
tables = []
def replace_table(match):
tables.append(match.group(1))
return f'__TABLE_PLACEHOLDER_{len(tables)-1}__'
processed_article = re.sub(table_pattern, replace_table, processed_article)
processed_article = re.sub(r'(? str:
"""Build score cards for ICBCBench side-by-side viewer."""
track = entry.get("track", "subjective")
overall = entry.get("overall_score")
objective = entry.get("objective_score")
subjective = entry.get("subjective_score")
expert = entry.get("expert_score")
citation = entry.get("citation_score")
source = entry.get("source_quality_score")
confidence = entry.get("confidence")
correct = entry.get("correct")
comp = entry.get("comprehensiveness_score")
insight = entry.get("insight_score")
inst = entry.get("instruction_following_score")
read = entry.get("readability_score")
def fmt(val):
if val is None:
return "N/A"
try:
return f"{float(val):.2f}"
except (TypeError, ValueError):
return str(val)
if track == "objective":
scores_data = [
("Overall
Score", fmt(overall)),
("Objective
Score", fmt(objective)),
("Confidence", fmt(confidence)),
("Correct", "Yes" if correct is True else ("No" if correct is False else "N/A")),
]
else:
scores_data = [
("Overall
Score", fmt(overall)),
("Subjective
Score", fmt(subjective)),
("Expert
Score", fmt(expert)),
("Citation", fmt(citation)),
("Source
Quality", fmt(source)),
]
if subjective is None and any(v is not None for v in [comp, insight, inst, read]):
scores_data = [
("Overall
Score", fmt(overall)),
("Comprehen-
siveness", fmt(comp)),
("Insight
Score", fmt(insight)),
("Instruction
Following", fmt(inst)),
("Readability
Score", fmt(read)),
]
html_items_str = ""
for title, score in scores_data:
html_items_str += f"""
"""
return f"""
"""
# ---------- 生成 Tab ----------
def create_data_viewer_side_by_side_tab():
with gr.Tab("⚔️Side-by-Side Viewer"):
gr.HTML(
""""""
)
with gr.Row():
task_dd = gr.Dropdown(label="Select Task", choices=[], interactive=True)
user_task_display_md = gr.Markdown(value="Loading data…", elem_classes=["card", "scrollable-sm"])
with gr.Row():
with gr.Column(scale=1):
model_a_dd = gr.Dropdown(label="Select Model A", choices=[], interactive=True)
article_a_md = gr.Markdown(elem_classes=["card", "scrollable-lg"])
scores_a_html = gr.HTML()
with gr.Column(scale=1):
model_b_dd = gr.Dropdown(label="Select Model B", choices=[], interactive=True)
article_b_md = gr.Markdown(elem_classes=["card", "scrollable-lg"])
scores_b_html = gr.HTML()
def fetch_side_by_side_data(selected_task_display, model_a_name, model_b_name):
empty_article = make_article_markdown("")
empty_scores = make_scores_html({})
if not selected_task_display:
no_task_msg = "请选择一个任务。"
return make_user_task_markdown("--", no_task_msg), \
empty_article, empty_scores, empty_article, empty_scores
item_id_str = selected_task_display.split(".", 1)[0].strip()
index = get_index()
task_prompt = next(
(task.get("prompt", "") for task in index.get("tasks", []) if str(task.get("id")) == item_id_str),
"任务描述未找到。"
)
user_task_md_content = make_user_task_markdown(item_id_str, task_prompt)
outputs_a = [make_article_markdown("模型A未选择或数据未找到"), empty_scores]
outputs_b = [make_article_markdown("模型B未选择或数据未找到"), empty_scores]
selected_models = {name for name in (model_a_name, model_b_name) if name}
entries = get_entries_for_task(item_id_str, selected_models)
if model_a_name:
entry_a = entries.get(model_a_name)
if entry_a:
outputs_a[0] = make_article_markdown(entry_a.get("article", ""))
outputs_a[1] = make_scores_html(entry_a)
if model_b_name:
entry_b = entries.get(model_b_name)
if entry_b:
outputs_b[0] = make_article_markdown(entry_b.get("article", ""))
outputs_b[1] = make_scores_html(entry_b)
return user_task_md_content, outputs_a[0], outputs_a[1], outputs_b[0], outputs_b[1]
def _build_task_choices(tasks):
return [
f"{task['id']}. {task.get('prompt', '')[:60] + ('…' if len(task.get('prompt', '')) > 60 else '')}"
for task in tasks
]
def on_load():
index = get_index()
empty_article = make_article_markdown("")
empty_scores = make_scores_html({})
all_models = index.get("models", [])
tasks = index.get("tasks", [])
if not all_models or not tasks:
return (gr.update(choices=[], value=None),
gr.update(choices=[], value=None), gr.update(choices=[], value=None),
make_user_task_markdown("--", "No data"),
empty_article, empty_scores, empty_article, empty_scores)
task_choices = _build_task_choices(tasks)
init_task = random.choice(task_choices) if task_choices else None
init_a = random.choice(all_models) if all_models else None
init_b = random.choice([m for m in all_models if m != init_a]) if len(all_models) > 1 else init_a
data = (
make_user_task_markdown("--", "请选择任务"),
empty_article, empty_scores, empty_article, empty_scores
)
return (gr.update(choices=task_choices, value=init_task),
gr.update(choices=all_models, value=init_a),
gr.update(choices=all_models, value=init_b),
*data)
task_dd.change(fetch_side_by_side_data, inputs=[task_dd, model_a_dd, model_b_dd],
outputs=[user_task_display_md, article_a_md, scores_a_html, article_b_md, scores_b_html])
model_a_dd.change(fetch_side_by_side_data, inputs=[task_dd, model_a_dd, model_b_dd],
outputs=[user_task_display_md, article_a_md, scores_a_html, article_b_md, scores_b_html])
model_b_dd.change(fetch_side_by_side_data, inputs=[task_dd, model_a_dd, model_b_dd],
outputs=[user_task_display_md, article_a_md, scores_a_html, article_b_md, scores_b_html])
return on_load, [task_dd, model_a_dd, model_b_dd, user_task_display_md, article_a_md, scores_a_html, article_b_md, scores_b_html]