Artefactual
Estimating how likely a language model answer is to be a hallucination.
Artefactual is a Python module that assigns a language model's answer a probability of being a hallucination. It reads the answer that has already been generated, together with the token probabilities returned alongside it, and needs nothing else from the model.
Quick start
from openai import OpenAI
from artefactual.scoring import BaseDetector
MODEL = "mistralai/Ministral-8B-Instruct-2410" # the model being scored
DETECTOR = "artefactory/wepr-ministral" # the detector trained for it
client = OpenAI(base_url="https://your-provider.example/v1") # any OpenAI-compatible endpoint
response = client.chat.completions.create(
model=MODEL,
messages=[{"role": "user", "content": "Who wrote the Rust book?"}],
logprobs=True,
top_logprobs=15,
)
detector = WEPR.from_pretrained(DETECTOR)
print(detector.predict_proba(response)[:, 1]) # P(hallucination) per sequence
print(detector.predict_token_proba(response)) # ...and per token
A detector is trained for one model, so DETECTOR must be the one published for whatever
produced the response — see published detectors for the pairs. There is no default threshold; choosing one is covered in the
user guide.
No endpoint is needed to try the library: two of the example notebooks run against checked-in fixtures and need no GPU and no API key. Training a detector for a model with no published weights is covered, with three more notebooks, in training a detector.
Requirements
Two conditions apply to whatever produced the response:
logprobsandtop_logprobsare enabled. Providers that do not expose them cannot be scored at all.top_logprobsis at leastk, the rank count the detector's own weights were trained at. The shipped files usek = 15.
Neither needs auditing in advance — a response that fails one is refused by name. Why a narrow response is refused rather than padded is in the reference.
Installation
pip install artefactual
Dependencies
Artefactual requires:
- Python (>= 3.11)
- NumPy
- scikit-learn
- pydantic
- beartype
Two optional extras are available: [adapters] installs langfuse and openai for the
integration examples, and [docs] installs Sphinx and the theme for building the
documentation.
From source
git clone https://github.com/artefactory/artefactual
cd artefactual
uv sync
Usage
Two detectors are provided. wepr is the default and the more accurate; epr fits a
single coefficient instead of 2k, for when labelled data is scarce. Both take the same
arguments and return the same type.
from artefactual.scoring import BaseDetector, wepr
# Unfitted, as a scikit-learn estimator is; y is 0/1 per sequence, 1 marking a hallucination
WEPR(k=15).fit(responses, y)
# Published weights, or your own file, are loaded rather than fitted
WEPR.from_pretrained("artefactory/wepr-phi4")
WEPR.from_pretrained("/path/to/my_detector.skops")
EPR.from_pretrained("artefactory/epr-phi4") # the single-coefficient variant
Scoring a batch, reading per-token scores, scoring Langfuse traces, composing into
GridSearchCV and training a detector for a model that is not shipped are covered in the
user guide.
Published detectors
A detector is named by its own Hugging Face repository, not by the model it scores. Pick the row for the model that produced the responses, and the column for the reduction:
| Model that produced the responses | "epr" |
"wepr" |
|---|---|---|
mistralai/Ministral-8B-Instruct-2410 |
artefactory/epr-ministral |
artefactory/wepr-ministral |
mistralai/Mistral-Small-3.1-24B-Instruct-2503 |
artefactory/epr-mistral-small |
artefactory/wepr-mistral-small |
tiiuae/Falcon3-10B-Instruct |
artefactory/epr-falcon3 |
artefactory/wepr-falcon3 |
microsoft/phi-4 |
artefactory/epr-phi4 |
artefactory/wepr-phi4 |
All are trained at k = 15. Both factories also accept a path to a .skops file, so a
detector you trained yourself is named the same way one published here is — the package
holds no list of models, and publishing another detector needs no release.
Limitations
- Not every provider can be scored. The requirements above rule out any provider that
hides
logprobs, and any that capstop_logprobsbelow the detector'sk. - Detectors are model-specific. Scoring a model that is not shipped requires training a detector for it, which requires labelled data.
- The probability is only as good as its training data. Rankings transfer more readily than absolute values.
- It measures uncertainty, not truth. A model that is confidently wrong is not uncertain, and scores low. This complements retrieval grounding or a judge rather than replacing either.
- Scoring is per sequence. There is no cross-response consistency check.
Results
ROC-AUC on TriviaQA hallucination detection at k = 15, as reported in Table 1 of the
paper:
| Model | SelfCheckGPT | EPR | HalluDetect | WEPR |
|---|---|---|---|---|
Mistral-Small-3.1-24B |
79.0 | 74.6 | 78.7 | 82.0 |
Falcon-3-10B |
70.1 | 75.4 | 79.0 | 84.1 |
Phi-4 (14.7B) |
71.4 | 78.2 | 83.8 | 85.4 |
Ministral-8B-2410 |
81.1 | 81.4 | 86.1 | 85.8 |
The full tables and the procedure that produced them are in the
scripts/ecir
subdirectory.
Documentation
- Documentation and user guide: https://artefactory.github.io/artefactual/
- Example notebooks: https://artefactory.github.io/artefactual/examples/
- Training a detector: https://artefactory.github.io/artefactual/guide/training.html
- How it works: https://artefactory.github.io/artefactual/guide/how-it-works.html
Development
Contributions are welcome — see CONTRIBUTING.md.
- Source code: https://github.com/artefactory/artefactual
- Issue tracker: https://github.com/artefactory/artefactual/issues
uv sync
uv run pytest tests # test suite (uv sync resolves the env first)
uv run pytest tests --cov # with coverage
uvx ruff check src tests # lint — a standalone tool, no project env needed
uvx ruff format src tests
uvx --from shellcheck-py shellcheck scripts/ecir/*.sh
Versioning
Releases are dated (YYYY.MM.PATCH). Breaking changes to the public surface are called out
in the release notes.
Citation
If artefactual is useful in your research, please cite the ECIR 2026 paper:
@inproceedings{moslonka2026learned,
title = {Learned Hallucination Detection in Black-Box LLMs Using Token-Level Entropy Production Rate},
author = {Moslonka, Charles and Randrianarivo, Hicham and Garnier, Arthur and Malherbe, Emmanuel},
booktitle = {Advances in Information Retrieval},
series = {Lecture Notes in Computer Science},
volume = {16483},
pages = {115--130},
publisher = {Springer, Cham},
year = {2026},
doi = {10.1007/978-3-032-21289-4_8},
}
License
MIT — no limitation of usage, including for commercial applications.
Metadata
Release files for artefactual 2026.9.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| artefactual-2026.9.1.tar.gz | 75.1 kB | With provenance | Details for artefactual-2026.9.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| artefactual-2026.9.1-py3-none-any.whl | Python 3 | none | any | Details for artefactual-2026.9.1-py3-none-any.whl |
Total release size: 110.3 kB
Release files / artefactual-2026.9.1.tar.gz
| Download URL | artefactual-2026.9.1.tar.gz |
|---|---|
| Size | 75.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
011d09bfa18743d6ed9e5a68ed7bdfd8398e95599120823f63d6902e4baeabc0
|
|
BLAKE2b-256 checksum How to use checksums |
01d933b852411287617451368627ee9bae3bf5ed6bad3a42792b1be322978ae8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logRelease files / artefactual-2026.9.1-py3-none-any.whl
| Download URL | artefactual-2026.9.1-py3-none-any.whl |
|---|---|
| Size | 35.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e1ee8c464713f846ce87c9f5d22e4556038e544eddd9c0ead74789ca35ba69fa
|
|
BLAKE2b-256 checksum How to use checksums |
5f4e710e9eebae884b2ccdcc080b0bc4855654dd7e234dc9306ae75d4459d8b9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logSecurity for artefactual 2026.9.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for artefactual-2026.9.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.