Processing Data¶
This guide covers running data processing pipelines with Data-Juicer—both CLI and Python API.
If you haven’t run your first pipeline yet, start with the Quick Start. For the full parameter list, see Global Configuration Reference.
CLI¶
Basic Usage¶
dj-process --config my-recipe.yaml
Data-Juicer reads the recipe, executes operators in the listed order by default, and writes results to export_path.
Command-Line Overrides¶
Override any recipe parameter without modifying the YAML:
dj-process --config recipe.yaml --np 8 --export_path ./out/result.parquet
dj-process --config recipe.yaml --language_id_score_filter.lang=en
Auto-Install Operator Dependencies¶
dj-install --config my-recipe.yaml
The tool scans source files for the operators in the recipe and preinstalls the dependencies it identifies. See Installation for the scan scope and environment preparation.
Python API¶
The Python API provides finer control than YAML recipes—ideal for training scripts, notebooks, or automated pipelines.
Option 1: Load a Recipe¶
from data_juicer.config import init_configs
from data_juicer.core import DefaultExecutor
cfg = init_configs(args=['--config', 'my-recipe.yaml'])
executor = DefaultExecutor(cfg)
dataset = executor.run()
If you already hold a dataset object in memory (e.g. assembled or sampled upstream), you can skip the recipe’s data source and reuse only its operator pipeline:
dataset = executor.run(dataset=my_dataset, skip_export=True)
Option 2: Instantiate Operators from Config¶
No YAML needed—assemble an operator chain in Python:
from data_juicer.ops import load_ops
from data_juicer.core import NestedDataset
# Load ops from dict config (same format as YAML process list)
ops = load_ops([
{'language_id_score_filter': {'lang': 'en', 'min_score': 0.8}},
{'text_length_filter': {'min_len': 10, 'max_len': 50000}},
{'document_minhash_deduplicator': {'tokenization': 'space', 'window_size': 5}},
])
dataset = NestedDataset(NestedDataset.from_json('my-data.jsonl'))
dataset = dataset.process(ops)
Option 3: Fine-Grained Single-Operator Control¶
When you need conditional logic, loops, or intermediate inspection:
from data_juicer.ops.filter import LanguageIDScoreFilter, TextLengthFilter
from data_juicer.ops.deduplicator import DocumentMinhashDeduplicator
from data_juicer.core import NestedDataset
dataset = NestedDataset(NestedDataset.from_json('my-data.jsonl'))
# Step 1: Language filter
lang_filter = LanguageIDScoreFilter(lang='en', min_score=0.8)
dataset = lang_filter.run(dataset=dataset)
print(f"After language filter: {len(dataset)} samples")
# Step 2: Conditional dedup — only when dataset is large
if len(dataset) > 10000:
dedup = DocumentMinhashDeduplicator(tokenization='space', window_size=5)
dataset = dedup.run(dataset=dataset)
print(f"After dedup: {len(dataset)} samples")
# Step 3: Length filter
length_filter = TextLengthFilter(min_len=10, max_len=50000)
dataset = length_filter.run(dataset=dataset)
Option 4: Dynamic Operator Composition¶
Choose operators programmatically based on data characteristics—useful for automated pipelines:
from data_juicer.ops import load_ops
from data_juicer.core import NestedDataset
dataset = NestedDataset(NestedDataset.from_json('input.jsonl'))
# Inspect data to decide processing strategy
sample = dataset[0]
ops_config = []
# Add language filter if text field exists
if 'text' in sample:
ops_config.append({'language_id_score_filter': {'lang': 'en', 'min_score': 0.5}})
# Add image filter if images present
if 'images' in sample and sample['images']:
ops_config.append({'image_shape_filter': {'min_width': 256, 'min_height': 256}})
# Common cleaning
ops_config.append({'clean_html_mapper': {}})
ops_config.append({'text_length_filter': {'min_len': 10}})
ops = load_ops(ops_config)
dataset = dataset.process(ops)
API Models¶
Use an API operator such as extract_keyword_mapper to process text with a hosted model. Set api_model to the model name supplied by your service and configure the connection in model_params.
OpenAI-Compatible Services¶
Install the API dependencies in your activated environment:
uv pip install "py-data-juicer[ai_services]"
Set the service URL and API key in your shell:
export OPENAI_BASE_URL="https://api.openai.com/v1"
export OPENAI_API_KEY="your-api-key"
To use another OpenAI-compatible service, replace the URL and key with that service’s values. Save this recipe as extract.yaml and set dataset_path to a JSONL file with a text field:
dataset_path: ./input.jsonl
export_path: ./outputs/extracted.jsonl
keep_stats_in_res_ds: true
process:
- extract_keyword_mapper:
api_model: gpt-4o-mini
model_params:
api_backend: openai_compatible
sampling_params:
temperature: 0
Run dj-process --config extract.yaml. The operator saves the extracted keywords under __dj__meta__.keyword; keep_stats_in_res_ds: true retains that metadata in the output.
openai_compatible is the default backend. You can also supply base_url and api_key in model_params; these values take precedence over the corresponding environment variables.
LiteLLM¶
To route requests through LiteLLM, set model_params.api_backend: litellm and use a provider-qualified model name. For example, replace the operator entry in the recipe above with:
process:
- extract_keyword_mapper:
api_model: openai/gpt-4o-mini
model_params:
api_backend: litellm
sampling_params:
temperature: 0
Configure credentials for the selected provider. The OpenAI example uses OPENAI_API_KEY; other providers use their own LiteLLM authentication settings. You can supply api_key and base_url in model_params when the provider requires them.
Choose an operator that supports the task you need. The API backend supports chat, embedding, and Responses endpoints; operators that expose api_endpoint can select the corresponding endpoint. Use sampling_params for request options such as temperature and model_params for the backend, service URL, and credentials.
Operator Execution Order¶
By default, operators run top-to-bottom sequentially. Order matters:
Cheap filters first: Text length, language ID—reduce sample count early
Dedup in the middle: Requires global state; run after initial filtering
Expensive operators last: GPU inference only sees the filtered subset
process:
# Cheap
- text_length_filter: { min_len: 10, max_len: 50000 }
- language_id_score_filter: { lang: en, min_score: 0.5 }
# Dedup
- document_minhash_deduplicator: { tokenization: space, window_size: 5 }
# Expensive
- clean_html_mapper: {}
- perplexity_filter: { lang: en, max_ppl: 1500 }
Performance Tuning¶
Op Fusion¶
Fuses compatible operators to reduce repeated processing. Both default and Ray execution paths support fusion. Throughput gains depend on the recipe and data; measure them for your workload:
op_fusion: true
fusion_strategy: probe # probe: group and sort by measured speed; greedy: order by fusion group
Fusion groups compatible operators and may change their order in the recipe. With probe, the default executor and standard Analyzer use the first 1,000 rows of the current dataset by default, or all rows of a smaller dataset. Each operator runs the probe on copies of this batch, with one copy per runtime process. Ray executors arrange operators by fusion group.
GPU Mapper Fusion¶
Fuses consecutive GPU Mappers into one GPU pass:
op_fusion: true
mapper_fusion: true
adaptive_batch_size: true
The default executor uses adaptive_batch_size to probe and adjust batch sizes for batched operators.
Sampling Dry Run¶
For a source with at least 1,000 rows, validate a recipe on 1,000 samples with the default executor by replacing its dataset_path with a structured dataset configuration. Keep its process list:
dataset:
max_sample_num: 1000
configs:
- type: local
path: path/to/your/dataset.jsonl
Replace the path with your dataset. max_sample_num sets the sample count; for a small trial, choose a count no larger than the source. Larger budgets are filled by repeating samples.
Sampling runs after data loading. To also reduce input reads, prepare a small sample file and use it as the input. Remove max_sample_num to process the full dataset.
Checkpointing & Resumption¶
use_checkpoint: true
The default executor locates checkpoints by job_id and the working-directory base. Specify a fixed ID on the first run. To resume after interruption, run the same command with the same input, recipe, and working-directory configuration:
dj-process --config your-recipe.yaml --use_checkpoint true --job_id recipe-checkpoint
Checkpoints live in the resolved <cfg.work_dir>/ckpt, where work_dir includes job_id. use_checkpoint disables data caching and is mutually exclusive with op_fusion.
For ray_partitioned, finer strategies are available; resume with --resume <job_id>. See Global Config.
Tracing & Debugging¶
open_tracer: true
trace_num: 10
Writes before/after comparisons per operator. See Tracing.
Next Steps¶
Data Analysis—understand your data distribution before processing
Dataset Configuration—input formats, mixing, remote datasets
Global Configuration Reference—full parameter list
Distributed Processing—scale to Ray clusters
Operator Library—browse 200+ available operators