AI Skill Report Card

Benchmarking VLM Crochet Pattern Understanding

B+78·Sep 23, 2026·Source: Extension-page
13 / 15
Bash
# 1. Run a single model on a single task python benchmark_task/task_a_gemini.py --input data/selected_crochet_patterns_3.json --output results/task_a_gemini.jsonl # 2. Evaluate the task's outputs python benchmark_task/eval_task_a.py --predictions results/task_a_gemini.jsonl --output results/task_a_gemini_scored.csv # 3. Compare rendered images against ground-truth photos across all models python batch_compare_images.py --patterns data/selected_crochet_patterns_3.json --img_dirs render_outputs/ --output csv_results/
Recommendation▾
Description is long and hyper-specific to crochet domain, but the skill is really a generic multi-model benchmarking pattern — consider generalizing name/description or acknowledging the narrow niche explicitly so triggers are unambiguous
13 / 15

Progress:

  • Step 1: Define the task family (Task A/B/C/D-project/D-step) and its input/output schema
  • Step 2: For each task, write one script per model, sharing a common interface (utils.py)
  • Step 3: Write one eval_task_X.py per task that scores all models' outputs against ground truth
  • Step 4: For visual comparison tasks, batch-discover generated images and match them to dataset entries by ID/filename pattern
  • Step 5: Load all similarity models once (LPIPS, DINO, CLIP, SSIM) and reuse across the batch
  • Step 6: Write per-model CSV results with a timestamp column; never overwrite prior runs
  • Step 7: Aggregate CSVs into a summary comparison table across models/metrics

Task family design pattern

  • Task A: single-image → attribute/description generation (e.g., identify pattern from photo)
  • Task B: text pattern → property extraction / classification
  • Task C: multi-step reasoning or generation graded at output level
  • Task D-project: full-project-level evaluation (holistic, multi-image)
  • Task D-step: step-level evaluation (per-instruction-step grading)

Each task gets a separate script per model (task_a_claude.py, task_a_gemini.py, task_a_qwen_72b.py, etc.) rather than one script with a --model flag. This keeps model-specific SDK quirks (auth, rate limits, prompt formatting, multimodal input encoding) isolated and lets any single model's script fail without breaking the others. Share only generic helpers (I/O, prompt templates, retries) via utils.py.

Model script skeleton (replicate per model)

Python
# task_a_<model>.py import json, time, argparse from utils import load_dataset, save_jsonl, retry_with_backoff def call_model(image_path, prompt, client): # model-specific API call, wrapped in retry_with_backoff ... def main(): args = parse_args() dataset = load_dataset(args.input) results = [] for item in dataset: try: response = call_model(item["image_path"], build_prompt(item), client) results.append({"id": item["id"], "prediction": response}) except Exception as e: results.append({"id": item["id"], "error": str(e)}) time.sleep(args.rate_limit_delay) save_jsonl(results, args.output)

Image similarity pipeline design

Load every model once at startup (load_models(device)), never per-image-pair — model loading (LPIPS/DINO/CLIP) is expensive. Compute multiple complementary metrics per pair since they capture different notions of similarity:

  • LPIPS: perceptual similarity (low-level texture/structure), lower distance = more similar
  • DINO: self-supervised semantic feature similarity (cosine similarity of embeddings), good for shape/object-level match
  • CLIP: semantic/text-aligned similarity, useful for coarse "is this the same object type"
  • SSIM: structural similarity, sensitive to exact pixel alignment — use only for near-identical crops
  • Wasserstein distance: color/histogram distribution comparison

Auto-discover rendering directories by convention (*_img/) and match files to dataset entries via ID embedded in filename — don't hardcode paths per pattern.

Recommendation▾
Add a bad-output example (e.g., a common failure like reloading models per-pair or mismatched metric scales) to reinforce pitfalls with concrete before/after code
14 / 20

Example 1: Input: Add support for a new VLM ("Mistral") to Task C. Output: Create task_c_mistral.py mirroring task_c_qwen.py's structure (same CLI args, same JSONL output schema), swap in Mistral's SDK client and prompt formatting, keep eval_task_c.py untouched since it consumes the shared output schema.

Example 2: Input: Compare 50 simulator-rendered images against real product photos. Output: Run batch_compare_images.py, which loads LPIPS/DINO/CLIP once, iterates matched pairs, computes all four metrics per pair, writes one row per pair to a per-model CSV with columns [pattern_id, lpips_sim, dino_sim, clip_sim, ssim, timestamp].

Recommendation▾
Include a minimal utils.py example (retry_with_backoff, save_jsonl) since it's referenced repeatedly but never shown
  • Keep one script per (task × model) — resist the urge to parametrize models into a single mega-script; API differences make this brittle.
  • Always wrap external model calls in retry/backoff; batch jobs run long and APIs rate-limit or transiently fail.
  • Load heavyweight vision models (LPIPS/DINO/CLIP) once per process, pass instances into comparison functions.
  • Normalize/preprocess per model's expected input range (LPIPS wants [-1,1], DINO/CLIP want ImageNet normalization) — don't share one transform across metrics.
  • Separate generation (task_X_model.py) from evaluation (eval_task_X.py) — generation produces raw model outputs, evaluation scores them, so re-scoring never requires re-running expensive API calls.
  • Timestamp every output CSV/JSONL so reruns don't silently overwrite prior benchmark results.
  • Use try/except per-item in batch loops so one failure doesn't kill the whole batch; log errors alongside partial results.
  • Don't reload LPIPS/DINO/CLIP inside a per-pair loop — instantiate once in load_models().
  • Don't mix similarity metric scales in one aggregate score without normalizing — LPIPS distance and cosine similarity have opposite directions (lower vs. higher = better).
  • Don't hardcode image directory names — discover via glob pattern (*_img/) since new models each get their own render output folder.
  • Don't skip the .convert("RGB") step when loading images — grayscale or RGBA inputs silently break model preprocessing.
  • Don't conflate step-level (task_d_step) and project-level (task_d_project) evaluation logic — they need different aggregation (per-instruction vs. whole-pattern).
0
Grade B+AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
13/15
Workflow
13/15
Examples
14/20
Completeness
17/20
Format
13/15
Conciseness
13/15