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'{label}'
def _confidence_text_html(conf_pct: int) -> str:
return (
"
"
f"{conf_pct}%"
"confidence"
"
"
)
def _confidence_bar_html(conf_pct: int) -> str:
return (
""
)
# 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("")
# ===== Analyzer tab =====
with gr.Tab("Analyzer"):
header()
gr.HTML(
"""
Check Cebuano text for a misleading writing style.
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.
"""
)
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(
""
"Tip: Keep inputs under 1,000 characters for faster results."
"",
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(
""
"Model: CMD\u2011BERT (fine\u2011tuned BERT\u2011base). "
"Output: Label and confidence score for the submitted text."
"",
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())