关于 tao-mine-aoi-images
这项 DEFT 工作流 skill 先对目标图像和来源图像生成嵌入,再挖掘最近邻并输出去重后的 parquet,供后续 VCN AOI 训练轮次使用。
主要功能
- 01为目标和来源图像 parquet 生成嵌入
- 02按选定指标挖掘最近邻
- 03对挖掘出的图像路径去重
- 04可选按标签过滤
- 05输出挖掘摘要和中间 parquet
适用场景
- 01查找与弱目标相似的来源图像
- 02为下一轮训练准备图像数据
- 03在多次挖掘中复用嵌入
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ promptingcompany/ nv-skills --skill tao-mine-aoi-images安装后在 Claude Code 中输入/tao-mine-aoi-images确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
BENCHMARK.mdskill-card.mdskill.oms.sigevals/evals.jsonhooks/_parse-stdin.shmining-artifacts-check.shmining-package.shmining-script-check.shmining-section-check.shreferences/invocation.mdreporting_spec.mdtroubleshooting.md详细介绍
DEFT 挖掘与嵌入技能
你是 VCN AOI 的 DEFT 先嵌入后挖掘工作流的操作人员。你的任务是获取一个弱目标图像的 parquet 文件(缺口分析或路由输出)和一个源数据池,然后生成一个去重后的源图像挖掘结果 parquet 文件,其中包含与目标图像相似的图像,可直接用于下一轮训练。
该工作流固定且具有确定性:嵌入目标图像、嵌入源数据池,然后挖掘最近邻。 每一步的输出 parquet 文件都是下一步的输入。工作流不包含迭代搜索、聚类步骤或人工参与筛选——挖掘深度取决于选择合适的编码器和 topn,而非多阶段调查。
整个技能只是对 versions.yaml 中声明的 tao_toolkit.data_services 镜像执行三次直接 docker run 调用的轻量封装(运行时解析——参见 Setup)。容器的入口点接受 <category> <action> -e <spec.yaml> [hydra overrides...]:嵌入时使用 embedding image_embeddings -e <embedding_spec.yaml> …,挖掘时使用 tmm nearest_neighbors -e <mining_spec.yaml> …。-e 标志指向包含架构默认值的 YAML 文件;其后的所有内容都是裸 Hydra 覆盖项(key=value),并按次运行应用。容器内没有 dataset 关键字——那是 TAO 启动器的支柱前缀,此处会将其去掉。不同 data-services 版本中的架构键可能会更名,因此不确定时,请针对每个镜像运行一次 docker run --rm "$DS_IMAGE" embedding image_embeddings --cfg=job 和 ... tmm nearest_neighbors --cfg=job 进行检查。完整的入口点约定、--cfg=job 检查方法,以及可复制并编辑的端到端操作步骤,请参见 references/invocation.md。
输入
- 目标 parquet 文件 — 缺口分析的输出,通常是
tao-route-visual-changenet-samples生成的mining_gaps.parquet(如果跳过了路由,则为tao-analyze-gaps-visual-changenet生成的gaps.parquet)。必需列:filepath。如果还包含label,则挖掘时可按标签筛选;否则挖掘任务会静默跳过筛选。 - 源数据池 — 包含候选图像的 parquet 文件,需有
filepath列。如果用户只有 CSV,请在第 2 步之前将其转换为列保持一致的 parquet 文件。若要按标签筛选,数据池还必须包含label列。 - 嵌入规范文件 — 包含
model、model_path、batch_size的 YAML;仅当model_path是 TAO.pth/.ckpt文件时,还需包含model_config_path。第 1 步和第 2 步共用此文件;运行时通过 Hydra 覆盖项提供input_parquet/output_parquet。两个嵌入步骤 MUST 使用同一个规范文件——不同编码器生成的嵌入不可比较,编码器不匹配是“挖掘出的图像看起来毫不相关”这类反馈最常见的原因。 - 挖掘规范文件 — 包含
topn、knn_metric、filter_by_label,以及(极少更改的)source_embed_column_name/target_embed_column_name的 YAML 文件。运行时通过 Hydra 覆盖项提供source_parquet/target_parquet/output_parquet。SigLIP 和 CLIP 嵌入应使用knn_metric: cosine。当filter_by_label: true,但任一嵌入 parquet 文件缺少label列时,容器会记录警告并继续运行,不进行筛选。
设置
挖掘和嵌入任务位于 versions.yaml 中声明的 tao_toolkit.data_services 镜像内。在运行开始时解析一次具体的 URI,然后先确认 Docker、NVIDIA 容器工具包和 GPU 均已就绪,再执行其他操作:
# Resolve tao_toolkit.data_services → concrete nvcr.io/... URI from versions.yaml
DS_IMAGE=$(python3 -c "import yaml,os; print(yaml.safe_load(open(os.environ['TAO_SKILL_BANK_PATH']+'/versions.yaml'))['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"
插件的 session_start 钩子会导出 TAO_SKILL_BANK_PATH。如果该变量未设置(例如在 Claude Code 插件之外运行),请在解析前将其指向 skill-bank 仓库根目录。编码器前向传递和 cuML/cuDF k-NN 搜索都需要 GPU;没有 CUDA 时,这两个步骤都会失败。
路径挂载。 容器读取或写入的所有主机路径——输入 parquet 文件、输出目录和源池图像根目录——都必须进行绑定挂载。最简单、最可靠的方法是挂载工作区根目录,并让容器内外的路径完全一致,这样 parquet 参数中的绝对路径在两端都能正确解析:
WORKSPACE=<absolute path that contains all parquets, outputs, and the source-pool images>
DOCKER="docker run --gpus all --rm --ipc=host --user $(id -u):$(id -g) -v $WORKSPACE:$WORKSPACE -w $WORKSPACE $DS_IMAGE"
以下三个命令中都要复用 $DOCKER。
CSV 源池。 如果源池仅以 CSV 格式提供,请预先使用 pd.read_csv(...).to_parquet(..., index=False) 将其转换为 parquet,并原样保留 filepath 列(如果存在 label 列,也要保留)。不要添加路径前缀——容器会直接读取输入 parquet,而 $WORKSPACE 挂载会确保主机和容器中的路径一致。
每次迭代只需编写一次这两个规格文件。 两个文件都放在 $WORKSPACE 下,这样 -e 参数在挂载两侧都能解析。每次运行的参数不要写入规格文件,而是在调用时通过 Hydra 覆盖传入。默认值为:嵌入任务使用 model: SigLIP、model_path: google/siglip-base-patch16-224、batch_size: 64;挖掘任务使用 topn: 5、knn_metric: cosine、filter_by_label: "false"(需加引号——架构会将其读取为字符串)。SigLIP/CLIP 使用 cosine,其他模型使用 euclidean/manhattan;仅当 model_path 是 TAO 检查点时,才添加 model_config_path。仍可在 CLI 中覆盖任何字段(例如 topn=10)——Hydra 会在规格文件的基础上应用 CLI 覆盖项。
关于规格文件的原样模板、CSV 转换代码片段以及完整的挂载和镜像解析细节,请参阅 references/invocation.md。
方法
按顺序执行三个命令。每个命令生成的 parquet 都是下一个命令的输入。将它们作为普通 Bash 命令运行;设置部分中的 $DOCKER 别名会处理容器、GPU 和挂载。每次调用的结构都相同:先使用 -e <spec> 指定预设默认值,再添加少量 Hydra 覆盖项指定本次运行的路径。
步骤 1 — 嵌入目标图像
$DOCKER embedding image_embeddings -e <embedding_spec.yaml> \
input_parquet=<target_parquet> output_parquet=<target_embeddings_parquet>
读取差距分析/路由输出,并生成包含 filepath、embedding 以及原样传递的其他元数据列(例如 label、siamese_score、weakness)的 parquet。将输出架构(pd.read_parquet(...).columns)打印到 stdout,以便脚本检查钩子确认嵌入列存在。若要在单次运行中覆盖 model / model_path / batch_size,而不修改规格文件,请将它们作为 Hydra 覆盖项追加。
步骤 2 — 嵌入源池
$DOCKER embedding image_embeddings -e <embedding_spec.yaml> \
input_parquet=<source_pool_parquet> output_parquet=<source_embeddings_parquet>
命令结构与步骤 1 相同,但应用于源池。使用与步骤 1 完全相同的 embedding_spec.yaml,并且不要在此处以不同的值覆盖 model / model_path / batch_size——两个步骤的编码器配置不匹配会导致生成的嵌入无法相互比较。
步骤 3 — 挖掘最近邻
$DOCKER tmm nearest_neighbors -e <mining_spec.yaml> \
source_parquet=<source_embeddings_parquet> \
target_parquet=<target_embeddings_parquet> output_parquet=<mined_parquet>
对于每个目标嵌入,按所选指标查找最接近的 topn 个源嵌入,跨目标去重,并写入仅含一列(filepath)的 parquet 文件,其中包含挖掘到的唯一源路径。容器还会在输出 parquet 旁生成 mining_summary.txt,其中包含:查询数、邻居数、移除的重复项数量,以及(启用标签过滤时)保留与丢弃的配对数。执行批量扫描时,可通过内联 Hydra 覆盖项调整 topn、knn_metric 或 filter_by_label,无需重写配置。如果 filter_by_label=true,但某个嵌入 parquet 缺少 label 列,容器会记录警告并继续运行,不进行过滤;如果挖掘输出看起来过大,或包含跨标签配对,请先检查 Docker 日志中是否有该警告。
参见 references/invocation.md,了解完整的复制粘贴并编辑操作步骤;该步骤会通过一个流式 Bash 代码块运行全部三个步骤,并打印行数以供合理性检查。
输出
将所有内容写入实验 / 迭代目录下带时间戳的文件夹。写入 Mining_Report.md 时,打包钩子会自动添加 mining_config/ 和 claude_session.jsonl。
<output_dir>/mining_results/YYYY-MM-DD_HHMMSS/
├── Mining_Report.md # Full mining report
├── embedding_spec.yaml # The -e spec used for Steps 1 and 2
├── mining_spec.yaml # The -e spec used for Step 3
├── target_embeddings.parquet # Step 1 output (filepath, embedding, + carried metadata)
├── source_embeddings.parquet # Step 2 output (filepath, embedding, + carried metadata)
├── mined.parquet # Step 3 output — unique mined source filepaths
├── mining_summary.txt # Auto-emitted next to mined.parquet by the container
├── mining_config/ # Auto-copied by hook
└── claude_session.jsonl # Auto-copied by hook
运行开始时,在 Bash 中运行 date +%Y-%m-%d_%H%M%S 获取实际时间戳。不要硬编码或猜测。如果用户指定了自定义输出路径,请直接使用,但保持相同的内部布局。
下游训练会使用挖掘得到的 parquet 文件。两个嵌入 parquet 文件是中间文件,但值得保留:它们可在针对相同源数据池的多次挖掘运行中重复使用;当报告指出结果“看起来不相关”时,它们也是唯一可用于编码器级调试的文件。
常见问题
输出无用的最常见原因是编码器不匹配——两个嵌入步骤必须使用相同的 embedding_spec.yaml,任何 model / model_path / batch_size 覆盖项也必须同时应用于两个步骤,或两个步骤都不应用。其他常见问题包括:跳过某个嵌入步骤、在 filter_by_label=true 时缺少 label 列(静默无操作)、规范文件位于 $WORKSPACE 之外、未解析的 ??? 占位符、缺少 model_config_path 的 TAO 检查点、CSV 数据池未转换为 parquet、主机 / 容器路径不匹配、没有 GPU、镜像标签错误,以及 topn × N_targets 超过源数据大小(这是预期情况,并非错误——请报告实际挖掘数量)。
参见 references/troubleshooting.md,了解这些问题的完整诊断与修复方法。
报告结构
报告控制在 600–1200 字。挖掘是确定性流水线;报告的价值在于让编码器选择、行数和任何静默的过滤无操作都可审计,而不是叙述过程。报告包含七个部分:结论、输入、编码器一致性、挖掘运行、按标签细分(目标 parquet 不含 label 列时跳过)、输出合理性检查和建议措施。
参见 references/reporting_spec.md,查看完整的填报模板,其中列出了所有部分和字段。
执行顺序
- 从
versions.yaml(images.tao_toolkit.data_services)解析DS_IMAGE,然后运行docker info、nvidia-smi和docker image inspect "$DS_IMAGE"(如果镜像不存在则拉取),以确认环境。若任一步失败,显示明确的消息并中止。 - 运行
date +%Y-%m-%d_%H%M%S获取时间戳;创建<output_dir>/mining_results/<timestamp>/。 - 在带时间戳的目录中编写
embedding_spec.yaml和mining_spec.yaml,填写编码器选项和挖掘参数。将这些文件保存在$WORKSPACE下,以确保容器内的-e路径有效。 - 如果源数据池是 CSV,先将其转换为 parquet(保留
filepath和label)。 - 通过
docker run … embedding image_embeddings -e embedding_spec.yaml input_parquet=… output_parquet=…运行步骤 1(嵌入目标)。将输出 parquet 的行数和列名打印到标准输出。 - 使用与步骤 1 完全相同的
embedding_spec.yaml运行步骤 2(嵌入源数据池)。打印输出的行数和列名。 - 通过
docker run … tmm nearest_neighbors -e mining_spec.yaml source_parquet=… target_parquet=… output_parquet=…运行步骤 3(挖掘最近邻)。确认mining_summary.txt已写入mined.parquet所在目录。 - 如果目标嵌入 parquet 和挖掘输出都包含
label,则通过 filepath 连接两者,计算每个标签的细分结果(第 5 节)。 - 最后编写
Mining_Report.md——编写该文件会触发打包钩子,复制会话日志和技能配置。