MedDeID
MedDeID is a local-first, multilingual framework for clinical text de-identification. It provides a Python API, command-line interface, batch processor, and optional FastAPI service for compatible model bundles and locale-specific language profiles. Public models support Dutch and English; data generation, training, evaluation, and annotation packages are not required for inference.
For cross-suite navigation and task-oriented guidance, see the MedDeID website and documentation. This repository remains authoritative for inference APIs, CLI options, service settings, and deployment.
Language support
| Language | Language profiles | Public model |
|---|---|---|
| Dutch | nl-BE in the current public bundle |
stighellemans/meddeid-dutch-synth |
| English | en-GB, en-US |
stighellemans/meddeid-english-synth |
| Additional languages | Pluggable | Requires a compatible model bundle and language profile |
Model bundles pin their supported profiles. MedDeID selects a regional profile explicitly and never guesses between locales such as British and US English.
Easiest start: Python CLI
For the shortest first run, install the released package and use the CLI. This does not require writing Python code or installing Docker:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install meddeid
meddeid models
meddeid deidentify note.txt \
--model stighellemans/meddeid-dutch-synth
meddeid models ends by stating where to use the selected model ID.
Try MedDeID in your browser
Install and start Docker Desktop, then clone this repository once:
git clone https://github.com/stighellemans/meddeid.git
cd meddeid
Choose Dutch:
./scripts/start-local.sh \
--model stighellemans/meddeid-dutch-synth \
--language-profile nl-BE
Or choose English:
./scripts/start-local.sh \
--model stighellemans/meddeid-english-synth \
--language-profile en-GB
The browser opens with the API key already filled in. Paste a note and select
De-identify. Stop MedDeID with ./scripts/stop-local.sh.
Developers testing source changes can add --build. For a shared service, see
Production deployment.
Python HTTP service
Add the HTTP dependencies when another application needs the service or when deploying MedDeID as an HTTP service in a production environment:
python -m pip install 'meddeid[server]'
This installs the service runtime, not the surrounding production controls. See Production deployment for authentication, TLS, network, resource, monitoring, and validation requirements, and Inference and deployment for the availability matrix.
For dataset review, benchmarking, evaluation, training, synthetic-data, and contributor workflows, install the suite front door with the matching extras:
python -m pip install 'meddeid[research]'
# Language/profile and model-bundle contributors:
python -m pip install 'meddeid[contributor]'
Guided suite workflows
Use one entry point when you know the outcome but do not yet know which suite components or optional stages apply:
meddeid start
meddeid status ./my-workflow
meddeid next ./my-workflow
start first groups the suite into six familiar goals: de-identify text,
prepare data, train, evaluate, deploy, or contribute. A second menu appears only
when that goal has several possible workflows. Choices are numbered and ?
explains why a scientific decision is being requested. next runs exactly one
eligible stage and stops instead of guessing an unanswered branch. Hardware,
browser runtime, and other operational choices are requested only when needed.
Run status or next without a path from anywhere inside the workflow
directory. Add --details for every technical stage and exclusion reason.
Every workspace contains a checksummed meddeid.workflow.v1 manifest. Inspect
the rationale and the underlying component command at any time:
meddeid status ./my-workflow --details
meddeid workflow explain ./my-benchmark
meddeid workflow run ./my-benchmark score --dry-run
The existing meddeid workflow ... commands remain the advanced and automation
interface. Changing a scientific decision after work begins shows which stages
become invalid and requires configure --yes before outputs are archived.
Quick start
First review the available public baselines and their validation scope:
meddeid models
Then select the model explicitly. MedDeID does not silently choose Dutch or a synthetic baseline for you:
meddeid deidentify note.txt \
--model stighellemans/meddeid-dutch-synth
from meddeid import Deidentifier
deid = Deidentifier.from_pretrained("stighellemans/meddeid-dutch-synth")
result = deid("Patiënt Alex Voorbeeld kwam op controle.")
print(result.deid_text)
deid.close()
Use the public English model by selecting its regional profile:
meddeid deidentify note.txt \
--model stighellemans/meddeid-english-synth \
--language-profile en-GB
Dates use placeholders unless the caller explicitly supplies
metadata.date_shift_days. A nonzero shift produces deterministic shifted
dates; zero produces placeholders and a structured warning. One declarative
age-granularity JSON policy is loaded for the complete engine, independent of
the selected language profile.
The self-contained model bundle is downloaded and cached on first use. Document text is processed locally and is not sent to Hugging Face. Quickly inspect the resolved model, immutable revision, language profiles, files, and package versions with:
meddeid model-info --model stighellemans/meddeid-dutch-synth
The default inspection does not load the model weights into an inference
runtime. Use --verify-runtime when an administrator also needs to verify that
the configured backend and device can initialize:
meddeid model-info \
--model stighellemans/meddeid-dutch-synth \
--verify-runtime
model-info is read-only and does not set a persistent default. Each inference
command still names its model explicitly. It is also the detailed local
administrator view: model/cache paths, file inventory, and complete package
versions are reported, so saved output should be treated as operationally
sensitive. runtime.checked distinguishes inspection from runtime verification.
When no revision is supplied, the command reports
requested_revision: "latest" together with the immutable
resolved_revision that was resolved.
CLI JSON and HTTP results remain flat and use the logical order deid_text,
spans, processing, warnings, provenance. The nested provenance field
contains only the MedDeID version, model identity, and selected language
profile. Runtime, dependencies, cache details, and filesystem paths stay in
model-info and batch manifests. Clinical text is not sent to Hugging Face.
For offline or air-gapped use, download an immutable snapshot in advance:
hf download stighellemans/meddeid-dutch-synth \
--revision <immutable-hub-sha> \
--local-dir ./meddeid-dutch-synth
meddeid deidentify note.txt --model ./meddeid-dutch-synth
Use revision= in Python or --revision on the CLI to pin reproducible
deployments.
Batch inference
Canonical MedDeID JSONL can be processed directly. The batch command preserves document IDs and order, supports interruption-safe resume, and writes a sidecar manifest with input, output, model, profile, runtime, and timing metadata. Existing output is never overwritten implicitly.
meddeid batch project/splits/test.jsonl \
--output predictions.jsonl \
--model stighellemans/meddeid-dutch-synth
The input path may instead be written explicitly as
meddeid batch --input project/splits/test.jsonl .... Both forms are
equivalent for batch and deidentify; do not supply both in one command.
MedDeID checks that the input is a readable file before resolving or loading
the model, so path mistakes fail immediately.
The model is downloaded once and reused from the Hugging Face cache. Each
online run checks whether the selected Hub revision changed; use --offline
to prohibit that check. Automatic device selection prefers CUDA, then Apple
MPS, and falls back to CPU. Use --device to override that order. Native MPS
on the measured M4 Pro preserved semantics over all 300 public fixture notes
and ran 1.6--2.0 times faster than native CPU across interactive, ETL, and
long-note workloads. It is a native Python path rather than a container image.
HTTP service
PyTorch inference works on CPU, Apple MPS, and CUDA:
MEDDEID_MODEL=stighellemans/meddeid-dutch-synth \
MEDDEID_DEVICE=cpu \
meddeid-server
Multi-profile services can set a locale fallback once while still allowing
trusted metadata.lang on a request to override it:
MEDDEID_MODEL=stighellemans/meddeid-english-synth \
MEDDEID_LANGUAGE_PROFILE=en-GB \
meddeid-server
The bundle declares its post-processing locales; users choose only the locale. The browser UI shows the active model and profile, and enables profile selection when the model supports more than one.
For an authenticated service:
export MEDDEID_MODEL=stighellemans/meddeid-dutch-synth
export MEDDEID_API_KEY='<random secret>'
export MEDDEID_REQUIRE_API_KEY=true
meddeid-server
For a reproducible direct installation, keep the non-secret settings in the provided environment-file template. Edit the copied file to select the model, profile policy, and API-key handling, then run:
cp server.env.example meddeid-server.env
chmod 600 meddeid-server.env
meddeid-server --env-file meddeid-server.env
Unknown and duplicate settings are rejected. Existing process environment
variables take precedence, so a service manager can inject MEDDEID_API_KEY
without storing it in the file. Docker Compose continues to use .env or
docker compose --env-file <path>.
The service provides:
POST /deidentifyfor one document;POST /deidentify-batchfor throughput-oriented batches; andGET /healthfor minimal readiness and enabled model/profile information.
Server operators can optionally restrict startup and request profile selection:
export MEDDEID_ALLOWED_MODELS=stighellemans/meddeid-dutch-synth
export MEDDEID_ALLOWED_LANGUAGE_PROFILES=nl-BE
The model allowlist contains exact accepted MEDDEID_MODEL values. The profile
allowlist limits the regional profiles that requests may select. Both are
optional and do not affect ordinary Python, CLI, or batch use.
For a shared service, choose CPU for the simplest portable deployment, PyTorch CUDA when the NVIDIA GPU may vary, or a target-specific TensorRT runtime for a fixed, optimized GPU target. Native Apple MPS is also available through the Python installation. All paths retain the same API, tokenization, decoding, and locale-selected post-processing contract. The PyTorch CUDA image runs with:
docker compose \
--env-file .env.cuda \
-f compose.yaml \
-f compose.cuda.yaml \
up --detach meddeid
TensorRT is optimized for a specific GPU. The first supported target is NVIDIA T4; choose CUDA instead when the GPU model may vary. For an optimized A10G, L4, or another target, contact stig.hellemans@uantwerpen.be without sending sensitive data.
Use /deidentify for individual notes and /deidentify-batch for planned
batches. If interactive traffic and large batch jobs run simultaneously,
operate separate service instances so batch work cannot delay interactive
requests.
See the reader-focused production deployment guide for setup. Benchmark evidence and advanced tuning remain in the technical production reference, CUDA guide, and TensorRT guide.
Language profiles and metadata
The current public Dutch model bundle declares nl-BE. The Dutch language
package also provides nl-NL, but it can only be selected when a compatible
model bundle declares that profile. The public English model bundle supports
both en-GB and en-US; metadata.lang or --language-profile selects the
regional resources and post-processing. Bare en is rejected because it does
not choose a regional profile.
Model bundles pin installed profiles provided through
meddeid.language_profiles entry points, with no source-tree fallback. For a
multi-profile bundle, document metadata is used first, followed by an explicit
load-time default and then a single-profile bundle default; MedDeID never
guesses between multiple profiles. Additional languages require a compatible
model bundle and language profile. See
Language profile selection.
Optional trusted metadata can recover known patient or caregiver names and birth-date representations or other known values after neural inference. Metadata is not concatenated to the note or sent to the model as an input feature. Incorrect metadata can create false-positive redactions, so callers must validate it.
Belgian DEDUCE is an independent comparison system and is not installed by this package.
Privacy and limitations
Local processing reduces data movement but does not guarantee anonymity. Validate the model on representative data from the intended setting, monitor both missed PII and unnecessary redaction, and use human review where errors can create material privacy risk. Secure cached models, inputs, outputs, manifests, and service logs according to your organization’s requirements.
Development
python -m pip install \
-e ../meddeid-core \
-e ../meddeid-language-nl \
-e '.[dev]'
pytest
Licence
AGPL-3.0-only. Model weights are distributed separately under the terms stated in their model card.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file meddeid-0.3.0.tar.gz.
File metadata
- Download URL: meddeid-0.3.0.tar.gz
- Upload date:
- Size: 147.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8d56c1bd4d2386ab4c72067619e4a43563028570dd822bf921ed0fcc559452e9
|
|
| MD5 |
5c73aadeeb04672cc747e24caeba4db3
|
|
| BLAKE2b-256 |
f87da220da1634ec0fc749c454c0dfc5aab89e70cdad638dfca24657b838df4d
|
Provenance
The following attestation bundles were made for meddeid-0.3.0.tar.gz:
Publisher:
publish-python.yml on stighellemans/meddeid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
meddeid-0.3.0.tar.gz -
Subject digest:
8d56c1bd4d2386ab4c72067619e4a43563028570dd822bf921ed0fcc559452e9 - Sigstore transparency entry: 2732739011
- Sigstore integration time:
-
Permalink:
stighellemans/meddeid@6370c67e020b2b8165bdab2276c431a5b0d09802 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/stighellemans
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@6370c67e020b2b8165bdab2276c431a5b0d09802 -
Trigger Event:
push
-
Statement type:
File details
Details for the file meddeid-0.3.0-py3-none-any.whl.
File metadata
- Download URL: meddeid-0.3.0-py3-none-any.whl
- Upload date:
- Size: 122.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
86aa15d95e90e0dc2cf5766472ef10c36ecd0dcae6f908798f5adf074ac26099
|
|
| MD5 |
5a5cb9c00e1d4b40d72eff20e9384b0c
|
|
| BLAKE2b-256 |
0e73a2d32b03a6ea0760c3b59ee7f0418e2213c1385ceb042a6ea58c402a3f1b
|
Provenance
The following attestation bundles were made for meddeid-0.3.0-py3-none-any.whl:
Publisher:
publish-python.yml on stighellemans/meddeid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
meddeid-0.3.0-py3-none-any.whl -
Subject digest:
86aa15d95e90e0dc2cf5766472ef10c36ecd0dcae6f908798f5adf074ac26099 - Sigstore transparency entry: 2732739044
- Sigstore integration time:
-
Permalink:
stighellemans/meddeid@6370c67e020b2b8165bdab2276c431a5b0d09802 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/stighellemans
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@6370c67e020b2b8165bdab2276c431a5b0d09802 -
Trigger Event:
push
-
Statement type: