Skip to content

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Omini-Text: Unified AI Text Detection

Python 3.10+ License: MIT

A unified interface for 9 state-of-the-art AI text detection methods, spanning zero-shot, supervised, and boundary detection approaches. Part of the Omini-Detect project.

Quick Start

from omini_text import pipeline

pipe = pipeline("ai-text-detection", model="e5-small")
result = pipe("Your text here")

print(result)
# {'text': '...', 'label': 1, 'score': 0.87, 'metadata': {'num_tokens': 45}}

Output format:

  • label: 0 = human, 1 = AI-generated
  • score: Probability (0.0–1.0)
  • metadata: Detection details (tokens, model info)

Installation

Using uv (Recommended)

uv is the fastest Python package manager (~10-100x faster than pip).

# Install uv (if not installed)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Clone and setup
git clone https://github.com/your-org/Omini-Text.git
cd Omini-Text
uv venv                              # Create virtual environment
uv pip sync requirements.lock        # Install locked dependencies (reproducible)
source .venv/bin/activate            # Activate

Using pip

git clone https://github.com/your-org/Omini-Text.git
cd Omini-Text
pip install -r requirements.txt

For Glimpse detector, set your OpenAI API key in .env (see .env.example).

Available Detectors

Detector Type Venue Key Feature Hardware Pretrained
e5-small Supervised MS Hackathon '24 93.9% RAID accuracy CPU/GPU ✅
RADAR Supervised NeurIPS 2023 Adversarial robustness CPU/GPU ✅
Desklib Supervised - Simple baseline CPU/GPU ✅
Fast-DetectGPT Zero-shot ICLR 2024 340× faster than DetectGPT GPU (6-16GB) ✅
Binoculars Zero-shot ICML 2024 Perplexity ratio analysis GPU (~14GB) ✅
Glimpse Zero-shot ICLR 2025 Detects GPT-4/Claude/Gemini CPU + API ✅
GigaCheck Boundary arXiv 2024 AI text interval detection (official) GPU (~14GB) ✅
SeqXGPT Boundary EMNLP 2023 Sentence-level BIOES (reproduction) GPU (~28GB) ✅*
RoFT Boundary arXiv 2023 Training-free NLL boundary GPU (~1-2GB) ✅

*SeqXGPT requires training but we provide pretrained checkpoint at zcahjl3/seqxgpt-detector

Supervised Methods (trained on AI text)

e5-small LoRA

[Model]

Microsoft Hackathon 2024 winner. Fine-tuned e5-small with LoRA achieving 93.9% accuracy on RAID benchmark, with strong robustness against adversarial attacks (85.7%).

pipe = pipeline("ai-text-detection", model="e5-small")

RADAR

[Paper] [Code]

NeurIPS 2023. Robust AI-Text Detector via Adversarial LeaRning. Uses RoBERTa-large trained with paraphrase-based adversarial learning for improved robustness against text modifications.

pipe = pipeline("ai-text-detection", model="radar")

Desklib

[Model]

Simple transformer classifier with mean pooling. Good baseline for experiments and easy to fine-tune on custom data.

pipe = pipeline("ai-text-detection", model="desklib")

Zero-Shot Methods (no training needed)

Fast-DetectGPT

[Paper] [Code]

ICLR 2024. Uses conditional probability curvature for detection. 340× faster than original DetectGPT with better accuracy.

pipe = pipeline("ai-text-detection", model="fast-detectgpt")

Binoculars

[Paper] [Code]

ICML 2024. Analyzes perplexity ratio between observer (base) and performer (instruction-tuned) LLM pairs. Pre-calibrated thresholds for low FPR or balanced accuracy.

pipe = pipeline("ai-text-detection", model="binoculars")

Glimpse

[Paper] [Code]

ICLR 2025. Bridges white-box detection with proprietary LLMs (GPT-4, Claude, Gemini) via probability distribution estimation. Runs on CPU but incurs API costs (~$0.001/text).

pipe = pipeline("ai-text-detection", model="glimpse")

Boundary Detection (character-level segmentation)

These methods detect where AI-generated content appears within a document, returning character-level intervals.

Input: Plain text string (or list for batch processing) Output: ai_intervals with [start_char, end_char] positions

GigaCheck

[Paper] [Code] [Model]

arXiv 2024. Mistral-7B + DETR for detecting AI-written character intervals in mixed human/AI text. Uses official pretrained weights from HuggingFace - no training required.

~14GB VRAM | Pretrained

pipe = pipeline("ai-text-detection", model="gigacheck", device="cuda:0")

