CoolFace
Apppublic

Eskhat/AI_Scam_Shield

sourceHugging Facemitupdated 7mo agoView on Hugging Face
0likes
app.py208 linesDownload Raw Back to root
1import gradio as gr
2import numpy as np
3import librosa
4
5# ---------------------------
6# 1) TEXT SCAM HEURISTICS (Explainable + WOW)
7# ---------------------------
8SCAM_TRIGGERS = [
9    ("urgency", ["срочно", "тез", "қазір", "немедленно", "urgent", "asap"]),
10    ("money", ["ақша", "аудар", "переведи", "карта", "kaspi", "счет", "iban", "номер карты"]),
11    ("secrecy", ["ешкімге айтпа", "никому не говори", "құпия", "secret"]),
12    ("verification", ["код", "otp", "sms", "пароль", "confirm", "подтверд"]),
13    ("link", ["http://", "https://", "t.me/", "bit.ly", "goo.gl"]),
14    ("threat", ["блок", "полиция", "сот", "штраф", "уголов", "арест"]),
15]
16
17def text_scam_score(text: str):
18    if not text or not text.strip():
19        return 0, [], "Введите текст."
20
21    t = text.lower()
22    hits = []
23    score = 0
24
25    for label, words in SCAM_TRIGGERS:
26        found = [w for w in words if w in t]
27        if found:
28            hits.append((label, found[:3]))
29            # weights (tuned for demo impact)
30            if label in ["money", "verification"]:
31                score += 30
32            elif label in ["urgency", "secrecy", "link"]:
33                score += 20
34            elif label in ["threat"]:
35                score += 15
36            else:
37                score += 10
38
39    # extra: suspicious punctuation / caps
40    if "!!!" in text:
41        score += 8
42    if sum(1 for c in text if c.isupper()) >= 10:
43        score += 8
44
45    score = int(min(100, score))
46    if score >= 80:
47        level = "HIGH"
48    elif score >= 45:
49        level = "MEDIUM"
50    else:
51        level = "LOW"
52
53    explanation = []
54    for label, found in hits:
55        explanation.append(f"• {label}: {', '.join(found)}")
56
57    action = recommend_actions(level)
58    return score, explanation, action
59
60def recommend_actions(level: str):
61    if level == "HIGH":
62        return (
63            "🚨 Не отправляйте деньги.\n"
64            "✅ Перезвоните родственнику сами (другим каналом).\n"
65            "✅ Никогда не сообщайте OTP/SMS-коды.\n"
66            "✅ Попросите видео-звонок и контрольный вопрос."
67        )
68    if level == "MEDIUM":
69        return (
70            "⚠️ Будьте осторожны.\n"
71            "✅ Уточните через другой канал.\n"
72            "✅ Не переходите по ссылкам.\n"
73            "✅ Не отправляйте личные данные."
74        )
75    return (
76        "✅ Риск низкий.\n"
77        "Но всё равно: проверяйте неизвестные номера и ссылки."
78    )
79
80# ---------------------------
81# 2) VOICE "SPOOF RISK" (Fast MVP)
82# NOTE: This is NOT a full deepfake detector.
83# For hackathon demo, it gives a risk based on audio artifacts.
84# ---------------------------
85def voice_spoof_risk(audio_path):
86    if audio_path is None:
87        return 0, "Загрузите аудио (wav/mp3)."
88
89    y, sr = librosa.load(audio_path, sr=16000, mono=True)
90    if len(y) < sr * 1.0:
91        return 10, "Аудио слишком короткое. Нужны хотя бы 1–2 секунды."
92
93    # simple features for demo: spectral flatness, rolloff, zero-crossing, rms variance
94    flat = float(np.mean(librosa.feature.spectral_flatness(y=y)))
95    zcr = float(np.mean(librosa.feature.zero_crossing_rate(y)))
96    rms = librosa.feature.rms(y=y)[0]
97    rms_var = float(np.var(rms))
98    roll = float(np.mean(librosa.feature.spectral_rolloff(y=y, sr=sr)))
99
100    # heuristic scoring (demo-oriented)
101    score = 0
102    # overly flat spectrum can indicate synthetic or over-processed audio
103    if flat > 0.25:
104        score += 35
105    if zcr > 0.12:
106        score += 20
107    if rms_var < 0.0005:
108        score += 25
109    if roll > 6000:
110        score += 15
111
112    score = int(min(100, score))
113    if score >= 70:
114        verdict = "FAKE SUSPECT (High spoof risk)"
115    elif score >= 35:
116        verdict = "SUSPICIOUS (Medium spoof risk)"
117    else:
118        verdict = "LIKELY REAL (Low spoof risk)"
119
120    details = (
121        f"{verdict}\n"
122        f"Features: flatness={flat:.3f}, zcr={zcr:.3f}, rms_var={rms_var:.6f}, rolloff={roll:.0f}Hz\n"
123        "Note: For production, replace this with a real anti-spoof / deepfake detection model."
124    )
125    return score, details
126
127# ---------------------------
128# 3) COMBINED DASHBOARD
129# ---------------------------
130def analyze_all(text, audio):
131    t_score, t_reasons, t_action = text_scam_score(text)
132    v_score, v_details = voice_spoof_risk(audio)
133
134    # Combine: weighted (text is often strongest signal in chat scams)
135    final = int(min(100, 0.65 * t_score + 0.35 * v_score))
136
137    if final >= 80:
138        status = "🔴 HIGH RISK"
139    elif final >= 45:
140        status = "🟠 MEDIUM RISK"
141    else:
142        status = "🟢 LOW RISK"
143
144    reasons_md = ""
145    if t_reasons:
146        reasons_md += "### 🧾 Text reasons\n" + "\n".join(t_reasons) + "\n\n"
147    reasons_md += "### 🎙️ Voice analysis\n" + f"```{v_details}```\n\n"
148    reasons_md += "### ✅ Recommended actions\n" + f"```{t_action}```"
149
150    return final, status, reasons_md
151
152# ---------------------------
153# UI (WOW)
154# ---------------------------
155THEME = gr.themes.Soft()
156
157with gr.Blocks(theme=THEME, title="AI Scam Shield — Demo") as demo:
158    gr.Markdown(
159        """
160# 🛡️ AI Scam Shield (DeepFake & Fraud Detector)
161**Demo:** Text + Voice + Risk Score + Explainable Reasons  
162*Hackathon-ready dashboard*
163"""
164    )
165
166    with gr.Row():
167        with gr.Column():
168            text_in = gr.Textbox(
169                label="💬 Paste message (Telegram/WhatsApp)",
170                placeholder="Мысалы: Срочно ақша жіберші, қазір проблема, ешкімге айтпа…",
171                lines=6,
172            )
173            with gr.Row():
174                btn_scam = gr.Button("⚡ Try sample SCAM", variant="primary")
175                btn_normal = gr.Button("🙂 Try sample NORMAL")
176
177        with gr.Column():
178            audio_in = gr.Audio(label="🎙️ Upload voice note (wav/mp3)", type="filepath")
179            gr.Markdown("Tip: Демода 2 файл дайындап қойыңдар: **real.wav** және **fake.wav**")
180
181    analyze_btn = gr.Button("🔎 Analyze", variant="primary")
182
183    with gr.Row():
184        risk = gr.Slider(0, 100, value=0, label="🔥 Risk Score", interactive=False)
185        status = gr.Textbox(label="Status", interactive=False)
186
187    details = gr.Markdown()
188
189    def fill_scam():
190        return "Срочно ақша жіберші. Мен қазір полициядамын. Ешкімге айтпа. Kaspi-ға аудар. Код келсе жазып жібер."
191
192    def fill_normal():
193        return "Сәлем! Кешке кездесеміз бе? 19:00-де кофеханада болайын. 🙂"
194
195    btn_scam.click(fn=fill_scam, outputs=text_in)
196    btn_normal.click(fn=fill_normal, outputs=text_in)
197    analyze_btn.click(fn=analyze_all, inputs=[text_in, audio_in], outputs=[risk, status, details])
198
199    gr.Markdown(
200        """
201---
202### 🔐 Disclaimer
203This is a hackathon demo. For real deployment: add **production anti-spoof model**, dataset evaluation, and privacy safeguards.
204"""
205    )
206
207demo.launch()
208