Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from transformers import AutoTokenizer, AutoModelForSequenceClassification | |
| import torch | |
| from theme import custom_css, header | |
| # -------------------------- | |
| # Model setup | |
| # -------------------------- | |
| MODEL_ID = "roncc13/autotrain-ixzm9-t6dbc" | |
| tokenizer = AutoTokenizer.from_pretrained(MODEL_ID) | |
| model = AutoModelForSequenceClassification.from_pretrained(MODEL_ID) | |
| label_names = ["fake", "real"] | |
| def classify(text: str): | |
| if not text.strip(): | |
| return {"fake": 0.0, "real": 0.0} | |
| inputs = tokenizer( | |
| text, | |
| return_tensors="pt", | |
| truncation=True, | |
| padding=True, | |
| max_length=256, | |
| ) | |
| with torch.no_grad(): | |
| outputs = model(**inputs) | |
| probs = torch.softmax(outputs.logits, dim=-1)[0].tolist() | |
| return {label_names[i]: float(probs[i]) for i in range(len(label_names))} | |
| # -------------------------- | |
| # Helpers for rendering result HTML | |
| # -------------------------- | |
| def _result_label_html(label: str, css_class: str) -> str: | |
| return f'<span class="{css_class}">{label}</span>' | |
| def _confidence_text_html(conf_pct: int) -> str: | |
| return ( | |
| "<div class='conf-text-row'>" | |
| f"<span class='conf-val'>{conf_pct}%</span>" | |
| "<span class='conf-caption'>confidence</span>" | |
| "</div>" | |
| ) | |
| def _confidence_bar_html(conf_pct: int) -> str: | |
| return ( | |
| "<div class='conf-bar-bg'>" | |
| f"<div class='conf-bar-fill' style='width:{conf_pct}%;'></div>" | |
| "</div>" | |
| ) | |
| # Initial (empty) state values for the result card | |
| INITIAL_LABEL_HTML = _result_label_html("—", "badge-pill badge-neutral") | |
| INITIAL_CONF_HTML = _confidence_text_html(0) | |
| INITIAL_BAR_HTML = _confidence_bar_html(0) | |
| # -------------------------- | |
| # UI with Tabs | |
| # -------------------------- | |
| with gr.Blocks(fill_height=True) as demo: | |
| gr.HTML("<div style='height:12px;'></div>") | |
| # ===== Analyzer tab ===== | |
| with gr.Tab("Analyzer"): | |
| header() | |
| gr.HTML( | |
| """ | |
| <section class="hero-section"> | |
| <div class="hero-title"> | |
| Check Cebuano text for a misleading writing style. | |
| </div> | |
| <div class="hero-subtitle"> | |
| This tool analyzes linguistic patterns and writing style in Cebuano text to detect potential | |
| misinformation. It does not verify factual correctness. The model returns a classification | |
| (Fake/Legit) and a confidence score based on writing patterns. | |
| </div> | |
| </section> | |
| """ | |
| ) | |
| with gr.Row(elem_classes=["two-col"], equal_height=True): | |
| # Left: input card | |
| with gr.Column(scale=3): | |
| with gr.Group(elem_classes=["glass-card"], elem_id="input-card"): | |
| gr.Markdown( | |
| "#### Text input\n" | |
| "Cebuano only. This tool checks linguistic patterns; it does not verify facts." | |
| ) | |
| gr.Markdown( | |
| "> **Example** \n" | |
| "> \u201cNakadisubre og milagro nga tambal sa COVID\u201119 ang usa ka local doktor, " | |
| "giingon nga walay side effects ug dili kinahanglan og bakuna.\u201d" | |
| ) | |
| news_text = gr.Textbox( | |
| lines=7, | |
| label="", | |
| placeholder="Paste Cebuano news text here...", | |
| elem_id="news-textbox", | |
| ) | |
| with gr.Row(elem_classes=["btn-row"]): | |
| analyze_btn = gr.Button("Analyze", elem_classes=["btn-primary-custom"]) | |
| clear_btn = gr.Button("Clear", elem_classes=["btn-secondary-custom"]) | |
| gr.Markdown( | |
| "<span class='helper-text'>" | |
| "Tip: Keep inputs under 1,000 characters for faster results." | |
| "</span>", | |
| container=False, | |
| ) | |
| # Right: result card | |
| with gr.Column(scale=2): | |
| with gr.Group(elem_classes=["glass-card"], elem_id="result-card"): | |
| gr.Markdown("#### Result") | |
| result_label_html = gr.HTML(INITIAL_LABEL_HTML) | |
| conf_text = gr.HTML(INITIAL_CONF_HTML) | |
| conf_bar = gr.HTML(INITIAL_BAR_HTML) | |
| gr.Markdown( | |
| "<span class='helper-text'>" | |
| "Model: CMD\u2011BERT (fine\u2011tuned BERT\u2011base). " | |
| "Output: Label and confidence score for the submitted text." | |
| "</span>", | |
| container=False, | |
| ) | |
| def analyze_ui(text): | |
| if not text or not text.strip(): | |
| return INITIAL_LABEL_HTML, INITIAL_CONF_HTML, INITIAL_BAR_HTML | |
| probs = classify(text) | |
| fake_p = probs.get("fake", 0.0) | |
| real_p = probs.get("real", 0.0) | |
| if fake_p >= real_p: | |
| label, css_class, conf = "FAKE", "badge-pill badge-fake", fake_p | |
| else: | |
| label, css_class, conf = "LEGIT", "badge-pill badge-real", real_p | |
| # Clamp and convert to integer percentage 0–100 | |
| conf_pct = max(0, min(100, int(round(conf * 100)))) | |
| return ( | |
| _result_label_html(label, css_class), | |
| _confidence_text_html(conf_pct), | |
| _confidence_bar_html(conf_pct), | |
| ) | |
| def clear_ui(): | |
| return "", INITIAL_LABEL_HTML, INITIAL_CONF_HTML, INITIAL_BAR_HTML | |
| analyze_btn.click( | |
| fn=analyze_ui, | |
| inputs=news_text, | |
| outputs=[result_label_html, conf_text, conf_bar], | |
| ) | |
| clear_btn.click( | |
| fn=clear_ui, | |
| inputs=None, | |
| outputs=[news_text, result_label_html, conf_text, conf_bar], | |
| ) | |
| # ===== How it works tab ===== | |
| with gr.Tab("How it works"): | |
| header() | |
| with gr.Group(elem_classes=["glass-card"], elem_id="hiw-intro-card"): | |
| gr.Markdown( | |
| "## How CMD\u2011BERT works\n" | |
| "CMD\u2011BERT is an AI\u2011augmented linguistic model that focuses on writing style, " | |
| "not literal truth. It looks for patterns such as exaggerated wording, " | |
| "over\u2011confident claims, and framing that often appear in misleading content." | |
| ) | |
| with gr.Row(elem_classes=["card-row"]): | |
| with gr.Column(): | |
| with gr.Group(elem_classes=["glass-card"], elem_id="hiw-step1-card"): | |
| gr.Markdown( | |
| "### 1. Input and preprocessing\n" | |
| "- User pastes a Cebuano headline, post, or short article.\n" | |
| "- The text is tokenized and trimmed to a safe maximum length.\n" | |
| "- Inputs are processed in memory and not stored permanently." | |
| ) | |
| with gr.Column(): | |
| with gr.Group(elem_classes=["glass-card"], elem_id="hiw-step2-card"): | |
| gr.Markdown( | |
| "### 2. CMD\u2011BERT analysis\n" | |
| "- CMD\u2011BERT is a fine\u2011tuned BERT\u2011base model trained on Cebuano news.\n" | |
| "- It computes probabilities for two classes: **Fake** and **Legit**.\n" | |
| "- The highest\u2011probability class becomes the predicted label." | |
| ) | |
| with gr.Group(elem_classes=["glass-card"], elem_id="hiw-step3-card"): | |
| gr.Markdown( | |
| "### 3. Result and interpretation\n" | |
| "- The interface shows the predicted label and confidence bar.\n" | |
| "- Users are reminded that this is a screening tool only.\n" | |
| "- Final judgment should always involve human critical thinking." | |
| ) | |
| # ===== About tab ===== | |
| with gr.Tab("About"): | |
| header() | |
| with gr.Group(elem_classes=["glass-card"], elem_id="about-intro-card"): | |
| gr.Markdown( | |
| "## About CMD\u2011BERT\n" | |
| "**CMD\u2011BERT: An AI Augmented Linguistic Recognition Model for Cebuano Fake News Detection**\n\n" | |
| "CMD\u2011BERT is a thesis project in the Department of Computer Engineering at " | |
| "Cebu Technological University\u2013Main Campus. The tool aims to support Cebuano readers " | |
| "by highlighting potentially misleading writing patterns in online news and posts." | |
| ) | |
| with gr.Group(elem_classes=["glass-card"], elem_id="about-thesis-card"): | |
| gr.Markdown( | |
| "### Thesis information\n" | |
| "_A Thesis Project presented to the Faculty of the Department of Computer Engineering_\n\n" | |
| "Cebu Technological University\u2013Main Campus \n" | |
| "Cebu City, Philippines \n\n" | |
| "_In partial fulfillment of the requirements for the degree_ \n" | |
| "**Bachelor of Science in Computer Engineering**\n\n" | |
| "**By:** \n" | |
| "- Cabag, Ronilo Jose Jr. S. \n" | |
| "- Libron, Andio Mart \n" | |
| "- Omega, Noel \n\n" | |
| "**Adviser:** Engr. Jueco, M.Eng. \n" | |
| "January 2026" | |
| ) | |
| # ===== Feedback tab ===== | |
| with gr.Tab("Feedback"): | |
| header() | |
| with gr.Group(elem_classes=["glass-card"], elem_id="fb-intro-card"): | |
| gr.Markdown( | |
| "## Feedback and model improvement\n" | |
| "CMD\u2011BERT is experimental and continuously improving. Your feedback can help " | |
| "identify model mistakes, usability issues, and opportunities to refine the dataset." | |
| ) | |
| with gr.Row(elem_classes=["card-row"]): | |
| with gr.Column(): | |
| with gr.Group(elem_classes=["glass-card"], elem_id="fb-form-card"): | |
| fb_type = gr.Dropdown( | |
| ["Bug / technical issue", "Model mistake", "UI suggestion", "Other"], | |
| label="Feedback type", | |
| ) | |
| fb_text = gr.Textbox( | |
| lines=6, | |
| label="Your message or example text", | |
| placeholder="Describe the issue or paste an example of text the model misclassified.", | |
| elem_id="fb-textbox", | |
| ) | |
| fb_email = gr.Textbox( | |
| label="Email (optional, for follow\u2011up)", | |
| placeholder="you@example.com", | |
| elem_id="fb-email-textbox", | |
| ) | |
| fb_checkbox = gr.Checkbox( | |
| label="Allow us to use this text anonymously for future model improvements.", | |
| value=True, | |
| ) | |
| fb_submit = gr.Button("Submit feedback", elem_classes=["btn-primary-custom"]) | |
| with gr.Column(): | |
| with gr.Group(elem_classes=["glass-card"], elem_id="fb-faq-card"): | |
| fb_status = gr.Markdown("No feedback submitted yet.") | |
| gr.Markdown( | |
| "### FAQ\n" | |
| "**What happens to my feedback?** \n" | |
| "It is stored securely and reviewed by the CMD\u2011BERT thesis team.\n\n" | |
| "**Will CMD\u2011BERT replace human fact\u2011checkers?** \n" | |
| "No. It is a support tool to encourage critical reading.\n\n" | |
| "**Who maintains this tool?** \n" | |
| "The CMD\u2011BERT thesis team at Cebu Technological University\u2013Main Campus." | |
| ) | |
| def save_feedback(ftype, text, email, consent): | |
| if not text.strip(): | |
| return "Please enter a message before submitting." | |
| return "Thank you for your feedback! It has been recorded." | |
| fb_submit.click( | |
| fn=save_feedback, | |
| inputs=[fb_type, fb_text, fb_email, fb_checkbox], | |
| outputs=fb_status, | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch(css=custom_css, theme=gr.themes.Soft()) | |