SahilSingh0 commited on
Commit
a14e700
Β·
verified Β·
1 Parent(s): 869dd64

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +146 -23
app.py CHANGED
@@ -1,41 +1,164 @@
1
  import gradio as gr
2
  from transformers import pipeline
3
 
4
- # Load state-of-the-art AI text detector
5
- text_pipe = pipeline("text-classification", model="wangkevin02/AI_Detect_Model")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
  def detect_text(input_text: str):
8
- if not input_text.strip():
 
9
  return {}, "❌ Please enter some text."
10
 
11
  try:
12
- outputs = text_pipe(input_text)
13
- # Outputs look like: [{'label':'0'/'1','score':...}]
14
- label = outputs[0]["label"]
15
- score = float(outputs[0]["score"])
16
-
17
- prob = {"Human-written": 1 - score, "AI-generated": score}
18
- verdict = "πŸ€– This looks AI-generated" if label == "1" else "πŸ“ This looks Human-written"
19
- return prob, verdict
 
 
 
 
 
 
 
 
20
  except Exception as e:
21
  return {}, f"❌ Error: {str(e)}"
22
 
23
- with gr.Blocks() as demo:
24
- gr.Markdown("# AI Content Detector (Upgraded)\nFaster and more reliable detection using an advanced classifier.")
 
 
 
 
 
 
25
 
26
- with gr.Row():
27
- text_input = gr.Textbox(lines=10, placeholder="Paste text here...", label="Enter Text to Analyze")
 
 
 
 
 
 
 
 
 
 
 
28
 
29
- with gr.Row():
30
- output_probs = gr.Label(label="Probabilities")
31
- output_verdict = gr.Textbox(label="Verdict", interactive=False)
 
 
32
 
33
- with gr.Row():
34
- submit_btn = gr.Button("Check Text", variant="primary")
35
- clear_btn = gr.Button("Clear")
 
 
 
36
 
37
- submit_btn.click(detect_text, inputs=text_input, outputs=[output_probs, output_verdict])
38
- clear_btn.click(lambda: ("", {}, ""), inputs=[], outputs=[text_input, output_probs, output_verdict])
 
 
 
 
39
 
40
  if __name__ == "__main__":
41
  demo.launch()
 
1
  import gradio as gr
2
  from transformers import pipeline
3
 
4
+ # ----------------------------
5
+ # Load TEXT detector (upgradeable)
6
+ # ----------------------------
7
+ TEXT_MODEL_ID = "wangkevin02/AI_Detect_Model" # swap if you try another model
8
+
9
+ text_pipe = pipeline("text-classification", model=TEXT_MODEL_ID)
10
+
11
+ def _canonical(label: str) -> str | None:
12
+ """Map raw label names to 'AI' or 'HUMAN' when possible."""
13
+ if not label:
14
+ return None
15
+ l = label.strip().lower()
16
+ # Common explicit names
17
+ if any(k in l for k in ["ai", "machine", "generated", "fake", "synthetic", "gpt"]):
18
+ return "AI"
19
+ if any(k in l for k in ["human", "real", "authentic", "organic"]):
20
+ return "HUMAN"
21
+ # Try LABEL_X -> use id2label if present
22
+ if l.startswith("label_"):
23
+ try:
24
+ idx = int(l.split("_")[-1])
25
+ except ValueError:
26
+ return None
27
+ id2label = getattr(text_pipe.model.config, "id2label", None)
28
+ if isinstance(id2label, dict) and idx in id2label:
29
+ return _canonical(str(id2label[idx]))
30
+ # Sometimes labels are just "0"/"1"
31
+ if l in {"0", "1"}:
32
+ id2label = getattr(text_pipe.model.config, "id2label", None)
33
+ if isinstance(id2label, dict) and l.isdigit():
34
+ mapped = id2label.get(int(l))
35
+ if mapped:
36
+ return _canonical(str(mapped))
37
+ return None
38
+
39
+ def _aggregate_probs(raw_results):
40
+ """
41
+ Convert pipeline outputs into {'AI': p, 'HUMAN': p, 'raw': {...}} robustly.
42
+ Ensures both keys exist and sum <= 1.0 (may be < 1 if labels don't map).
43
+ """
44
+ # text-classification with top_k=None returns a list of dicts
45
+ # e.g. [{'label': 'AI', 'score': 0.82}, {'label': 'HUMAN', 'score': 0.18}]
46
+ if isinstance(raw_results, list) and raw_results and isinstance(raw_results[0], dict):
47
+ label_scores = {d["label"]: float(d["score"]) for d in raw_results}
48
+ elif isinstance(raw_results, list) and raw_results and isinstance(raw_results[0], list):
49
+ # return_all_scores=True style: [[{label, score}, {label, score}, ...]]
50
+ label_scores = {d["label"]: float(d["score"]) for d in raw_results[0]}
51
+ else:
52
+ label_scores = {}
53
+
54
+ ai_p = 0.0
55
+ human_p = 0.0
56
+ for lbl, sc in label_scores.items():
57
+ canon = _canonical(lbl)
58
+ if canon == "AI":
59
+ ai_p += sc
60
+ elif canon == "HUMAN":
61
+ human_p += sc
62
+
63
+ # If nothing mapped, fall back to top label heuristic
64
+ if ai_p == 0.0 and human_p == 0.0 and label_scores:
65
+ top_lbl = max(label_scores, key=label_scores.get)
66
+ top_sc = label_scores[top_lbl]
67
+ canon = _canonical(top_lbl)
68
+ if canon == "AI":
69
+ ai_p = top_sc
70
+ human_p = 1.0 - top_sc
71
+ elif canon == "HUMAN":
72
+ human_p = top_sc
73
+ ai_p = 1.0 - top_sc
74
+
75
+ return {"AI": round(ai_p, 6), "HUMAN": round(human_p, 6), "raw": label_scores}
76
+
77
+ def _verdict(ai_p: float, human_p: float, n_words: int) -> str:
78
+ conf = max(ai_p, human_p)
79
+ if n_words < 120:
80
+ band = "LOW (short text)"
81
+ elif conf < 0.60:
82
+ band = "LOW (uncertain)"
83
+ elif conf < 0.80:
84
+ band = "MEDIUM"
85
+ else:
86
+ band = "HIGH"
87
+
88
+ if ai_p > human_p:
89
+ return f"πŸ€– Likely AI β€” Confidence: {band}"
90
+ elif human_p > ai_p:
91
+ return f"πŸ“ Likely Human β€” Confidence: {band}"
92
+ else:
93
+ return "❓ Uncertain β€” Confidence: LOW"
94
 
95
  def detect_text(input_text: str):
96
+ text = (input_text or "").strip()
97
+ if not text:
98
  return {}, "❌ Please enter some text."
99
 
100
  try:
101
+ # Get ALL label scores so we can map correctly
102
+ results = text_pipe(text, top_k=None)
103
+ agg = _aggregate_probs(results)
104
+ ai_p, human_p = float(agg["AI"]), float(agg["HUMAN"])
105
+
106
+ # Normalize to show nicely, but keep raw too
107
+ probs_out = {
108
+ "AI-generated": round(ai_p, 4),
109
+ "Human-written": round(human_p, 4),
110
+ }
111
+ # Optional: include raw labels so you can debug mappings in UI
112
+ # probs_out.update({f"raw::{k}": round(v, 4) for k, v in agg["raw"].items()})
113
+
114
+ verdict = _verdict(ai_p, human_p, n_words=len(text.split()))
115
+ return probs_out, verdict
116
+
117
  except Exception as e:
118
  return {}, f"❌ Error: {str(e)}"
119
 
120
+ # ----------------------------
121
+ # (Optional) IMAGE detector β€” won't crash if model unavailable
122
+ # ----------------------------
123
+ try:
124
+ from PIL import Image
125
+ image_pipe = pipeline("image-classification", model="umm-maybe/ai-vs-human-images")
126
+ except Exception:
127
+ image_pipe = None
128
 
129
+ def detect_image(img):
130
+ if image_pipe is None:
131
+ return {}, "⚠️ Image detector not available on this Space."
132
+ try:
133
+ results = image_pipe(img)
134
+ label_scores = {d["label"]: float(d["score"]) for d in results}
135
+ best = max(label_scores, key=label_scores.get)
136
+ if any(k in best.lower() for k in ["ai", "fake", "generated", "synthetic"]):
137
+ return label_scores, "πŸ€– This image looks AI-generated"
138
+ else:
139
+ return label_scores, "πŸ“· This image looks Human/Real"
140
+ except Exception as e:
141
+ return {}, f"❌ Error: {str(e)}"
142
 
143
+ # ----------------------------
144
+ # UI
145
+ # ----------------------------
146
+ with gr.Blocks() as demo:
147
+ gr.Markdown("# πŸ” AI Content Detector\nDetect whether **text** (and optionally images) are AI-generated or human-made.")
148
 
149
+ with gr.Tab("πŸ“ Text"):
150
+ txt = gr.Textbox(label="Enter text", lines=10, placeholder="Paste text here…")
151
+ out_probs = gr.Label(label="Probabilities")
152
+ out_verdict = gr.Textbox(label="Verdict", interactive=False)
153
+ btn = gr.Button("Analyze", variant="primary")
154
+ btn.click(detect_text, inputs=txt, outputs=[out_probs, out_verdict])
155
 
156
+ with gr.Tab("πŸ“· Image"):
157
+ img_in = gr.Image(type="pil", label="Upload an image")
158
+ img_probs = gr.Label(label="Probabilities")
159
+ img_verdict = gr.Textbox(label="Verdict", interactive=False)
160
+ btn2 = gr.Button("Analyze Image")
161
+ btn2.click(detect_image, inputs=img_in, outputs=[img_probs, img_verdict])
162
 
163
  if __name__ == "__main__":
164
  demo.launch()