Spaces:
Sleeping
Sleeping
Labeling Pipeline (CLIP Text Labels)
Data based on NEXON Open API.
Overview
This pipeline generates CLIP-ready text labels for MapleStory item icons using Qwen2-VL. It consumes either a manifest file or the SQLite DB and writes:
labels.jsonl(one JSON record per image)labels.parquet(optional)
Requirements
- Python 3.11+
- GPU recommended for Qwen2-VL inference
Install
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
Optional (for 4-bit quantization):
pip install bitsandbytes
Input Adapters
You can use one of the following:
A) Manifest (recommended)
data/<DATE>/manifest.parquetormanifest.jsonl- Required columns:
image_path,item_name,source_type
B) SQLite DB
data/<DATE>/db.sqlite- Joins
equipment_shape_items/cash_itemswithicon_assets
Run
python -m labeler run \
--input data/2026-01-10/manifest.parquet \
--outdir data/2026-01-10/labels \
--model Qwen/Qwen2-VL-2B-Instruct \
--device auto \
--batch-size 8 \
--upscale 2 \
--resume
Using DB input:
python -m labeler run \
--db data/2026-01-10/db.sqlite \
--outdir data/2026-01-10/labels \
--quality-retry
Range filter by run_id (optional):
python -m labeler run --db data/2026-01-10/db.sqlite --run-id <RUN_ID>
Output Schema
Each line in labels.jsonl is a JSON object:
{
"image_path": "...",
"image_sha256": "...",
"source_type": "equipment_shape" | "cash",
"item_name": "...",
"item_description": "...",
"label_ko": "...",
"label_en": "...",
"tags_ko": ["..."],
"attributes": {
"colors": ["..."],
"theme": ["..."],
"material": ["..."],
"vibe": ["..."],
"item_type_guess": "..."
},
"query_variants_ko": ["..."],
"quality_flags": {
"is_uncertain": true,
"reasons": ["too_small", "ambiguous_icon"]
},
"model": "Qwen/Qwen2-VL-2B-Instruct",
"prompt_version": "v1",
"generated_at": "ISO-8601"
}
Prompt Versioning
- Prompt version is stored as
prompt_versionin each record. - Current version:
v2(seesrc/labeler/prompts.py).
Quality
- For higher-quality labels (more visual descriptors), use
--quality-retry.
Resume / Idempotency
- If
labels.jsonlalready exists, use--resume. - The pipeline skips images already labeled by
image_pathorimage_sha256.
Comparisons
You can compare modes:
--no-image(metadata only)--no-metadata(image only)
Example Output (3 lines)
{"image_path":"icons/equipment_shape/abc.png","image_sha256":"sha...","source_type":"equipment_shape","item_name":"Sample Hat","item_description":null,"label_ko":"μν λͺ¨μ μμ΄μ½, λΆμ μκ°","label_en":null,"tags_ko":["λͺ¨μ","λΆμ","μμ΄μ½","μ₯λΉ","μΊλ¦ν°"],"attributes":{"colors":["red"],"theme":["fantasy"],"material":["cloth"],"vibe":["cute"],"item_type_guess":"hat"},"query_variants_ko":["μν λͺ¨μ","λΆμ λͺ¨μ μμ΄μ½","λ©μ΄ν λͺ¨μ"],"quality_flags":{"is_uncertain":false,"reasons":[]},"model":"Qwen/Qwen2-VL-2B-Instruct","prompt_version":"v2","generated_at":"2026-01-10T00:00:00Z"}
{"image_path":"icons/cash/def.png","image_sha256":"sha...","source_type":"cash","item_name":"Sample Cape","item_description":"Example","label_ko":"μν λ§ν μμ΄μ½, νΈλ₯Έ κ³μ΄","label_en":null,"tags_ko":["λ§ν ","νΈλ₯Έ","μ½λ","μΊμ","μμ΄μ½"],"attributes":{"colors":["blue"],"theme":["classic"],"material":["silk"],"vibe":["elegant"],"item_type_guess":"cape"},"query_variants_ko":["νΈλ₯Έ λ§ν ","μν λ§ν μμ΄μ½","λ©μ΄ν μΊμ λ§ν "],"quality_flags":{"is_uncertain":false,"reasons":[]},"model":"Qwen/Qwen2-VL-2B-Instruct","prompt_version":"v2","generated_at":"2026-01-10T00:00:00Z"}
{"image_path":"icons/equipment_shape/ghi.png","image_sha256":"sha...","source_type":"equipment_shape","item_name":"Sample Sword","item_description":null,"label_ko":"μν κ² μμ΄μ½, κΈμ λλ","label_en":null,"tags_ko":["κ²","무기","κΈμ","μμ΄μ½","μ₯λΉ"],"attributes":{"colors":["silver"],"theme":["fantasy"],"material":["metal"],"vibe":["sharp"],"item_type_guess":"sword"},"query_variants_ko":["μν κ²","λ©μ΄ν κ² μμ΄μ½","κΈμ κ²"],"quality_flags":{"is_uncertain":false,"reasons":[]},"model":"Qwen/Qwen2-VL-2B-Instruct","prompt_version":"v2","generated_at":"2026-01-10T00:00:00Z"}