Savizzz-35 commited on
Commit
1cfeeda
·
verified ·
1 Parent(s): a83948f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -95
app.py CHANGED
@@ -2,17 +2,21 @@ import gradio as gr
2
  import numpy as np
3
  import tensorflow as tf
4
  import joblib
5
- import requests
6
  import os
7
 
 
8
  from tensorflow.keras.preprocessing.sequence import pad_sequences
9
  from tensorflow.keras.layers import Layer
 
 
10
 
11
  print("Loading models...")
12
 
13
- ############################################
 
14
  # Custom Attention Layer
15
- ############################################
16
 
17
  class AttentionLayer(Layer):
18
 
@@ -37,15 +41,20 @@ class AttentionLayer(Layer):
37
  return context
38
 
39
 
40
- ############################################
41
- # Load Models
42
- ############################################
43
 
44
  vectorizer = joblib.load("models/tfidf_vectorizer.pkl")
45
 
46
  lr_model = joblib.load("models/logistic_model.pkl")
47
  rf_model = joblib.load("models/random_forest_model.pkl")
48
 
 
 
 
 
 
49
  tokenizer = joblib.load("models/tokenizer.pkl")
50
 
51
  lstm_model = tf.keras.models.load_model(
@@ -57,28 +66,32 @@ bilstm_model = tf.keras.models.load_model(
57
  custom_objects={"AttentionLayer": AttentionLayer}
58
  )
59
 
60
- print("All models loaded successfully")
61
 
 
 
 
62
 
63
- ############################################
64
- # HuggingFace DistilBERT Setup
65
- ############################################
66
 
67
- BERT_API = "https://router.huggingface.co/hf-inference/pipeline/text-classification/Savizzz-35/phishguard-distilbert"
 
 
 
 
 
 
68
 
69
- HF_TOKEN = os.getenv("HF_TOKEN")
70
 
71
- print("HF TOKEN LOADED:", HF_TOKEN is not None)
72
 
73
- headers = {
74
- "Authorization": f"Bearer {HF_TOKEN}",
75
- "Content-Type": "application/json"
76
- }
77
 
78
 
79
- ############################################
80
- # Feature Fix for sklearn models
81
- ############################################
82
 
83
  def adjust_features(vec, model):
84
 
@@ -97,9 +110,9 @@ def adjust_features(vec, model):
97
  return vec
98
 
99
 
100
- ############################################
101
  # Individual Model Predictions
102
- ############################################
103
 
104
  def lr_predict(text):
105
 
@@ -141,64 +154,29 @@ def bilstm_predict(text):
141
  return float(prob)
142
 
143
 
144
- ############################################
145
- # DEBUG DISTILBERT
146
- ############################################
147
-
148
  def bert_predict(text):
149
 
150
- payload = {
151
- "inputs": text
152
- }
153
-
154
- print("\n============================")
155
- print("BERT DEBUG START")
156
- print("Payload:", payload)
157
-
158
- try:
159
-
160
- r = requests.post(
161
- BERT_API,
162
- headers=headers,
163
- json=payload,
164
- timeout=30
165
- )
166
-
167
- print("HTTP STATUS:", r.status_code)
168
- print("RAW RESPONSE:", r.text)
169
-
170
- result = r.json()
171
-
172
- print("JSON RESPONSE:", result)
173
-
174
- if isinstance(result, list):
175
-
176
- if len(result) > 0 and isinstance(result[0], list):
177
- result = result[0]
178
-
179
- for item in result:
180
-
181
- if item["label"] == "phishing_email":
182
-
183
- score = float(item["score"])
184
- print("BERT SCORE:", score)
185
- print("============================\n")
186
-
187
- return score
188
 
189
- except Exception as e:
190
 
191
- print("BERT EXCEPTION:", str(e))
 
192
 
193
- print("BERT FAILED → returning fallback 0.5")
194
- print("============================\n")
195
 
196
- return 0.5
197
 
198
 
199
- ############################################
200
- # Ensemble
201
- ############################################
202
 
203
  WEIGHTS = {
204
  "lr": 0.25,
@@ -209,20 +187,31 @@ WEIGHTS = {
209
  }
210
 
211
 
 
 
 
 
212
  def predict_email(text):
213
 
214
- lr = lr_predict(text)
215
- rf = rf_predict(text)
216
- lstm = lstm_predict(text)
217
- bilstm = bilstm_predict(text)
218
- bert = bert_predict(text)
 
 
 
 
 
 
 
219
 
220
  final_score = (
221
- lr * WEIGHTS["lr"]
222
- + rf * WEIGHTS["rf"]
223
- + lstm * WEIGHTS["lstm"]
224
- + bilstm * WEIGHTS["bilstm"]
225
- + bert * WEIGHTS["bert"]
226
  )
227
 
228
  if final_score < 0.5:
@@ -235,19 +224,13 @@ def predict_email(text):
235
  return {
236
  "phishing_probability": float(final_score),
237
  "risk_level": risk,
238
- "model_outputs": {
239
- "lr": lr,
240
- "rf": rf,
241
- "lstm": lstm,
242
- "bilstm": bilstm,
243
- "bert": bert
244
- }
245
  }
246
 
247
 
248
- ############################################
249
- # API Wrapper
250
- ############################################
251
 
252
  def run_detection(text):
253
 
@@ -260,9 +243,9 @@ def run_detection(text):
260
  return {"error": str(e)}
261
 
262
 
263
- ############################################
264
- # Gradio UI
265
- ############################################
266
 
267
  iface = gr.Interface(
268
  fn=run_detection,
 
2
  import numpy as np
3
  import tensorflow as tf
4
  import joblib
5
+ import torch
6
  import os
7
 
8
+ from concurrent.futures import ThreadPoolExecutor
9
  from tensorflow.keras.preprocessing.sequence import pad_sequences
10
  from tensorflow.keras.layers import Layer
11
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
12
+
13
 
14
  print("Loading models...")
15
 
16
+
17
+ ########################################
18
  # Custom Attention Layer
19
+ ########################################
20
 
21
  class AttentionLayer(Layer):
22
 
 
41
  return context
42
 
43
 
44
+ ########################################
45
+ # Load Classical ML Models
46
+ ########################################
47
 
48
  vectorizer = joblib.load("models/tfidf_vectorizer.pkl")
49
 
50
  lr_model = joblib.load("models/logistic_model.pkl")
51
  rf_model = joblib.load("models/random_forest_model.pkl")
52
 
53
+
54
+ ########################################
55
+ # Load Tokenizer + Neural Models
56
+ ########################################
57
+
58
  tokenizer = joblib.load("models/tokenizer.pkl")
59
 
60
  lstm_model = tf.keras.models.load_model(
 
66
  custom_objects={"AttentionLayer": AttentionLayer}
67
  )
68
 
 
69
 
70
+ ########################################
71
+ # Load DistilBERT
72
+ ########################################
73
 
74
+ print("Loading DistilBERT...")
 
 
75
 
76
+ bert_tokenizer = AutoTokenizer.from_pretrained(
77
+ "Savizzz-35/phishguard-distilbert"
78
+ )
79
+
80
+ bert_model = AutoModelForSequenceClassification.from_pretrained(
81
+ "Savizzz-35/phishguard-distilbert"
82
+ )
83
 
84
+ bert_model.eval()
85
 
86
+ print("DistilBERT loaded")
87
 
88
+
89
+ print("All models loaded successfully")
 
 
90
 
91
 
92
+ ########################################
93
+ # Fix feature mismatch (sklearn)
94
+ ########################################
95
 
96
  def adjust_features(vec, model):
97
 
 
110
  return vec
111
 
112
 
113
+ ########################################
114
  # Individual Model Predictions
115
+ ########################################
116
 
117
  def lr_predict(text):
118
 
 
154
  return float(prob)
155
 
156
 
 
 
 
 
157
  def bert_predict(text):
158
 
159
+ inputs = bert_tokenizer(
160
+ text,
161
+ return_tensors="pt",
162
+ truncation=True,
163
+ padding=True,
164
+ max_length=512
165
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
 
167
+ with torch.no_grad():
168
 
169
+ outputs = bert_model(**inputs)
170
+ probs = torch.softmax(outputs.logits, dim=1)
171
 
172
+ phishing_prob = probs[0][1].item()
 
173
 
174
+ return float(phishing_prob)
175
 
176
 
177
+ ########################################
178
+ # Ensemble Weights
179
+ ########################################
180
 
181
  WEIGHTS = {
182
  "lr": 0.25,
 
187
  }
188
 
189
 
190
+ ########################################
191
+ # Parallel Prediction
192
+ ########################################
193
+
194
  def predict_email(text):
195
 
196
+ with ThreadPoolExecutor() as executor:
197
+
198
+ futures = {
199
+
200
+ "lr": executor.submit(lr_predict, text),
201
+ "rf": executor.submit(rf_predict, text),
202
+ "lstm": executor.submit(lstm_predict, text),
203
+ "bilstm": executor.submit(bilstm_predict, text),
204
+ "bert": executor.submit(bert_predict, text)
205
+ }
206
+
207
+ results = {name: f.result() for name, f in futures.items()}
208
 
209
  final_score = (
210
+ results["lr"] * WEIGHTS["lr"]
211
+ + results["rf"] * WEIGHTS["rf"]
212
+ + results["lstm"] * WEIGHTS["lstm"]
213
+ + results["bilstm"] * WEIGHTS["bilstm"]
214
+ + results["bert"] * WEIGHTS["bert"]
215
  )
216
 
217
  if final_score < 0.5:
 
224
  return {
225
  "phishing_probability": float(final_score),
226
  "risk_level": risk,
227
+ "model_outputs": results
 
 
 
 
 
 
228
  }
229
 
230
 
231
+ ########################################
232
+ # API wrapper
233
+ ########################################
234
 
235
  def run_detection(text):
236
 
 
243
  return {"error": str(e)}
244
 
245
 
246
+ ########################################
247
+ # Gradio Interface
248
+ ########################################
249
 
250
  iface = gr.Interface(
251
  fn=run_detection,