from __future__ import annotations from typing import Any, Dict, Mapping, Tuple import gradio as gr from dialect_analysis.pipeline import classify_text def _format_scores(scores: Mapping[str, float]) -> str: ordered = sorted(scores.items(), key=lambda kv: kv[1], reverse=True) return "\n".join(f"- {d}: {pct:.1f}%" for d, pct in ordered) def analyze_text(text: str, strip_diacritics: bool) -> Tuple[str, str, str]: """Gradio callback. NOTE: Gradio passes inputs positionally, so callback args must not be keyword-only. """ try: text = (text or "").strip() if not text: return "", "", "" result: Dict[str, Any] = classify_text(text, strip_diacritics=bool(strip_diacritics)) dialect = str(result.get("dialect", "")) confidence = float(result.get("confidence", 0.0) or 0.0) * 100.0 scores: Mapping[str, float] = result.get("scores", {}) or {} explanation = str(result.get("explanation", "")) summary_md = f"**Dialect:** {dialect}\n\n**Confidence:** {confidence:.1f}%" scores_md = _format_scores(scores) explanation_md = f"```\n{explanation}\n```" if explanation else "" return summary_md, scores_md, explanation_md except Exception as e: # Surface errors in the UI instead of failing silently. return "", "", f"```\nError: {type(e).__name__}: {e}\n```" with gr.Blocks(title="Ancient Greek Dialect Classifier") as demo: gr.Markdown( "# Ancient Greek Dialect Classifier\n" "Rule-based, explainable classifier for Attic / Ionic / Doric / Aeolic / Koine.\n" "\nPaste Greek text below and click **Analyze**." ) with gr.Row(): strip = gr.Checkbox(value=True, label="Strip diacritics (recommended)") inp = gr.Textbox( label="Greek text", lines=12, placeholder="Paste Ancient Greek text here…", ) btn = gr.Button("Analyze") with gr.Row(): summary = gr.Markdown(label="Summary") with gr.Row(): scores = gr.Markdown(label="Scores") explanation = gr.Markdown(label="Explanation") btn.click( fn=analyze_text, inputs=[inp, strip], outputs=[summary, scores, explanation], ) # Nice-to-have for Spaces: enable Shift+Enter submit. inp.submit( fn=analyze_text, inputs=[inp, strip], outputs=[summary, scores, explanation], ) if __name__ == "__main__": demo.launch()