Skip to main content

NeMo Anonymizer

License Python 3.11+

Detect and replace sensitive entities in text using LLM-powered workflows.


What can you do with Anonymizer?

  • Detect entities using GLiNER-PII and LLM-based 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

Quick Start

1. Install

pip install nemo-anonymizer

Or install from source:

git clone https://github.com/NVIDIA-NeMo/Anonymizer.git
cd Anonymizer
make install

2. Set up model providers

By default, Anonymizer expects a compatible local GLiNER2 endpoint for entity detection and uses text LLMs hosted on OpenRouter for augmentation and validation. The tutorial notebooks can start the local detector automatically. You can also bring your own models via custom provider configs.

Use of OpenRouter is subject to its own terms of service and privacy practices, which are separate from and independent of the NeMo Framework library. Review those terms and the data policies of the models you select before sending sensitive data to the default endpoint.

export OPENROUTER_API_KEY="your-openrouter-api-key"

3. Anonymize text

CLI

Tip: All examples below use uv run to invoke commands. If you prefer, activate the venv with source .venv/bin/activate and run commands directly.

DATA_URL="https://raw.githubusercontent.com/NVIDIA-NeMo/Anonymizer/refs/heads/main/docs/data/NVIDIA_synthetic_biographies.csv"

# Preview on a small sample
uv run anonymizer preview --source $DATA_URL --text-column biography --replace redact --num_records 3

# Full run with output file
uv run anonymizer run --source $DATA_URL --text-column biography --replace redact --output result.csv

# Validate config without running
uv run anonymizer validate --source $DATA_URL --text-column biography --replace hash

Run anonymizer --help or anonymizer <subcommand> --help for all options.

Python API

from anonymizer import Anonymizer, AnonymizerConfig, AnonymizerInput, Redact
DATA_URL = "https://raw.githubusercontent.com/NVIDIA-NeMo/Anonymizer/refs/heads/main/docs/data/NVIDIA_synthetic_biographies.csv"

# Uses Anonymizer's bundled model providers (see src/anonymizer/config/default_model_configs/providers.yaml)
anonymizer = Anonymizer()

config = AnonymizerConfig(replace=Redact())

preview = anonymizer.preview(
    config=config,
    data=AnonymizerInput(source=DATA_URL, text_column="biography"),
    num_records=3,
)

# Visualize with entity highlights and replacement map
preview.display_record()

# Most important columns only
preview.dataframe

# Full pipeline trace, including internal underscore-prefixed columns
preview.trace_dataframe

For custom model endpoints, pass a providers YAML:

anonymizer = Anonymizer(model_providers="path/to/model_providers.yaml")

For services and other applications that already hold text in memory, pass typed records instead of writing a temporary CSV or Parquet file:

from anonymizer import TextRecord, TextRecordsInput

data = TextRecordsInput(
    records=[
        TextRecord(id="turn-1", text="Contact Alice at alice@example.com"),
        TextRecord(id="turn-2", text="Bob works at Acme"),
    ],
    data_summary="Application observability messages",
)
result = anonymizer.run(config=config, data=data)

# Stable public output: IDs, transformed text, and validated entity spans.
print(result.dataframe[["id", "text_replaced", "final_entities"]])

IDs and input order are retained for records that complete the pipeline. A dropped record uses the same caller-provided ID in result.failed_records. trace_dataframe is for pipeline diagnostics.

Language And Regional Coverage

Anonymizer has been tested most extensively on English-language data. Multilingual quality has not yet been evaluated systematically across languages, domains, and models.

Although testing so far has been primarily in English, the supported entity set is not limited to U.S.-specific identifiers. Detection and anonymization can also apply to international formats such as non-U.S. phone numbers, addresses, legal references, and national or regional identification numbers, though coverage will vary by language, region, and model configuration.

If you are working with another language, we encourage you to experiment on a small sample first with preview(), validate detected entities and transformed output carefully, and adjust your model providers and model configs as needed.


Replacement Strategies

Strategy Output for "Alice" (first_name) Configurable
Substitute Maya instructions
Redact [REDACTED_FIRST_NAME] format_template
Annotate <Alice, first_name> format_template
Hash <HASH_FIRST_NAME_3bc51062973c> format_template, algorithm, digest_length
from anonymizer import Redact, Annotate, Hash, Substitute

# LLM-generated contextual replacements
AnonymizerConfig(replace=Substitute())

# Constant redaction
AnonymizerConfig(replace=Redact(format_template="****"))

# Annotation with entities tagging
AnonymizerConfig(replace=Annotate(format_template="<{text}-|-{label}>"))

# Deterministic hash with short digest
AnonymizerConfig(replace=Hash(algorithm="sha256", digest_length=8))

Using the Agent Skill

This repo ships an Agent Skill at skills/anonymizer/ that elicits your dataset's privacy requirements, helps choose Rewrite or Replace with an appropriate strategy, and drafts a runnable script for you to iterate on.

Install via skills.sh:

npx skills add NVIDIA-NeMo/Anonymizer

After installation, invoke it with /anonymizer in an agent that supports slash-style skill calls, or describe what you want to anonymize and let it auto-trigger.


Development

make install-dev          # Install with dev dependencies
make test                 # Run tests
make coverage             # Run with coverage report
make format-check         # Lint + format check (read-only)
anonymizer --help         # CLI usage
make install-pre-commit   # Install pre-commit hooks

Requirements

  • Python 3.11+
  • NeMo Data Designer (installed as dependency)
  • A compatible local GLiNER2 endpoint (the tutorial notebooks can start one automatically)
  • OpenRouter API key for the default text LLM provider, or custom model endpoints

Telemetry and Privacy

NeMo Anonymizer collects anonymous run-level telemetry to help prioritize product improvements. One event is sent per Anonymizer.run() / Anonymizer.preview() call, containing only technical metadata: the replacement strategy in use, models used, model hosts (e.g. nvidia-build, openrouter, other), input-record counts, run duration, and failure attribution by pipeline step. No user data, record contents, prompts, or model outputs are collected. See the Telemetry and Privacy docs for the full field list.

You may opt out of telemetry at any time:

  • For one CLI invocation: pass --no-emit-telemetry
    uv run anonymizer run --source data.csv --text-column text --replace redact --no-emit-telemetry
    
  • In the SDK: set emit_telemetry=False on AnonymizerConfig
    config = AnonymizerConfig(replace=Redact(), emit_telemetry=False)
    
  • For the current shell: set the environment variable
    export NEMO_TELEMETRY_ENABLED=false
    

Aggregate usage data (such as which models are most popular) will be shared back with the community. It is not used to track any individual user behavior.

Use of third-party endpoints, including OpenRouter and NVIDIA Build: Anonymizer can be configured to use various inference endpoints, including OpenRouter, build.nvidia.com, or local model servers. If you choose to use a third-party endpoint, that endpoint's own terms of service and privacy practices apply independently of this library. Any opt-out you exercise within Anonymizer does not extend to data collection by your chosen endpoint.


License

Apache License 2.0 — see LICENSE for details.

Metadata

Release files for nemo-anonymizer 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for nemo-anonymizer 0.5.0
File Interpreter ABI Platform Actions
nemo_anonymizer-0.5.0-py3-none-any.whl Python 3 none any Details for nemo_anonymizer-0.5.0-py3-none-any.whl

Release files / nemo_anonymizer-0.5.0-py3-none-any.whl

Download URL nemo_anonymizer-0.5.0-py3-none-any.whl
Size 279.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fc33da110cddd21111fa8afc90f848a3fc73e9cb5679695a45d9d7a9943b7eb4
BLAKE2b-256 checksum
How to use checksums
b6626bc90eb88a3f1530775963e13f6f326aafcfab90b4a121e330c93e354412
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.17

Security for nemo-anonymizer 0.5.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A 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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page