roncc13 commited on
Commit
06b8083
·
verified ·
1 Parent(s): 45963e1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +11 -440
app.py CHANGED
@@ -7,12 +7,10 @@ MODEL_ID = "roncc13/trainCMDBERT-sample"
7
  tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
8
  model = AutoModelForSequenceClassification.from_pretrained(MODEL_ID)
9
 
10
- label_names = ["fake", "real"] # adjust if your order is different
 
11
 
12
  def classify(text):
13
- if not text.strip():
14
- return "—", 0.0, "", [], "Please enter some text."
15
-
16
  inputs = tokenizer(
17
  text,
18
  return_tensors="pt",
@@ -23,442 +21,15 @@ def classify(text):
23
  with torch.no_grad():
24
  outputs = model(**inputs)
25
  probs = torch.softmax(outputs.logits, dim=-1)[0].tolist()
 
26
 
27
- best_idx = int(torch.argmax(torch.tensor(probs)))
28
- best_label = label_names[best_idx].upper()
29
- best_score = float(probs[best_idx])
30
-
31
- # For now, mock some highlighted phrases & tags.
32
- # Later you can replace this with real explanation logic.
33
- phrases = ["walay side effects", "dili kinahanglan og bakuna"]
34
- tags = ["Sensational claim", "Absolute wording", "Authority framing"]
35
-
36
- explanation = (
37
- "Highlighted phrases are examples of strong cues the model may rely on "
38
- "when estimating whether the text is misleading."
39
- )
40
-
41
- return best_label, best_score, text, phrases, explanation, tags
42
-
43
- custom_css = """
44
- body {
45
- background: radial-gradient(circle at top left, #2b2c4a 0, #121320 45%, #080910 100%);
46
- }
47
-
48
- /* overall container */
49
- .gradio-container {
50
- font-family: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text",
51
- "Segoe UI", sans-serif;
52
- max-width: 1100px !important;
53
- margin: 0 auto !important;
54
- padding: 20px 10px 40px 10px !important;
55
- color: #f5f6ff;
56
- }
57
-
58
- /* hide default borders */
59
- .gradio-container .block {
60
- border: none;
61
- box-shadow: none;
62
- }
63
-
64
- /* top nav bar */
65
- #top-nav {
66
- display: flex;
67
- align-items: center;
68
- justify-content: space-between;
69
- margin-bottom: 18px;
70
- }
71
-
72
- #top-nav-left {
73
- display: flex;
74
- align-items: center;
75
- gap: 10px;
76
- }
77
-
78
- .nav-logo {
79
- width: 24px;
80
- height: 24px;
81
- border-radius: 8px;
82
- background: linear-gradient(135deg, #ffffff, #c1c5ff);
83
- }
84
-
85
- .nav-title {
86
- font-weight: 600;
87
- letter-spacing: 0.04em;
88
- font-size: 14px;
89
- }
90
-
91
- .nav-subtitle {
92
- font-size: 11px;
93
- opacity: 0.7;
94
- }
95
-
96
- #top-nav-right {
97
- display: flex;
98
- gap: 24px;
99
- font-size: 13px;
100
- opacity: 0.8;
101
- }
102
-
103
- /* big hero text */
104
- #hero {
105
- margin: 16px 0 18px 0;
106
- }
107
-
108
- .hero-title {
109
- font-size: 30px;
110
- font-weight: 700;
111
- letter-spacing: 0.02em;
112
- line-height: 1.15;
113
- }
114
-
115
- .hero-subtitle {
116
- margin-top: 8px;
117
- font-size: 13px;
118
- max-width: 520px;
119
- opacity: 0.8;
120
- }
121
-
122
- /* 2-column main layout */
123
- #main-row {
124
- display: grid;
125
- grid-template-columns: minmax(0, 2.1fr) minmax(0, 1.3fr);
126
- gap: 20px;
127
- }
128
-
129
- /* glass panels */
130
- .glass-card {
131
- background: linear-gradient(145deg, rgba(255,255,255,0.12), rgba(255,255,255,0.02));
132
- border-radius: 18px;
133
- border: 1px solid rgba(255,255,255,0.12);
134
- box-shadow: 0 18px 45px rgba(0,0,0,0.6);
135
- padding: 18px 20px;
136
- backdrop-filter: blur(14px);
137
- }
138
-
139
- /* left column inner layout */
140
- #left-column {
141
- display: grid;
142
- grid-template-rows: auto auto;
143
- gap: 14px;
144
- }
145
-
146
- /* text input card */
147
- .card-title {
148
- font-size: 15px;
149
- font-weight: 600;
150
- margin-bottom: 6px;
151
- }
152
-
153
- .card-subtitle {
154
- font-size: 11px;
155
- opacity: 0.75;
156
- margin-bottom: 8px;
157
- }
158
-
159
- #example-box {
160
- background: #050515;
161
- border-radius: 10px;
162
- padding: 10px 12px;
163
- font-size: 11px;
164
- line-height: 1.4;
165
- color: rgba(245,246,255,0.86);
166
- margin-bottom: 10px;
167
- }
168
-
169
- /* gradio textbox */
170
- textarea {
171
- background: #050515 !important;
172
- border-radius: 10px !important;
173
- border: 1px solid rgba(255,255,255,0.08) !important;
174
- color: #f5f6ff !important;
175
- font-size: 13px !important;
176
- }
177
-
178
- /* buttons row */
179
- #input-buttons {
180
- display: flex;
181
- align-items: center;
182
- justify-content: space-between;
183
- margin-top: 10px;
184
- font-size: 11px;
185
- }
186
-
187
- .btn-primary-custom {
188
- background: linear-gradient(135deg, #21c38f, #1ab07f) !important;
189
- color: #041110 !important;
190
- border-radius: 999px !important;
191
- border: none !important;
192
- padding: 6px 20px !important;
193
- font-weight: 600 !important;
194
- box-shadow: 0 12px 25px rgba(8, 160, 110, 0.55);
195
- }
196
-
197
- .btn-secondary-custom {
198
- background: transparent !important;
199
- color: rgba(245,246,255,0.85) !important;
200
- border-radius: 999px !important;
201
- border: 1px solid rgba(255,255,255,0.2) !important;
202
- padding: 6px 18px !important;
203
- font-size: 11px !important;
204
- }
205
 
206
- /* result + why flagged stack */
207
- #right-column {
208
- display: grid;
209
- grid-template-rows: auto auto;
210
- gap: 14px;
211
- }
212
-
213
- /* Result panel */
214
- .result-label {
215
- display: inline-flex;
216
- align-items: center;
217
- padding: 4px 14px;
218
- border-radius: 999px;
219
- font-size: 12px;
220
- font-weight: 600;
221
- background: #ff9c8b;
222
- color: #3b1b19;
223
- margin-bottom: 4px;
224
- }
225
-
226
- .result-meta {
227
- font-size: 11px;
228
- opacity: 0.75;
229
- }
230
-
231
- .result-confidence {
232
- font-size: 26px;
233
- font-weight: 600;
234
- }
235
-
236
- /* bar */
237
- .conf-bar-bg {
238
- margin-top: 10px;
239
- width: 100%;
240
- height: 8px;
241
- border-radius: 999px;
242
- background: rgba(255,255,255,0.1);
243
- }
244
-
245
- .conf-bar-fill {
246
- height: 100%;
247
- border-radius: inherit;
248
- background: linear-gradient(90deg, #ff9c8b, #ff6e87);
249
- }
250
-
251
- /* Why flagged */
252
- .badge-phrase {
253
- background: #050515;
254
- padding: 6px 10px;
255
- border-radius: 10px;
256
- font-size: 11px;
257
- margin: 4px 6px 4px 0;
258
- display: inline-block;
259
- }
260
-
261
- .badge-tag {
262
- display: inline-block;
263
- padding: 4px 10px;
264
- border-radius: 999px;
265
- font-size: 11px;
266
- margin-right: 6px;
267
- margin-top: 6px;
268
- background: rgba(255,255,255,0.08);
269
- }
270
-
271
- /* Mobile tweaks */
272
- @media (max-width: 900px) {
273
- #main-row {
274
- grid-template-columns: minmax(0, 1fr);
275
- }
276
- }
277
- """
278
-
279
- with gr.Blocks(fill_height=True) as demo:
280
- # Top bar
281
- with gr.Row(elem_id="top-nav"):
282
- with gr.Column(scale=3, elem_id="top-nav-left"):
283
- gr.HTML(
284
- """
285
- <div style="display:flex;align-items:center;gap:10px;">
286
- <div class="nav-logo"></div>
287
- <div>
288
- <div class="nav-title">CMD‑BERT</div>
289
- <div class="nav-subtitle">Cebuano Misinformation Detector</div>
290
- </div>
291
- </div>
292
- """
293
- )
294
- with gr.Column(scale=2, elem_id="top-nav-right"):
295
- gr.HTML(
296
- """
297
- <div id="top-nav-right">
298
- <span>Analyzer</span>
299
- <span>How it works</span>
300
- <span>About</span>
301
- <span>Feedback</span>
302
- </div>
303
- """
304
- )
305
-
306
- # Hero
307
- gr.HTML(
308
- """
309
- <section id="hero">
310
- <div class="hero-title">
311
- Check Cebuano text for<br>a misleading writing style.
312
- </div>
313
- <div class="hero-subtitle">
314
- Paste a headline, post, or short article. CMD‑BERT returns a label
315
- (Fake or Legit), confidence score, and key text cues to support the result.
316
- </div>
317
- </section>
318
- """
319
- )
320
-
321
- # Main content
322
- with gr.Row(elem_id="main-row"):
323
- # Left: text input
324
- with gr.Column(elem_id="left-column"):
325
- with gr.Group(elem_classes=["glass-card"]):
326
- gr.HTML(
327
- """
328
- <div class="card-title">Text input</div>
329
- <div class="card-subtitle">
330
- Cebuano only. This tool checks linguistic patterns; it does not verify facts.
331
- </div>
332
- <div id="example-box">
333
- <b>Example:</b><br>
334
- “Nakadisubre og milagro nga tambal sa COVID‑19 ang usa ka local doktor,
335
- giingon nga walay side effects ug dili kinahanglan og bakuna.”
336
- </div>
337
- """
338
- )
339
- input_text = gr.Textbox(
340
- lines=6,
341
- label="",
342
- placeholder="Paste Cebuano news here..."
343
- )
344
- with gr.Row(elem_id="input-buttons"):
345
- with gr.Row():
346
- analyze_btn = gr.Button("Analyze", elem_classes=["btn-primary-custom"])
347
- clear_btn = gr.Button("Clear", elem_classes=["btn-secondary-custom"])
348
- gr.Markdown("Tip: Keep inputs under 1,000 characters for faster results.")
349
-
350
- # Right: result + explanation
351
- with gr.Column(elem_id="right-column"):
352
- # Result card
353
- with gr.Group(elem_classes=["glass-card"]):
354
- gr.HTML('<div class="card-title">Result</div>')
355
- result_label = gr.HTML("<div class='result-label'>FAKE</div>")
356
- result_conf_html = gr.HTML(
357
- """
358
- <div style="display:flex;align-items:flex-end;gap:6px;margin-top:2px;">
359
- <span class="result-confidence" id="conf-val">0.87</span>
360
- <span style="font-size:11px;opacity:0.8;">confidence</span>
361
- </div>
362
- """
363
- )
364
- bar_bg = gr.HTML(
365
- """
366
- <div class="conf-bar-bg">
367
- <div id="conf-bar-fill" class="conf-bar-fill" style="width:87%;"></div>
368
- </div>
369
- """
370
- )
371
- result_meta = gr.Markdown(
372
- "Model: CMD‑BERT (fine‑tuned BERT‑base).\n\n"
373
- "Output: Label + confidence score for this text."
374
- )
375
-
376
- # Why flagged card
377
- with gr.Group(elem_classes=["glass-card"]):
378
- gr.HTML('<div class="card-title">Why this was flagged</div>')
379
- gr.Markdown(
380
- "Highlighted phrases are shown as the strongest signals used by the model."
381
- )
382
- highlighted_text = gr.HTML(
383
- "<div class='badge-phrase'>walay side effects</div>"
384
- )
385
- tags_md = gr.HTML(
386
- """
387
- <div>
388
- <span class="badge-tag">Sensational claim</span>
389
- <span class="badge-tag">Absolute wording</span>
390
- <span class="badge-tag">Authority framing</span>
391
- </div>
392
- """
393
- )
394
- explanation_md = gr.Markdown(
395
- "Use this as a screening tool. Always verify with trusted sources."
396
- )
397
-
398
- # Wiring function to UI (update label, confidence, bars, explanations)
399
- def update_ui(text):
400
- label, score, _, phrases, explanation, tags = classify(text)
401
- score_pct = int(score * 100)
402
-
403
- # Result label (FAKE / REAL)
404
- label_html = f"<div class='result-label'>{label}</div>"
405
-
406
- # Confidence text
407
- conf_html = (
408
- '<div style="display:flex;align-items:flex-end;gap:6px;margin-top:2px;">'
409
- f'<span class="result-confidence">{score:.2f}</span>'
410
- '<span style="font-size:11px;opacity:0.8;"> confidence</span>'
411
- "</div>"
412
- )
413
-
414
- # Confidence bar
415
- bar_html = (
416
- '<div class="conf-bar-bg">'
417
- f'<div id="conf-bar-fill" class="conf-bar-fill" style="width:{score_pct}%;"></div>'
418
- "</div>"
419
- )
420
-
421
- # Highlighted phrases
422
- phrase_html = "".join(
423
- [f"<span class='badge-phrase'>{p}</span>" for p in phrases]
424
- )
425
-
426
- # Tags
427
- tags_html = "".join(
428
- [f"<span class='badge-tag'>{t}</span>" for t in tags]
429
- )
430
-
431
- return (
432
- label_html,
433
- conf_html,
434
- bar_html,
435
- phrase_html,
436
- explanation,
437
- tags_html,
438
- )
439
-
440
- analyze_btn.click(
441
- fn=update_ui,
442
- inputs=input_text,
443
- outputs=[
444
- result_label,
445
- result_conf_html,
446
- bar_bg,
447
- highlighted_text,
448
- explanation_md,
449
- tags_md,
450
- ],
451
- )
452
-
453
- clear_btn.click(
454
- fn=lambda: "",
455
- inputs=None,
456
- outputs=input_text,
457
- )
458
-
459
  if __name__ == "__main__":
460
- demo.launch(
461
- css=custom_css,
462
- theme=gr.themes.Soft()
463
- )
464
-
 
7
  tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
8
  model = AutoModelForSequenceClassification.from_pretrained(MODEL_ID)
9
 
10
+ # Adjust these to match your label order
11
+ label_names = ["fake", "real"]
12
 
13
  def classify(text):
 
 
 
14
  inputs = tokenizer(
15
  text,
16
  return_tensors="pt",
 
21
  with torch.no_grad():
22
  outputs = model(**inputs)
23
  probs = torch.softmax(outputs.logits, dim=-1)[0].tolist()
24
+ return {label_names[i]: float(probs[i]) for i in range(len(label_names))}
25
 
26
+ demo = gr.Interface(
27
+ fn=classify,
28
+ inputs=gr.Textbox(lines=4, label="Enter Cebuano news text"),
29
+ outputs=gr.Label(num_top_classes=2, label="Prediction"),
30
+ title="CMD-BERT Cebuano Fake News Detector",
31
+ description="Paste Cebuano news text to check if it is likely fake or real."
32
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  if __name__ == "__main__":
35
+ demo.launch()