iyadalagha commited on
Commit
35534f7
·
1 Parent(s): 97c4648

handle both ar and eng

Browse files
Files changed (1) hide show
  1. app.py +64 -24
app.py CHANGED
@@ -138,13 +138,19 @@ def detect(input_text: TextInput):
138
  cleaned_text = clean_text(input_text.text, detected_lang)
139
  burstiness = calculate_burstiness(cleaned_text)
140
  ttr = calculate_ttr(cleaned_text)
141
- note_features = f"Burstiness: {burstiness:.2f} (high suggests human), TTR: {ttr:.2f} (low suggests human)"
 
 
142
 
143
  # Select appropriate models
144
  detectors = english_detectors if detected_lang == 'en' else [arabic_detector]
145
- ppl_model = ppl_english if detected_lang == 'en' else ppl_arabic
146
  is_ensemble = detected_lang == 'en'
147
 
 
 
 
 
 
148
  if len(cleaned_text) > 10000:
149
  chunks = split_text(cleaned_text, max_chars=5000)
150
  labels = []
@@ -156,29 +162,43 @@ def detect(input_text: TextInput):
156
  chunk_clf_scores = []
157
  for det_idx, detector in enumerate(detectors):
158
  clf_score = get_classifier_score(chunk, detector)
159
- label = "AI" if clf_score >= 0.99 else "Human" if clf_score < 0.60 else "Uncertain"
160
  chunk_labels.append(label)
161
  chunk_clf_scores.append(clf_score)
162
  logging.debug(f"Chunk {chunk_idx}, Model {det_idx}: Label={label}, Classifier Score={clf_score:.4f}")
163
- ppl = get_perplexity(chunk, ppl_model["tokenizer"], ppl_model["model"])
164
  chunk_final_label = Counter(chunk_labels).most_common(1)[0][0]
165
  avg_clf_score = np.mean(chunk_clf_scores)
166
 
167
- # Combine classifier, perplexity, burstiness, and TTR
 
 
 
 
 
 
 
 
168
  if chunk_final_label == "Uncertain" or len(set(chunk_labels)) == len(detectors) or any(l == "Human" for l in chunk_labels):
169
- if ppl > 60 or burstiness > 1.2 or ttr < 0.12:
170
  chunk_final_label = "Human"
171
- elif chunk_final_label == "AI" and (ppl > 60 or burstiness > 1.2 or ttr < 0.12):
172
  chunk_final_label = "Human"
 
173
  labels.append(chunk_final_label)
174
  clf_scores.append(avg_clf_score)
175
- ppls.append(ppl)
176
- logging.debug(f"Chunk {chunk_idx} Final: Label={chunk_final_label}, Avg Classifier Score={avg_clf_score:.4f}, Perplexity={ppl:.2f}, Burstiness={burstiness:.2f}, TTR={ttr:.2f}")
177
 
178
  label_counts = Counter(labels)
179
  final_label = label_counts.most_common(1)[0][0]
180
  if final_label == "Uncertain" or len(set(labels)) == len(detectors) or any(l == "Human" for l in labels):
181
- if any(ppl > 60 for ppl in ppls) or burstiness > 1.2 or ttr < 0.12:
 
 
 
 
 
182
  final_label = "Human"
183
  avg_clf_score = sum(clf_scores) / len(clf_scores) if clf_scores else 0.0
184
  avg_ppl = sum(ppls) / len(ppls) if ppls else 0.0
@@ -199,35 +219,55 @@ def detect(input_text: TextInput):
199
  labels = []
200
  for det_idx, detector in enumerate(detectors):
201
  clf_score = get_classifier_score(cleaned_text, detector)
202
- label = "AI" if clf_score >= 0.99 else "Human" if clf_score < 0.60 else "Uncertain"
203
  labels.append(label)
204
  clf_scores.append(clf_score)
205
  logging.debug(f"Model {det_idx}: Label={label}, Classifier Score={clf_score:.4f}")
206
- ppl = get_perplexity(cleaned_text, ppl_model["tokenizer"], ppl_model["model"])
207
  label_counts = Counter(labels)
208
  final_label = label_counts.most_common(1)[0][0]
 
 
 
 
 
 
 
 
 
 
 
209
  if final_label == "Uncertain" or len(set(labels)) == len(detectors) or any(l == "Human" for l in labels):
210
- if ppl > 60 or burstiness > 1.2 or ttr < 0.12:
211
  final_label = "Human"
212
- elif final_label == "AI" and (ppl > 60 or burstiness > 1.2 or ttr < 0.12):
213
  final_label = "Human"
