NVIDIANeMo Curator
Menu

Distributed Data Classification

NVIDIA NeMo Curator provides a module for performing distributed classification on large text datasets using GPU acceleration. This enables the categorization and filtering of text documents based on multiple dimensions such as domain, quality, safety, educational value, content type, and more. These classifications can enhance the quality of training data for large language models by identifying high-value content and removing problematic material.

How It Works

The distributed data classification in NeMo Curator works by:

  1. Parallel Processing: Chunking datasets across multiple computing nodes and GPUs to accelerate classification
  2. Pre-trained Models: Using specialized models for different classification tasks
  3. Batched Inference: Optimizing throughput with intelligent batching
  4. Consistent API: Providing a unified interface through the DistributedDataClassifier base class

The DistributedDataClassifier is designed to run on GPU clusters with minimal code changes regardless of which specific classifier you’re using. All classifiers support filtering based on classification results and storing prediction scores as metadata.


Usage

NVIDIA NeMo Curator provides a base class DistributedDataClassifier that can be extended to fit your specific model. The only requirement is that the model can fit on a single GPU. This module operates on the GPU and works within the pipeline framework using DocumentBatch processing.

Classifier Comparison

ClassifierPurposeModel LocationKey ParametersRequirements
DomainClassifierAssigns one of 26 domain labels (such as “Sports,” “Science,” “News”) to English textnvidia/domain-classifierfilter_by, text_fieldNone
MultilingualDomainClassifierAssigns domain labels to text in 52 languages; same labels as DomainClassifiernvidia/multilingual-domain-classifierfilter_by, text_fieldNone
QualityClassifierRates document quality as “Low,” “Medium,” or “High” using a DeBERTa modelnvidia/quality-classifier-debertafilter_by, text_fieldNone
AegisClassifierDetects unsafe content across 13 risk categories (violence, hate speech, and others) using LlamaGuardnvidia/Aegis-AI-Content-Safety-LlamaGuard-Defensive-1.0aegis_variant, filter_byHuggingFace token
InstructionDataGuardClassifierIdentifies LLM poisoning attacks in instruction-response pairsnvidia/instruction-data-guardtext_field, label_fieldHuggingFace token
FineWebEduClassifierScores educational value from 0 to 5 (0=spam, 5=scholarly) for training data selectionHuggingFaceFW/fineweb-edu-classifierlabel_field, int_fieldNone
FineWebMixtralEduClassifierScores educational value from 0 to 5 using Mixtral 8x22B annotation datanvidia/nemocurator-fineweb-mixtral-edu-classifierlabel_field, int_field, model_inference_batch_size=1024None
FineWebNemotronEduClassifierScores educational value from 0 to 5 using Nemotron-4-340B annotation datanvidia/nemocurator-fineweb-nemotron-4-edu-classifierlabel_field, int_field, model_inference_batch_size=1024None
ContentTypeClassifierCategorizes text into 11 speech types (such as “Blogs,” “News,” “Academic”)nvidia/content-type-classifier-debertafilter_by, text_fieldNone
PromptTaskComplexityClassifierLabels prompts by task type (such as QA and summarization) and complexity dimensionsnvidia/prompt-task-and-complexity-classifiertext_fieldNone

Domain Classifier

The Domain Classifier categorizes English text documents into specific domains or subject areas.

from nemo_curator.pipeline import Pipeline
from nemo_curator.stages.text.io.reader import JsonlReader
from nemo_curator.stages.text.io.writer import JsonlWriter
from nemo_curator.stages.text.classifiers import DomainClassifier

# Create pipeline
pipeline = Pipeline(name="domain_classification")

# Load dataset
reader = JsonlReader(
    file_paths="books_dataset/",
    fields=["text", "id"]
)
pipeline.add_stage(reader)

# Apply the classifier, filtering for specific domains
domain_classifier = DomainClassifier(filter_by=["Games", "Sports"])
pipeline.add_stage(domain_classifier)

# Save the results
writer = JsonlWriter(path="games_and_sports/")
pipeline.add_stage(writer)

# Execute pipeline
results = pipeline.run()  # Uses XennaExecutor by default

