VictorM-Coder commited on
Commit
96c50c6
·
verified ·
1 Parent(s): 5a39ff3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -25
app.py CHANGED
@@ -13,9 +13,7 @@ MODEL_NAME = "distilgpt2"
13
  tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
14
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
15
 
16
- model = AutoModelForCausalLM.from_pretrained(
17
- MODEL_NAME
18
- ).to(device).eval()
19
 
20
 
21
  # ----------------------------------------------------
@@ -28,7 +26,7 @@ def sentence_split(text):
28
 
29
 
30
  # ----------------------------------------------------
31
- # PERPLEXITY FUNCTION (very fast on distilgpt2)
32
  # ----------------------------------------------------
33
  def perplexity(sentence):
34
  inputs = tokenizer(sentence, return_tensors="pt").to(device)
@@ -50,27 +48,31 @@ def perturb(text):
50
 
51
 
52
  # ----------------------------------------------------
53
- # DETECTGPT SCORE
54
  # ----------------------------------------------------
55
- def detectgpt_score(sentence, perturbations=5):
 
 
 
 
56
  try:
57
  base = perplexity(sentence)
58
- except:
59
- return 0
60
 
61
  pert_scores = []
62
  for _ in range(perturbations):
63
  p = perturb(sentence)
64
  try:
65
  pert_scores.append(perplexity(p))
66
- except:
67
  continue
68
 
69
  if not pert_scores:
70
- return 0
71
 
72
- # DetectGPT signal
73
- return float(np.mean(pert_scores) - base)
74
 
75
 
76
  # ----------------------------------------------------
@@ -81,19 +83,55 @@ def classify_text(text):
81
  return "⚠️ Please enter some text.", None, None
82
 
83
  sentences = sentence_split(text)
84
- results = []
85
- highlighted = []
 
 
86
  scores = []
 
87
 
 
88
  for s in sentences:
89
- score = detectgpt_score(s)
 
 
 
 
90
  scores.append(score)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
- label = "AI" if score > 0 else "Human"
 
 
 
93
 
94
- results.append([s, label, f"{abs(score):.4f}"])
 
 
 
 
 
 
 
 
95
 
96
  if label == "AI":
 
97
  highlighted.append(
98
  f"<p style='color:red;font-weight:bold'>{s}</p>"
99
  )
@@ -102,21 +140,33 @@ def classify_text(text):
102
  f"<p style='color:green;font-weight:bold'>{s}</p>"
103
  )
104
 
105
- # Document-level score (Turnitin-like scaling)
106
- avg = np.mean(scores)
107
- doc_ai = max(0, min(100, (avg + 1) * 50))
108
-
109
- df = pd.DataFrame(results, columns=["Sentence", "Label", "Score"])
 
 
 
 
 
 
 
 
 
 
 
 
110
  html = "\n".join(highlighted)
111
 
112
- return f"⚖️ Document AI Likelihood: {doc_ai:.1f}%", html, df
113
 
114
 
115
  # ----------------------------------------------------
116
  # GRADIO UI
117
  # ----------------------------------------------------
118
  with gr.Blocks() as demo:
119
- gr.Markdown("## 🧠 Writenix DetectGPT (distilgpt2 — Ultra Fast Version)")
120
 
