Spaces:
Sleeping
Sleeping
Commit
·
35534f7
1
Parent(s):
97c4648
handle both ar and eng
Browse files
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 |
-
|
|
|
|
|
|
|
| 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.
|
| 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 |
-
|
| 164 |
chunk_final_label = Counter(chunk_labels).most_common(1)[0][0]
|
| 165 |
avg_clf_score = np.mean(chunk_clf_scores)
|
| 166 |
|
| 167 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
if chunk_final_label == "Uncertain" or len(set(chunk_labels)) == len(detectors) or any(l == "Human" for l in chunk_labels):
|
| 169 |
-
if
|
| 170 |
chunk_final_label = "Human"
|
| 171 |
-
elif chunk_final_label == "AI" and
|
| 172 |
chunk_final_label = "Human"
|
|
|
|
| 173 |
labels.append(chunk_final_label)
|
| 174 |
clf_scores.append(avg_clf_score)
|
| 175 |
-
ppls.append(
|
| 176 |
-
logging.debug(f"Chunk {chunk_idx} Final: Label={chunk_final_label}, Avg Classifier Score={avg_clf_score:.4f}, Perplexity={
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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.
|
| 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
|
| 211 |
final_label = "Human"
|
| 212 |
-
elif final_label == "AI" and
|
| 213 |
final_label = "Human"
|
| 214 |
-
|
| 215 |
-
note = f"{note_lang}. Ensemble used: {len(detectors)} models. {note_features}.
|
| 216 |
-
if 0.60 <= avg_clf_score < 0.
|
| 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} |
|
| 219 |
else:
|
| 220 |
clf_score = get_classifier_score(cleaned_text, arabic_detector)
|
| 221 |
-
|
| 222 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
if final_label == "Uncertain" or final_label == "Human":
|
| 224 |
-
if
|
| 225 |
final_label = "Human"
|
|
|
|
|
|
|
| 226 |
avg_clf_score = clf_score
|
| 227 |
-
note = f"{note_lang}. {note_features}.
|
| 228 |
-
if 0.60 <= clf_score < 0.
|
| 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),
|