214
- avg_clf_score = sum(clf_scores) / len(clf_scores) if clf_scores else 0.0
215
- note = f"{note_lang}. Ensemble used: {len(detectors)} models. {note_features}. Perplexity: {ppl:.2f}."
216
- if 0.60 <= avg_clf_score < 0.99:
217
  note += " Warning: Close to threshold, result may be uncertain."
218
- logging.info(f"Language: {detected_lang} | Text Length: {len(cleaned_text)} | Prediction: {final_label} | Avg Classifier Score: {avg_clf_score:.4f} | Perplexity: {ppl:.2f} | Model Scores: {clf_scores} | {note_features}")
219
  else:
220
  clf_score = get_classifier_score(cleaned_text, arabic_detector)
221
- ppl = get_perplexity(cleaned_text, ppl_model["tokenizer"], ppl_model["model"])
222
- final_label = "AI" if clf_score >= 0.97 else "Human" if clf_score < 0.60 else "Uncertain"
 
 
 
 
 
 
 
 
223
  if final_label == "Uncertain" or final_label == "Human":
224
- if ppl > 60 or burstiness > 0.8 or ttr < 0.12:
225
  final_label = "Human"
 
 
226
  avg_clf_score = clf_score
227
- note = f"{note_lang}. {note_features}. Perplexity: {ppl:.2f}."
228
- if 0.60 <= clf_score < 0.97:
229
  note += " Warning: Close to threshold, result may be uncertain."
