Ken2707 commited on
Commit
88a43dc
·
verified ·
1 Parent(s): 2989306

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -42
app.py CHANGED
@@ -16,8 +16,8 @@ os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
16
  from tensorflow.keras.models import load_model
17
  from tensorflow.keras.preprocessing.sequence import pad_sequences
18
 
19
- nltk.download('punkt')
20
- nltk.download('stopwords')
21
 
22
  app = FastAPI()
23
 
@@ -75,11 +75,12 @@ def preprocessing(statement):
75
  tokens = [token for token in tokens if token.isalpha() and len(token) > 2]
76
  return ' '.join(tokens)
77
 
78
- def analyze_text(text: str, mode: str, model_type: str):
 
79
  if mode not in ["fake_review", "spam"]: return {"error": "Mode invalid."}
80
-
81
- clean_text = preprocessing(text)
82
- score = 0.0
83
 
84
  if model_type == "lstm":
85
  tokenizer = models_dict[mode]["tokenizer"]
@@ -88,10 +89,11 @@ def analyze_text(text: str, mode: str, model_type: str):
88
  if not tokenizer or not lstm_model:
89
  return {"error": f"File model LSTM untuk {mode} tidak ditemukan."}
90
 
91
- seq = tokenizer.texts_to_sequences([clean_text])
92
- padded = pad_sequences(seq, maxlen=100, padding='post', truncating='post')
93
- prediction = lstm_model.predict(padded, verbose=0)[0][0]
94
- score = float(prediction) * 100
 
95
 
96
  elif model_type in ["lr", "rf", "xgb"]:
97
  tfidf = models_dict[mode]["tfidf"]
@@ -100,30 +102,34 @@ def analyze_text(text: str, mode: str, model_type: str):
100
  if not tfidf or not clf_model:
101
  return {"error": f"File model {model_type} untuk {mode} tidak ditemukan."}
102
 
103
- vec_text = tfidf.transform([clean_text])
104
- proba = clf_model.predict_proba(vec_text)[0]
105
- score = float(proba[1]) * 100
106
-
107
  else:
108
  return {"error": "Model type tidak dikenali."}
109
 
110
- is_flagged = score > 50
111
- confidence = score if is_flagged else 100 - score
112
-
113
- if mode == "spam":
114
- label = "Spam" if is_flagged else "Safe (Ham)"
115
- reason = "The text contains word order patterns similar to those found in promotional messages or scams." if is_flagged else "The sentence appears similar to ordinary conversational message."
116
- else:
117
- label = "Fake" if is_flagged else "Genuine"
118
- reason = "The writing style bears a strong resemblance to paid review templates or no clear context." if is_flagged else "The review has a natural variety of vocabulary and recounts the experience in detail."
119
 
120
- return {
121
- "text": text,
122
- "label": label,
123
- "confidence": confidence,
124
- "is_flagged": is_flagged,
125
- "reason": reason
126
- }
 
 
 
 
 
 
 
 
 
127
 
128
  class TextRequest(BaseModel):
129
  text: str
@@ -136,10 +142,11 @@ class TextRequest(BaseModel):
136
 
137
  @app.post("/api/analyze/text")
138
  def analyze_single(req: TextRequest):
139
- result = analyze_text(req.text, req.mode, req.model_type)
140
- if "error" in result:
 
141
  raise HTTPException(status_code=500, detail=result["error"])
142
- return {"status": "success", "result": result}
143
 
144
  @app.post("/api/analyze/file")
145
  async def analyze_file(mode: str = Form(...), model_type: str = Form(...), file: UploadFile = File(...)):
@@ -148,20 +155,19 @@ async def analyze_file(mode: str = Form(...), model_type: str = Form(...), file:
148
 
149
  content = await file.read()
150
  decoded = content.decode('utf-8')
151
- results = []
152
 
153
  if file.filename.endswith('.txt'):
154
- lines = [line.strip() for line in decoded.split('\n') if line.strip()]
155
- for line in lines:
156
- res = analyze_text(line, mode, model_type)
157
- if "error" not in res: results.append(res)
158
 
159
  elif file.filename.endswith('.csv'):
160
  df = pd.read_csv(StringIO(decoded))
161
  text_col = next((col for col in ['text', 'review', 'v2', 'text_'] if col in df.columns), df.columns[0])
 
162
 
163
- for text in df[text_col].dropna().astype(str):
164
- res = analyze_text(text, mode, model_type)
165
- if "error" not in res: results.append(res)
166
-
 
167
  return {"status": "success", "total": len(results), "results": results}
 
16
  from tensorflow.keras.models import load_model
17
  from tensorflow.keras.preprocessing.sequence import pad_sequences
18
 
19
+ nltk.download('punkt', quiet=True)
20
+ nltk.download('stopwords', quiet=True)
21
 
22
  app = FastAPI()
23
 
 
75
  tokens = [token for token in tokens if token.isalpha() and len(token) > 2]
76
  return ' '.join(tokens)
77
 
78
+ # FUNGSI BARU: Menganalisis banyak teks sekaligus (Batch Processing)
79
+ def analyze_bulk(texts: list, mode: str, model_type: str):
80
  if mode not in ["fake_review", "spam"]: return {"error": "Mode invalid."}
81
+ if not texts: return []
82
+
83
+ clean_texts = [preprocessing(t) for t in texts]
84
 
85
  if model_type == "lstm":
86
  tokenizer = models_dict[mode]["tokenizer"]
 
89
  if not tokenizer or not lstm_model:
90
  return {"error": f"File model LSTM untuk {mode} tidak ditemukan."}
91
 
92
+ seqs = tokenizer.texts_to_sequences(clean_texts)
93
+ padded = pad_sequences(seqs, maxlen=100, padding='post', truncating='post')
94
+ # Prediksi sekaligus dalam satu tarikan
95
+ predictions = lstm_model.predict(padded, batch_size=32, verbose=0).flatten()
96
+ scores = [float(p) * 100 for p in predictions]
97
 
98
  elif model_type in ["lr", "rf", "xgb"]:
99
  tfidf = models_dict[mode]["tfidf"]
 
102
  if not tfidf or not clf_model:
103
  return {"error": f"File model {model_type} untuk {mode} tidak ditemukan."}
104
 
105
+ vec_texts = tfidf.transform(clean_texts)
106
+ # Prediksi sekaligus dalam satu tarikan
107
+ probas = clf_model.predict_proba(vec_texts)
108
+ scores = [float(p[1]) * 100 for p in probas]
109
  else:
110
  return {"error": "Model type tidak dikenali."}
111
 
112
+ results = []
113
+ for text, score in zip(texts, scores):
114
+ is_flagged = score > 50
115
+ confidence = score if is_flagged else 100 - score
 
 
 
 
 
116
 
117
+ if mode == "spam":
118
+ label = "Spam" if is_flagged else "Safe (Ham)"
119
+ reason = "The text contains word order patterns similar to those found in promotional messages or scams." if is_flagged else "The sentence appears similar to ordinary conversational message."
120
+ else:
121
+ label = "Fake" if is_flagged else "Genuine"
122
+ reason = "The writing style bears a strong resemblance to paid review templates or no clear context." if is_flagged else "The review has a natural variety of vocabulary and recounts the experience in detail."
123
+
124
+ results.append({
125
+ "text": text,
126
+ "label": label,
127
+ "confidence": confidence,
128
+ "is_flagged": is_flagged,
129
+ "reason": reason
130
+ })
131
+
132
+ return results
133
 
134
  class TextRequest(BaseModel):
135
  text: str
 
142
 
143
  @app.post("/api/analyze/text")
144
  def analyze_single(req: TextRequest):
145
+ # Memanfaatkan fungsi bulk untuk 1 teks
146
+ result = analyze_bulk([req.text], req.mode, req.model_type)
147
+ if isinstance(result, dict) and "error" in result:
148
  raise HTTPException(status_code=500, detail=result["error"])
149
+ return {"status": "success", "result": result[0]}
150
 
151
  @app.post("/api/analyze/file")
152
  async def analyze_file(mode: str = Form(...), model_type: str = Form(...), file: UploadFile = File(...)):
 
155
 
156
  content = await file.read()
157
  decoded = content.decode('utf-8')
158
+ texts = []
159
 
160
  if file.filename.endswith('.txt'):
161
+ texts = [line.strip() for line in decoded.split('\n') if line.strip()]
 
 
 
162
 
163
  elif file.filename.endswith('.csv'):
164
  df = pd.read_csv(StringIO(decoded))
165
  text_col = next((col for col in ['text', 'review', 'v2', 'text_'] if col in df.columns), df.columns[0])
166
+ texts = df[text_col].dropna().astype(str).tolist()
167
 
168
+ # Seluruh teks dikirim langsung ke fungsi bulk
169
+ results = analyze_bulk(texts, mode, model_type)
170
+ if isinstance(results, dict) and "error" in results:
171
+ raise HTTPException(status_code=500, detail=results["error"])
172
+
173
  return {"status": "success", "total": len(results), "results": results}