DEFT for Object Detection#
DEFT for Object Detection is an agent-run loop that grows a Grounding DINO training set by
mining a pseudo-labeled source pool against per-class mean average precision (mAP) gaps
measured on a key performance indicator (KPI) set, and it runs for a bounded iteration count.
The loop evaluates a zero-shot checkpoint first, analyzes which classes fall short on which
images, embeds those weak images, mines visually similar images out of a prepared pool, stages
them as new training annotations, and retrains. It repeats that sequence for a fixed
max_iterations. This workflow is new in TAO 7.2.0.
This workflow is one of the loops described in Data Enhanced Fine-tuning (DEFT),
and it trains the model described in Grounding DINO. It is not the
right tool for a single standalone TAO training run, a one-off inference, or a gap analysis on
its own. Invoke the relevant single-purpose skill directly for those. The SKILL.md file
and its references/ files remain the executable contract that the agent follows. This page
summarizes them so that you can decide whether the loop fits your problem and prepare the
inputs it needs.
Supported Models#
This loop targets Grounding DINO with open-set object detection with visual grounding (ODVG)
training annotations only, namely tmm_odvg.jsonl and labelmap.json, matching the
reference pipeline. This workflow does not support DINO or RT-DETR with COCO annotations.
Invoke the single-purpose skills directly for those models.
The list shape of dataset.train_data_sources is what makes the growth mechanism work. Each
iteration appends one {image_dir, json_file, label_map} entry to that list rather than
rewriting a combined file, and earlier sources are never removed. Pre-flight enforces the
shape and rejects a mapping there, because a mapping means the specification is COCO-shaped
and this workflow cannot append to it. Both the Pre-Flight Summary and the loop report record
the model as Grounding DINO with ODVG annotations.
A closed-vocabulary variant covering RT-DETR and YOLO is planned for a future release.
The Two Invocations#
Preparing the source pool and running the loop are two separate runs of the same skill. A separate run prepares the source pool before the loop launches. The two stay separate because you prepare a pool one time and then reuse it across many loop runs, and coupling them would re-label and re-embed the same images on every launch.
Invocation |
What it does |
What it produces |
|---|---|---|
Prepare the source pool |
Co-DETR pseudo-labels raw pool images, folds them to the target classes, converts KITTI to COCO to ODVG, verifies, and embeds |
|
Run the DEFT loop |
Runs the baseline and then the iterations |
Checkpoints, KPI results, and the mAP trend |
The loop takes those four paths as inputs. Pre-flight validates them and init_deft_state.py
pins them, so a run cannot reach the mining stage with no corpus to search.
Preparing the Source Pool#
The preparation run pseudo-labels the pool with Co-DETR, folds the predictions onto your target classes, converts KITTI to COCO to ODVG, and embeds the pool. The chain runs in the following order:
Refuse a pool that has duplicate basenames, using
scripts/verify_pseudo_labels.py --pool-images-dir "$POOL_IMAGES".Emit the two mappings with
scripts/prepare_class_mappings_for_mining_data_prep.py, which writescodetr_category_mapping.yaml,kitti_mapping.yaml, andclassmap_target.txtinto the preparation directory.Pseudo-label the pool with Co-DETR, using
codetr inference -e "$CODETR_SPEC" inference.checkpoint=... results_dir=${PREP_DIR} inference.num_gpus=...in$TAO_PYT_IMAGE. When thecodetrconsole script is unregistered, the fallback entry point ispython3 -m nvidia_tao_pytorch.cv.codetr.entrypoint.codetr. The class fold applies at detection time throughinference.category_mapping. The overlayassets/overlays/codetr_inference.yamlpinsmodel.num_selectto1000, where the TAO default is300, andinference.conf_thresholdto0.3, where the TAO default is0.5. A gate runs afterward:scripts/verify_pseudo_labels.pywritespseudo_label_report.json.Convert KITTI to COCO with
annotations convert -e "${PREP_DIR}/kitti_to_coco.yaml"in$TAO_DS_IMAGE. The overlayassets/overlays/kitti_to_coco.yamlpinskitti.projecttococo, which names the output filecoco.json. The output lands at<workspace>/source_pool/coco.jsonand is recorded asconfig.source_detection_file.Verify the result with
scripts/validate_pool_coco.py, which writespool_report.jsonand settlesmax_labels, one per target class.Convert COCO to ODVG with
annotations convert -e "${PREP_DIR}/coco_to_odvg.yaml"in$TAO_DS_IMAGE, withresults_dirset to<workspace>/source_pool/odvg. The output is named after the input, as<basename>_odvg.jsonland<basename>_odvg_labelmap.json. There is no direct KITTI to ODVG conversion, which is why the pipeline converts to COCO first and then to ODVG.Embed the pool.
scripts/prepare_input_for_image_embeddings.pywritespool_input.parquet, and thenembedding image_embeddings -e "$EMBED_SPEC"runs in$TAO_DS_IMAGEwithoutput_parquetset to<workspace>/source_pool/source_embeddings.parquet,modelset to$EMBEDDING_MODEL,model_pathset to$EMBEDDING_MODEL_PATH,model_config_pathset to'""', andbatch_sizeset to64. For background on this data service, refer to Embedding Generation.
The run finishes with scripts/commit_stage.py --iter-label prep --stage prep, which records
the pool ODVG tree, the pool embeddings, and the pool report. The --pool-report argument is
what settles rare_class_list. The preparation run writes
source_pool/source_embeddings.parquet, source_pool/coco.json, and the
source_pool/odvg/ tree, plus pool_report.json, codetr_category_mapping.yaml,
kitti_mapping.yaml, classmap_target.txt, pseudo_label_report.json,
codetr_spec_report.json, and pool_input.parquet under ${RESULTS_DIR}/prep/.
Preparation is idempotent. The agent skips any step whose output already exists and never re-labels or re-embeds a pool that already has current artifacts. Labeling and embedding are proportional to pool size, not to what mining eventually selects, so a large pool costs a large preparation run even when a single loop iteration draws only a few hundred images from it. Preparation must finish before the baseline starts, and the agent reports the pool image count in the Pre-Flight Summary.
Prerequisites and Pre-Flight#
The loop requires Docker, NVIDIA Container Toolkit, and one or more CUDA GPUs. Before it launches anything, the agent runs 13 ordered pre-flight checks and prints a Pre-Flight Summary.
Check |
Subject |
What it establishes |
|---|---|---|
1 |
Workspace and run directory |
Resolves |
2 |
Host Python |
Probes the interpreter with |
3 |
Credentials |
Records the presence of |
4 |
Container images |
Resolves |
5 |
Image presence |
Runs |
6 |
Zero-shot checkpoint |
Resolves the Grounding DINO checkpoint, reporting only, with the real download deferred until after approval |
7 |
Train specification template |
Confirms that the template parses and that |
8 |
Source pool |
Requires both a non-empty embeddings parquet file carrying the |
9 |
Encoder resolution |
Resolves the SigLIP encoder from a local snapshot first and never from an implicit online default |
10 |
KPI inputs |
Confirms that the KPI inputs exist and that |
11 |
Class thresholds and mining configuration |
Records the class thresholds and the mining settings; the agent does not interrogate you about the defaults |
12 |
GPU count |
Counts GPUs with |
13 |
Specification sanity |
Confirms that |
The host Python probe imports exactly six modules: pandas, numpy, matplotlib,
pyarrow, PIL, and yaml. deft_python.sh selects an interpreter only when every
one of them imports, so a host missing just matplotlib makes it exit 2 with no
interpreter at all. Installing packages is out of scope for the skill, and deft_python.sh
never installs. It auto-selects $WORKSPACE/.venv/bin/python when that path exists and
WORKSPACE or WORKSPACE_DIR is exported; otherwise you pass DEFT_PYTHON yourself.
Both credentials are conditional. NGC_KEY is needed only when an nvcr.io image has to
be pulled or the Grounding DINO checkpoint has to be downloaded. Two images that are already
local, together with an ngc command line interface holding its own credentials, make a
complete run possible with NGC_KEY unset. HF_TOKEN is needed only when the encoder
resolves to a Hugging Face identifier rather than a local snapshot directory.
Two container images cover every stage, and the deploy image is not used by this workflow.
Variable |
Resolved value at 7.2.0 |
Stages that use it |
|---|---|---|
|
|
|
|
|
|
A checkpoint path that you supply always wins. Otherwise
scripts/fetch_gdino_checkpoint.py resolves
nvidia/tao/grounding_dino:grounding_dino_swin_tiny_commercial_trainable_v1.1, which is
1.93 GB, from NVIDIA GPU Cloud (NGC) and requires the ngc command line interface. The script runs with
--plan before the gate and reports only. It must be a trainable release, not a deployable
one. The specification fields and the checkpoint architecture fields that must agree are
model.backbone, num_queries, enc_layers, dec_layers, num_feature_levels,
and class_embed_bias. On an air-gapped host, or any time the download cannot run, you
supply --zero-shot-checkpoint directly, and the script says so rather than failing
obscurely.
Encoder resolution prefers a local snapshot. The agent searches HF_HOME/hub,
HUGGINGFACE_HUB_CACHE, $HOME/.cache/huggingface/hub,
$WORKSPACE/source_pool/hf_cache/hub, and $WORKSPACE/source_pool/hf_cache for a
models--google--siglip-base-patch16-224/snapshots/* directory that holds a config.json
file. The bare Hugging Face identifier google/siglip-base-patch16-224 is used only after
outbound access is verified, and only then is HF_TOKEN required. The result is recorded as
config.embedding_model and config.embedding_model_path.
There is exactly one user gate: pre-flight confirmation. The agent prints the Pre-Flight Summary, stops, and waits for explicit approval before it launches any side-effecting step. After the gate, the skill is fully autonomous, so the Pre-Flight Summary also reminds you to enable auto-mode before you approve.
Defaults#
The agent does not ask you about the values in the following table. Confirm them in the Pre-Flight Summary if you want something else.
Setting |
Default |
|---|---|
|
Taken from the train specification template |
|
|
|
|
|
|
|
Every target class holding a below-mean share of the pool’s annotations, derived at the
preparation commit from |
|
|
|
|
|
SigLIP; |
|
|
|
|
Workspace root |
Taken from your prompt, otherwise |
|
When |
Data Layout#
The loop reads and writes a single workspace directory. You author the specifications, the KPI set, and the optional seed training data. The workspace has the following layout:
<workspace>/
specs/
train_grounding_dino.yaml
inference_gdino.yaml
checkpoints/zero_shot.pth
kpi/
images/
labels/ KITTI ground truth
coco.json yours; target_detection_file for mining
mapping.yaml
base/ optional seed training set
images/
odvg/ *.jsonl and labelmap.json
source_pool/
source_embeddings.parquet filepath and embedding
odvg/ *.jsonl and labelmap.json
coco.json generated by prep; source_detection_file for mining
hf_cache/ optional local encoder snapshot
results/run_<YYYYMMDD_HHMMSS>/ created by this workflow
Note
Do not hand-author source_pool/odvg/ or source_pool/coco.json; the source pool
preparation run generates both. Do not hand-author anything under
results/run_<YYYYMMDD_HHMMSS>/ either, because the loop creates it.
You must make the following inputs present in the workspace before the run. The preparation
run produces the source_pool/ entries; you author the rest:
Input |
What it provides |
|---|---|
|
The train specification template, and the source of truth for the backbone, the image
size, and |
|
|
|
The required checkpoint that the baseline scores without training |
|
The KPI evaluation images |
|
The KPI ground truth, one KITTI |
|
The class mapping that |
|
The mining target detection file, required only for |
|
The pool embeddings that mining searches |
|
The pool annotations that staging looks up |
|
Session credentials, both conditional |
Optional Seed Training Data#
Seed training data under base/ is optional, and that is a deliberate difference from the
automated optical inspection (AOI) loop. The AOI loop requires a seed training set because Visual
ChangeNet must learn the task from scratch. Grounding DINO is zero-shot capable, so this loop can start cold. Two cases
follow from that:
When the template already lists base sources, pre-flight validates that they resolve, and iteration 1 appends mined data to them.
When the template’s
train_data_sourcesis empty, iteration 1 trains on mined data alone. That is not an error, but the first iteration’s dataset is small.
The source pool is mandatory either way. Seed data is what you start from, and the pool is what you draw from. They are not interchangeable, and the loop cannot mine without a pool.
Warning
kpi/mapping.yaml is a YAML list of single-key dictionaries whose values are lists. A
bare string value is iterated character by character, so nothing matches and every metric
is zero while the run still exits 0. Write - car: [car, automobile], not
- car: car. Matching is case-sensitive in both annotations convert and
analytics kpi_analyze, so a mapping must enumerate every spelling it expects to see,
including Bicycle and bicycle, or AutoMobile and Automobile. The agent
narrows the mapping to the target classes before scoring, using
scripts/prepare_mapping_for_kpi_analyze.py.
Annotation Formats#
Three annotation formats travel through the loop, and each has its own job. The TAO documentation covers all three in full, so this section covers only where each one lives and what it does here.
Format |
Where it lives |
Job in this loop |
|---|---|---|
|
Carries the KPI ground truth and every set of predictions the loop scores |
|
|
Supplies the Grounding DINO training annotations that each iteration appends |
|
|
Feeds |
The two stages that read KITTI spell the format differently on purpose. gap_analysis takes
input_format: kitti in lowercase, and kpi_analyze takes input_format: KITTI in
uppercase. Both are correct for their own stage, so treat the difference as expected rather
than as a typographical error to fix.
Warning
This loop does not verify that mined images are absent from the KPI evaluation set. That is a deliberate decision, and it is documented as one. If the pool does overlap the KPI set, mining pulls evaluation images into training, and every mAP number the loop reports becomes optimistic. The AOI loop takes the opposite stance and treats train and validation leakage as an unrecoverable hard stop.
Loop Stages#
The agent enforces an ordered set of stage transitions, and the audit script checks them. The transitions are the following:
prep: prep (once; skipped when artifacts exist)
baseline: inference -> kpi_analyze
iterN: gap_analysis -> embed -> mine -> stage -> train -> inference -> kpi_analyze
The loop does not train at baseline. It evaluates the supplied zero-shot or pretrained
checkpoint as iteration 0 and only trains from iteration 1 onward, after mining has produced
data to add. Baseline labels land in ${RESULTS_DIR}/baseline/inference/labels/, and the
baseline also seeds ${RESULTS_DIR}/train_grounding_dino.yaml by copying your train
specification template. The phase directory and the iteration label are both baseline, not
iter_0; the spelling iter_0 appears in prose only.
Stage |
What it does |
Underlying TAO command |
Image |
|---|---|---|---|
|
Finds the per-class gaps and the weak images |
|
|
|
Embeds the weak images |
|
|
|
Selects pool images near the weak images |
|
|
|
Copies images and writes the ODVG annotations |
Host scripts only, with no container |
Not applicable |
|
Fine-tunes on the grown dataset |
|
|
|
Scores the KPI images with the new checkpoint |
|
|
|
Computes the per-class metrics and the aggregate mAP |
|
|
Gap Analysis#
The gap_analysis stage consumes the previous phase’s inference labels, so iteration 1 reads
the baseline output and iteration N reads iter${N-1}, together with the KPI ground truth
and
config.kpi_images_dir. Its key settings are input_format: kitti, iou_threshold: 0.5,
conf_threshold: 0.0, min_area: 0, default_ap50_threshold: 0.0,
default_recall_threshold: 0.0, default_precision_threshold: 0.0, class_mapping: {},
and every gated class listed explicitly in weak_thresholds. Setting
default_ap50_threshold: 0.0 is mandatory: leaving it unset means every class you did not
list starts marking images weak at 0.5, which quietly inflates the gap set and the mining
budget derived from it. The agent runs emit_default_spec.py --stage gap_analysis, which
copies assets/gap_analysis_object_detection.yaml because gap_analysis is absent from
the TAO default specification list. This stage is backed by the TAO Data Services
gap_analysis command.
Embedding#
The embed stage takes weak_images.parquet directly, because that file already carries
filepath and needs no projection step, and it writes
weak_images_embeddings.parquet. The model is SigLIP, resolved from the
google/siglip-base-patch16-224 snapshot, with batch_size of 64 and
model_config_path set with --set model_config_path='""'. The encoder must match the one
used to build the source-pool parquet file. Encoder consistency is the whole point of this
stage: mismatched encoders produce vectors that are not comparable, and the failure is silent,
because mining succeeds and returns confidently wrong neighbors. For background, refer to
Embedding Generation.
Mining#
The mine stage runs tmm unique_neighbor_matching with source_path set to the source
pool embeddings, target_path set to weak_images_embeddings.parquet, and
desired_unique_count supplied by prepare_budget_for_mining.py. Its other specification
fields are allocation_policy, which is class_stratified or global and to which the
reference pipeline’s class_balanced mode maps, distance_metric: euclidean,
candidate_expansion_factor: 5, embedding_column: embedding and
filepath_column: filepath on both the source and the target, source_detection_file,
target_detection_file, rare_class_list, save_embeddings: false, and
visualize: false. The value detection_format: coco is never inferred, so set it
explicitly. For background on targeted mode matching, refer to
Targeted Mode Matching.
Staging#
The stage stage is bundled glue with no leaf skill and no container. It runs three host
scripts in order. stage_mined_odvg.py copies the images, looks up the ODVG records by
basename, renumbers image_id from 0, remaps instances[].label, and writes
tmm_odvg.jsonl and labelmap.json, truncating the JSONL file first, with
--min-success-rate defaulting to 0.9. validate_odvg_images.py is a hard-stop gate.
prepare_exclude_for_mining.py extends the exclude set and omits --parquet-b on
iteration 1 only.
Training, Inference, and KPI Analysis#
This loop searches for the training data mixture that produces the best model, not for a
training trajectory. Every iteration therefore fine-tunes the original base checkpoint rather
than the previous iteration’s weights. That way the loop evaluates every candidate data
mixture from the same starting point, and accumulated weight drift does not confound the
comparison across iterations. train.pretrained_model_path stays pointed at the original
base checkpoint on
every iteration. What grows across iterations is the dataset, not the weights. The loop uses
the previous iteration’s checkpoint only for inference and the gap analysis that follows it,
and never as a training initialization.
The prepare_spec_for_train.py script builds the train specification and appends one
{image_dir, json_file, label_map} entry, preceded by prepare_val_split_for_train.py,
which builds a validation COCO file from 10 percent of the pool with the category identifiers
rewritten to be zero-based. Inference then runs with
inference.checkpoint=${RESULTS_DIR}/iter${N}/train/gdino_model_latest.pth. The
agent launches the kpi_analyze stage detached with docker run -d and without --rm,
because
the mAP exists only on that container’s standard output, and its input_format is the
uppercase KITTI.
Zero weak images ends the loop early. If weak_images.parquet has zero rows, no data can be
mined this iteration, so the agent commits gap_analysis with status=ok and
--weak-image-count 0 and advances directly to loop_stop, because there is nothing for
the remaining six stages to consume. That zero is the only proof of the early stop the audit
can read: without it, --require-complete reports a fully successful run as INCOMPLETE.
It also means every class met its configured AP50 threshold on every image.
Stopping Behavior#
This loop has no metric contract and no target. The mAP is reported, not gated. The loop does
not early-exit on a metric target, a regression does not stop the loop and does not trigger a
retry, and kpi_analyze records where the model stands only so the report can show the trend
across iterations. If you want target-gated stopping, that is a change to the workflow
contract rather than something the agent improvises mid-run.
Three conditions stop the loop:
max_iterationsis reached, and the agent runs the loop-end sequence and reports the mAP trend across iterations.Zero weak images appear at any
gap_analysis, and the agent commitsloop_stopand reports that the model met every configured per-classAP50threshold.An unrecoverable gate failure occurs, and the agent halts and reports the exact missing artifact.
The hard stops are any stage with status=error, a missing or zero-row source-pool embedding
parquet file, a zero-row mining result when weak images were present, a missing ODVG annotation
source, an image and annotation mismatch after staging, and a train exit that emits no new
iteration checkpoint. Pool exhaustion also stops the loop and is recorded with
commit_stage.py --stage loop_stop --pool-exhausted --pool-remaining N. Before anyone claims
the loop is complete, audit_deft_run.py --results-dir "${RESULTS_DIR}" --require-complete
must exit zero.
max_iterations defaults to 1, which is one mine, train, and score pass, the smallest
run that yields a comparison against the baseline. The agent confirms the value with you when
you have not said how many iterations you want, and an unattended run takes the default rather
than stopping to ask.
Behavior Worth Knowing#
The following properties of this loop are easy to get wrong, and assuming otherwise leads to a wrong conclusion about a run:
results_dirauto-appends the task name. The TAOupdate_results_dirhelper appends the task name, so passingresults_dir=XtotrainwritesX/train/and passing it toinferencewritesX/inference/. Never append the subdirectory yourself.exclude_pathmust benullon iteration 1, because TAO Data Servicesload_datasetsraisesFileNotFoundErrorwhenexclude_pathis set but is not a file. From iteration 2 onward it points at the previousmined_cumulative.parquet.candidate_expansion_factoris not the loop iteration count. It seeds the miner’s internal candidate-pool growth and is unrelated tomax_iterations.The agent seeds the mining budget from iteration 1’s
weak_images.parqueton every iteration. That is deliberate, so the data added per iteration stays constant as the gap set shrinks.desired_unique_countis the weak image count multiplied bymultiplier, which defaults to3.Grounding DINO caption order is the label map. The model assigns a detection to a class by the position of the caption token it matched, so reordering the list silently relabels every prediction, and
max_labelsmust equallen(captions).verify_class_contract.pychecks this before every inference.The target classes are a run-wide contract across four places:
classes.yaml,weak_thresholdsingap_analysis,rare_class_listinmine, andkpi/mapping.yamlinkpi_analyze.
Outputs#
Every run writes one timestamped directory under results/. Its layout is the following:
results/run_<YYYYMMDD_HHMMSS>/
deft_state.json
loop_log.jsonl
.deft_commit.lock commit_stage.py, one writer at a time
.deft_commit.journal present only while a commit is in flight
DEFT_Loop_Report.md
train_grounding_dino.yaml seeded at baseline from your template
prep/ present only when prep ran
inference/labels/ Co-DETR pseudo-labels, already folded
codetr_category_mapping.yaml
kitti_mapping.yaml
classmap_target.txt
pool_report.json
iter${N}_summary.md
baseline/
inference/labels/*.txt
kpi/kpi_calc.csv
iter${N}/
gaps/ weak_images.parquet, box_gaps.parquet,
image_metrics.parquet, gap_report.json
embeddings/weak_images_embeddings.parquet
mining/ final_unique_files.parquet, summary.json
tmm/
images/
annotations/ tmm_odvg.jsonl, labelmap.json
mined_cumulative.parquet
train_grounding_dino.yaml
train/ gdino_model_latest.pth, status.json
inference/labels/*.txt
kpi/kpi_calc.csv
Artifact |
What it holds |
|---|---|
|
The loop report, in Markdown |
|
Iteration N’s checkpoint, which must be a newly emitted file under
|
|
The per-class metrics, with the columns |
|
The aggregate mAP, written by |
|
The mining result, alongside |
|
The resume snapshot |
|
The append-only event stream, one JSON line per stage |
Other per-iteration files |
|
The loop report is Markdown at ${RESULTS_DIR}/DEFT_Loop_Report.md. There is no HTML
report and no HTML template, and the reporter subagent composes the Markdown directly. The
agent renders the report after each completed iteration and once more at loop end by spawning
that subagent, and never renders it inline. The reporter follows the same rule as the loop: the mAP is reported,
not gated, so it does not describe a regression as a failure and does not claim that a target
was met or missed, because there is no target.
Each phase also writes a precision-recall curve plot and a kpi_analyze.log file into
${RESULTS_DIR}/<phase>/kpi/. The aggregate mAP is printed to standard output only, and
nothing writes it into kpi_calc.csv, which is why the loop captures it into
kpi_summary.json. The trend itself lives in the ## 1. KPI Trend section of
DEFT_Loop_Report.md, with one row per phase carrying the mAP plus one AP50 column per
target class, and in ${RESULTS_DIR}/iter${N}_summary.md, which is at most 300 words.
There is no separate trend CSV or JSON file.
Read coverage_pct from iter${N}/mining/summary.json. A retrieved_unique_count of
0 with weak images present is a hard stop, because the source pool has nothing left to give
or the exclude set has consumed it. A coverage_pct below 50 percent is a warning rather
than a
gate: the agent warns in the iteration summary that the pool is running dry and that later
iterations add little, and then proceeds. The reporter also flags any iteration whose mining
coverage fell below 50 percent.
State lives on disk. init_deft_state.py initializes deft_state.json once, handles fresh
runs only, and refuses to overwrite without --force. commit_stage.py is the only
supported state writer. audit_deft_run.py is read-only and prints DEFT_RUN_STATUS,
last_committed, next_action, and read_before_action. The loop_log.jsonl schema
carries seq, ts, iter, stage, status, summary, duration_sec,
context_tokens, which is always 0 and reserved, and tokens, an object added at loop
end. Stage identifiers are prep, inference, kpi_analyze, gap_analysis,
embed, mine, stage, train, and loop_stop, and the iter field takes
baseline, iter1, iter2, and so on. Because disk is the source of truth, the agent
runs the audit before every stage and, on startup or resume, prints the last five entries of
loop_log.jsonl and proceeds from disk-loaded state.
Execution Platforms#
After you confirm that you want to run this workflow, the skill asks which supported platform you intend to run on and discovers the execution platforms from the installed platform skills, which are Docker, SLURM, Kubernetes, and Brev. After platform selection, it reads the chosen platform skill’s credentials section. Every documented stage invocation in the skill is a direct Docker command, so treat the platform question as an intake step rather than as a claim of tested coverage on the other three.
This loop has no air-gapped mode. The single documented accommodation is the zero-shot
checkpoint: on an air-gapped host, or any time the download cannot run, you supply
--zero-shot-checkpoint directly. That is a single-artifact workaround for the NGC
checkpoint fetch, not a workflow-level offline mode. An offline host still needs both container
images already present locally, a local SigLIP snapshot, because encoder resolution hard-stops
when no local snapshot resolves and outbound Hugging Face access cannot be verified, a Co-DETR
checkpoint, which this skill does not obtain, and a fully provisioned host Python. For the
loop that takes a different stance on these questions, refer to
DEFT for Automated Optical Inspection.
Example Prompts#
The skill lists the following prompts for a loop run:
“Run the DEFT OD loop”
“Run smart data augmentation for grounding dino”
“Mine more training data for my detection model and retrain”
“Improve detection mAP with gap analysis and unique-neighbor mining”
The skill lists the following prompts for the source pool preparation, which is a separate run that completes before the loop launches:
“Prep the source pool”
“Pseudo-label my unlabeled images for mining”
“Build the mining pool from these raw images”
Source of Truth#
The skill sources below are the executable contract for this workflow. This page summarizes them, and where the two differ, the skill sources win. For an overview of the workflow family, refer to Reference Workflows, and to install the toolkit, refer to the TAO Quick Start Guide.