Buckets:
| # 13 · Synthetic Multimodal Data Generation (CPU) | |
| Build a synthetic image-caption dataset by captioning pre-generated | |
| Stable Diffusion images and scoring how well the generated caption | |
| aligns with the original prompt — entirely on CPU. | |
| ## What this example shows | |
| - Using an existing Hub dataset of AI-generated images as a synthetic data source (no GPU inference) | |
| - Free quality filtering using a dataset's precomputed metadata (`image_nsfw`, `prompt_nsfw`) | |
| - CPU-based image captioning with `transformers` (BLIP-base) | |
| - CPU-based semantic similarity scoring with `sentence-transformers` (MiniLM) | |
| - Lazy global model loading to avoid reloading per-row | |
| - A multi-stage funnel report and asset checks on the final filtered output | |
| ## Dataset | |
| [`poloclub/diffusiondb`](https://huggingface.co/datasets/poloclub/diffusiondb) (`2m_random_1k` config) — 1,000 | |
| random (image, prompt, generation-parameter) triples from Stable | |
| Diffusion generations submitted to the DiffusionDB Discord. Only | |
| `SAMPLE_SIZE` (default **40**) rows are used to keep CPU runtime short. | |
| | Field | Description | | |
| |-------|-------------| | |
| | `image` | Generated image (PIL) | | |
| | `prompt` | Text prompt used to generate it | | |
| | `seed`, `cfg`, `sampler`, `step` | Generation parameters | | |
| | `image_nsfw`, `prompt_nsfw` | Precomputed NSFW scores (0-1, or -1 if unscored) | | |
| ## Asset graph | |
| ``` | |
| diffusiondb_sample | |
| │ | |
| ▼ | |
| nsfw_filtered (drop image_nsfw/prompt_nsfw >= 0.5) | |
| │ | |
| ▼ | |
| synthetic_captions (BLIP-base captions each image, CPU) | |
| │ | |
| ▼ | |
| caption_alignment_scores (MiniLM cosine similarity: prompt vs. caption) | |
| │ | |
| ▼ | |
| synthetic_dataset_final (keep alignment_score >= 0.2) | |
| │ | |
| ▼ | |
| synthetic_generation_report | |
| │ | |
| [checks] | |
| ``` | |
| ## Key implementation details | |
| **Lazy global model loading** — avoids reloading BLIP/MiniLM on every | |
| row by caching at module scope: | |
| ```python | |
| _blip_model = None | |
| def _load_blip(): | |
| global _blip_model | |
| if _blip_model is None: | |
| _blip_model = BlipForConditionalGeneration.from_pretrained(...) | |
| return _blip_model | |
| ``` | |
| **Per-image captioning loop** (no batching — keeps CPU memory bounded): | |
| ```python | |
| for example in nsfw_filtered: | |
| inputs = processor(example["image"].convert("RGB"), return_tensors="pt") | |
| out = model.generate(**inputs, max_new_tokens=30) | |
| caption = processor.decode(out[0], skip_special_tokens=True) | |
| ``` | |
| **Alignment scoring** via sentence-embedding cosine similarity: | |
| ```python | |
| emb = model.encode([prompt, generated_caption], convert_to_tensor=True) | |
| score = float(util.cos_sim(emb[0], emb[1])) | |
| ``` | |
| ## Thresholds | |
| | Parameter | Default | Purpose | | |
| |-----------|---------|---------| | |
| | `SAMPLE_SIZE` | 40 | Rows processed; controls CPU runtime | | |
| | `NSFW_THRESHOLD` | 0.5 | Drop rows scoring above this on image/prompt NSFW | | |
| | `ALIGNMENT_THRESHOLD` | 0.2 | Minimum caption↔prompt cosine similarity to keep | | |
| All three are tunable constants at the top of `assets.py`. | |
| ## Asset checks | |
| | Check | Severity | Condition | | |
| |-------|----------|-----------| | |
| | `check_no_empty_captions` | ERROR | No empty `generated_caption` values in final output | | |
| | `check_mean_alignment` | WARN | Mean `alignment_score` in final dataset ≥ `ALIGNMENT_THRESHOLD` | | |
| ## Storage layout | |
| ``` | |
| .dagster_hf_storage/ | |
| ├── diffusiondb_sample/ | |
| ├── nsfw_filtered/ | |
| ├── synthetic_captions/ | |
| ├── caption_alignment_scores/ | |
| └── synthetic_dataset_final/ | |
| ``` | |
| `synthetic_generation_report` returns a plain `dict` and is not persisted. | |
| ## How to run | |
| ```bash | |
| pip install dagster dagster-hf-datasets Pillow | |
| pip install torch --index-url https://download.pytorch.org/whl/cpu | |
| pip install transformers sentence-transformers | |
| cd dagster_hf_datasets_examples | |
| dagster dev -m synthetic_multimodal_data.definitions | |
| ``` | |
| First run downloads BLIP-base (~990MB) and MiniLM (~90MB) to the local | |
| HF cache — subsequent runs reuse the cache. With `SAMPLE_SIZE=40`, | |
| expect the full pipeline to complete in roughly 1-3 minutes on a | |
| modern CPU. | |
| Materialize sequentially from `diffusiondb_sample` through | |
| `synthetic_dataset_final`, then `synthetic_generation_report`, then | |
| run checks from the **Checks** tab on `synthetic_dataset_final`. |
Xet Storage Details
- Size:
- 4.26 kB
- Xet hash:
- 267d3c84e8d44224ac13dfcbf17c348503efa50e944cd4af0745468b563e6016
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.