Tao Mine Aoi Images
NVIDIAOfficialCreated by NVIDIA Corporation
- Skill
- Workflow
- Data and AI
- Apache-2.0
- Medium risk
- Has scripts
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The tao-mine-aoi-images skill provides a deterministic, GPU-accelerated pipeline for mining nearest-neighbor images from a source pool to match target gap-analysis images. Designed for VCN AOI iterations, it uses the DEFT (embed-then-mine) workflow to generate augmented training data. The process involves embedding both target and source datasets using identical encoder configurations, performing k-NN mining, and optionally applying history-aware filtering to ensure only novel samples are selected for subsequent training rounds.
What it does
- Embeds target gap-analysis images into a vector space using a specified encoder model.
- Embeds a large source pool of candidate images using the same encoder configuration.
- Performs k-NN mining to identify the top-N most similar source images for each target.
- Deduplicates mined results to produce a clean parquet of unique source filepaths.
- Applies history-aware post-processing to exclude samples selected in previous iterations.
- Generates a structured mining report for auditability and sanity checking.
When to use it
- Immediately following the tao-route-visual-changenet-samples skill in an iterative training loop.
- When you need to expand a real-image augmentation queue based on identified model weaknesses.
- When performing iterative DEFT workflows that require history-aware sample selection.
- When you have a set of target images and a large source pool that requires similarity-based mining.
Advantages
- Ensures deterministic and reproducible mining results through fixed workflow steps.
- Prevents redundant training data by filtering out previously mined samples.
- Supports label-aware filtering to maintain class consistency during augmentation.
- Provides clear audit trails through structured reporting and history tracking.
Usage examples
- “Run the DEFT mining workflow for my current gap analysis results.”
- The agent will execute the embedding of targets and source pool, perform k-NN mining, and output a deduplicated parquet of candidate images for training.
- “Perform an iterative mining step while excluding previously selected samples.”
- The agent will run the full mining pipeline and then execute the history-aware filter to ensure only novel images are added to the training set.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/nvidia/tao-mine-aoi-images/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip tao-mine-aoi-images.zip -d .agents/skills
Documentation by NVIDIA Corporation
DEFT Mining and Embedding Skill
Standalone install? If this session was not initialized by the TAO skill bank plugin, run the
tao-setupskill first (host preflight, credentials, cross-skill discovery).
You are the operator of the DEFT embed-then-mine workflow for VCN AOI. Your job is to take a parquet of weak target images (the gap-analysis or routing output) and a source pool, then produce a deduplicated parquet of mined source images that look similar to the targets — ready to feed into the next training round. Iterative DEFT callers also run the bundled history-aware post-processing step so a sample selected in an earlier iteration is not selected again.
The workflow is fixed and deterministic: embed the targets, embed the source pool, mine nearest neighbours, then (for iterative workflows) remove previously mined samples. Each GPU step's output parquet is the next step's input; history-aware selection is a host-side post-processing step, not another k-NN search. There is no clustering pass or human-in-the-loop selection — depth comes from picking the right encoder and a topn wide enough to leave novel candidates after history filtering.
The whole skill is a thin wrapper around three direct docker run invocations against the pinned TAO data-services image plus one optional bundled host-Python post-processor for iterative history (see versions.yaml, resolved at runtime in Setup). The container's entrypoint takes <category> <action> -e <spec.yaml> [hydra overrides...] — pass embedding image_embeddings -e <embedding_spec.yaml> … for embedding and tmm nearest_neighbors -e <mining_spec.yaml> … for mining. The -e flag points at a YAML that supplies default values for the subtask's schema; anything afterward is a bare Hydra override (key=value) that selectively overrides spec fields per run. (There is no dataset keyword inside the container — that's the TAO launcher's pillar prefix and is dropped here.) Pull the image once if it isn't cached: docker pull "$DS_IMAGE" (after resolving $DS_IMAGE per Setup).
Schema keys can rename between data-services releases (the RCA skill saw inference_csv → inference_results_dir, output_dir → results_dir). When in doubt, introspect the actual schema once per image: docker run --rm "$DS_IMAGE" embedding image_embeddings --cfg=job and ... tmm nearest_neighbors --cfg=job.
Inputs
Target parquet — the gap-analysis output, typically
mining_gaps.parquetfromtao-route-visual-changenet-samples(orkpi_gaps.parquetfromtao-analyze-gaps-visual-changenetif routing was skipped). Required column:filepath. Iflabelis also present, label-aware filtering during mining is available; otherwise the mining task silently no-ops the filter.Source pool — a parquet of candidate images to mine against, with a
filepathcolumn. If the user only has a CSV, convert it to a parquet with the same columns before Step 2. For label-aware filtering, the pool must also carry alabelcolumn.Embedding spec file — a YAML containing
model,model_path,batch_size, and (only whenmodel_pathis a TAO.pth/.ckpt)model_config_path. Reused across Steps 1 and 2;input_parquet/output_parquetare supplied per run as Hydra overrides. The same spec MUST drive both embedding steps — embeddings from different encoders are not comparable, and mismatched encoders are the most common cause of "the mined images look unrelated" reports.Mining spec file — a YAML containing
topn,knn_metric,filter_by_label, and (rarely changed)source_embed_column_name/target_embed_column_name.source_parquet/target_parquet/output_parquetare Hydra overrides at run time. SigLIP and CLIP embeddings should useknn_metric: cosine. Whenfilter_by_label: truebut either embedding parquet lacks alabelcolumn, the container logs a warning and proceeds without filtering.Mining history (iterative workflows only) — one JSON ledger under the run-level results directory, plus a per-iteration history summary.
scripts/filter_mined_history.pyowns both files. It identifies a sample by normalizedfilepath, validates all earlier output hashes, and rejects an iteration gap or duplicate selection. Never hand-edit or reconstruct this ledger on resume.
Setup
Use the pinned TAO data-services URI below, then confirm Docker, the NVIDIA container toolkit, and a GPU are present before doing anything else. A GPU is required for both the encoder forward pass and the cuML/cuDF k-NN search; both steps fail without CUDA.
# Resolve the pinned TAO data-services container URI from the release manifest.
DS_IMAGE="$(scripts/resolve_versions_key.py images.tao_toolkit.data_services)"
echo "DS_IMAGE=$DS_IMAGE"
docker info > /dev/null && echo "OK: docker"
nvidia-smi > /dev/null && echo "OK: GPU"
docker image inspect "$DS_IMAGE" > /dev/null \
|| docker pull "$DS_IMAGE"Every host path the container reads or writes must be bind-mounted. The most predictable approach mounts the workspace root with identical paths inside and outside the container, then reuses one $DOCKER alias for the three invocations:
WORKSPACE=<absolute path that contains all parquets, outputs, and the source-pool images>
DOCKER="docker run --gpus all --rm --shm-size=8g -v $WORKSPACE:$WORKSPACE -w $WORKSPACE $DS_IMAGE"Do not pass --user $(id -u):$(id -g) — it triggers a getpwuid() KeyError during the transformers import before any work starts. The container runs as root; chown outputs back to the host UID afterward.
Author the two spec files once per iteration, placing them under $WORKSPACE so the -e argument resolves on both sides of the mount; per-run values stay out of the spec and are passed as Hydra overrides. If the source pool is a CSV, convert it to parquet up front (preserving filepath, and label if present). The default embedding_spec.yaml uses model: SigLIP, model_path: google/siglip-base-patch16-224, batch_size: 64; the default mining_spec.yaml uses topn: 5, knn_metric: cosine, filter_by_label: "false" (quoted — the schema reads it as a string). Iterative DEFT workflows keep the same topn: 5 default; preserve an explicit user value. Increase it only when the history summary shows that the narrow neighborhood is dominated by prior selections.
See references/setup.md for the full environment notes, TAO_SKILL_BANK_PATH handling, the path-mounting rationale, the getpwuid chown workaround, the CSV-to-parquet snippet, and the verbatim spec-file authoring blocks.
Method
Three commands, in order. Each command's output parquet is the next command's input. Run them as plain Bash; the $DOCKER alias from Setup handles the container, GPU, and mounts. Every invocation follows the same shape: -e <spec> for the baked-in defaults, then a handful of Hydra overrides for the run-specific paths.
Step 1 — Embed the target images
$DOCKER embedding image_embeddings \
-e <embedding_spec.yaml> \
input_parquet=<target_parquet> \
output_parquet=<target_embeddings_parquet>Reads the gap-analysis / routing output and writes a parquet with filepath, embedding, and any extra metadata columns (e.g. label, siamese_score, weakness) carried forward verbatim from the input. Print the output schema (pd.read_parquet(...).columns) to stdout so the script-check hook can confirm the embedding column exists.
If you need to override model / model_path / batch_size for one run without editing the spec, append them as Hydra overrides (e.g. model_path=...).
Step 2 — Embed the source pool
$DOCKER embedding image_embeddings \
-e <embedding_spec.yaml> \
input_parquet=<source_pool_parquet> \
output_parquet=<source_embeddings_parquet>Same command shape as Step 1, applied to the source pool. Use the identical embedding_spec.yaml as Step 1, and do not override model / model_path / batch_size differently here — mismatched encoder configs across the two steps produce non-comparable embeddings.
Step 3 — Mine nearest neighbours
$DOCKER tmm nearest_neighbors \
-e <mining_spec.yaml> \
source_parquet=<source_embeddings_parquet> \
target_parquet=<target_embeddings_parquet> \
output_parquet=<mined_parquet>For each target embedding, finds the topn closest source embeddings under the chosen metric, deduplicates across targets, and writes a single-column (filepath) parquet of unique mined source paths. For a one-off run this may be the final mined.parquet; for a DEFT iteration write it as mined_candidates.parquet so the immutable candidate set is preserved for Step 4. The container also drops a mining_summary.txt next to the output parquet with: query count, neighbour count, duplicates removed, and (when label filtering is on) kept-vs-dropped pair counts. Tweak topn, knn_metric, or filter_by_label via inline Hydra override when sweeping — no need to rewrite the spec.
When filter_by_label=true but one of the embedding parquets is missing the label column, the container logs a warning and proceeds without filtering. If the mined output looks larger than expected or contains cross-label pairs, scan the docker log for that warning before assuming the task did the right thing.
See references/reference-invocation.md for the minimal paste-and-edit end-to-end recipe (resolves $DS_IMAGE, writes both specs, runs all three steps, chowns outputs, and prints row counts) to run as a single streamed Bash block.
Step 4 — History-aware selection (iterative DEFT only)
Run after any label/similarity retention filter, so the input represents the actual candidates eligible for training:
python3 skills/data/tao-mine-aoi-images/scripts/filter_mined_history.py \
--candidate-parquet <mined_candidates.parquet> \
--output-parquet <mined.parquet> \
--history-file <run_results_dir>/mining_history.json \
--summary <iteration_dir>/mining_history_summary.json \
--iteration <N> \
--topn <topn>The output preserves candidate order and schema but contains only filepaths not
selected by an earlier committed iteration. The ledger records selected paths,
candidate/output hashes, counts, and topn; --resume reuses an already
committed iteration only after verifying those artifacts. A zero-row output is
valid evidence that the current k-NN candidate set contained no novel samples.
The caller decides whether another producer (for example AnomalyGen) can carry
the iteration or whether to hard-stop. When the summary reports a high
historical_candidate_rate, increase topn or expand the source pool; history
filtering cannot manufacture variance when every iteration retrieves the same
weak neighborhood.
Outputs and report
Write everything into a timestamped folder under the experiment / iteration directory. Get the real timestamp by running date +%Y-%m-%d_%H%M%S in Bash — do NOT hardcode or guess. If the user specifies a custom output path, use it directly but maintain the same internal layout. The packaging hook adds mining_config/ and claude_session.jsonl automatically when Mining_Report.md is written.
The final history-filtered mined parquet is the artifact an iterative downstream training stage consumes. Preserve the pre-history candidate parquet, per-iteration history summary, and run-level mining_history.json alongside the two embedding parquets; these distinguish "k-NN found nothing" from "k-NN returned only samples already used by prior iterations."
See references/outputs-and-reporting.md for the full output-directory layout and the verbatim Mining_Report.md template (Verdict, Inputs, Encoder Consistency, Mining Run, Per-Label Breakdown, Output Sanity, Recommended Actions; keep it 600–1200 words).
Common pitfalls
The most frequent failure is mismatched encoders between the two embedding steps — the single most common cause of garbage mining output; both steps must consume the same embedding_spec.yaml. Other recurring traps: passing --user (the getpwuid KeyError), skipping an embedding step, a missing label column silently no-oping filter_by_label=true, spec files outside $WORKSPACE, unresolved ??? sentinels, TAO checkpoints without model_config_path, CSV source pools fed in directly, host/container path mismatches, no GPU, an unpulled or :latest image tag, topn × N_targets ≫ source size (expected — report the actual mined count), and a topn too narrow to yield any novel samples after history filtering.
See references/troubleshooting.md for the full pitfall list with the exact errors, causes, and fixes.
Execution Order
Set
DS_IMAGEto the pinned data-services URI (see Setup), then rundocker info,nvidia-smi, anddocker image inspect "$DS_IMAGE"(pulling if missing) once to confirm the environment. Abort with a clear message if any fail.Run
date +%Y-%m-%d_%H%M%Sto get the timestamp; create<output_dir>/mining_results/<timestamp>/.Write
embedding_spec.yamlandmining_spec.yamlinto the timestamped dir, filling in the encoder choice and mining knobs. Keep these under$WORKSPACEso the-epath resolves inside the container.If the source pool is a CSV, convert to parquet first (preserve
filepathandlabel).Run Step 1 (embed targets) via
docker run … embedding image_embeddings -e embedding_spec.yaml input_parquet=… output_parquet=…. Print the output parquet's row count and columns to stdout.Run Step 2 (embed source pool) with the identical
embedding_spec.yamlas Step 1. Print output row count and columns.Run Step 3 (mine nearest neighbours) via
docker run … tmm nearest_neighbors -e mining_spec.yaml source_parquet=… target_parquet=… output_parquet=…. Confirmmining_summary.txtwas written next to the raw/candidate parquet.For an iterative DEFT caller, apply every configured retention filter and then run Step 4 with the current iteration number, recorded
topn, run-level ledger path, and a distinct finalmined.parquet. Never feed the raw candidate parquet directly into cumulative training.Compute the per-label breakdown (Section 5) by joining the target embeddings parquet with the final mined output on filepath, if both carry
label.Write
Mining_Report.mdlast — writing it triggers the packaging hook, which copies session logs and skill config alongside.
Files
- ATTRIBUTION.mdAdded by AutoGineer927 B
- BENCHMARK.md6.9 KiB
- LICENSELicence file added by AutoGineer11.2 KiB
- SKILL.md15.0 KiB
- config/skillspector-baseline.yaml2.6 KiB
- evals/evals.json941 B
- hooks/_parse-stdin.shScript1.4 KiB
- hooks/mining-artifacts-check.shScript3.5 KiB
- hooks/mining-package.shScript2.5 KiB
- hooks/mining-script-check.shScript5.3 KiB
- hooks/mining-section-check.shScript2.8 KiB
- references/outputs-and-reporting.md4.9 KiB
- references/reference-invocation.md2.6 KiB
- references/setup.md3.2 KiB
- references/troubleshooting.md3.5 KiB
- scripts/filter_mined_history.pyScript13.8 KiB
- skill-card.md4.1 KiB
- skill.oms.sig7.3 KiB
- tests/test_filter_mined_history.pyScript5.3 KiB
scripts/filter_mined_history.py
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
"""Drop samples selected by earlier mining iterations and commit an audit ledger.
The TAO nearest-neighbor task deduplicates candidates inside one invocation but
does not know about earlier DEFT iterations. This host-side post-processing
step preserves the candidate order, keeps only the first occurrence of each
normalized filepath, drops paths already committed by a previous iteration,
and records enough metadata to verify or safely resume the selection.
"""
from __future__ import annotations
import argparse
import hashlib
import json
import os
import pathlib
import posixpath
import sys
import tempfile
from typing import Any
HISTORY_VERSION = 1
HISTORY_IDENTITY = "filepath"
def _normalize_filepath(value: Any) -> str:
text = str(value or "").strip().replace("\\", "/")
if not text:
raise ValueError("every mined row requires a non-empty filepath")
normalized = posixpath.normpath(text)
if normalized in {"", "."}:
raise ValueError(f"invalid mined filepath: {value!r}")
return normalized
def _sha256(path: pathlib.Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as handle:
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def _atomic_json(path: pathlib.Path, payload: dict[str, Any]) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
fd, temporary = tempfile.mkstemp(
prefix=f".{path.name}.", suffix=".tmp", dir=str(path.parent)
)
try:
with os.fdopen(fd, "w", encoding="utf-8") as handle:
json.dump(payload, handle, indent=2, ensure_ascii=False)
handle.write("\n")
handle.flush()
os.fsync(handle.fileno())
os.replace(temporary, path)
except Exception:
try:
os.unlink(temporary)
except OSError:
pass
raise
def _atomic_parquet(table: Any, path: pathlib.Path) -> None:
try:
import pyarrow.parquet as pq
except ImportError as exc:
raise ValueError("pyarrow is required for history-aware mining") from exc
path.parent.mkdir(parents=True, exist_ok=True)
fd, temporary = tempfile.mkstemp(
prefix=f".{path.name}.", suffix=".tmp", dir=str(path.parent)
)
os.close(fd)
try:
pq.write_table(table, temporary)
with open(temporary, "rb") as handle:
os.fsync(handle.fileno())
os.replace(temporary, path)
except Exception:
try:
os.unlink(temporary)
except OSError:
pass
raise
def _validated_history(path: pathlib.Path, iteration: int) -> dict[str, Any]:
if not path.is_file():
if iteration != 1:
raise FileNotFoundError(
f"mining history is required before iteration {iteration}: {path}"
)
return {
"version": HISTORY_VERSION,
"identity": HISTORY_IDENTITY,
"iterations": [],
}
payload = json.loads(path.read_text())
if not isinstance(payload, dict) or payload.get("version") != HISTORY_VERSION:
raise ValueError(f"unsupported or malformed mining history: {path}")
if payload.get("identity") != HISTORY_IDENTITY:
raise ValueError("mining history identity must be filepath")
entries = payload.get("iterations")
if not isinstance(entries, list):
raise ValueError("mining history iterations must be a list")
expected_numbers = list(range(1, len(entries) + 1))
actual_numbers: list[int] = []
all_selected: set[str] = set()
for entry in entries:
if not isinstance(entry, dict):
raise ValueError("every mining history iteration must be an object")
number = int(entry.get("iteration", 0))
actual_numbers.append(number)
selected = entry.get("selected_filepaths")
if not isinstance(selected, list):
raise ValueError(
f"mining history iteration {number} has no selected_filepaths list"
)
normalized = [_normalize_filepath(value) for value in selected]
if len(normalized) != len(set(normalized)):
raise ValueError(
f"mining history iteration {number} contains duplicate filepaths"
)
overlap = all_selected.intersection(normalized)
if overlap:
raise ValueError(
f"mining history iteration {number} reselects prior filepaths: "
f"{sorted(overlap)[:3]}"
)
if int(entry.get("selected_count", -1)) != len(normalized):
raise ValueError(
f"mining history iteration {number} selected_count disagrees with "
"selected_filepaths"
)
for path_field, hash_field in (
("candidate_parquet", "candidate_sha256"),
("output_parquet", "output_sha256"),
("summary_file", "summary_sha256"),
):
artifact = pathlib.Path(str(entry.get(path_field) or ""))
expected_hash = str(entry.get(hash_field) or "")
if not artifact.is_absolute() or not artifact.is_file() or not expected_hash:
raise ValueError(
f"mining history iteration {number} has invalid {path_field} proof"
)
actual_hash = _sha256(artifact)
if actual_hash != expected_hash:
raise ValueError(
f"mining history iteration {number} {path_field} hash mismatch"
)
entry["selected_filepaths"] = normalized
all_selected.update(normalized)
if actual_numbers != expected_numbers:
raise ValueError(
"mining history iterations must be contiguous from 1; "
f"found {actual_numbers}"
)
if payload.get("cumulative_unique_count") != len(all_selected):
raise ValueError(
"mining history cumulative_unique_count disagrees with "
"selected_filepaths"
)
return payload
def select_novel_samples(
*,
candidate_parquet: pathlib.Path,
output_parquet: pathlib.Path,
history_file: pathlib.Path,
summary_file: pathlib.Path,
iteration: int,
topn: int,
filepath_column: str = "filepath",
resume: bool = False,
) -> dict[str, Any]:
"""Write the current iteration's novel candidates and append the ledger."""
try:
import pyarrow as pa
import pyarrow.parquet as pq
except ImportError as exc:
raise ValueError("pyarrow is required for history-aware mining") from exc
candidate_parquet = candidate_parquet.expanduser().resolve()
output_parquet = output_parquet.expanduser().resolve()
history_file = history_file.expanduser().resolve()
summary_file = summary_file.expanduser().resolve()
if iteration < 1:
raise ValueError("iteration must be >= 1")
if topn < 1:
raise ValueError("topn must be >= 1")
if candidate_parquet == output_parquet:
raise ValueError("candidate and output parquet paths must differ")
if not candidate_parquet.is_file():
raise FileNotFoundError(f"candidate parquet is missing: {candidate_parquet}")
if len({output_parquet, history_file, summary_file}) != 3:
raise ValueError("output parquet, history, and summary paths must differ")
state = _validated_history(history_file, iteration)
entries: list[dict[str, Any]] = state["iterations"]
committed = next(
(entry for entry in entries if int(entry["iteration"]) == iteration), None
)
if committed is not None:
if not resume:
raise ValueError(
f"iteration {iteration} is already committed in {history_file}; "
"pass --resume to verify and reuse it"
)
if pathlib.Path(committed["output_parquet"]).resolve() != output_parquet:
raise ValueError("committed output parquet does not match --output-parquet")
if pathlib.Path(committed["summary_file"]).resolve() != summary_file:
raise ValueError("committed summary does not match --summary")
if pathlib.Path(committed["candidate_parquet"]).resolve() != candidate_parquet:
raise ValueError(
"committed candidate parquet does not match --candidate-parquet"
)
if _sha256(candidate_parquet) != committed.get("candidate_sha256"):
raise ValueError("committed candidate parquet hash mismatch")
if int(committed.get("topn", 0)) != topn:
raise ValueError("committed topn does not match the requested topn")
return json.loads(summary_file.read_text())
if len(entries) != iteration - 1:
raise ValueError(
f"cannot select iteration {iteration}; mining history ends at "
f"iteration {len(entries)}"
)
table = pq.read_table(candidate_parquet)
if filepath_column not in table.column_names:
raise ValueError(
f"candidate parquet is missing {filepath_column!r}; "
f"columns={table.column_names}"
)
historical = {
value
for entry in entries
for value in entry["selected_filepaths"]
}
candidate_seen: set[str] = set()
selected_names: list[str] = []
selected_indices: list[int] = []
candidate_duplicate_count = 0
already_mined_count = 0
for index, value in enumerate(table[filepath_column].to_pylist()):
identity = _normalize_filepath(value)
if identity in candidate_seen:
candidate_duplicate_count += 1
continue
candidate_seen.add(identity)
if identity in historical:
already_mined_count += 1
continue
selected_names.append(identity)
selected_indices.append(index)
filtered = table.take(pa.array(selected_indices, type=pa.int64()))
_atomic_parquet(filtered, output_parquet)
historical_candidate_rate = (
already_mined_count / len(candidate_seen) if candidate_seen else 0.0
)
recommendation = None
if not selected_names and candidate_seen:
recommendation = (
"all candidates were selected in earlier iterations; increase topn "
"or expand the source pool"
)
elif historical_candidate_rate >= 0.5:
recommendation = (
"at least half of the unique candidates were already mined; consider "
"increasing topn to cast a wider net"
)
summary: dict[str, Any] = {
"version": HISTORY_VERSION,
"iteration": iteration,
"identity": HISTORY_IDENTITY,
"topn": topn,
"candidate_parquet": str(candidate_parquet),
"candidate_sha256": _sha256(candidate_parquet),
"candidate_row_count": table.num_rows,
"candidate_unique_count": len(candidate_seen),
"candidate_duplicate_count": candidate_duplicate_count,
"history_count_before": len(historical),
"already_mined_count": already_mined_count,
"historical_candidate_rate": historical_candidate_rate,
"selected_count": len(selected_names),
"cumulative_unique_count": len(historical) + len(selected_names),
"output_parquet": str(output_parquet),
"output_sha256": _sha256(output_parquet),
"recommendation": recommendation,
}
_atomic_json(summary_file, summary)
entry = {
"iteration": iteration,
"topn": topn,
"candidate_parquet": str(candidate_parquet),
"candidate_sha256": summary["candidate_sha256"],
"candidate_unique_count": len(candidate_seen),
"already_mined_count": already_mined_count,
"selected_count": len(selected_names),
"selected_filepaths": selected_names,
"output_parquet": str(output_parquet),
"output_sha256": summary["output_sha256"],
"summary_file": str(summary_file),
"summary_sha256": _sha256(summary_file),
}
entries.append(entry)
state["iterations"] = entries
state["cumulative_unique_count"] = len(historical) + len(selected_names)
_atomic_json(history_file, state)
return summary
def _parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--candidate-parquet", required=True, type=pathlib.Path)
parser.add_argument("--output-parquet", required=True, type=pathlib.Path)
parser.add_argument("--history-file", required=True, type=pathlib.Path)
parser.add_argument("--summary", required=True, type=pathlib.Path)
parser.add_argument("--iteration", required=True, type=int)
parser.add_argument("--topn", required=True, type=int)
parser.add_argument("--filepath-column", default="filepath")
parser.add_argument("--resume", action="store_true")
return parser
def main(argv: list[str] | None = None) -> int:
args = _parser().parse_args(argv)
try:
summary = select_novel_samples(
candidate_parquet=args.candidate_parquet,
output_parquet=args.output_parquet,
history_file=args.history_file,
summary_file=args.summary,
iteration=args.iteration,
topn=args.topn,
filepath_column=args.filepath_column,
resume=args.resume,
)
except (OSError, ValueError, TypeError, json.JSONDecodeError) as exc:
print(f"filter_mined_history: {exc}", file=sys.stderr)
return 2
print(
"filter_mined_history: "
f"candidates={summary['candidate_unique_count']} "
f"already_mined={summary['already_mined_count']} "
f"selected={summary['selected_count']} topn={summary['topn']}"
)
if summary.get("recommendation"):
print(f"filter_mined_history: warning: {summary['recommendation']}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Declares allowed tools, Needs a command-line tool, Needs Python
The author says: Requires docker + nvidia-container-toolkit and a CUDA GPU. Pulls the TAO data-services container pinned in this skill.yaml` at the skill bank root.
Security
What our scanner noticed· Medium risk
- Large base64-encoded blobs
- Scripts that your agent may run
This skill includes scripts that your agent may run. Read them before you use it.
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- NVIDIA Corporation
- Publisher
- NVIDIA (Official)
- Source
- NVIDIA/skills · skills/tao-mine-aoi-images · commit fce3cca
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE-APACHE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by NVIDIA Corporation or NVIDIA.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download tao-mine-aoi-images.zip