File size: 12,230 Bytes
4de736a
 
 
83d99ca
4de736a
042d556
 
 
e7b18a3
4de736a
 
 
 
075ee77
4de736a
aeb0e6c
 
 
 
4de736a
 
 
 
 
075ee77
4de736a
 
 
 
06b8083
11bc4db
aeb0e6c
ef5873e
 
 
62edc86
ef5873e
 
075ee77
ef5873e
075ee77
 
ef5873e
 
359c12a
ef5873e
 
 
 
 
 
 
 
 
 
aeb0e6c
83d99ca
547c955
 
 
83d99ca
547c955
 
 
 
 
 
83d99ca
 
547c955
 
 
 
 
83d99ca
547c955
 
83d99ca
 
547c955
 
 
 
 
 
83d99ca
547c955
 
83d99ca
547c955
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83d99ca
547c955
 
 
 
ef5873e
 
 
 
 
 
83d99ca
ef5873e
83d99ca
ef5873e
 
 
075ee77
 
 
 
ef5873e
 
075ee77
 
 
ef5873e
 
 
83d99ca
ef5873e
042d556
075ee77
ef5873e
075ee77
83d99ca
ef5873e
83d99ca
 
ef5873e
83d99ca
ef5873e
 
 
83d99ca
ef5873e
 
 
 
 
 
 
83d99ca
ef5873e
83d99ca
 
ef5873e
83d99ca
ef5873e
83d99ca
ef5873e
 
 
 
 
 
 
075ee77
ef5873e
075ee77
83d99ca
ef5873e
83d99ca
 
 
 
ef5873e
 
83d99ca
ef5873e
 
 
83d99ca
ef5873e
 
 
 
 
 
 
 
 
 
 
075ee77
ef5873e
075ee77
83d99ca
ef5873e
 
83d99ca
ef5873e
 
 
 
83d99ca
ef5873e
 
075ee77
ef5873e
 
 
 
075ee77
83d99ca
ef5873e
 
83d99ca
075ee77
83d99ca
ef5873e
 
83d99ca
075ee77
ef5873e
83d99ca
ef5873e
83d99ca
ef5873e
 
 
 
83d99ca
 
ef5873e
 
83d99ca
ef5873e
 
 
 
 
 
 
 
 
 
 
 
11bc4db
45963e1
62edc86
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
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))}


# --------------------------
#  UI with Tabs
# --------------------------
with gr.Blocks(fill_height=True) as demo:
    gr.HTML("<div style='height:8px;'></div>")

    # ===== Analyzer tab =====
    with gr.Tab("Analyzer"):
        header()

        gr.HTML(
            """
            <section style="margin:0 auto 22px auto; max-width:1120px;">
              <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():
                        analyze_btn = gr.Button("Analyze", elem_classes=["btn-primary-custom"])
                        clear_btn = gr.Button("Clear", elem_classes=["btn-secondary-custom"])
                    gr.Markdown(
                        "<span style='font-size:11px;opacity:0.8;'>"
                        "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(
                        '<span class="badge-pill badge-fake">FAKE</span>'
                    )
                    conf_text = gr.HTML(
                        """
                        <div style="display:flex;align-items:flex-end;gap:6px;margin-top:10px;">
                          <span style="font-size:28px;font-weight:600;" id="conf-val">0.00</span>
                          <span style="font-size:12px;opacity:0.8;">confidence</span>
                        </div>
                        """
                    )
                    conf_bar = gr.HTML(
                        """
                        <div class="conf-bar-bg">
                          <div class="conf-bar-fill" style="width:0%;"></div>
                        </div>
                        """
                    )
                    gr.Markdown(
                        "<span style='font-size:11px;opacity:0.85;'>"
                        "Model: CMD\u2011BERT (fine\u2011tuned BERT\u2011base). "
                        "Output: Label and confidence score for the submitted text."
                        "</span>",
                        container=False,
                    )

        def analyze_ui(text):
            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
            conf_pct = int(conf * 100)
            label_html = f'<span class="{css_class}">{label}</span>'
            conf_html = (
                "<div style='display:flex;align-items:flex-end;gap:6px;margin-top:10px;'>"
                f"<span style='font-size:28px;font-weight:600;' id='conf-val'>{conf:.2f}</span>"
                "<span style='font-size:12px;opacity:0.8;'>confidence</span>"
                "</div>"
            )
            bar_html = (
                "<div class='conf-bar-bg'>"
                f"<div class='conf-bar-fill' style='width:{conf_pct}%;'></div>"
                "</div>"
            )
            return label_html, conf_html, bar_html

        analyze_btn.click(fn=analyze_ui, inputs=news_text, outputs=[result_label_html, conf_text, conf_bar])
        clear_btn.click(fn=lambda: "", inputs=None, outputs=[news_text])

    # ===== 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():
            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():
            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())