thong0710 commited on
Commit
1d90061
·
verified ·
1 Parent(s): 64642fb
Files changed (1) hide show
  1. app/safety_check.py +95 -225
app/safety_check.py CHANGED
@@ -1,5 +1,3 @@
1
- from functools import lru_cache
2
- from concurrent.futures import ThreadPoolExecutor
3
  from detoxify import Detoxify
4
  from transformers import (
5
  AutoProcessor, AutoModelForImageClassification,
@@ -11,244 +9,116 @@ import torch
11
  import re
12
  from urllib.parse import urlparse, unquote
13
 
14
- # Kiểm tra GPU thiết lập device
15
- device = "cuda" if torch.cuda.is_available() else "cpu"
16
- torch.set_num_threads(4 if device == "cpu" else 1)
17
-
18
- # Load các model song song
19
- def load_models():
20
- with ThreadPoolExecutor() as executor:
21
- # Model phát hiện URL độc hại
22
- classifier_future = executor.submit(
23
- pipeline,
24
- "zero-shot-classification",
25
- device=0 if device == "cuda" else -1
26
- )
27
-
28
- # Model detoxify
29
- detox_future = executor.submit(Detoxify, 'original')
30
-
31
- # Model NSFW
32
- nsfw_model_id = "Falconsai/nsfw_image_detection"
33
- nsfw_future = executor.submit(
34
- AutoProcessor.from_pretrained,
35
- nsfw_model_id
36
- )
37
- nsfw_model_future = executor.submit(
38
- AutoModelForImageClassification.from_pretrained,
39
- nsfw_model_id
40
- )
41
-
42
- # Model bạo lực
43
- violence_model_id = "jaranohaal/vit-base-violence-detection"
44
- violence_model_future = executor.submit(
45
- ViTForImageClassification.from_pretrained,
46
- violence_model_id
47
- )
48
- violence_processor_future = executor.submit(
49
- ViTFeatureExtractor.from_pretrained,
50
- violence_model_id
51
- )
52
-
53
- # Model BLIP
54
- blip_processor_future = executor.submit(
55
- BlipProcessor.from_pretrained,
56
- "Salesforce/blip-image-captioning-base"
57
- )
58
- blip_model_future = executor.submit(
59
- BlipForConditionalGeneration.from_pretrained,
60
- "Salesforce/blip-image-captioning-base"
61
- )
62
-
63
- # Lấy kết quả
64
- classifier = classifier_future.result()
65
- detox_model = detox_future.result()
66
- nsfw_processor = nsfw_future.result()
67
- nsfw_model = nsfw_model_future.result().to(device)
68
- violence_model = violence_model_future.result().to(device)
69
- violence_processor = violence_processor_future.result()
70
- blip_processor = blip_processor_future.result()
71
- blip_model = blip_model_future.result().to(device)
72
-
73
- return (
74
- classifier, detox_model,
75
- nsfw_processor, nsfw_model,
76
- violence_processor, violence_model,
77
- blip_processor, blip_model
78
- )
79
-
80
- (
81
- classifier, detox_model,
82
- nsfw_processor, nsfw_model,
83
- violence_processor, violence_model,
84
- blip_processor, blip_model
85
- ) = load_models()
86
-
87
- # Cache cho các hàm xử lý text
88
- @lru_cache(maxsize=1000)
89
- def is_prompt_safe_cached(prompt: str):
90
  results = detox_model.predict(prompt)
91
  threshold = 0.5
92
  flagged = {label: score for label, score in results.items() if score > threshold}
93
- if flagged:
94
- return False, list(flagged.keys())
95
- return True, []
96
-
97
- def is_prompt_safe(prompt: str):
98
- return is_prompt_safe_cached(prompt[:500]) # Giới hạn độ dài để cache hiệu quả
99
 
100
- # Tối ưu xử lý ảnh
101
- def process_image(image: Image.Image):
102
- # Tạo caption
103
- inputs = blip_processor(images=image, return_tensors="pt").to(device)
104
  with torch.no_grad():
105
- out = blip_model.generate(**inputs)
106
- caption = blip_processor.decode(out[0], skip_special_tokens=True)
107
-
108
- # Xử lý NSFW
109
- nsfw_inputs = nsfw_processor(images=image, return_tensors="pt").to(device)
110
  with torch.no_grad():
111
- nsfw_outputs = nsfw_model(**nsfw_inputs)
112
- nsfw_probs = torch.nn.functional.softmax(nsfw_outputs.logits, dim=1)[0]
113
-
114
- nsfw_labels = list(nsfw_model.config.id2label.values())
115
- nsfw_pred = nsfw_probs.argmax().item()
116
- nsfw_label = nsfw_labels[nsfw_pred]
117
- nsfw_score = nsfw_probs[nsfw_pred].item() * 100
118
-
119
- # Xử lý bạo lực
120
- violence_inputs = violence_processor(images=image, return_tensors="pt").to(device)
121
  with torch.no_grad():
122
- violence_outputs = violence_model(**violence_inputs)
123
- violence_probs = torch.nn.functional.softmax(violence_outputs.logits, dim=1)[0]
124
-
125
- violence_labels = ["Non-Violent", "Violent"]
126
- violence_pred = violence_probs.argmax().item()
127
- violence_label = violence_labels[violence_pred]
128
- violence_score = violence_probs[violence_pred].item() * 100
129
-
130
- return {
131
- "caption": caption,
132
- "nsfw": (nsfw_label, nsfw_score),
133
- "violence": (violence_label, violence_score)
134
- }
135
-
136
- def check_nsfw_image(image: Image.Image) -> str:
137
- """Kiểm tra trả về kết quả NSFW của ảnh"""
138
- results = process_image(image)
139
- nsfw_label, nsfw_score = results["nsfw"]
140
- caption = results["caption"]
141
-
142
- if nsfw_label.lower() in ["porn", "hentai", "sex", "nsfw"]:
143
- return f"""🚨 Ảnh KHÔNG an toàn (NSFW):
144
- - Loại: {nsfw_label}
145
- - Độ chính xác: {nsfw_score:.2f}%
146
- - Mô tả: {caption}"""
147
  else:
148
- return f"""Ảnh an toàn (NSFW):
149
- - Loại: {nsfw_label}
150
- - Độ chính xác: {nsfw_score:.2f}%
151
- - tả: {caption}"""
152
-
153
- def check_violence_image(image: Image.Image) -> str:
154
- """Kiểm tra và trả về kết quả bạo lực của ảnh"""
155
- results = process_image(image)
156
- violence_label, violence_score = results["violence"]
157
- caption = results["caption"]
158
-
159
- is_violent = (violence_label.lower() == "non-violent" and violence_score > 50) or \
160
- (violence_label.lower() == "violent" and violence_score > 80)
161
-
162
- if is_violent:
163
- return f"""🚨 Ảnh KHÔNG an toàn (Bạo lực):
164
- - Loại: {violence_label}
165
- - Độ chính xác: {violence_score:.2f}%
166
- - Mô tả: {caption}"""
167
  else:
168
- return f"""Ảnh an toàn (Bạo lực):
169
- - Loại: {violence_label}
170
- - Độ chính xác: {violence_score:.2f}%
171
- - Mô tả: {caption}"""
172
-
173
- # Cache cho URL check
174
- @lru_cache(maxsize=1000)
175
- def check_url_cached(url: str):
176
  try:
177
- decoded_url = unquote(url)
178
- parsed = urlparse(decoded_url)
179
  warnings = []
180
-
181
- # Các rule kiểm tra URL (giữ nguyên như cũ)
182
- if re.match(r'^https?://\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', decoded_url):
183
- warnings.append("🚨 Nguy hiểm: Truy cập trực tiếp bằng IP")
184
  if re.search(r'\.(exe|msi|bat|js|jar|apk|dmg)(\?|$)', parsed.path.lower()):
185
- warnings.append("🚨 Nguy hiểm: URL chứa file thực thi")
186
  if 'redirect' in parsed.path.lower() or 'url=' in parsed.query.lower():
187
- warnings.append("⚠️ Cảnh báo: URL chứa chức năng redirect")
188
  if re.search(r'%[0-9a-f]{2}|[\x00-\x1f\x7f]', url):
189
- warnings.append("🚨 Nguy hiểm: URL chứa ký tự mã hóa đáng ngờ")
190
  if '@' in parsed.netloc:
191
- warnings.append("🚨 Lừa đảo: URL chứa kỹ thuật giả mạo domain")
192
- if any(keyword in parsed.netloc.lower() for keyword in ['login', 'secure', 'account', 'verify', 'update']):
193
- warnings.append("⚠️ Cảnh báo: Domain dấu hiệu giả mạo")
194
  if parsed.scheme == 'http':
195
- warnings.append("⚠️ Cảnh báo: Kết nối không mã hóa")
196
-
197
- # AI classifier (chỉ chạy nếu có cảnh báo)
198
- ai_result = None
199
- if warnings:
200
- ai_result = classifier(url, candidate_labels=["malicious", "safe"])
201
- ai_label = ai_result["labels"][0]
202
- ai_score = ai_result["scores"][0] * 100
 
 
 
203
  else:
204
- ai_label = "safe"
205
- ai_score = 90.0 # Giả định an toàn nếu không có cảnh báo
206
-
207
- return {
208
- "url": url,
209
- "decoded_url": decoded_url,
210
- "domain": parsed.netloc,
211
- "path": parsed.path,
212
- "warnings": warnings,
213
- "ai_analysis": {
214
- "label": ai_label,
215
- "confidence": ai_score
216
- }
217
- }
218
  except Exception as e:
219
- return {"error": str(e)}
220
-
221
- def check_url(url: str):
222
- # Giới hạn độ dài URL để cache hiệu quả
223
- cache_key = url[:200] if len(url) > 200 else url
224
- report = check_url_cached(cache_key)
225
-
226
- if "error" in report:
227
- return f"⚠️ Lỗi khi phân tích URL: {report['error']}"
228
-
229
- warning_text = "\n".join(f"- {w}" for w in report["warnings"]) if report["warnings"] else "- Không phát hiện cảnh báo"
230
-
231
- if report["warnings"] or report["ai_analysis"]["label"] == "malicious":
232
- return f"""🚨 URL KHÔNG AN TOÀN
233
- 🔍 Phân tích chi tiết:
234
- • URL gốc: {report['url']}
235
- • Domain: {report['domain']}
236
- • Đường dẫn: {report['path']}
237
-
238
- 📢 CẢNH BÁO:
239
- {warning_text}
240
-
241
- 🤖 Phân tích AI:
242
- - Kết quả: {report['ai_analysis']['label']}
243
- - Độ tin cậy: {report['ai_analysis']['confidence']:.2f}%
244
-
245
- 🛡️ Khuyến nghị: KHÔNG TRUY CẬP!"""
246
- else:
247
- return f"""✅ URL AN TOÀN
248
- 🔍 Phân tích chi tiết:
249
- • URL gốc: {report['url']}
250
- • Domain: {report['domain']}
251
-
252
- 🤖 Phân tích AI:
253
- - Kết quả: {report['ai_analysis']['label']}
254
- - Độ tin cậy: {report['ai_analysis']['confidence']:.2f}%"""
 
 
 
1
  from detoxify import Detoxify
2
  from transformers import (
3
  AutoProcessor, AutoModelForImageClassification,
 
9
  import re
10
  from urllib.parse import urlparse, unquote
11
 
12
+ # ==== Load models 1 lần duy nhất ====
13
+ # Text độc hại
14
+ detox_model = Detoxify('original')
15
+
16
+ # NSFW
17
+ nsfw_model_id = "Falconsai/nsfw_image_detection"
18
+ nsfw_processor = AutoProcessor.from_pretrained(nsfw_model_id)
19
+ nsfw_model = AutoModelForImageClassification.from_pretrained(nsfw_model_id)
20
+
21
+ # Bạo lực
22
+ violence_model_id = "jaranohaal/vit-base-violence-detection"
23
+ violence_processor = ViTFeatureExtractor.from_pretrained(violence_model_id)
24
+ violence_model = ViTForImageClassification.from_pretrained(violence_model_id)
25
+
26
+ # Caption ảnh
27
+ blip_processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-base")
28
+ blip_model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image-captioning-base")
29
+
30
+ # AI phân loại URL
31
+ url_classifier = pipeline("zero-shot-classification")
32
+
33
+ # ==== HÀM CHÍNH ====
34
+
35
+ def is_prompt_safe(prompt: str):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  results = detox_model.predict(prompt)
37
  threshold = 0.5
38
  flagged = {label: score for label, score in results.items() if score > threshold}
39
+ return False if flagged else True, list(flagged.keys())
 
 
 
 
 
40
 
41
+ def generate_caption(image: Image.Image):
42
+ inputs = blip_processor(images=image, return_tensors="pt")
 
 
43
  with torch.no_grad():
44
+ output = blip_model.generate(**inputs)
45
+ return blip_processor.decode(output[0], skip_special_tokens=True)
46
+
47
+ def check_nsfw_image(image: Image.Image):
48
+ inputs = nsfw_processor(images=image, return_tensors="pt")
49
  with torch.no_grad():
50
+ logits = nsfw_model(**inputs).logits
51
+ probs = torch.nn.functional.softmax(logits, dim=1)[0]
52
+ labels = list(nsfw_model.config.id2label.values())
53
+ pred_idx = probs.argmax().item()
54
+ return labels[pred_idx], probs[pred_idx].item() * 100
55
+
56
+ def check_violence_image(image: Image.Image):
57
+ inputs = violence_processor(images=image, return_tensors="pt")
 
 
58
  with torch.no_grad():
59
+ logits = violence_model(**inputs).logits
60
+ probs = torch.nn.functional.softmax(logits, dim=1)[0]
61
+ labels = ["Non-Violent", "Violent"]
62
+ pred_idx = probs.argmax().item()
63
+ return labels[pred_idx], probs[pred_idx].item() * 100
64
+
65
+ def analyze_image(image: Image.Image) -> str:
66
+ nsfw_label, nsfw_score = check_nsfw_image(image)
67
+ violence_label, violence_score = check_violence_image(image)
68
+ caption = generate_caption(image)
69
+
70
+ result = f"🖼️ tả ảnh: {caption}\n\n"
71
+
72
+ # NSFW
73
+ if nsfw_label.lower() in ["porn", "hentai", "sex", "nsfw"] and nsfw_score > 60:
74
+ result += f"🚨 NSFW: {nsfw_label} ({nsfw_score:.2f}%)\n"
 
 
 
 
 
 
 
 
 
75
  else:
76
+ result += f"✅ An toàn NSFW: {nsfw_label} ({nsfw_score:.2f}%)\n"
77
+
78
+ # Bạo lực
79
+ if violence_label == "Violent" and violence_score > 80:
80
+ result += f"🚨 Bạo lực: {violence_label} ({violence_score:.2f}%)"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  else:
82
+ result += f"✅ An toàn bạo lực: {violence_label} ({violence_score:.2f}%)"
83
+
84
+ return result
85
+
86
+ def check_url(url: str) -> str:
 
 
 
87
  try:
88
+ decoded = unquote(url)
89
+ parsed = urlparse(decoded)
90
  warnings = []
91
+
92
+ # Kiểm tra dấu hiệu đáng ngờ
93
+ if re.match(r'^https?://\d{1,3}(\.\d{1,3}){3}', decoded):
94
+ warnings.append("🚨 Truy cập IP trực tiếp")
95
  if re.search(r'\.(exe|msi|bat|js|jar|apk|dmg)(\?|$)', parsed.path.lower()):
96
+ warnings.append("🚨 URL chứa file thực thi")
97
  if 'redirect' in parsed.path.lower() or 'url=' in parsed.query.lower():
98
+ warnings.append("⚠️ Chứa chức năng chuyển hướng")
99
  if re.search(r'%[0-9a-f]{2}|[\x00-\x1f\x7f]', url):
100
+ warnings.append("🚨 t�� mã hóa bất thường")
101
  if '@' in parsed.netloc:
102
+ warnings.append("🚨 URL giả mạo domain (dùng @)")
103
+ if any(k in parsed.netloc.lower() for k in ['login', 'secure', 'account']):
104
+ warnings.append("⚠️ Domain trông giống dịch vụ đăng nhập")
105
  if parsed.scheme == 'http':
106
+ warnings.append("⚠️ Kết nối không mã hóa (HTTP)")
107
+
108
+ # Phân tích bằng AI
109
+ ai_result = url_classifier(url, candidate_labels=["malicious", "safe"])
110
+ ai_label = ai_result["labels"][0]
111
+ ai_score = ai_result["scores"][0] * 100
112
+
113
+ # Kết luận
114
+ result = f"🔗 URL: {url}\n"
115
+ if warnings or ai_label == "malicious":
116
+ result += f"🚨 KHÔNG AN TOÀN\n\n📢 Cảnh báo:\n" + "\n".join(f"- {w}" for w in warnings)
117
  else:
118
+ result += "✅ An toàn\n"
119
+
120
+ result += f"\n🤖 AI đánh giá: {ai_label} ({ai_score:.2f}%)"
121
+ return result
122
+
 
 
 
 
 
 
 
 
 
123
  except Exception as e:
124
+ return f"⚠️ Lỗi phân tích URL: {str(e)}"