Prepare and annotate data¶
This workflow turns exported notes into a reviewed MedDeID dataset. Import and model inference run locally; reviewers use a local browser application to inspect every document and correct its identifier spans.
source notes → imported JSONL → optional model suggestions → human review
→ optional curation → optional detailed evaluation labels
Before you begin¶
Choose the installation that matches how far you plan to go:
- For an end-to-end research project, install the complete Python toolset once:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install 'meddeid[research]'
- If you only need to import and review data, install
meddeid-data. Addmeddeidonly when reviewers should start from model suggestions.
The review applications run in Docker and are not installed by pip. Docker
is not needed to import data or generate model suggestions.
1. Import the source notes¶
Owner: meddeid-data
Install the importer if you did not install the complete research toolset:
Create a project and import a CSV file:
meddeid-data project create my-project notes.csv \
--namespace hospital-study \
--language-profile nl-BE \
--id-column note_id \
--text-column note_text
The same command accepts TSV files and directories of UTF-8 .txt files.
For Parquet, install meddeid-data[parquet] first.
The command writes the annotation-ready data to
my-project/artifacts/annotations.jsonl. In a table, columns other than the
selected ID and text columns are kept as metadata by default.
MedDeID replaces source IDs with stable project IDs. The project key and the
mapping back to source records are stored under my-project/private/.
Protect the private directory
The private mapping can reconnect project IDs to source records. Keep it inside the approved data boundary, restrict access, and back it up with the project. Do not include it in a dataset release.
If the column mapping is wrong
A failed first import keeps the empty project and its private key. Correct
the column names and repeat project create with the same namespace and
language profile, or use the recovery command printed by MedDeID:
Once a project contains imported or reviewed data, project create will
not overwrite it. Use project import only when you deliberately intend
to replace the project's imported dataset.
For more complex column mappings, see the
meddeid-data import documentation.
2. Create the split before review when training¶
Skip this step when you only need one reviewed dataset.
If the data will be used for training or domain adaptation, assign documents to development and test roles before reviewers or models can influence that choice:
This creates train.jsonl, validation.jsonl, and test.jsonl under
my-project/splits/. The remaining 10% becomes the test set. Keep those
roles fixed: training decisions may use the train and validation files, but
must not use the test answers.
In the following steps, process each split as a separate assignment. The examples use the complete imported file to keep the basic annotation path short; replace that input with a split file when preparing training data.
3. Choose the reviewer's starting point¶
A reviewer can begin with model suggestions or with an empty assignment. Both routes lead to the same annotation interface and require full human review.
Start with model suggestions¶
Install inference if needed:
Generate a writable reviewer assignment:
meddeid batch my-project/artifacts/annotations.jsonl \
--output my-project/assignments/reviewer-a.jsonl \
--model stighellemans/meddeid-dutch-synth
The example model is a Dutch synthetic baseline. Select a model and language profile that match the notes, and prefer an institution-validated bundle when one is available. Model spans are only a starting point: the reviewer must keep, correct, remove, or add identifiers after reading the complete document.
Start without model suggestions¶
Copy the empty imported records to a writable assignment:
Do not open the canonical file under artifacts/ as the writable assignment.
Keeping a separate copy preserves the imported source state.
For a split project, repeat either route with splits/train.jsonl,
splits/validation.jsonl, and splits/test.jsonl, using a distinct output
name for each assignment.
4. Review every document¶
Owner: meddeid-annotate
Start the local annotation application:
docker run --rm -p 127.0.0.1:8787:8787 \
--read-only --cap-drop ALL --security-opt no-new-privileges \
-e MEDDEID_ANNOTATIONS_PATH=/input/reviewer-a.jsonl \
-v "$PWD/my-project/assignments/reviewer-a.jsonl:/input/reviewer-a.jsonl" \
ghcr.io/stighellemans/meddeid-annotate:0.2.0
Open http://127.0.0.1:8787. The application saves directly to
reviewer-a.jsonl.
Read the entire document, not only the highlighted text. Correct the spans and save every document, including documents that contain no identifiers. Saving marks the document as reviewed.
Give every reviewer a separate assignment file. If two reviewers need the same starting point, make both copies before either reviewer begins; never mount the same writable file in two application instances.
5. Package a completed assignment¶
Owner: meddeid-data
When the assignment will be curated or handed off as a reproducible result, validate it and create its manifest:
meddeid-data project package-annotation my-project \
my-project/assignments/reviewer-a.jsonl \
--annotation-set-id hospital-study-round-1 \
--annotator-id reviewer-7
The command checks that every document was reviewed and writes a manifest next to the JSONL file. The manifest identifies the annotation set and records the exact file checksum and data contracts. Use a pseudonymous annotator ID rather than a name or email address.
6. Reconcile multiple reviewers only when required¶
Owner: meddeid-curate
Skip curation when one completed reviewer is authoritative for the project.
When two or more people reviewed independent copies, use meddeid-curate to
compare their spans and record the curator's decisions.
mkdir -p my-project/curation
docker run --rm -p 127.0.0.1:8793:8793 \
--read-only --cap-drop ALL --security-opt no-new-privileges \
-v "$PWD/my-project/curation:/app/data" \
ghcr.io/stighellemans/meddeid-curate:0.2.0
Open http://127.0.0.1:8793, select each completed reviewer JSONL together
with its manifest, and resolve the differences. Publishing the result writes
annotations.jsonl, decisions.jsonl, and manifest.json under
my-project/curation/exports/.
7. Add detailed labels only for detailed evaluation¶
Owner: meddeid-subannotate
Ordinary training and span-level evaluation do not require this step.
meddeid-subannotate is for benchmarks that need to measure which individual
characters inside an identifier were successfully removed.
Choose the completed reviewer file, or the curator-approved
curation/exports/annotations.jsonl when curation was used:
ANNOTATIONS_PATH="$PWD/my-project/assignments/reviewer-a.jsonl"
mkdir -p my-project/subannotation
docker run --rm -p 127.0.0.1:8791:8787 \
--read-only --cap-drop ALL --security-opt no-new-privileges \
-e MEDDEID_ANNOTATIONS_PATH=/input/annotations.jsonl \
-v "$ANNOTATIONS_PATH:/input/annotations.jsonl:ro" \
-v "$PWD/my-project/subannotation:/app/data" \
ghcr.io/stighellemans/meddeid-subannotate:0.2.0
Open http://127.0.0.1:8791. The public image uses a language-neutral
profile. Language-specific suggestion profiles are optional; their setup is
documented in the
meddeid-subannotate repository.
What to use next¶
| Your next goal | Input to keep |
|---|---|
| Train a model | Completed development assignments, plus the fixed project split |
| Evaluate a model | Completed test gold, optionally with detailed subannotations |
| Curate reviewers | Every completed reviewer JSONL together with its manifest |
| Preserve or hand off the dataset | The authoritative JSONL and its manifest; keep private mappings separate |
Continue with Train and evaluate when the development and test assignments are complete. See Artifact lineage for how manifests connect the workflow outputs.