Multilingual Domain Classifier

Functionally similar to the Domain Classifier, but supports 52 languages.

from nemo_curator.pipeline import Pipeline
from nemo_curator.stages.text.io.reader import JsonlReader
from nemo_curator.stages.text.io.writer import JsonlWriter
from nemo_curator.stages.text.classifiers import MultilingualDomainClassifier

pipeline = Pipeline(name="multilingual_domain_classification")
pipeline.add_stage(JsonlReader(file_paths="multilingual_dataset/", fields=["text", "id"]))
pipeline.add_stage(MultilingualDomainClassifier(filter_by=["Games", "Sports"]))
pipeline.add_stage(JsonlWriter(path="classified_output/"))

results = pipeline.run()  # Uses XennaExecutor by default

Quality Classifier

The Quality Classifier assesses document quality using the NVIDIA Quality Classifier DeBERTa model.

from nemo_curator.pipeline import Pipeline
from nemo_curator.stages.text.io.reader import JsonlReader
from nemo_curator.stages.text.io.writer import JsonlWriter
from nemo_curator.stages.text.classifiers import QualityClassifier

pipeline = Pipeline(name="quality_classification")
pipeline.add_stage(JsonlReader(file_paths="web_documents/", fields=["text", "id"]))
pipeline.add_stage(QualityClassifier())
pipeline.add_stage(JsonlWriter(path="quality_classified/"))

results = pipeline.run()  # Uses XennaExecutor by default

AEGIS Safety Classifier

The AEGIS classifier detects unsafe content across 13 critical risk categories. It requires a HuggingFace token for access to Llama Guard.

from nemo_curator.pipeline import Pipeline
from nemo_curator.stages.text.io.reader import JsonlReader
from nemo_curator.stages.text.io.writer import JsonlWriter
from nemo_curator.stages.text.classifiers import AegisClassifier

# Create pipeline
pipeline = Pipeline(name="aegis_classification")

# Load dataset
reader = JsonlReader(
    file_paths="content/",
    fields=["text", "id"]
)
pipeline.add_stage(reader)

# Apply the AEGIS classifier
token = "hf_1234"  # Your HuggingFace user access token
safety_classifier = AegisClassifier(
    aegis_variant="nvidia/Aegis-AI-Content-Safety-LlamaGuard-Defensive-1.0",
    hf_token=token,
    filter_by=["safe", "O13"]  # Keep only safe content and "needs caution" category
)
pipeline.add_stage(safety_classifier)

# Save the results
writer = JsonlWriter(path="safe_content/")
pipeline.add_stage(writer)

# Execute pipeline
results = pipeline.run()  # Uses XennaExecutor by default

The classifier adds a column with labels: “safe,” “O1” through “O13” (each representing specific safety risks), or “unknown.”

For raw LLM output, use:

safety_classifier = AegisClassifier(
    aegis_variant="nvidia/Aegis-AI-Content-Safety-LlamaGuard-Defensive-1.0",
    hf_token=token,
    keep_raw_output=True,
    raw_output_field="raw_predictions"
)

Instruction Data Guard

Detects LLM poisoning attacks in instruction-response datasets. Requires HuggingFace token access.

from nemo_curator.pipeline import Pipeline
from nemo_curator.stages.text.io.reader import JsonlReader
from nemo_curator.stages.text.io.writer import JsonlWriter
from nemo_curator.stages.text.classifiers import InstructionDataGuardClassifier

# Create pipeline
pipeline = Pipeline(name="instruction_data_guard")

# Load dataset
# For instruction-response data: "Instruction: {instruction}. Input: {input_}. Response: {response}."
reader = JsonlReader(
    file_paths="instruction_data/",
    fields=["text", "id"]
)
pipeline.add_stage(reader)

# Apply the classifier
token = "hf_1234"  # Your HuggingFace user access token
classifier = InstructionDataGuardClassifier(hf_token=token)
pipeline.add_stage(classifier)

# Save the results
writer = JsonlWriter(path="guard_classified/")
pipeline.add_stage(writer)

# Execute pipeline
results = pipeline.run()  # Uses XennaExecutor by default