121
  text_input = gr.Textbox(
122
  label="Enter text",
@@ -128,7 +178,7 @@ with gr.Blocks() as demo:
128
 
129
  ai_score = gr.Label(label="Overall AI Likelihood")
130
  highlighted = gr.HTML()
131
- table = gr.Dataframe(headers=["Sentence", "Label", "Score"], wrap=True)
132
 
133
  classify_btn.click(classify_text, text_input, [ai_score, highlighted, table])
134
 
 
13
  tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
14
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
15
 
16
+ model = AutoModelForCausalLM.from_pretrained(MODEL_NAME).to(device).eval()
 
 
17
 
18
 
19
  # ----------------------------------------------------
 
26
 
27
 
28
  # ----------------------------------------------------
29
+ # PERPLEXITY FUNCTION
30
  # ----------------------------------------------------
31
  def perplexity(sentence):
32
  inputs = tokenizer(sentence, return_tensors="pt").to(device)
 
48
 
49
 
50
  # ----------------------------------------------------
51
+ # BASE PERPLEXITY + DETECTGPT SCORE
52
  # ----------------------------------------------------
53
+ def detectgpt_base_and_score(sentence, perturbations=3):
54
+ """
55
+ Returns:
56
+ base_perplexity, detectgpt_score
57
+ """
58
  try:
59
  base = perplexity(sentence)
60
+ except Exception:
61
+ return None, 0.0
62
 
63
  pert_scores = []
64
  for _ in range(perturbations):
65
  p = perturb(sentence)
66
  try:
67
  pert_scores.append(perplexity(p))
68
+ except Exception:
69
  continue
70
 
71
  if not pert_scores:
72
+ return base, 0.0
73
 
74
+ score = float(np.mean(pert_scores) - base)
75
+ return base, score
76
 
77
 
78
  # ----------------------------------------------------
 
83
  return "⚠️ Please enter some text.", None, None
84
 
85
  sentences = sentence_split(text)
86
+ if not sentences:
87
+ return "⚠️ No valid sentences found.", None, None
88
+
89
+ perps = []
90
  scores = []
91
+ tmp_results = []
92
 
93
+ # 1. Compute base perplexity & DetectGPT score per sentence
94
  for s in sentences:
95
+ base_perp, score = detectgpt_base_and_score(s)
96
+ if base_perp is None:
97
+ base_perp = float("nan")
98
+
99
+ perps.append(base_perp)
100
  scores.append(score)
101
+ tmp_results.append({"sentence": s, "perp": base_perp, "score": score})
102
+
103
+ # Handle NaNs if any
104
+ perps_clean = [p for p in perps if not np.isnan(p)]
105
+ if perps_clean:
106
+ median_perp = float(np.median(perps_clean))
107
+ else:
108
+ median_perp = np.nan
109
+
110
+ # 2. Classify using calibrated rule
111
+ results = []
112
+ highlighted = []
113
+ ai_count = 0
114
+ total = len(tmp_results)
115
+
116
+ SCORE_THRESHOLD = 0.05 # Require meaningful positive signal
117
 
118
+ for item in tmp_results:
119
+ s = item["sentence"]
120
+ perp = item["perp"]
121
+ score = item["score"]
122
 
123
+ # Default label is Human
124
+ label = "Human"
125
+
126
+ # Conditions for AI-like:
127
+ # - score significantly positive
128
+ # - perplexity lower than median (more predictable)
129
+ if not np.isnan(perp) and not np.isnan(median_perp):
130
+ if (score > SCORE_THRESHOLD) and (perp < median_perp):
131
+ label = "AI"
132
 
133
  if label == "AI":
134
+ ai_count += 1
135
  highlighted.append(
136
  f"<p style='color:red;font-weight:bold'>{s}</p>"
137
  )
 
140
  f"<p style='color:green;font-weight:bold'>{s}</p>"
141
  )
142
 
143
+ results.append([
144
+ s,
145
+ label,
146
+ f"{perp:.2f}" if not np.isnan(perp) else "NaN",
147
+ f"{score:.4f}"
148
+ ])
149
+
150
+ # 3. Document-level AI percentage = fraction of AI sentences
151
+ if total > 0:
152
+ doc_ai_percent = (ai_count / total) * 100.0
153
+ else:
154
+ doc_ai_percent = 0.0
155
+
156
+ df = pd.DataFrame(
157
+ results,
158
+ columns=["Sentence", "Label", "Perplexity", "DetectGPT Score"]
159
+ )
160
  html = "\n".join(highlighted)
161
 
162
+ return f"⚖️ Document AI Likelihood (approx): {doc_ai_percent:.1f}%", html, df
163
 
164
 
165
  # ----------------------------------------------------
166
  # GRADIO UI
167
  # ----------------------------------------------------
168
  with gr.Blocks() as demo:
169
+ gr.Markdown("## 🧠 Writenix DetectGPT (Calibrated, distilgpt2)")
170
 
171
  text_input = gr.Textbox(
172
  label="Enter text",
 
178
 
179
  ai_score = gr.Label(label="Overall AI Likelihood")
180
  highlighted = gr.HTML()
181
+ table = gr.Dataframe(headers=["Sentence", "Label", "Perplexity", "DetectGPT Score"], wrap=True)
182
 
183
  classify_btn.click(classify_text, text_input, [ai_score, highlighted, table])
184