text = "I went to the coffee shop yesterday. The implementation of transformer architectures revolutionized NLP."
result = pipe(text)

print(result["label"])                    # 1 (AI detected)
print(result["score"])                    # 0.68 (AI content ratio)
print(result["metadata"]["pred_label"])   # "mixed"
print(result["metadata"]["ai_intervals"]) # [[65, 203]] - character positions
# Extract AI-generated portion:
for start, end in result["metadata"]["ai_intervals"]:
    print(f"AI text: {text[start:end]}")

SeqXGPT

[Paper] [Code] [Checkpoint]

EMNLP 2023. Sentence-level AI text detection using log-probability features from 4 LLMs (GPT-2, GPT-Neo-1.3B, GPT-J-6B, LLaMA-7B). Uses BIOES sequence labeling with 6-class source attribution. We provide pretrained checkpoint.

~28GB VRAM (4 models, distribute with feature_devices)

pipe = pipeline(
    "ai-text-detection",
    model="seqxgpt",
    device="cuda:0",
    feature_devices=['cuda:0', 'cuda:1', 'cuda:2', 'cuda:3']  # Distribute 4 models
)

text = "I went to the coffee shop. The transformer architecture enables parallel computation."
result = pipe(text)

print(result["label"])                         # 0 or 1
print(result["metadata"]["pred_label"])        # "human", "ai", or "mixed"
print(result["metadata"]["ai_intervals"])      # [[start, end], ...] character positions
print(result["metadata"]["words"][:5])         # ['I', 'went', 'to', 'the', 'coffee']
print(result["metadata"]["word_predictions"][:5])  # ['B-human', 'M-human', ...]

RoFT Boundary

[Paper] [Code]

arXiv 2023. Training-free boundary detection using perplexity (NLL) patterns. Detects the transition point where human text ends and AI-generated text begins. No pretrained weights required - uses off-the-shelf LMs (GPT-2).

~1-2GB VRAM | Training-free | Detects single human→AI transition

pipe = pipeline("ai-text-detection", model="roft-boundary", device="cuda:0")

# Use _SEP_ to mark sentence boundaries (optional - auto-splits on .!?)
text = "I went to the coffee shop._SEP_The transformer architecture enables parallel computation._SEP_Machine learning is powerful."
result = pipe(text)

print(result["label"])                         # 1 (AI detected)
print(result["score"])                         # 0.34 (AI content ratio)
print(result["metadata"]["boundary_index"])    # 2 (AI starts at sentence 2)
print(result["metadata"]["ai_intervals"])      # [[113, 172]] character positions
print(result["metadata"]["sentence_nlls"])     # [3.90, 7.20, 4.68] NLL per sentence

Boundary Detection Output Format

All three boundary detectors return character-level AI intervals in a unified format:

{
    "text": str,           # Input text
    "label": int,          # 0=human, 1=AI (binary: any AI content)
    "score": float,        # AI content coverage ratio (0.0-1.0)
    "metadata": {
        "pred_label": str,              # "human", "ai", or "mixed"
        "ai_intervals": [[start, end], ...],  # Character positions of AI-written spans
        # GigaCheck-specific:
        "classification_head_probs": [float, ...],  # Class probabilities
        # SeqXGPT-specific:
        "predictions": [str, ...],      # Per-word BIOES labels (6-class source attribution)
        "words": [str, ...],            # Tokenized words
        "word_positions": [(int, int), ...]  # Word char positions
        # RoFT-specific:
        "boundary_index": int,          # Sentence index where AI starts
        "boundary_char_pos": int,       # Character position of boundary
        "sentence_nlls": [float, ...]   # NLL per sentence (for debugging)
    }
}

Converting Intervals to Word Labels:

GigaCheck can convert its character intervals to word-level labels for comparison with SeqXGPT:

from omini_text.detectors import GigacheckDetector

detector = GigacheckDetector({"device": "cuda:0"})
result = detector.detect_with_word_labels("Human intro. AI generated text.")
# result["word_labels"] = ['human', 'human', 'ai', 'ai', 'ai']
# result["words"] = ['Human', 'intro.', 'AI', 'generated', 'text.']
Feature GigaCheck SeqXGPT RoFT
Output Character intervals Word BIOES + char intervals Sentence boundary + char intervals
Source Attribution No (ai/human) Yes (gpt2, gptneo, gptj, llama, gpt3re, human) No
Multi-boundary Yes Yes No (single human→AI transition)
Training Required No (pretrained) Yes (checkpoint provided) No (training-free)
VRAM ~14GB ~28GB (4 models) ~1-2GB
Speed ~2-5s/text ~2-5s/text ~0.5-2s/text