The output includes two columns: a float score instruction_data_guard_poisoning_score and a Boolean is_poisoned.

FineWeb Educational Content Classifier

Scores documents on educational value from 0–5. This helps prioritize content for knowledge-intensive tasks.

Score Ranges and Meanings

ScoreLabelDescriptionExample Content
0-1Very LowNo educational valueSpam, advertisements, broken content
2LowMinimal educational contentSimple lists, basic product descriptions
3ModerateSome educational valueNews articles, basic how-to guides
4HighGood educational contentDetailed tutorials, academic discussions
5Very HighExcellent educational materialComprehensive guides, scholarly articles
from nemo_curator.pipeline import Pipeline
from nemo_curator.stages.text.io.reader import JsonlReader
from nemo_curator.stages.text.io.writer import JsonlWriter
from nemo_curator.stages.text.classifiers import FineWebEduClassifier

# Create pipeline
pipeline = Pipeline(name="fineweb_edu_classification")

# Load dataset
reader = JsonlReader(
    file_paths="web_documents/*.jsonl",
    fields=["text", "id"]
)
pipeline.add_stage(reader)

# Apply the FineWeb Edu classifier
edu_classifier = FineWebEduClassifier(
    model_inference_batch_size=256,
    float_score_field="fineweb-edu-score-float",  # Raw float scores
    int_score_field="fineweb-edu-score-int",      # Rounded integer scores
    label_field="fineweb-edu-score-label"         # Quality labels
)
pipeline.add_stage(edu_classifier)

# Save the results
writer = JsonlWriter(path="edu_classified/")
pipeline.add_stage(writer)

# Execute pipeline
results = pipeline.run()  # Uses XennaExecutor by default

FineWeb Mixtral and Nemotron Edu Classifiers

Similar to the FineWeb Edu Classifier but trained with different annotation sources:

  • FineWebMixtralEduClassifier: Uses annotations from Mixtral 8x22B-Instruct
  • FineWebNemotronEduClassifier: Uses annotations from Nemotron-4-340B-Instruct

Both provide a quality label column marking scores above 2.5 as “high_quality”:

Quality Label Mapping

Score RangeQuality LabelDescription
0.0 - 2.5low_qualityBelow average educational value
2.5 - 5.0high_qualityAbove average educational value
from nemo_curator.pipeline import Pipeline
from nemo_curator.stages.text.io.reader import JsonlReader
from nemo_curator.stages.text.io.writer import JsonlWriter
from nemo_curator.stages.text.classifiers import FineWebMixtralEduClassifier  # or FineWebNemotronEduClassifier

# Create pipeline
pipeline = Pipeline(name="fineweb_mixtral_edu_classification")

# Load dataset
reader = JsonlReader(
    file_paths="web_documents/*.jsonl",
    fields=["text", "id"]
)
pipeline.add_stage(reader)

# Apply the FineWeb Mixtral Edu classifier
classifier = FineWebMixtralEduClassifier(
    float_score_field="fineweb-mixtral-edu-score-float",  # Raw float scores
    int_score_field="fineweb-mixtral-edu-score-int",      # Rounded integer scores
    label_field="fineweb-mixtral-edu-score-label"          # "high_quality" or "low_quality"
)
pipeline.add_stage(classifier)

# Save the results
writer = JsonlWriter(path="mixtral_edu_classified/")
pipeline.add_stage(writer)

# Execute pipeline
results = pipeline.run()  # Uses XennaExecutor by default

Content Type Classifier

Categorizes documents into 11 distinct speech types.

from nemo_curator.pipeline import Pipeline
from nemo_curator.stages.text.io.reader import JsonlReader
from nemo_curator.stages.text.io.writer import JsonlWriter
from nemo_curator.stages.text.classifiers import ContentTypeClassifier

# Create pipeline
pipeline = Pipeline(name="content_type_classification")

# Load dataset
reader = JsonlReader(
    file_paths="content/",
    fields=["text", "id"]
)
pipeline.add_stage(reader)

# Apply the Content Type classifier
classifier = ContentTypeClassifier(filter_by=["Blogs", "News"])
pipeline.add_stage(classifier)

