# GPTZero, reimplemented locally with perplexity rather than an API

> This repository is an open source reimplementation of the GPTZero AI text detector, built on GPT-2 perplexity with the HuggingFace transformers library. It runs entirely on your machine, with an all-pinned dependency stack and no releases on GitHub.

**BurhanUlTayyab/GPTZero** — An open-source implementation of GPTZero 

- Repository: https://github.com/BurhanUlTayyab/GPTZero
- Website: https://gptzero.sg
- Stars: 607 · Forks: 92
- Language: Python
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/burhanultayyab-gptzero

## A detector you can run without giving anyone your text

GPTZero is a commercial service that answers one question: was this text written by a person or by a language model. The service is closed source, and this repository is an attempt to rebuild the same thing in the open. The project states the motivation directly, that the original implementation is closed source, and that the authors set out to construct an identical solution.

The result is a small Python codebase with three files at its centre, infer.py, local_infer.py and model.py, plus a webapp directory. There is no account, no API key and no network call to a detection service, which is the practical appeal for anyone who needs to check a draft but does not want the draft uploaded to a third party.

Two caveats frame everything else. First, the README's parity claim is the project's own, and it is stated against a hosted service that can change without notice. Second, the top of the readme now advertises a different project from the same maintainers, a safety layer between AI agents and databases, which tells you where the author's attention has moved.

## Perplexity is the mechanism, and it is a proxy for authorship

The README describes GPTZero as an AI model with some mathematical formulation to determine whether a text was written by AI or a human. The acknowledgement section points at the HuggingFace transformers documentation for perplexity as the basis, and cites the RoBERTa paper on optimised BERT pretraining, which is where the underlying language model comes from.

Perplexity is a measure of how predictable a passage is to a given language model. Text that a model finds easy to predict has lower perplexity, and text that is surprising to it has higher perplexity. The design assumption behind detectors of this kind is that generated prose tends to be more predictable than human prose. That assumption is doing all the work, and it is why the approach can be reproduced at all: it needs a model and a formula, not a secret dataset.

The consequences are worth being clear about. The output is a score derived from perplexity, not a proof of authorship. It is sensitive to the model used, and the model is a pinned dependency rather than something the project trains. It also inherits the biases of the corpus the model was trained on, since a model that finds one group's writing harder to predict will assign it a higher perplexity for reasons unrelated to who typed it.

## Install the pinned requirements, then run one of two scripts

Installation is a single requirements file, and the versions in it are the thing to read before you start.

```sh
pip install -r requirements.txt
```

For a batch file of text, the project documents running infer.py.

```sh
python3 infer.py
```

For typing text in by hand, the entry point is local_infer.py, and the documented session looks like this.

```sh
python3 local_infer.py
```

```
Please enter your sentence: (Press Enter twice to start processing)
Hello World.
My name is mike.
(empty line)
```

The empty line is the signal to start processing, which is a reasonable choice for a script that reads from standard input. The webapp directory, with the FastAPI, Gradio and Uvicorn dependencies behind it, is the third way in and covers the case where you want a browser interface instead of a terminal.

## The API surface is one class and one call

The Python interface is deliberately thin. The model class is imported from model, instantiated without arguments, and called with a string.

```python
from model import GPT2PPL
model = GPT2PPL()
sentence = "your text here"
model(sentence)
```

There is no configuration object, no threshold parameter and no batch method in that snippet, which is both the appeal and the limit. For a quick check on one passage it is a three line script. For anything systematic, such as scoring a directory of submissions or applying a consistent threshold, there is no documented API for it, and you are writing against a single file whose contents the README does not describe.

The repository layout is small enough to read end to end, which is a real advantage for anyone who wants to know exactly what happens to their text. model.py holds the model, the two infer scripts are entry points, and the webapp directory holds the serving code. There is no configuration file, no model registry and no plugin system, so nothing hides the computation.

## Dependencies frozen at versions from early 2022

The requirements file pins every dependency exactly, with no version ranges.

```
fastapi==0.89.1
gradio==3.16.2
transformers==4.26.0
uvicorn==0.20.0
```

Four packages, all pinned to specific releases rather than lower bounds. That choice is understandable for a reproduction of a specific result, since the exact model behaviour can shift when a library moves. It is also the main installation risk, because these are old releases and the environment they expect is an older one.

