Curate Flow Configuration#
The curate flow runs the six curation steps from one configuration file, derives every cross-step path so that a producer and its consumer cannot disagree, and refuses a misconfigured run before any step does work.
The flow is a script, not a registered step: it takes a configuration path and accepts no key=value overrides.
The driver is src/nemotron/steps/curate/nemo_curator/scripts/run_flow.py.
Syntax#
uv run --extra curate --extra xenna \
python -m nemotron.steps.curate.nemo_curator.scripts.run_flow \
--config <path/to/flow.yaml> [--plan]
Flag |
Meaning |
|---|---|
|
Path to the flow configuration file. |
|
Write |
Both extras are required.
NeMo Curator executes the filter step on Ray, and Ray resolves the worker interpreter independently of the launching one; without xenna on the worker side, the run fails inside a worker with ModuleNotFoundError: No module named 'cosmos_xenna' after the plan has already been printed.
Configuration Files#
Two worked-example configurations ship under src/nemotron/steps/curate/nemo_curator/config/.
File |
Purpose |
|---|---|
|
First run: ingest, profile, filter with language and length gates only, and audit. |
|
Second run: identical above |
Copy both files and edit corpus.input, output_root, and corpus.langpack_dir.
Those three values must be identical between the two runs.
Top-Level Keys#
- corpus#
Describes the corpus that every step reads. Refer to Corpus Block.
- output_root#
Directory under which every step writes. Refer to Derived Paths.
Default:
./output/curate.
- steps#
One block per step, keyed
ingest,profile,filter,audit,decontamination, andsubset. Each block carriesenabledplus any parameter of the underlying step; a key written in a step block overrides the value the flow derived for it. Thefilterblock configures the registeredcurate/nemo_curatorstep.
- approve#
Promotes a candidate policy into an approved policy before the steps run. Refer to Approve Block.
Default:
null.
Corpus Block#
- corpus.input#
Required. Glob, directory, or list of raw corpus files.
- corpus.text_field#
Column holding the text in the raw corpus.
Default:
text.
- corpus.id_field#
Document identifier field. When
steps.ingestis enabled, every downstream step reads the canonicalidfield that ingestion writes.
- corpus.id_field_in_source#
Set
truewhen the raw corpus already carriescorpus.id_field; ingestion then keeps it rather than minting one.
- corpus.id_fields#
Columns from which ingestion mints a content-derived identifier. Defaults to
url(when it is a metadata field) and the text field.
- corpus.id_prefix#
Prefix for minted identifiers.
Default:
"".
- corpus.source_field#
Field naming the source of each record. When ingestion is enabled, downstream steps read the canonical
sourcefield.
- corpus.source_field_in_source#
Column in the raw corpus to map onto
source.
- corpus.source_value#
A constant source label when the raw corpus has no source column.
- corpus.metadata_fields#
Columns carried through filtering. Ingestion keeps every listed field other than
idandsource, which it produces itself.
- corpus.language#
BCP-47 tag that selects the language pack for profiling. Required when
steps.profileis enabled; there is no default language. This is separate fromsteps.filter.language_codes, which decides which languages are kept.
- corpus.langpack_dir#
Root directory of the language packs. Required when
steps.profileis enabled; the flow never selects a pack root implicitly.
Approve Block#
- approve.from#
Path of the candidate policy to promote.
Default:
<output_root>/profile/candidate_policies.yaml.
- approve.thresholds#
Required. List of
{signal, min},{signal, max}, or{signal, min, max}entries. Every signal must have been profiled, and each bound must match the signal’s registered direction.
- approve.approver#
Person recording the approval. Required by the approved-policy contract.
- approve.evidence#
What was examined and why these values were chosen. Required by the approved-policy contract.
- approve.method#
manualorablation.
- approve.date#
Optional provenance.
- approve.verify_corpus#
Compare the fingerprint recorded in the candidate policy against the corpus that the filter step will read. A mismatch is refused. When ingestion is enabled, verification is deferred until ingestion has written the prepared corpus.
Default:
true.
The promoted policy is written to <output_root>/policy/approved_policy.yaml and set as steps.filter.heuristic_filters.approved_policy.
Refer to Filter Policy File for the resulting document.
Derived Paths#
The flow computes every artifact path from output_root.
Artifact |
Path |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Per-step derivations:
profileandfilterread the ingested JSONL whensteps.ingestis enabled, otherwisecorpus.input.filterreceivesemit_manifestandemit_ledgerset to the manifest and ledger paths.auditreceivesdeclared_manifest,ledger_glob,reference_glob, anddigest_rootfrom the same table.decontaminationreadssteps.decontamination.holdoutas itsholdout_glob; the training split is the filtered corpus.subsetreads the decontaminated file whensteps.decontaminationis enabled, otherwise the filtered corpus.
Preflight Checks#
The flow refuses to run when any of the following hold:
corpus.inputis missing.approveis set whilesteps.profileis enabled. Profiling and approval are separate runs.approve.fromnames a file that does not exist.approve.thresholdsis empty, names a signal the profile did not measure, or uses a bound the signal does not accept.approve.verify_corpusistrueand the corpus fingerprint does not match the candidate policy.steps.filter.heuristic_filters.approved_policyis set to a path other than the one the flow promotes.steps.profileis enabled withoutcorpus.languageor without an explicitlangpack_dir.steps.decontaminationis enabled withoutholdout.steps.subset.quality_score_fieldnames a__<signal>column, but no policy is configured, the signal is not amongapprove.thresholds, orsteps.filter.modeisfilter.<output_root>/filtered_jsonl/already holds corpus shards from an earlier run. The filter step appends rather than replaces; delete the directory or choose anotheroutput_root.A disabled step’s artifact is required by an enabled step and is absent under
output_root.steps.ingestis enabled andcorpus.source_fieldis set withoutcorpus.source_field_in_sourceorcorpus.source_value, so ingestion would have nothing to write into that column.
The flow warns, but runs, when:
approveis set whilesteps.filteris disabled, so the policy is promoted but nothing applies it.steps.auditruns without the manifest or ledger of a disabled producer; completeness is then not claimed and removals are not attributed.steps.subsetruns withsteps.decontaminationdisabled while a decontaminated corpus from an earlier run exists; the tiers are cut from the corpus before decontamination.steps.decontaminationruns the GPU similarity pass rather thanskip_similarity: true.
Flow Report#
After a run, the flow writes <output_root>/flow_report.json:
Field |
Meaning |
|---|---|
|
Report schema version. |
|
|
|
UTC timestamps. |
|
The resolved output root. |
|
The derived-path table. |
|
Per-step results in execution order. |
|
Preflight and promotion warnings. |
|
The audit’s verdict, or |
|
|
|
Whether the filter applied policy thresholds. |
|
Whether this run carried an |
|
|
--plan writes flow_plan.json with the same derived configurations, so the preview cannot describe a run other than the one that executes.