Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

## What can you do with Anonymizer?

- **Detect entities** using GLiNER-PII and LLM-based augmentation and validation
- **Detect entities** using LLM-based detection, augmentation, and validation
- **Replace with 4 strategies** — LLM-generated substitute, redact, annotate, or hash (deterministic, local)
- **Preview results** before full runs with `display_record()` visualization

Expand All @@ -30,7 +30,7 @@ make install

### 2. Set up model providers

By default, Anonymizer uses models hosted on [build.nvidia.com](https://build.nvidia.com/models) — GLiNER-PII for entity detection and a text LLM for augmentation/validation. You can also bring your own models via custom provider configs.
By default, Anonymizer uses Nemotron Super hosted on [build.nvidia.com](https://build.nvidia.com/models) for its model-backed workflow roles. You can also bring your own models, including a self-hosted GLiNER detector, via custom provider configs.

The default build.nvidia.com (NVIDIA Build) setup is a convenient way to try Anonymizer and iterate on previews. Use of NVIDIA Build is subject to NVIDIA Build's own terms of service and privacy practices, which are separate from and independent of the NeMo Framework library. NVIDIA Build is intended for evaluation and testing purposes only and may not be used in production environments. Do not upload any confidential information or personal data when using NVIDIA Build. Your use of NVIDIA Build is logged for security purposes and to improve NVIDIA products and services.

Expand Down Expand Up @@ -160,7 +160,7 @@ make install-pre-commit # Install pre-commit hooks

- Python 3.11+
- [NeMo Data Designer](https://github.com/NVIDIA-NeMo/DataDesigner) (installed as dependency)
- [NVIDIA API key](https://build.nvidia.com) for default model providers (GLiNER-PII + text LLM), or custom model endpoints
- [NVIDIA API key](https://build.nvidia.com) for the default Nemotron Super provider, or custom model endpoints

---

Expand Down
16 changes: 8 additions & 8 deletions docs/concepts/detection.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Entity detection is the first stage of every Anonymizer pipeline. Both replace a

## How it works

Detection combines a lightweight NER model (GLiNER-PII) with LLM-based refinement. GLiNER PII produces an initial set of entity spans, then an LLM augments it with entities the NER missed and validates each detection -- keeping, reclassifying, or dropping entities based on context.
By default, detection uses Nemotron Super to produce an initial set of entity values, materializes those values as text spans, then validates and augments them. A custom `gliner-pii-detector` alias instead uses the GLiNER request and span-response protocol, which supports lightweight self-hosted NER.

When rewrite is configured, an additional step identifies **latent entities** -- sensitive information inferable from context but not explicitly stated in the text.

Expand Down Expand Up @@ -44,7 +44,7 @@ config = AnonymizerConfig(
| Field | Default | Description |
|-------|---------|-------------|
| `entity_labels` | `None` (all defaults) | List of labels to detect. Leave unset (or pass `None`) to use the full default set. |
| `gliner_threshold` | `0.3` | GLiNER confidence threshold (0.0--1.0). Lower values detect more entities but may increase false positives. |
| `gliner_threshold` | `0.3` | Confidence threshold for a detector configured with the `gliner-pii-detector` alias. It does not affect the default LLM detector. |
| `validation_max_entities_per_call` | `100` | Maximum candidate entities per validator LLM call. Rows with more candidates are split into chunks. See [Chunked validation](#chunked-validation). |
| `validation_excerpt_window_chars` | `500` | Characters of context included before and after a chunk's entity spans in the validator prompt. Bounds per-chunk prompt size; not the model's context-window limit. |

Expand Down Expand Up @@ -95,7 +95,7 @@ print(DEFAULT_ENTITY_LABELS)

### Custom labels

When you pass `entity_labels` explicitly, the augmenter operates in **strict mode** -- it only outputs entities matching your list. When `entity_labels=None`, the augmenter can create additional labels beyond the defaults (e.g., `clinic_name`, `server_name`).
When you pass `entity_labels` explicitly, the LLM detector and augmenter operate in **strict mode** -- they only output entities matching your list. When `entity_labels=None`, they can create additional labels beyond the defaults (e.g., `clinic_name`, `server_name`).

```python
# Strict: only detect these 3 labels
Expand All @@ -106,7 +106,7 @@ Detect() # entity_labels=None
```
## Tuning the threshold

For `gliner_threshold`, start with the default `0.3`. If you're seeing too many false positives, raise it to `0.5`. If entities are being missed, try lowering to `0.2`. The LLM validation step catches many false positives, so erring on the side of lower thresholds is usually safe.
If you configure the self-hosted `gliner-pii-detector` alias, start with the default `gliner_threshold` of `0.3`. Raise it to `0.5` to reduce false positives, or lower it to `0.2` to improve recall. The setting does not apply to the default Nemotron Super detector.

---

Expand All @@ -116,9 +116,9 @@ The detection pipeline uses three model roles, each mapped to a model alias in t

| Role | Default alias | Purpose |
|------|--------------|---------|
| `entity_detector` | [`gliner-pii-detector`](https://build.nvidia.com/nvidia/gliner-pii) | GLiNER-PII NER model. |
| `entity_validator` | [`gpt-oss-120b`](https://build.nvidia.com/openai/gpt-oss-120b) | Validates and reclassifies detected entities. |
| `entity_augmenter` | [`gpt-oss-120b`](https://build.nvidia.com/openai/gpt-oss-120b) | Finds entities the NER model missed. |
| `latent_detector` | [`nemotron-30b-thinking`](https://build.nvidia.com/nvidia/nemotron-3-nano-30b-a3b) | Identifies inferable entities (rewrite only). |
| `entity_detector` | `nemotron-super` | Finds sensitive entity values. |
| `entity_validator` | `nemotron-super` | Validates and reclassifies detected entities. |
| `entity_augmenter` | `nemotron-super` | Finds entities the first pass missed. |
| `latent_detector` | `nemotron-super` | Identifies inferable entities (rewrite only). |

See [Models](models.md) for how to override these.
4 changes: 2 additions & 2 deletions docs/concepts/evaluation.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ Use `trace_dataframe` for the full internal trace including raw judge outputs.

### Model roles

The entity coverage judge defaults to `nemotron-super`; the other replace-evaluation judges default to `gpt-oss-120b`. Defaults are defined in [`evaluate.yaml`](https://github.com/NVIDIA-NeMo/Anonymizer/blob/main/src/anonymizer/config/default_model_configs/evaluate.yaml). Override them by passing a `model_configs` YAML to `Anonymizer(model_configs=...)` — see [Models](models.md) for the full override pattern.
All replace-evaluation judges default to `nemotron-super`. Defaults are defined in [`evaluate.yaml`](https://github.com/NVIDIA-NeMo/Anonymizer/blob/main/src/anonymizer/config/default_model_configs/evaluate.yaml). Override them by passing a `model_configs` YAML to `Anonymizer(model_configs=...)` — see [Models](models.md) for the full override pattern.

The roles are `entity_coverage_judge`, `detection_validity_judge`, `replace_type_fidelity_judge`, `replace_attribute_fidelity_judge`, and `replace_relational_consistency_judge`.

Expand Down Expand Up @@ -344,7 +344,7 @@ Use `trace_dataframe` for the full internal trace including raw judge outputs.

### Model roles

The rewrite quality judge defaults to `nemotron-30b-thinking` and the entity coverage judge to `nemotron-super`. The detection validity judge shares the `detection_validity_judge` role used by replace evaluation. Defaults are defined in [`evaluate.yaml`](https://github.com/NVIDIA-NeMo/Anonymizer/blob/main/src/anonymizer/config/default_model_configs/evaluate.yaml). Override them via `model_configs`:
The rewrite quality, entity coverage, and detection validity judges default to `nemotron-super`. The detection validity judge shares the `detection_validity_judge` role used by replace evaluation. Defaults are defined in [`evaluate.yaml`](https://github.com/NVIDIA-NeMo/Anonymizer/blob/main/src/anonymizer/config/default_model_configs/evaluate.yaml). Override them via `model_configs`:

```yaml
# my_models.yaml
Expand Down
7 changes: 3 additions & 4 deletions docs/concepts/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@ export NVIDIA_API_KEY="your-nvidia-api-key"

| Alias | Model | Used by |
|-------|-------|---------|
| `gliner-pii-detector` | [`nvidia/gliner-pii`](https://build.nvidia.com/nvidia/gliner-pii) | Entity detection (NER) |
| `gpt-oss-120b` | [`openai/gpt-oss-120b`](https://build.nvidia.com/openai/gpt-oss-120b) | Detection validation & augmentation, replacement, replace evaluation, rewriting |
| `nemotron-30b-thinking` | [`nvidia/nemotron-3-nano-30b-a3b`](https://build.nvidia.com/nvidia/nemotron-3-nano-30b-a3b) | Latent detection, rewrite evaluation, final judge |
| `nemotron-super` | [`nvidia/nemotron-3-super-v3`](https://build.nvidia.com/nvidia/nemotron-3-super-v3) | Entity coverage evaluation |
| `nemotron-super` | [`nvidia/nemotron-3-super-120b-a12b`](https://build.nvidia.com/nvidia/nemotron-3-super-120b-a12b) | All default detection, replacement, rewrite, and evaluation roles |

Each pipeline stage has a **role** mapped to one of these aliases. See the full role list in the default configs: [`detection.yaml`](https://github.com/NVIDIA-NeMo/Anonymizer/blob/main/src/anonymizer/config/default_model_configs/detection.yaml), [`replace.yaml`](https://github.com/NVIDIA-NeMo/Anonymizer/blob/main/src/anonymizer/config/default_model_configs/replace.yaml), [`rewrite.yaml`](https://github.com/NVIDIA-NeMo/Anonymizer/blob/main/src/anonymizer/config/default_model_configs/rewrite.yaml).

Expand Down Expand Up @@ -143,6 +140,8 @@ anonymizer = Anonymizer(

You can pass `model_configs` as either a YAML file path or a YAML string.

The detector alias selects its wire contract. The reserved `gliner-pii-detector` alias receives GLiNER-specific labels, threshold, and span parameters and must return GLiNER span JSON. Any other detector alias uses the structured LLM detector contract and returns exact entity values and labels; Anonymizer materializes those values as text spans.

Roles you don't override keep their default alias selections, but those aliases must still exist in your `model_configs` pool.

!!! tip "Validate your config"
Expand Down
14 changes: 7 additions & 7 deletions docs/concepts/rewrite.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,13 @@ Rewrite uses multiple LLM roles. All default to models in the [default config](m

| Role | Default | Purpose |
|------|---------|---------|
| `domain_classifier` | `gpt-oss-120b` | Classifies text domain. |
| `disposition_analyzer` | `gpt-oss-120b` | Assigns sensitivity levels. |
| `meaning_extractor` | `gpt-oss-120b` | Extracts meaning units. |
| `qa_generator` | `gpt-oss-120b` | Generates QA pairs for evaluation. |
| `rewriter` | `gpt-oss-120b` | Generates the rewritten text. |
| `evaluator` | `nemotron-30b-thinking` | Evaluates quality and leakage. |
| `repairer` | `gpt-oss-120b` | Repairs high-leakage rewrites. |
| `domain_classifier` | `nemotron-super` | Classifies text domain. |
| `disposition_analyzer` | `nemotron-super` | Assigns sensitivity levels. |
| `meaning_extractor` | `nemotron-super` | Extracts meaning units. |
| `qa_generator` | `nemotron-super` | Generates QA pairs for evaluation. |
| `rewriter` | `nemotron-super` | Generates the rewritten text. |
| `evaluator` | `nemotron-super` | Evaluates quality and leakage. |
| `repairer` | `nemotron-super` | Repairs high-leakage rewrites. |

---

Expand Down
26 changes: 12 additions & 14 deletions docs/concepts/self-hosting-gliner.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

# Self-hosting GLiNER

By default, Anonymizer's entity detection stage calls the hosted `nvidia/gliner-pii` model on `build.nvidia.com`. For PHI-sensitive workloads that cannot leave the host, or latency-critical setups, you can serve GLiNER locally instead.
By default, Anonymizer's entity detection stage uses Nemotron Super on `build.nvidia.com`. For PHI-sensitive workloads that cannot leave the host, or latency-critical setups, you can replace that role with a locally served GLiNER detector.

The model is small (~500 MB) and runs comfortably on CPU — making it a good fit to run alongside a local LLM without competing for GPU memory. It also runs on GPU if one is available, which cuts detection latency on long documents.

Expand Down Expand Up @@ -169,7 +169,7 @@ An empty `"entities": []` means either no `labels` in the request matched real P

## Pointing Anonymizer at the local server

Pass separate `model_providers` and `model_configs` files to `Anonymizer`. **`model_configs` replaces the entire model pool** — it is not merged with defaults. Copy the bundled [`models.yaml`](https://github.com/NVIDIA-NeMo/Anonymizer/blob/main/src/anonymizer/config/default_model_configs/models.yaml), change only the `gliner-pii-detector` entry's `provider`, and keep the other default aliases (`gpt-oss-120b`, `nemotron-30b-thinking`). Default role→alias mappings still apply unless you override `selected_models` (see [Custom models](models.md#custom-models)).
Pass separate `model_providers` and `model_configs` files to `Anonymizer`. **`model_configs` replaces the entire model pool** — it is not merged with defaults. Keep the bundled `nemotron-super` entry, add the local `gliner-pii-detector` entry, and override the `entity_detector` role as shown below. Other roles retain their `nemotron-super` defaults.

Custom `model_providers` also replaces the provider list, so include both your local GLiNER endpoint and the `nvidia` provider used by the LLM roles:

Expand All @@ -191,6 +191,10 @@ export NVIDIA_API_KEY="your-nvidia-api-key"
```

```yaml title="models.yaml"
selected_models:
detection:
entity_detector: gliner-pii-detector

model_configs:
- alias: gliner-pii-detector
model: nvidia/gliner-pii
Expand All @@ -200,25 +204,19 @@ model_configs:
max_parallel_requests: 8 # send concurrent rows; the reference server batches them
timeout: 120

- alias: gpt-oss-120b
model: openai/gpt-oss-120b
- alias: nemotron-super
model: nvidia/nemotron-3-super-120b-a12b
provider: nvidia
inference_parameters:
max_parallel_requests: 16
max_tokens: 16384
temperature: 0.3
top_p: 0.95
timeout: 300

- alias: nemotron-30b-thinking
model: nvidia/nemotron-3-nano-30b-a3b
provider: nvidia
inference_parameters:
max_parallel_requests: 16
max_tokens: 8192
temperature: 0.4
top_p: 1.0
timeout: 300
extra_body:
reasoning_effort: none
chat_template_kwargs:
enable_thinking: false
```

```python
Expand Down
4 changes: 2 additions & 2 deletions docs/notebook_source/02_inspecting_detected_entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@
# ## 📡 Sources
#
# - Where each entity came from in the pipeline:
# - `detector` -- GLiNER NER
# - `augmenter` -- LLM-added (missed by GLiNER)
# - `detector` -- the configured first-pass detector
# - `augmenter` -- LLM-added (missed by the configured detector)
# - `validator` -- LLM decision step over detector-seed entities (keep/reclass/drop); does not emit a separate source value
# - `name_split` -- derived from splitting full names
# - `propagation` -- expanded from validated entities to all text occurrences
Expand Down
4 changes: 2 additions & 2 deletions docs/notebooks/02_inspecting_detected_entities.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -484,8 +484,8 @@
"## 📡 Sources\n",
"\n",
"- Where each entity came from in the pipeline:\n",
" - `detector` -- GLiNER NER\n",
" - `augmenter` -- LLM-added (missed by GLiNER)\n",
" - `detector` -- the configured first-pass detector\n",
" - `augmenter` -- LLM-added (missed by the configured detector)\n",
" - `validator` -- LLM decision step over detector-seed entities (keep/reclass/drop); does not emit a separate source value\n",
" - `name_split` -- derived from splitting full names\n",
" - `propagation` -- expanded from validated entities to all text occurrences"
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ anonymizer = "anonymizer.interface.cli.main:main"
[project.entry-points."data_designer.plugins"]
anonymizer-detection-transform = "anonymizer.engine.workflow_columns.detection.plugins:detection_transform_plugin"
anonymizer-chunked-validation = "anonymizer.engine.workflow_columns.detection.plugins:chunked_validation_plugin"
anonymizer-tolerant-structured = "anonymizer.engine.workflow_columns.structured.plugins:tolerant_structured_plugin"

[dependency-groups]
dev = [
Expand Down
Loading
Loading