# Save the results
writer = JsonlWriter(path="content_type_classified/")
pipeline.add_stage(writer)

# Execute pipeline
results = pipeline.run()  # Uses XennaExecutor by default

Prompt Task and Complexity Classifier

Classifies prompts by task type and complexity dimensions.

from nemo_curator.pipeline import Pipeline
from nemo_curator.stages.text.io.reader import JsonlReader
from nemo_curator.stages.text.io.writer import JsonlWriter
from nemo_curator.stages.text.classifiers import PromptTaskComplexityClassifier

# Create pipeline
pipeline = Pipeline(name="prompt_task_complexity_classification")

# Load dataset
reader = JsonlReader(
    file_paths="prompts/",
    fields=["text", "id"]
)
pipeline.add_stage(reader)

# Apply the Prompt Task Complexity classifier
classifier = PromptTaskComplexityClassifier()
pipeline.add_stage(classifier)

# Save the results
writer = JsonlWriter(path="prompt_complexity_classified/")
pipeline.add_stage(writer)

# Execute pipeline
results = pipeline.run()  # Uses XennaExecutor by default

Share Tokens Across Multiple Classifiers

Many of NeMo Curator’s text classifiers use the same underlying tokenizer. When you run multiple classifiers in a single pipeline, you can tokenize once and reuse the tokens for all compatible classifiers. This avoids redundant tokenization and speeds up your pipeline.

Compatible Tokenizer Groups

Classifiers that share the same base tokenizer can reuse each other’s tokens:

TokenizerClassifiers
DeBERTa-v3-baseDomainClassifier, MultilingualDomainClassifier, QualityClassifier, ContentTypeClassifier, FineWebEduClassifier, FineWebMixtralEduClassifier, FineWebNemotronEduClassifier, PromptTaskComplexityClassifier
LlamaGuard-7bAegisClassifier, InstructionDataGuardClassifier

How It Works

Each classifier exposes two parameters for token sharing:

  • keep_tokens (default: False): When True, the classifier preserves the input_ids and attention_mask columns in its output instead of dropping them. Set this on the first classifier in the pipeline so downstream classifiers can reuse the tokens.
  • use_existing_tokens (default: False): When True, the classifier skips its internal tokenization step and uses the input_ids and attention_mask columns already present in the data. Set this on all subsequent classifiers.

Example: Tokenize Once for Multiple Classifiers

The following pipeline tokenizes the input text once with the DomainClassifier, then passes those tokens to the QualityClassifier and ContentTypeClassifier:

from nemo_curator.pipeline import Pipeline
from nemo_curator.stages.text.io.reader import JsonlReader
from nemo_curator.stages.text.io.writer import JsonlWriter
from nemo_curator.stages.text.classifiers import (
    DomainClassifier,
    QualityClassifier,
    ContentTypeClassifier,
)

pipeline = Pipeline(name="shared_tokenizer_pipeline")

# Load dataset
pipeline.add_stage(JsonlReader(file_paths="documents/", fields=["text", "id"]))

# First classifier: tokenize and keep the tokens
pipeline.add_stage(DomainClassifier(keep_tokens=True))

# Second classifier: reuse existing tokens, keep them for the next stage
pipeline.add_stage(QualityClassifier(use_existing_tokens=True, keep_tokens=True))

# Third classifier: reuse existing tokens, drop them (last in chain)
pipeline.add_stage(ContentTypeClassifier(use_existing_tokens=True, keep_tokens=False))

# Save the results
pipeline.add_stage(JsonlWriter(path="classified_output/"))

results = pipeline.run()

Custom Model Integration

You can integrate your own classification models by extending DistributedDataClassifier. Refer to the Text Classifiers README for implementation details and examples.

Performance Optimization

NVIDIA NeMo Curator’s distributed classifiers are optimized for high-throughput processing through several key features:

Intelligent Batching and Sequence Handling

The classifiers optimize throughput through:

  • Length-based sorting: Input sequences are sorted by length when sort_by_length=True (default)
  • Efficient batching: Similar-length sequences are grouped together to minimize padding overhead
  • GPU memory optimization: Batches are sized to maximize GPU utilization based on available memory