Tao Generate Image Grounding
NVIDIAOfficialCreated by NVIDIA Corporation
- Skill
- Workflow
- Data and AI
- Apache-2.0
- Medium risk
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The tao-generate-image-grounding skill provides a structured workflow for generating phrase-grounded training data. It utilizes a vision-language model (VLM) to perform a two-step process: first, it cleans captions and extracts referring expressions with character spans; second, it predicts pixel-space bounding boxes for those expressions. The pipeline supports various VLM backends, including Gemini and OpenAI-compatible endpoints like NIM or vLLM, and includes built-in checkpointing to allow for efficient, resumable processing of large image datasets.
What it does
- Extracts referring expressions and character spans from image captions.
- Generates pixel-space bounding boxes for identified expressions.
- Supports multiple VLM backends including Gemini and OpenAI-compatible services.
- Provides per-sample checkpointing for resumable, fault-tolerant processing.
- Allows for flexible pipeline execution, enabling step-by-step or full-run processing.
- Outputs structured JSONL annotations suitable for training grounding models.
When to use it
- When you need to create phrase-grounded training datasets from existing image-caption pairs.
- When you want to auto-label images with bounding boxes for object detection or grounding tasks.
- When you need to validate or refine caption-to-image alignment using a VLM.
- When you have a large dataset and require a resumable, automated annotation workflow.
Advantages
- Automates labor-intensive manual annotation tasks using powerful VLM teacher models.
- Highly configurable with support for various self-hosted or cloud-based VLM endpoints.
- Resilient workflow design with built-in checkpointing to prevent data loss during long runs.
- Flexible execution allows for inspecting intermediate results before full-scale processing.
Usage examples
- “Run the image grounding pipeline on my dataset of images and captions.”
- The agent will guide you through setting up the input JSONL, selecting your VLM backend (e.g., Gemini or a local vLLM server), and executing the two-step extraction and grounding process.
- “I need to extract referring expressions from my captions but not ground them yet.”
- The agent will configure the workflow to run only step 0, producing a JSONL file containing cleaned captions and identified expressions with character spans.
- “How do I re-run the grounding step after fixing my configuration?”
- The agent will instruct you to set workflow.force_reprocess to true to ignore existing checkpoints and re-run the pipeline from scratch.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/nvidia/tao-generate-image-grounding/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip tao-generate-image-grounding.zip -d .agents/skills
Documentation by NVIDIA Corporation
Image Grounding Pipeline
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).
Turn (image, caption) pairs into per-image grounded annotations: cleaned captions, referring expressions with character spans, and pixel-space bounding boxes for each expression. A single VLM (Gemini or any OpenAI-compatible endpoint) handles both steps.
Purpose
Generate phrase-grounded training data for referring-expression and grounding models. The VLM acts as a "teacher" annotator: Step 0 extracts referring expressions from the caption while looking at the image; Step 1 returns one bbox set per expression for each image.
Pipeline Architecture
Step 0: Expression extraction → VLM cleans caption, extracts referring expressions + char spans
Step 1: Phrase grounding → VLM returns pixel bboxes + scores per expressionSteps are individually selectable via workflow.steps. Each step writes a per-sample checkpoint to step_<N>_*/.ckpt/<sample_id>.json and skips already-processed records on re-run. Set workflow.force_reprocess: true to ignore checkpoints and reprocess from scratch.
Instructions
Initial setup
When a user wants to run this pipeline, walk through these steps:
Input JSONL: Ask for the JSONL path. Each line must be one object like
{"image_path": "...", "caption": "..."}.image_pathcan be absolute or relative.Image root: If any
image_pathvalues are relative, setdata.image_rootto the directory they should resolve from.API access: Ask the user which VLM endpoint they want to use. Present these five options and act on the choice:
Gemini — set
vlm.backend: "gemini"; requireGOOGLE_API_KEY(env var orvlm.gemini.api_key).NIM (e.g.
https://inference-api.nvidia.com/v1) — setvlm.backend: "openai"; collectbase_url,model_name, andapi_key.TAO inference microservice (self-hosted, OpenAI-compatible). Confirm whether the server is already running:
Running — collect
base_url,model_name, and (optionally)api_key; setvlm.backend: "openai".Not running — guide the user through the
skills/applications/tao-run-inference-serviceskill, which stands up a local TAO inference microservice with an OpenAI-compatible API. Before promising a specific model, checkskills/applications/tao-run-inference-service/references/service.yamlforvalid_network_arch_config_basenames. Once the server is up, collectbase_url,model_name, and (optionally)api_key; setvlm.backend: "openai".
vLLM (self-hosted, OpenAI-compatible). Confirm whether the server is already running:
Running — collect
base_url,model_name, and (optionally)api_key; setvlm.backend: "openai".Not running — follow references/vllm_server.md to install and launch a vLLM server, then collect
base_url,model_name, and (optionally)api_key; setvlm.backend: "openai".
Custom (any other OpenAI-compatible endpoint) — set
vlm.backend: "openai"; collectbase_url,model_name, and (optionally)api_key.
If the user has no endpoint and does not want to set one up, stop and help resolve API access first.
Workflow steps: Choose one of:
Full pipeline:
["0", "1"]Expression extraction only:
["0"]Grounding only:
["1"], which requires existing step-0 output atresults_dir/step_0_expression_extraction/annotations.jsonl
Resume vs fresh run: By default, the workflow reuses checkpoints and skips completed records. To reprocess everything, set
image_grounding.workflow.force_reprocess=true.
Running the pipeline
The pipeline runs inside the TAO Toolkit container via the auto_label CLI:
auto_label generate -e /path/to/spec.yaml \
results_dir=/results \
image_grounding.data.input_jsonl=/data/captions.jsonl \
image_grounding.data.image_root=/data/images \
image_grounding.vlm.gemini.api_key=$GOOGLE_API_KEYGenerate a default spec: auto_label default_specs results_dir=/results module_name=auto_label, then set autolabel_type: "image_grounding". All fields support Hydra dot-notation overrides on the command line.
See references/configuration.md for the full YAML structure, all parameters, model/endpoint setup, and error patterns.
Recommended pilot workflow
Run on 5-10 images with both steps
Inspect
step_0_expression_extraction/annotations.jsonl— arecleaned_captionandexpressions[]accurate? Are the right noun phrases captured?Inspect
step_1_grounding/annotations.jsonl— do the bboxes inexpressions[].instances[]look right? Are confidence scores reasonable?If quality is insufficient, switch the VLM to a stronger model (e.g.
gemini-2.5-pro) or raisemedia_resolution/max_output_tokens, then re-run withforce_reprocess=true.Scale to the full dataset once satisfied.
Configuration
Key configuration fields (full reference in references/configuration.md):
| Field | Default | Description |
|---|---|---|
workflow.steps | ["0","1"] | Which pipeline steps to execute ("0" = expressions, "1" = grounding) |
workflow.max_workers | 4 | Parallel threads per step (watch API rate limits) |
workflow.force_reprocess | false | Ignore per-sample checkpoints and reprocess from scratch |
vlm.backend | "gemini" | "gemini" or "openai" (OpenAI-compatible endpoint) |
data.input_jsonl | required | Path to input JSONL with image_path + caption per line |
data.image_root | "" | Optional prefix for resolving relative image_path entries |
Inputs
A single JSONL file at data.input_jsonl. One JSON object per line:
| Field | Required | Description |
|---|---|---|
image_path | yes | Absolute path, or relative path resolved against data.image_root |
caption | yes | Free-text caption for the image |
image_id | no | Stable identifier; auto-derived from the filename if missing |
width, height | no | Image dimensions in pixels; default to 1920×1080 for bbox clamping if missing |
Outputs
All outputs go to results_dir/:
step_0_expression_extraction/annotations.jsonl— per-record output enriched withcleaned_captionandexpressions[](each withtext,expression_id,char_span,noun_chunk, emptyinstances[]).step_1_grounding/annotations.jsonl— same records withexpressions[].instances[]filled in (each instance hasbbox: [x1,y1,x2,y2]in pixel space,scorein[0.0, 1.0], andbbox_id).results_dir/annotations.jsonl— copy of the last step's output for convenience.step_<N>_*/.ckpt/<sample_id>.json— per-sample checkpoints used for resume.
Prerequisites
Container:
nvcr.io/nvidia/tao/tao-toolkit:7.3.0-pyt<!-- versions-key: images.tao_toolkit.pyt -->API access: At least one VLM endpoint (Gemini API key or OpenAI-compatible endpoint capable of image input)
Files
- ATTRIBUTION.mdAdded by AutoGineer954 B
- BENCHMARK.md7.1 KiB
- LICENSELicence file added by AutoGineer11.2 KiB
- SKILL.md7.9 KiB
- config/skillspector-baseline.yaml834 B
- evals/evals.json819 B
- references/configuration.md9.3 KiB
- references/skill_info.yaml1.1 KiB
- references/vllm_server.md6.8 KiB
- skill-card.md4.5 KiB
- skill.oms.sig5.4 KiB
references/configuration.md
Image Grounding — Full Configuration Reference
Use this reference only when the parent SKILL.md points here for the current task. If this file conflicts with current SKILL.md, skill_info.yaml, schemas, or platform/model skills, the current authoritative source wins.
Contents
Complete YAML Structure
Key Configuration Decisions
Model / Endpoint Configuration
Gemini (default)
OpenAI-compatible endpoints
All Parameters
Input JSONL Schema
Output Layout
Error Patterns
Complete YAML Structure
Generate a default experiment spec with auto_label default_specs results_dir=/results module_name=auto_label, then set autolabel_type: "image_grounding".
results_dir: ??? # Required — output directory
autolabel_type: "image_grounding"
image_grounding:
# --- VLM (vision-language model, used for both steps) ---
vlm:
backend: "gemini" # "gemini" or "openai"
gemini:
api_key: "" # Or set GOOGLE_API_KEY env var
model: "gemini-3.1-flash-lite-preview"
media_resolution: "MEDIA_RESOLUTION_HIGH" # LOW / MEDIUM / HIGH
temperature: 0.3
max_output_tokens: 8192
timeout: 120
openai: # For OpenAI-compatible endpoints (NIM, vLLM, etc.)
api_key: ""
base_url: "" # e.g. "https://inference-api.nvidia.com/v1" — no /chat/completions suffix
model_name: "" # e.g. "Qwen/Qwen3-VL-235B-A22B-Instruct"
temperature: 0.7
max_tokens: 4096
timeout: 60
# --- Workflow ---
workflow:
steps: ["0", "1"] # "0" = expression extraction, "1" = phrase grounding
max_workers: 4 # Parallel threads per step
force_reprocess: false # Ignore cached per-sample checkpoints
# --- Input data ---
data:
input_jsonl: ??? # Path to input JSONL (image_path + caption per line)
image_root: "" # Optional prefix for relative image_path entriesKey Configuration Decisions
| Decision | Config field | Guidance |
|---|---|---|
| Which steps to run | workflow.steps | Start with both (["0","1"]). Drop "1" to inspect extracted expressions before grounding; drop "0" to re-ground using existing step-0 output |
| VLM provider | vlm.backend | "gemini" for Google Gemini models, "openai" for any OpenAI-compatible endpoint (NIM, vLLM, etc.) |
| Parallelism | workflow.max_workers | Higher = faster but watch API rate limits. Start with 4, drop to 1-2 if you hit 429s |
| Resume vs restart | workflow.force_reprocess | false reuses per-sample checkpoints under step_<N>_*/.ckpt/. Set true to redo everything |
| Image path resolution | data.image_root | Leave empty if image_path entries are absolute. Otherwise set to the directory the relative paths are anchored to |
| Bounding box quality | vlm.gemini.media_resolution | Use MEDIA_RESOLUTION_HIGH for accurate pixel-space bboxes. Lower resolutions are cheaper but degrade localization |
| Output truncation | vlm.gemini.max_output_tokens / vlm.openai.max_tokens | If you see "could not parse response" warnings, raise this — Step 1 returns one bbox dict per expression and can be long |
Model / Endpoint Configuration
Gemini (default)
Set the API key via environment variable or config:
export GOOGLE_API_KEY=your_key_hereOr in the YAML: image_grounding.vlm.gemini.api_key: "your_key".
Recommended model assignments:
For both steps:
gemini-2.5-flash(fast, good enough for most images) orgemini-2.5-pro(better localization on small/cluttered objects).
Temperature guidance:
Expression extraction (Step 0): 0.2-0.3 for stable, factual phrases.
Phrase grounding (Step 1): 0.2-0.3 — bbox prediction should be deterministic.
OpenAI-compatible endpoints
For self-hosted models, the pipeline accepts any endpoint that speaks the OpenAI chat-completions API. Two common ways to provision one:
skills/applications/tao-run-inference-serviceskill — workflow for standing up a TAO inference microservice locally. Should support Cosmos, Qwen, and Gemma. Check that skill'sreferences/service.yamlvalid_network_arch_config_basenamesfor the current model list.Bring-your-own deployment — vLLM, NIM, or any other OpenAI-compatible server.
image_grounding:
vlm:
backend: "openai"
openai:
base_url: "http://your-endpoint:8000/v1"
model_name: "Qwen/Qwen3-VL-235B-A22B-Instruct"
api_key: "EMPTY"
temperature: 0.3
max_tokens: 8192All Parameters
| Parameter | Default | Description |
|---|---|---|
workflow.steps | ["0","1"] | Pipeline steps to execute ("0" = expression extraction, "1" = phrase grounding) |
workflow.max_workers | 4 | Thread pool size for parallel API calls |
workflow.force_reprocess | false | Ignore per-sample checkpoints and reprocess from scratch |
vlm.backend | "gemini" | VLM backend: "gemini" or "openai" |
vlm.gemini.api_key | "" | Gemini API key (or set GOOGLE_API_KEY env var) |
vlm.gemini.model | "gemini-3.1-flash-lite-preview" | Gemini model name |
vlm.gemini.media_resolution | "MEDIA_RESOLUTION_HIGH" | Image resolution sent to Gemini (LOW/MEDIUM/HIGH) |
vlm.gemini.temperature | 0.3 | VLM sampling temperature |
vlm.gemini.max_output_tokens | 8192 | Maximum tokens in Gemini response |
vlm.gemini.timeout | 120 | Request timeout in seconds |
vlm.openai.api_key | "" | API key for OpenAI-compatible endpoint |
vlm.openai.base_url | "" | Base URL of the OpenAI-compatible endpoint (no /chat/completions suffix) |
vlm.openai.model_name | "" | Model name to send in the OpenAI request |
vlm.openai.temperature | 0.7 | OpenAI-compatible sampling temperature |
vlm.openai.max_tokens | 4096 | Maximum tokens in the OpenAI-compatible response |
vlm.openai.timeout | 60 | Request timeout in seconds |
data.input_jsonl | (required) | Path to input JSONL with image_path + caption fields |
data.image_root | "" | Optional prefix used to resolve relative image_path entries |
Input JSONL Schema
One JSON object per line. Required and optional fields:
| Field | Required | Description |
|---|---|---|
image_path | yes | Absolute path or relative path resolved against data.image_root |
caption | yes | Free-text caption used as the basis for expression extraction |
image_id | no | Stable identifier; auto-derived from the filename when missing |
width, height | no | Image dimensions in pixels; default to 1920×1080 for bbox clamping when missing |
Any additional fields are passed through unchanged to the output records.
Output Layout
results_dir/
├── annotations.jsonl # copy of the last step's output
├── step_0_expression_extraction/
│ ├── annotations.jsonl # cleaned_caption + expressions[]
│ └── .ckpt/<sample_id>.json # per-sample resume checkpoints
└── step_1_grounding/
├── annotations.jsonl # expressions[].instances[] filled in
└── .ckpt/<sample_id>.jsonEach output record carries:
cleaned_caption— the caption after Step 0 normalizes "we can see...", "there is...", etc.expressions[]— one entry per referring expression, withtext,expression_id,char_span: [start, end],noun_chunk, andinstances[].expressions[].instances[]— populated in Step 1 withbbox: [x1, y1, x2, y2](pixel-space, clamped to image dims),scorein[0.0, 1.0], andbbox_id.pipeline_steps[]— list of step names that have processed this record.source— set to"image_grounding".
Error Patterns
| Error | Cause | Fix |
|---|---|---|
GOOGLE_API_KEY not set | Gemini API key missing | export GOOGLE_API_KEY=your_key or set image_grounding.vlm.gemini.api_key in the YAML |
| 429 / rate limit errors | Too many parallel API calls | Reduce workflow.max_workers (try 1 or 2) |
Could not parse response for <id> | VLM returned non-JSON or truncated output | Raise vlm.gemini.max_output_tokens / vlm.openai.max_tokens; lower temperature; for very long expression lists, split the input or use a stronger model |
Step 0: no input records at <path> | data.input_jsonl is empty or unreachable | Verify the path; check the JSONL has at least one valid line |
Step 1: no step-0 output at <path> | Re-ran with only ["1"] but step 0 was never run | Run with ["0","1"] first, or supply an existing step_0_expression_extraction/annotations.jsonl |
Empty instances[] for every expression | Image not found at image_path, or VLM cannot localize | Confirm data.image_root resolves; test the image path manually; raise media_resolution to MEDIA_RESOLUTION_HIGH |
Bboxes look correct but are clipped to 1920×1080 | width/height missing in input JSONL | Add the true width and height fields to each input record |
| Re-runs skip everything | Per-sample checkpoints exist under .ckpt/ | Set image_grounding.workflow.force_reprocess=true to ignore them |
Unknown autolabel_type | YAML missing or wrong autolabel_type | Set autolabel_type: "image_grounding" at the top of the spec |
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 an API key
The author says: Requires docker + nvidia-container-toolkit + at least one VLM endpoint (Gemini API key or OpenAI-compatible).
Security
What our scanner noticed· Medium risk
- Large base64-encoded blobs
- Instructions that use the network
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-generate-image-grounding · 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-generate-image-grounding.zip