Text Classification
Transformers
Safetensors
English
gpt2
ai-text-detection
binary-classification
variable-position-readout
Instructions to use rasbt/ai-text-detector-gpt2-variable with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use rasbt/ai-text-detector-gpt2-variable with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="rasbt/ai-text-detector-gpt2-variable")# Load model directly from transformers import AutoTokenizer, AutoModelForSequenceClassification tokenizer = AutoTokenizer.from_pretrained("rasbt/ai-text-detector-gpt2-variable") model = AutoModelForSequenceClassification.from_pretrained("rasbt/ai-text-detector-gpt2-variable", device_map="auto") - Notebooks
- Google Colab
- Kaggle
| language: | |
| - en | |
| license: apache-2.0 | |
| library_name: transformers | |
| pipeline_tag: text-classification | |
| datasets: | |
| - rasbt/human-vs-ai-50k | |
| base_model: openai-community/gpt2 | |
| base_model_relation: finetune | |
| metrics: | |
| - accuracy | |
| tags: | |
| - ai-text-detection | |
| - binary-classification | |
| - variable-position-readout | |
| # GPT-2 Variable-Position AI-Text Detector | |
| This is a fully fine-tuned GPT-2 classifier for distinguishing human-written and AI-generated text. It uses a variable-position readout token immediately after the input text. The model was trained on [`rasbt/human-vs-ai-50k`](https://huggingface.co/datasets/rasbt/human-vs-ai-50k). Human-written text has label 0 and AI-generated text has label 1. | |
| The maximum context length is 1,024 tokens. Temperature scaling is applied during inference. The recorded best validation accuracy was 97.44%. | |
| | |
| ## Download and use | |
| ```bash | |
| hf download rasbt/ai-text-detector-gpt2-variable \ | |
| --local-dir models/ai-text-detector-gpt2-variable | |
| ``` | |
| ```python | |
| import json | |
| from pathlib import Path | |
| import torch | |
| from transformers import AutoModelForSequenceClassification, AutoTokenizer | |
| model_dir = Path("models/ai-text-detector-gpt2-variable") | |
| metadata = json.loads( | |
| (model_dir / "detector-config.json").read_text(encoding="utf-8") | |
| ) | |
| tokenizer = AutoTokenizer.from_pretrained(model_dir) | |
| model = AutoModelForSequenceClassification.from_pretrained(model_dir) | |
| model.eval() | |
| text = "Paste the text to classify here." | |
| text_ids = tokenizer( | |
| text, | |
| add_special_tokens=False, | |
| truncation=True, | |
| max_length=metadata["max_text_length"], | |
| )["input_ids"] | |
| if metadata["readout_position"] == "fixed": | |
| padding_length = metadata["context_length"] - len(text_ids) - 1 | |
| input_ids = ( | |
| text_ids | |
| + [tokenizer.pad_token_id] * padding_length | |
| + [tokenizer.eos_token_id] | |
| ) | |
| attention_mask = [1] * len(text_ids) + [0] * padding_length + [1] | |
| else: | |
| input_ids = text_ids + [tokenizer.eos_token_id] | |
| attention_mask = [1] * len(input_ids) | |
| inputs = { | |
| "input_ids": torch.tensor([input_ids]), | |
| "attention_mask": torch.tensor([attention_mask]), | |
| } | |
| with torch.inference_mode(): | |
| logits = model(**inputs).logits / metadata["temperature"] | |
| probabilities = logits.float().softmax(dim=-1) | |
| ai_index = metadata["label_mapping"]["ai"] | |
| ai_probability = probabilities[0, ai_index].item() | |
| print({"score": round(100 * ai_probability, 4)}) | |
| ``` | |
| | |
| ## Test-set confusion matrix | |
|  | |
| `detector-config.json` contains the readout, calibration, and training metadata. The recommended inference implementation is provided in the [`rasbt/ai-detector`](https://github.com/rasbt/ai-detector) repository because classification requires selecting the configured readout position. | |
| | |
| ## Related models | |
| - [TF-IDF logistic regression](https://huggingface.co/rasbt/ai-text-detector-logreg) | |
| - [DistilBERT](https://huggingface.co/rasbt/ai-text-detector-distilbert) | |
| - [DistilBERT with LoRA](https://huggingface.co/rasbt/ai-text-detector-distilbert-lora) | |
| - [DistilBERT with MiCA](https://huggingface.co/rasbt/ai-text-detector-distilbert-mica) | |
| - [ModernBERT](https://huggingface.co/rasbt/ai-text-detector-modernbert) | |
| - [GPT-2 with a fixed-position readout](https://huggingface.co/rasbt/ai-text-detector-gpt2-fixed) | |
| - [Qwen3 0.6B with a fixed-position readout](https://huggingface.co/rasbt/ai-text-detector-qwen3-0.6b-fixed) | |
| - [Qwen3 0.6B with a variable-position readout](https://huggingface.co/rasbt/ai-text-detector-qwen3-0.6b-variable) | |
| | |
| ## Limitations | |
| Performance may change for text from generators, domains, languages, and editing workflows not represented in the training set. Short or partly AI-assisted text may also be harder to classify. The score should not be treated as definitive evidence that a person did or did not write a text. | |