230
- logging.info(f"Language: {detected_lang} | Text Length: {len(cleaned_text)} | Prediction: {final_label} | Classifier Score: {avg_clf_score:.4f} | Perplexity: {ppl:.2f} | {note_features}")
231
  return {
232
  "prediction": final_label,
233
  "classifier_score": round(avg_clf_score, 4),
 
138
  cleaned_text = clean_text(input_text.text, detected_lang)
139
  burstiness = calculate_burstiness(cleaned_text)
140
  ttr = calculate_ttr(cleaned_text)
141
+ ppl_model = ppl_english if detected_lang == 'en' else ppl_arabic
142
+ ppl = get_perplexity(cleaned_text, ppl_model["tokenizer"], ppl_model["model"])
143
+ note_features = f"Burstiness: {burstiness:.2f} (high suggests human), TTR: {ttr:.2f} (low suggests human), Perplexity: {ppl:.2f} (high suggests human)"
144
 
145
  # Select appropriate models
146
  detectors = english_detectors if detected_lang == 'en' else [arabic_detector]
 
147
  is_ensemble = detected_lang == 'en'
148
 
149
+ # Thresholds for human classification
150
+ ppl_threshold = 100 # Increased from 60
151
+ burstiness_threshold = 1.5 if detected_lang == 'en' else 1.0 # Increased from 1.2/0.8
152
+ ttr_threshold = 0.10 # Decreased from 0.12
153
+
154
  if len(cleaned_text) > 10000:
155
  chunks = split_text(cleaned_text, max_chars=5000)
156
  labels = []
 
162
  chunk_clf_scores = []
163
  for det_idx, detector in enumerate(detectors):
164
  clf_score = get_classifier_score(chunk, detector)
165
+ label = "AI" if clf_score >= 0.95 else "Human" if clf_score < 0.60 else "Uncertain" # Adjusted AI threshold from 0.99
166
  chunk_labels.append(label)
167
  chunk_clf_scores.append(clf_score)
168
  logging.debug(f"Chunk {chunk_idx}, Model {det_idx}: Label={label}, Classifier Score={clf_score:.4f}")
169
+ chunk_ppl = get_perplexity(chunk, ppl_model["tokenizer"], ppl_model["model"])
170
  chunk_final_label = Counter(chunk_labels).most_common(1)[0][0]
171
  avg_clf_score = np.mean(chunk_clf_scores)
172
 
173
+ # Count how many human-like features are present
174
+ human_features = sum([
175
+ chunk_ppl > ppl_threshold,
176
+ burstiness > burstiness_threshold,
177
+ ttr < ttr_threshold
178
+ ])
179
+ feature_note = f"Human-like features: {human_features}/3 (PPL={chunk_ppl:.2f}, Burstiness={burstiness:.2f}, TTR={ttr:.2f})"
180
+
181
+ # Require at least 2 features to override to Human
182
  if chunk_final_label == "Uncertain" or len(set(chunk_labels)) == len(detectors) or any(l == "Human" for l in chunk_labels):
183
+ if human_features >= 2:
184
  chunk_final_label = "Human"
185
+ elif chunk_final_label == "AI" and avg_clf_score < 0.95 and human_features >= 2:
186
  chunk_final_label = "Human"
187
+
188
  labels.append(chunk_final_label)
189
  clf_scores.append(avg_clf_score)
190
+ ppls.append(chunk_ppl)
191
+ logging.debug(f"Chunk {chunk_idx} Final: Label={chunk_final_label}, Avg Classifier Score={avg_clf_score:.4f}, Perplexity={chunk_ppl:.2f}, {feature_note}")
192
 
193
  label_counts = Counter(labels)
194
  final_label = label_counts.most_common(1)[0][0]
195
  if final_label == "Uncertain" or len(set(labels)) == len(detectors) or any(l == "Human" for l in labels):
196
+ human_features = sum([
197
+ any(ppl > ppl_threshold for ppl in ppls),
198
+ burstiness > burstiness_threshold,
199
+ ttr < ttr_threshold
200
+ ])
201
+ if human_features >= 2:
202
  final_label = "Human"
203
  avg_clf_score = sum(clf_scores) / len(clf_scores) if clf_scores else 0.0
204
  avg_ppl = sum(ppls) / len(ppls) if ppls else 0.0
 
219
  labels = []
220
  for det_idx, detector in enumerate(detectors):
221
  clf_score = get_classifier_score(cleaned_text, detector)
222
+ label = "AI" if clf_score >= 0.95 else "Human" if clf_score < 0.60 else "Uncertain" # Adjusted AI threshold from 0.99
223
  labels.append(label)
224
  clf_scores.append(clf_score)
225
  logging.debug(f"Model {det_idx}: Label={label}, Classifier Score={clf_score:.4f}")
 
226
  label_counts = Counter(labels)
227
  final_label = label_counts.most_common(1)[0][0]
228
+ avg_clf_score = sum(clf_scores) / len(clf_scores) if clf_scores else 0.0
229
+
230
+ # Count human-like features
231
+ human_features = sum([
232
+ ppl > ppl_threshold,
233
+ burstiness > burstiness_threshold,
234
+ ttr < ttr_threshold
235
+ ])
236
+ feature_note = f"Human-like features: {human_features}/3 (PPL={ppl:.2f}, Burstiness={burstiness:.2f}, TTR={ttr:.2f})"
237
+
238
+ # Require at least 2 features to override to Human
239
  if final_label == "Uncertain" or len(set(labels)) == len(detectors) or any(l == "Human" for l in labels):
240
+ if human_features >= 2:
241
  final_label = "Human"
242
+ elif final_label == "AI" and avg_clf_score < 0.95 and human_features >= 2:
243
  final_label = "Human"
244
+
245
+ note = f"{note_lang}. Ensemble used: {len(detectors)} models. {note_features}. {feature_note}."
246
+ if 0.60 <= avg_clf_score < 0.95:
247
  note += " Warning: Close to threshold, result may be uncertain."
248
+ logging.info(f"Language: {detected_lang} | Text Length: {len(cleaned_text)} | Prediction: {final_label} | Avg Classifier Score: {avg_clf_score:.4f} | Perplexity: {ppl:.2f} | {note_features} | {feature_note}")
249
  else:
250
  clf_score = get_classifier_score(cleaned_text, arabic_detector)
251
+ final_label = "AI" if clf_score >= 0.95 else "Human" if clf_score < 0.60 else "Uncertain" # Adjusted AI threshold from 0.97
252
+ # Count human-like features
253
+ human_features = sum([
254
+ ppl > ppl_threshold,
255
+ burstiness > burstiness_threshold,
256
+ ttr < ttr_threshold
257
+ ])
258
+ feature_note = f"Human-like features: {human_features}/3 (PPL={ppl:.2f}, Burstiness={burstiness:.2f}, TTR={ttr:.2f})"
259
+
260
+ # Require at least 2 features to override to Human
261
  if final_label == "Uncertain" or final_label == "Human":
262
+ if human_features >= 2:
263
  final_label = "Human"
264
+ elif final_label == "AI" and clf_score < 0.95 and human_features >= 2:
265
+ final_label = "Human"
266
  avg_clf_score = clf_score
267
+ note = f"{note_lang}. {note_features}. {feature_note}."
268
+ if 0.60 <= clf_score < 0.95:
269
  note += " Warning: Close to threshold, result may be uncertain."
270
+ logging.info(f"Language: {detected_lang} | Text Length: {len(cleaned_text)} | Prediction: {final_label} | Classifier Score: {avg_clf_score:.4f} | Perplexity: {ppl:.2f} | {note_features} | {feature_note}")
271
  return {
272
  "prediction": final_label,
273
  "classifier_score": round(avg_clf_score, 4),