Eskhat/AI_Scam_Shield
0
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 