Usage Examples

Batch Processing

texts = ["First text...", "Second text...", "Third text..."]
results = pipe(texts)

for r in results:
    label = "AI" if r["label"] == 1 else "Human"
    print(f"{r['text'][:40]}... → {label} ({r['score']:.1%})")

Config-Based Detection

from omini_text import get_pipeline_from_cfg

pipe = get_pipeline_from_cfg("configs/my_config.yaml")
result = pipe("Text to analyze")

See examples/ for more usage patterns.

Evaluation

Run detectors on evaluation datasets and generate accuracy reports:

cd evaluate

# Run all detectors on all datasets
python run_profile.py

# Run specific detectors on specific datasets
python run_profile.py --detectors e5-small radar --datasets enron privacy

# Specify custom data directory
python run_profile.py --data_dir /path/to/data --output_dir /path/to/results

Output:

  • results/<timestamp>/ – Timestamped results directory
  • results/<timestamp>/<dataset>/<detector>.jsonl – Per-record predictions
  • results/<timestamp>/profile_log.json – Run metadata and statistics
  • results/<timestamp>/accuracy_summary.csv – Accuracy table

Available datasets: education, enron, privacy

Output record format:

{
  "detection": {"detector": "e5-small", "label": 1, "correct": true},
  "ground_truth": {"label": 1},
  "metadata": {"domain": "business", "task": "title_to_body", "ai_model": "qwen3_8b"},
  "score": 0.95
}

Project Structure

Omini-Text/
├── omini_text/           # Core library
│   ├── detectors/        # Detector implementations
│   └── configs/          # Default configs
├── baseline/             # Original implementations
│   ├── fast-detect-gpt/
│   ├── glimpse/
│   ├── binoculars/
│   ├── radar/
│   ├── e5_small/
│   ├── desklib/
│   ├── gigacheck/
│   ├── seqxgpt/
│   └── roft-boundary/
├── evaluate/             # Evaluation pipeline
│   ├── run_profile.py    # Main evaluation script
│   └── data_loader.py    # Dataset loading utilities
├── examples/             # Usage examples
├── docs/                 # Documentation
│   ├── QUICKSTART.md     # 5-minute tutorial
│   ├── DETECTOR_GUIDE.md # Choosing a detector
│   ├── CONFIGURATION.md  # Parameter reference
│   └── API_REFERENCE.md  # Technical specification
└── cache/                # Model cache

Documentation

Citation

@inproceedings{hu2023radar,
  title={RADAR: Robust AI-Text Detection via Adversarial Learning},
  author={Hu, Xiaomeng and Chen, Pin-Yu and Ho, Tsung-Yi},
  booktitle={NeurIPS},
  year={2023}
}

@inproceedings{fastdetectgpt2024,
  title={Fast-DetectGPT: Efficient Zero-Shot Detection of Machine-Generated Text},
  author={Bao, Guangsheng and Zhao, Yanbin and Teng, Zhiyang and Yang, Linyi and Zhang, Yue},
  booktitle={ICLR},
  year={2024}
}

@inproceedings{glimpse2025,
  title={Glimpse: Enabling White-Box Methods to Detect AI-Generated Texts from Black-Box LLMs},
  author={Bao, Guangsheng and Zhao, Yanbin and Teng, Zhiyang and Zhang, Yue},
  booktitle={ICLR},
  year={2025}
}

@inproceedings{binoculars2024,
  title={Spotting LLMs With Binoculars: Zero-Shot Detection of Machine-Generated Text},
  author={Hans, Abhimanyu and Schwarzschild, Avi and Ramber, Valeriia and Pirber, Tonmoy and Goldblum, Micah and Goldstein, Tom},
  booktitle={ICML},
  year={2024}
}

@article{gigacheck2024,
  title={GigaCheck: Detecting LLM-generated Content},
  author={Tolstykh, Ivan and others},
  journal={arXiv preprint arXiv:2410.23728},
  year={2024}
}

@inproceedings{seqxgpt2023,
  title={SeqXGPT: Sentence-Level AI-Generated Text Detection},
  author={Wang, Pengyu and Li, Linyang and Ren, Ke and Jiang, Botian and Zhang, Dong and Qiu, Xipeng},
  booktitle={EMNLP},
  year={2023}
}

@article{roft2023,
  title={AI-generated text boundary detection with RoFT},
  author={Kushnareva, Laida and Gaintseva, Tatiana and Magai, German and others},
  journal={arXiv preprint arXiv:2311.08349},
  year={2023}
}

License

MIT License – See LICENSE for details.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages