"""Gradio app for the PIRD AI-text detector (Hugging Face Spaces). Expects the trained checkpoint in ./pird_deploy (pird.pt + config.json) and the `pird/` package present in the Space. Runs on CPU (free Spaces tier) — RoBERTa inference on one text is ~1-2s. """ import os from pird.detectors.pird import PIRDDetector CKPT = os.environ.get("PIRD_CKPT", "pird_deploy") detector = PIRDDetector(CKPT) def classify(text: str): text = (text or "").strip() n_words = len(text.split()) if n_words < 20: return ({"enter ≥ 20 words": 1.0}, "Please paste at least ~20 words for a reliable estimate.") p = float(detector.predict_proba([text])[0]) label = {"AI-generated": p, "Human-written": 1.0 - p} verdict = (f"P(AI-generated) = {p*100:.1f}% " f"— {'likely AI' if p >= 0.5 else 'likely human'} " f"(calibrated; {n_words} words)") return label, verdict import gradio as gr DESCRIPTION = ( "**PIRD** is a paraphrase-robust, cross-domain detector for AI-generated text. Unlike " "perplexity-based detectors, it stays reliable when AI text is paraphrased to evade detection. " "Paste a passage (≥ 20 words) to get a calibrated probability that it was AI-generated.\n\n" "_Research demo — predictions are probabilistic and not infallible; do not use as sole " "evidence of misconduct._" ) EXAMPLES = [ ["The proposed framework leverages a robust architecture to efficiently process large-scale data, " "demonstrating significant improvements across all evaluated benchmarks and establishing a new " "state of the art for the task under consideration."], ["honestly i wasn't sure the trip was gonna happen at all — the flight got delayed twice, my bag " "nearly didn't make it, and then it rained the whole first day. but somehow it turned out great."], ] demo = gr.Interface( fn=classify, inputs=gr.Textbox(lines=12, label="Paste text", placeholder="Paste a passage (≥ 20 words)..."), outputs=[gr.Label(num_top_classes=2, label="Prediction"), gr.Textbox(label="Calibrated probability")], title="PIRD — Paraphrase-Robust AI-Text Detector", description=DESCRIPTION, examples=EXAMPLES, flagging_mode="never", # Gradio 5/6 renamed allow_flagging -> flagging_mode ) if __name__ == "__main__": demo.launch()