import gradio as gr import json from constants import INTRODUCTION_TEXT from utils import ( init_repo, load_data, process_submit, get_datasets_description, get_metrics_html, compute_wer_cer, get_submit_html, DATASETS, ) from styles import LEADERBOARD_CSS init_repo() gr.set_static_paths(paths=["."]) with gr.Blocks(css=LEADERBOARD_CSS, theme=gr.themes.Soft()) as demo: gr.HTML( '' ) gr.Markdown(INTRODUCTION_TEXT, elem_classes="markdown-text") with gr.Tabs(): with gr.Tab("πŸ… Π›ΠΈΠ΄Π΅Ρ€Π±ΠΎΡ€Π΄"): leaderboard_html = gr.HTML(value=load_data(), every=60) with gr.Tab("πŸ“ˆ ΠœΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ"): gr.HTML(get_metrics_html()) with gr.Group(): gr.Markdown("### ΠŸΠ΅ΡΠΎΡ‡Π½ΠΈΡ†Π°: посчитайтС WER/CER Π½Π° своих строках") with gr.Row(): ref = gr.Textbox( label="РСфСрСнсный тСкст", placeholder="Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€: я люблю машинноС ΠΎΠ±ΡƒΡ‡Π΅Π½ΠΈΠ΅", lines=2, ) hyp = gr.Textbox( label="Π“ΠΈΠΏΠΎΡ‚Π΅Π·Π° (распознанный тСкст)", placeholder="Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€: я люблю ΠΌΠΎΡ‰ΠΈΠ½Π½ΠΎΠ΅ ΠΎΠ±ΡƒΡ‡Π΅Π½ΠΈΠ΅", lines=2, ) with gr.Row(): normalize = gr.Checkbox( value=True, label="ΠΠΎΡ€ΠΌΠ°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ (Π½ΠΈΠΆΠ½ΠΈΠΉ рСгистр, Π±Π΅Π· ΠΏΡƒΠ½ΠΊΡ‚ΡƒΠ°Ρ†ΠΈΠΈ)", ) btn_calc = gr.Button("ΠŸΠΎΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ") with gr.Row(): out_wer = gr.Number(label="WER, %", precision=2) out_cer = gr.Number(label="CER, %", precision=2) def _ui_compute(ref_text, hyp_text, norm): wer, cer = compute_wer_cer(ref_text or "", hyp_text or "", norm) return wer, cer btn_calc.click( _ui_compute, inputs=[ref, hyp, normalize], outputs=[out_wer, out_cer], ) with gr.Tab("πŸ“Š ДатасСты"): gr.HTML(get_datasets_description()) with gr.Tab("βœ‰οΈ ΠžΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚"): gr.HTML(get_submit_html()) with gr.Row(): with gr.Column(): model_name = gr.Textbox( label="НазваниС ΠΌΠΎΠ΄Π΅Π»ΠΈ *", placeholder="MyAwesomeASRModel" ) link = gr.Textbox( label="Бсылка Π½Π° модСль *", placeholder="https://huggingface.co/username/model", ) license_field = gr.Textbox( label="ЛицСнзия *", placeholder="MIT / Apache-2.0 / Closed" ) with gr.Column(): metrics_json = gr.TextArea( label="ΠœΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ JSON *", placeholder='{"Russian_LibriSpeech": {"wer": 0.1234, "cer": 0.0567}, ...}', lines=16, ) submit_btn = gr.Button("πŸš€ ΠžΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ", elem_classes="full-width-btn") output_msg = gr.HTML() def _alert(kind, text): return f'
{text}
' def build_json_and_submit(name, link_, lic, metrics_str): name = (name or "").strip() link_ = (link_ or "").strip() lic = (lic or "").strip() if not name: return ( gr.update(), _alert("error", "Π£ΠΊΠ°ΠΆΠΈΡ‚Π΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΠΌΠΎΠ΄Π΅Π»ΠΈ."), metrics_str, ) if not link_ or not ( link_.startswith("http://") or link_.startswith("https://") ): return ( gr.update(), _alert( "error", "Бсылка Π΄ΠΎΠ»ΠΆΠ½Π° Π½Π°Ρ‡ΠΈΠ½Π°Ρ‚ΡŒΡΡ с http:// ΠΈΠ»ΠΈ https://" ), metrics_str, ) if not lic: return ( gr.update(), _alert("error", "Π£ΠΊΠ°ΠΆΠΈΡ‚Π΅ Π»ΠΈΡ†Π΅Π½Π·ΠΈΡŽ ΠΌΠΎΠ΄Π΅Π»ΠΈ."), metrics_str, ) try: metrics = json.loads(metrics_str) except Exception as e: return ( gr.update(), _alert("error", f"НСвалидный JSON ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊ: {e}"), metrics_str, ) if not isinstance(metrics, dict): return ( gr.update(), _alert( "error", "ΠœΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠΌ JSON с датасСтами Π²Π΅Ρ€Ρ…Π½Π΅Π³ΠΎ уровня.", ), metrics_str, ) missing = [ds for ds in DATASETS if ds not in metrics] extra = [k for k in metrics.keys() if k not in DATASETS] if missing: return ( gr.update(), _alert("error", f"ΠžΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‚ датасСты: {', '.join(missing)}"), metrics_str, ) if extra: return ( gr.update(), _alert("error", f"Π›ΠΈΡˆΠ½ΠΈΠ΅ ΠΊΠ»ΡŽΡ‡ΠΈ Π² ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠ°Ρ…: {', '.join(extra)}"), metrics_str, ) for ds in DATASETS: entry = metrics.get(ds) if not isinstance(entry, dict): return ( gr.update(), _alert( "error", f"{ds}: Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠΌ с полями wer ΠΈ cer", ), metrics_str, ) for k in ("wer", "cer"): v = entry.get(k) if not isinstance(v, (int, float)): return ( gr.update(), _alert("error", f"{ds}: ΠΏΠΎΠ»Π΅ {k} Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ числом"), metrics_str, ) if not (0 <= float(v) <= 1): return ( gr.update(), _alert( "error", f"{ds}: ΠΏΠΎΠ»Π΅ {k} Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ Π² Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π΅ [0, 1]", ), metrics_str, ) payload = json.dumps( { "model_name": name, "link": link_, "license": lic, "metrics": metrics, }, ensure_ascii=False, ) updated_html, status_msg, cleared = process_submit(payload) if updated_html is None: msg = status_msg.replace("Ошибка:", "").strip() return ( gr.update(), _alert("error", f"НС ΡƒΠ΄Π°Π»ΠΎΡΡŒ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ: {msg}"), metrics_str, ) return ( updated_html, _alert("success", "βœ… Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ Π² Π»ΠΈΠ΄Π΅Ρ€Π±ΠΎΡ€Π΄."), "", ) submit_btn.click( build_json_and_submit, inputs=[model_name, link, license_field, metrics_json], outputs=[leaderboard_html, output_msg, metrics_json], ) demo.launch()