|
1 | 1 | # Zero-Shot SKU Onboarding — Zippin Edge AI Platform (v2.0) |
2 | 2 |
|
3 | | -   |
| 3 | +      |
4 | 4 |
|
5 | 5 | A production-grade, end-to-end pipeline that onboards a **new retail SKU in under 10 minutes** from a single product photograph — no real-world data collection required. |
6 | 6 |
|
@@ -124,16 +124,21 @@ zippin-synthetic-onboarding-poc/ |
124 | 124 | │ │ ├── extract.py ← Stage 1: LLaVA semantic extraction |
125 | 125 | │ │ ├── generate.py ← Stage 2: BlenderProc2 orchestration |
126 | 126 | │ │ ├── train.py ← Stage 3: YOLOv8n + EWC fine-tuning |
127 | | -│ │ └── eval.py ← Stage 4: pycocotools mAP evaluation |
| 127 | +│ │ └── eval.py ← Stage 4: mAP eval + failure gallery |
128 | 128 | │ ├── rendering/ |
129 | | -│ │ └── bproc_generator.py ← BlenderProc2 scene script |
| 129 | +│ │ └── bproc_generator.py ← BlenderProc2 + occlusion stress suites |
130 | 130 | │ ├── api/ |
131 | 131 | │ │ ├── server.py ← FastAPI REST service |
132 | 132 | │ │ └── schemas.py ← Pydantic request/response models |
133 | 133 | │ └── utils/ |
134 | 134 | │ ├── coco_to_yolo.py ← COCO → YOLO format conversion |
135 | 135 | │ ├── metrics.py ← pycocotools + NumPy mAP fallback |
136 | 136 | │ └── sku_registry.py ← Thread-safe multi-SKU state store |
| 137 | +├── scripts/ |
| 138 | +│ ├── benchmark_ewc.py ← EWC retention benchmark across N SKUs |
| 139 | +│ ├── export_tensorrt.py ← YOLOv8n → TensorRT FP16/INT8 engine |
| 140 | +│ ├── compute_dis.py ← Domain Invariance Score (CLIP embeddings) |
| 141 | +│ └── profile_edge.py ← Jetson Orin NX quantization profiler |
137 | 142 | ├── docker/ |
138 | 143 | │ ├── Dockerfile ← GPU worker (CUDA 12.1) |
139 | 144 | │ ├── Dockerfile.jetson ← Jetson Orin NX (L4T aarch64) |
@@ -254,6 +259,116 @@ approximately **25MB** for YOLOv8n. This is the entire continual learning memory |
254 | 259 |
|
255 | 260 | --- |
256 | 261 |
|
| 262 | +## Production QA Tooling |
| 263 | + |
| 264 | +Four additional scripts address the failure modes that matter most in a real Zippin deployment: |
| 265 | + |
| 266 | +### Occlusion Stress-Test Suite |
| 267 | + |
| 268 | +Zippin's Chief Scientist has noted that small products can be completely covered by a shopper's hand during a pick event. The renderer now generates targeted stress suites alongside standard data: |
| 269 | + |
| 270 | +```bash |
| 271 | +# Partial occlusion (30–55% SKU coverage) — reaching-arm events |
| 272 | +BPROC_OCCLUSION_MODE=partial_stress \ |
| 273 | + blenderproc run src/rendering/bproc_generator.py checkpoints/sku_features.json |
| 274 | + |
| 275 | +# Full occlusion (75–95% coverage) — product nearly invisible |
| 276 | +BPROC_OCCLUSION_MODE=full_stress \ |
| 277 | + blenderproc run src/rendering/bproc_generator.py checkpoints/sku_features.json |
| 278 | + |
| 279 | +# All three suites in sequence |
| 280 | +BPROC_OCCLUSION_MODE=all \ |
| 281 | + blenderproc run src/rendering/bproc_generator.py checkpoints/sku_features.json |
| 282 | +``` |
| 283 | + |
| 284 | +Outputs to `checkpoints/synthetic_dataset/occlusion_stress/partial/` and `.../full/` with independent COCO annotations. Use the `full/` suite to calibrate the sensor-fusion confidence threshold in `src/proposals/sensor_fusion.py`. |
| 285 | + |
| 286 | +--- |
| 287 | + |
| 288 | +### Domain Invariance Score (DIS) |
| 289 | + |
| 290 | +Measures how well synthetic renders approximate the visual feature space of the original product photo using **CLIP ViT-B/32** embeddings. Catches Sim2Real gaps before they become mAP surprises on real shelf cameras. |
| 291 | + |
| 292 | +```bash |
| 293 | +python scripts/compute_dis.py \ |
| 294 | + --original product.jpg \ |
| 295 | + --synthetic checkpoints/synthetic_dataset/images/ \ |
| 296 | + --output checkpoints/dis_report.json |
| 297 | +``` |
| 298 | + |
| 299 | +``` |
| 300 | +══════════════════════════════════════════════════════ |
| 301 | + Domain Invariance Score (DIS) — clip-vit-b32 |
| 302 | +══════════════════════════════════════════════════════ |
| 303 | + DIS (mean cosine sim) : 0.8341 [PASS] |
| 304 | + Std deviation : 0.0412 |
| 305 | + Range : [0.7190, 0.9203] |
| 306 | + p10 / p25 / p75 / p90 : 0.778 / 0.809 / 0.862 / 0.889 |
| 307 | + n_renders : 50 |
| 308 | + n < 0.70 (FAIL band) : 0 |
| 309 | + n < 0.80 (WARN band) : 9 |
| 310 | +══════════════════════════════════════════════════════ |
| 311 | +``` |
| 312 | + |
| 313 | +| DIS Score | Status | Action | |
| 314 | +|---|---|---| |
| 315 | +| ≥ 0.80 | **PASS** | Tight alignment — proceed to training | |
| 316 | +| 0.70–0.80 | **WARN** | Increase render count or DR passes | |
| 317 | +| < 0.70 | **FAIL** | Check VLM attribute extraction (Stage 1) | |
| 318 | + |
| 319 | +--- |
| 320 | + |
| 321 | +### Edge Quantization Profiler |
| 322 | + |
| 323 | +Profiles FP32, FP16, and INT8 quantization tiers against the Jetson Orin NX SLA. Works in **simulation mode** on any laptop (no Jetson required) by projecting CPU timings to expected Jetson performance. |
| 324 | + |
| 325 | +```bash |
| 326 | +# Full TensorRT profiling (requires CUDA) |
| 327 | +python scripts/profile_edge.py --weights checkpoints/new_sku_weights.pt |
| 328 | + |
| 329 | +# Simulation mode (CPU → Jetson projection, works on any machine) |
| 330 | +python scripts/profile_edge.py --weights checkpoints/new_sku_weights.pt --simulate |
| 331 | +``` |
| 332 | + |
| 333 | +``` |
| 334 | +══════════════════════════════════════════════════════════════════════ |
| 335 | + Tier Backend p50 (ms) FPS Size MB SLA |
| 336 | + -------- -------------------- ------------ -------- ---------- ---- |
| 337 | + FP32 PyTorch 31.4 31.8 12.1 FAIL |
| 338 | + FP16 PyTorch 11.8 84.7 6.1 PASS |
| 339 | + INT8 TensorRT 8.2 121.9 3.4 PASS |
| 340 | +══════════════════════════════════════════════════════════════════════ |
| 341 | + Recommended: FP16 — best FPS/accuracy tradeoff for 60-FPS SLA |
| 342 | + INT8 recommended when thermal budget is constrained (outdoor venues) |
| 343 | +``` |
| 344 | + |
| 345 | +--- |
| 346 | + |
| 347 | +### Automated Failure Gallery |
| 348 | + |
| 349 | +Every eval run automatically saves the **10 lowest-confidence images** to `checkpoints/failure_gallery/<job_id>/` with a ranked JSON summary. Zero-detection images (hardest cases) rank first. |
| 350 | + |
| 351 | +``` |
| 352 | +checkpoints/failure_gallery/abc123/ |
| 353 | +├── 01_conf0.000_shelf_front_01.jpg ← no detection (full occlusion?) |
| 354 | +├── 02_conf0.182_shelf_angle_07.jpg ← low confidence (lighting?) |
| 355 | +├── 03_conf0.241_shelf_tilt_03.jpg |
| 356 | +├── ... |
| 357 | +└── gallery_summary.json |
| 358 | +``` |
| 359 | + |
| 360 | +```json |
| 361 | +{ |
| 362 | + "rank": 1, |
| 363 | + "max_confidence": 0.0, |
| 364 | + "n_detections": 0, |
| 365 | + "diagnosis_hint": "No detections — possible full occlusion, extreme angle, |
| 366 | + or severe domain shift." |
| 367 | +} |
| 368 | +``` |
| 369 | + |
| 370 | +--- |
| 371 | + |
257 | 372 | ## Background: Why This Architecture? |
258 | 373 |
|
259 | 374 | At ATAI Labs, Pranav reduced end-to-end multi-stream inference latency from 8.0s to 1.5s via TensorRT dynamic batch scheduling and layer fusion on NVIDIA A100 clusters. The design choices here apply the same discipline — optimising every component against the hardware ceiling (Jetson Orin's 8GB VRAM and 60 FPS SLA) rather than building for demo conditions. |
|
0 commit comments