Two of the four exist for the webapp rather than for detection. Gradio supplies the browser interface and FastAPI with Uvicorn serves it. transformers is the one that matters for the core logic, since it provides the model and the perplexity machinery. uvicorn and gradio have both changed considerably since their pinned versions, and a reader who wants to install this on a current Python is likely to hit friction that has nothing to do with the detection method itself.

The webapp dependencies also mean the install pulls in a web server stack even if you only intend to run infer.py from a terminal.

## Parity with a hosted service is a moving target

The README makes a strong claim, that the implementation produces the same results as gptzero.me, based on an extensive comparison over a large corpus of text. Taken at face value that is a meaningful result for a reimplementation. It is also a claim about a moving target.

The hosted service is not described as frozen, so its model and thresholds can change at any time, and the reimplementation here is pinned to a specific dependency set from an earlier period. Any divergence between the two is therefore expected over time, and it would be indistinguishable from the reimplementation being wrong. The repository gives no way to check parity itself, since there is no test suite in the layout and no comparison script that ships with the code.

Maintenance status is the second limit. The repository is not archived and the last push was on 2026-05-04, but it has no GitHub releases at all, so there is no tagged version to install and no release history to read. The readme's lead item now points to a different project entirely. For a tool whose whole value is matching a moving commercial service, that combination is a fair reason to treat it as a research artefact rather than a dependency.

## What it is good for, and where it should not be trusted

The honest summary is that this is a compact, readable reference implementation of a perplexity based detector, licensed under MIT, with no strings attached on your text and no commercial dependency.

It suits three situations. Learning how perplexity based detection works, since the whole mechanism fits in one file. Checking your own drafts privately, where uploading them to a service would be the problem rather than the solution. Reproducing the project's parity claim for yourself, if you are willing to pin an older environment and do the comparison work it does not include.

It should not be trusted as an adjudicator. A perplexity score is a signal, and a signal that is easy to act on incorrectly, because the same number can mean machine generated text, unusual human writing, or a passage in a domain the model handles poorly. If a decision about a person hangs on the result, the score alone cannot support it.

The MIT licence means you can fork it, extend it, fold it into your own pipeline or point it at a newer model without negotiating anything. That flexibility is the strongest argument for the code over the hosted service, and it is also the reason the pinned versions are a starting point rather than a constraint you must accept.

## Conclusion

This repository suits teachers, reviewers and researchers who want to run an AI-text detector on their own machine, with no account, no API key and no text leaving the host. It is the wrong tool if you need a maintained service with a current model, if your text is sensitive enough that you do not want it in a HuggingFace pipeline, or if you expect a verdict rather than a perplexity score. Check first that the pinned dependencies in requirements.txt still install on your Python, that transformers 4.26.0 matches the model code in model.py, and that the last push on 2026-05-04 is recent enough for the detector you are comparing it against.

## FAQ

### How do I install this GPTZero implementation?

Run pip install -r requirements.txt, which installs fastapi 0.89.1, gradio 3.16.2, transformers 4.26.0 and uvicorn 0.20.0. Then run python3 infer.py for a file of text or python3 local_infer.py to type text in interactively.

### Does this GPTZero implementation need an API key or send my text to a server?

No. The project runs the model locally through the HuggingFace transformers library, so there is no account and no detection API involved. The webapp directory offers a local browser interface instead.

### How does the detection actually work?

It is built on the HuggingFace transformers approach to perplexity, using a RoBERTa based model, and the README acknowledges both the transformers perplexity documentation and the RoBERTa paper as the basis of the implementation.

### Is this GPTZero reimplementation still being updated?

The repository is not archived and the last push was on 2026-05-04, but it has no GitHub releases, so there is no tagged version to pin. The readme now leads with a different project from the same maintainers.

## Sources

- [BurhanUlTayyab/GPTZero on GitHub](https://github.com/BurhanUlTayyab/GPTZero)
- [Issues](https://github.com/BurhanUlTayyab/GPTZero/issues)
- [License: MIT](https://github.com/BurhanUlTayyab/GPTZero/blob/main/LICENSE)
- [Project website](https://gptzero.sg)
- [README](https://github.com/BurhanUlTayyab/GPTZero/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/burhanultayyab-gptzero
