Spaces:
Runtime error
Runtime error
Commit History
-
docs (blog): include blog post url
9350a8d -
fix (llm): improve prompts for choosing outfits
d81d91f -
feat(combinations): improve Get Dressed LLM ranking prompt
- Always rank combinations with the LLM, even without occasion text (previously only cartesian product order was shown). - Add stylist system prompt with explicit criteria: occasion fit, color harmony, formality, season, pattern balance, versatility. - Include structured garment attributes (color, material, pattern, season, formality, description) per combo instead of description only. - Inject previously liked outfits as a style preference signal. - Sample diverse combos across tops when the list exceeds 40 items. - Use system+user messages, lower temperature (0.2), more tokens (1024). Co-authored-by: Cursor <cursoragent@cursor.com>63a6b7d -
fix(ui): restore garment images and descriptions in Ask chat
- Load wardrobe on Ask tab open and await loadWardrobe() on init so garment lookups are ready before the first question. - Build garmentsById map for reliable O(1) lookup with zero-padded IDs (garment_1 -> garment_001). - Replace garment references before markdown parsing using placeholders, matching both [garment_XXX] and bare garment_XXX forms. - Show AI-generated description in inline chips (fallback: color + type). - Instruct the assistant to always use bracketed [garment_XXX] IDs. Co-authored-by: Cursor <cursoragent@cursor.com>74e743a -
fix(ui): add bounds to rectangle geometry so detected boxes render
Annotorious v3 rectangle geometry requires a bounds field (minX, minY, maxX, maxY) in addition to x/y/w/h — its spatial index relies on it, so annotations without bounds were stored but never drawn. Compute bounds from each detected box. Co-authored-by: Cursor <cursoragent@cursor.com>1aafe24 -
fix(ui): use Annotorious v3 internal annotation format for bounding boxes
initAnnotator was building annotations in W3C FragmentSelector format which Annotorious v3 does not recognise as a drawable shape, so auto-detected boxes were never rendered. - Use the internal format: target.selector.type = 'RECTANGLE' with geometry {x, y, w, h} as documented in the Annotorious v3 API. - Remove the invalid `drawingTool` init option; call setDrawingTool() after instantiation instead. - Defer annotator creation until the <img> has finished loading (el.complete check + 'load' event listener) so the SVG layer has correct dimensions. - analyzeBoxes: read geometry directly from target.selector.geometry instead of parsing a FragmentSelector regex. Co-authored-by: Cursor <cursoragent@cursor.com>ba65e78 -
feat(ui): manual garment crop with Annotorious bounding-box editor
Upload a photo → server auto-detects garments via YOLOS and returns bounding boxes → Annotorious v3.8.6 renders the image with the boxes pre-drawn → user adds/edits/deletes boxes → "Analyse N garments" crops each box server-side and runs the VLM on each crop. Backend (app.py): - Mount data/_uploads/ as /uploads (temp image store). - api_prepare_image: saves upload, runs detect_garments, returns token + image_url + detected boxes [{x,y,w,h}]. - api_analyze_boxes: validates token, crops each box via PIL, calls extract_from_crop_bytes per crop, adds to catalog, cleans up. Frontend (index.html): - Load @annotorious/annotorious@3.8.6 CSS + ESM (version pinned). - handleFile now calls /prepare_image then opens the editor. - initAnnotator: creates annotator, loads initial boxes as W3C FragmentSelector annotations, syncs box count on create/delete. - analyzeBoxes: reads annotations, maps to pixel coords, calls /analyze_boxes, refreshes wardrobe on success. - cancelEditor: destroys an…2d97bc2 -
refactor(ui): show garment detail in a side drawer
Convert the garment detail from a centred modal to a right-aligned full-height side panel that slides in. Full-width on mobile. Co-authored-by: Cursor <cursoragent@cursor.com>7235725 -
fix(ui): log dock, garment detail layout and image cache
- Restore `-> dict` return annotation on api_load_dataset so Gradio serialises each generator yield as an SSE data event (logs were silently dropped without it). - Move log console to a fixed bottom dock (.log-dock) with a header showing live progress, a minimise/expand toggle and a close button; dock is visible from any tab during dataset loading. - Redesign garment detail panel as a single column with object-fit:contain image (no more distorted/cropped previews) and a clean attribute list below. - Add _image_url() helper with ?v=<mtime> query param to bust browser cache when the same garment ID is reused after clearing the catalog. - Call loadWardrobe() after a successful photo upload so the new garment appears immediately without a manual refresh. Co-authored-by: Cursor <cursoragent@cursor.com>4f4b1b3 -
feat(ui): garment detail panel and real-time load logs
- Clicking a wardrobe card opens an overlay with the full garment attributes (type, color, material, pattern, season, formality) and the AI-generated natural-language description. - api_load_dataset converted from a blocking call to a streaming generator that yields progress per garment (count, log lines, preview URL). - loadDataset() in the frontend now uses gradioClient.submit() to iterate SSE events; a live log console (dark monospace) and a row of thumbnail previews update in real time as each garment is processed. - Wardrobe is refreshed automatically once loading completes. Co-authored-by: Cursor <cursoragent@cursor.com>ee5ec33
-
fix(deploy): use pre-built CPU wheels to avoid OOM build
Compiling llama-cpp-python from source exceeded 16 GB RAM on CPU Basic (exit 137 OOMKilled). Use whl/cpu and pytorch cpu indexes instead. - Pin llama-cpp-python==0.3.28 with abetlen cpu wheel index - Add pytorch.org/whl/cpu for lighter torch install - Remove cmake/build-essential from packages.txt - Update local install docs to force-reinstall cu124 after requirements Co-authored-by: Cursor <cursoragent@cursor.com>d099a59 -
fix(app): add type hint to api_add_photo for Gradio 6.17
Gradio Server API endpoints require type hints on all parameters. Without str | dict on image_path, server.launch() fails at startup. Co-authored-by: Cursor <cursoragent@cursor.com>2e31b50 -
docs(field-notes): update hosting and deployment for cpu-basic
Replace T4/ZeroGPU references with CPU Basic timings and correct custom frontend location (app.py gr.Server, not app_custom.py). Co-authored-by: Cursor <cursoragent@cursor.com>b02e0ce -
docs(readme): align Space docs with cpu-basic deployment
Update tech stack, badge descriptions, usage timings, and frontend references to match CPU Basic hardware and current app.py structure. Co-authored-by: Cursor <cursoragent@cursor.com>5e18928 -
perf(model): tune llama.cpp for cpu-basic
Set n_threads=2 when SPACE_ID is present to match 2 vCPU on CPU Basic. Update docstrings to reflect CPU Basic deployment instead of ZeroGPU. Co-authored-by: Cursor <cursoragent@cursor.com>632a1a3 -
refactor(deploy): remove ZeroGPU code for cpu-basic
Drop spaces package and @spaces.GPU decorators — they only apply to ZeroGPU hardware and are unnecessary on CPU Basic. Force CPU for PyTorch on Spaces via CUDA_VISIBLE_DEVICES="". Co-authored-by: Cursor <cursoragent@cursor.com>b60933b -
chore (hf): cambio a cpu basic
c5b6c0e -
fix(deploy): switch to CPU inference for ZeroGPU compatibility
ZeroGPU's CUDA emulation is PyTorch-specific — llama-cpp-python links directly against libcudart.so.12 which does not exist in the container. - Remove --extra-index-url cu124 (installs CPU-only llama-cpp-python) - Set python_version to 3.12 (ZeroGPU only supports 3.10/3.12) - Detect SPACE_ID to force n_gpu_layers=0 on HF Spaces - Remove @spaces.GPU from text-only LLM functions - Keep @spaces.GPU on detection functions (PyTorch YOLO benefits) - Add libopenblas-dev for CPU BLAS acceleration - Remove Python 3.13 unraisablehook patch (no longer needed) - Update README with local GPU install instructions All hackathon badges preserved: Off the Grid, Llama Champion, Tiny Titan. See docs/18-zerogpu-cpu-inference.md for full ADR. Co-authored-by: Cursor <cursoragent@cursor.com>4c7e762 -
fix (hf): image dict was failing
25d768b -
fix (hf): use gpu from hf space
e7af96c -
docs (readme): short description update
82204a5 -
chore (ui): Use new ui
6778432
-
feat(deploy): configure project for HF Spaces T4 GPU
- Add --extra-index-url for pre-built CUDA llama-cpp-python wheel - Add datasets as runtime dependency - Create packages.txt with system build deps (cmake, build-essential) - Rewrite README.md for hackathon submission (bonus quests, usage, arch) - Add hardware: t4-small to Space front matter - Gitignore data/samples/ (generated at runtime via Obtener Dataset) Co-authored-by: Cursor <cursoragent@cursor.com>8833292 -
refactor(ui): replace subprocess sample build with in-process dataset loader
- New obtener_dataset() generator runs VLM pipeline in-process - Real-time UI updates: log + gallery filling as garments are processed - Supports multiple HF datasets (second-hand, fashion-1k) - Single "Obtener Dataset" button replaces previous two-button setup - Add event context textbox in Combina tab for LLM ranking - Detect HF Spaces environment for server binding (0.0.0.0:7860) - Ensure data/ directories are created at startup Co-authored-by: Cursor <cursoragent@cursor.com>295e5db -
feat(combinations): add context-aware LLM ranking for outfits
Allow users to describe an occasion (e.g. "dinner on a terrace, summer") and have the LLM re-rank outfit combinations for that specific context. - rank_combinations_prompt() now accepts optional context parameter - New rank_with_llm() function calls LLM and parses ranked response - Robust JSON parsing with regex fallback for outfit IDs Co-authored-by: Cursor <cursoragent@cursor.com>b269444 -
feat(sample): add pre-processed sample wardrobe with 50 garments
Add "Cargar armario de ejemplo" button that instantly loads 50 pre-cataloged garments from Codatta/Fashion-1K dataset. Allows demoing the full app (wardrobe, combinations, chat) without waiting for VLM inference. - scripts/build_sample_wardrobe.py: offline pipeline that downloads Fashion-1K, runs detector + VLM, saves results to data/samples/ - data/samples/: 50 garment crops + catalog.json (1.7 MB) - app.py: load_sample_wardrobe() handler + UI button in Capture tab Co-authored-by: Cursor <cursoragent@cursor.com>5ee2642 -
refactor(detector): replace monolithic detector with pluggable multi-backend package
Replace src/detector.py with src/detector/ package featuring: - Separated interface: detect_garments() returns BoundingBox list, crop_garments() handles PIL cropping independently - Registry pattern: backends self-register via @register decorator - Three backends: yolos (YOLOS-tiny/HF), yolov8 (ultralytics), grounding_dino (open vocabulary, prompt-based) - is_available() per backend for graceful degradation Redesign Capture tab: - image_annotator always visible as primary input - Two coexisting buttons: auto-detect and manual selection - Settings accordion to switch detection backend at runtime Add src/settings.py for JSON-persisted runtime configuration. Co-authored-by: Cursor <cursoragent@cursor.com>746317a -
fix(ui): correct bbox annotator offset and remove label dialog
Two issues fixed: - Drawing offset: the annotator was inside a hidden gr.Column that prevented proper canvas dimension calculation. Replace with individually hidden components (visible=False on each) so the DOM always has correct sizing when they become visible. - Unwanted label dialog: add label_list=["prenda"] so the component auto-assigns the label without prompting the user. Co-authored-by: Cursor <cursoragent@cursor.com>98566b4 -
feat(ui): add manual bbox annotation fallback when detection fails
When YOLOS detects 0 garments in multi mode, the UI shows a gradio-image-annotation widget for manual bounding box selection. User draws rectangles over visible garments and clicks "Procesar selección" — crops are sent to the VLM for attribute extraction. - Add gradio-image-annotation>=0.5.0 dependency (Gradio 6 compatible) - New process_manual_boxes() handler in app.py - New extract_from_crop_bytes() in vision.py - analyze_images() now returns annotator state on detection failure Co-authored-by: Cursor <cursoragent@cursor.com>cc5f175 -
feat(ui): add manual bbox annotation fallback when detection fails
When YOLOS detects 0 garments in multi mode, the UI shows a gradio-image-annotation-v2 widget for manual bounding box selection. User draws rectangles over visible garments and clicks "Procesar selección" — crops are sent to the VLM for attribute extraction. - Add gradio-image-annotation-v2 dependency - New process_manual_boxes() handler in app.py - New extract_from_crop_bytes() in vision.py - analyze_images() now returns annotator state on detection failure Co-authored-by: Cursor <cursoragent@cursor.com>5be2181 -
refactor(detector): replace YOLOv8n with YOLOS-tiny for flat lay support
Replace kesimeg/yolov8n-clothing-detection (ultralytics) with yainage90/fashion-object-detection-yolos-tiny (transformers): - Trained on modanet + fashionpedia (includes flat lay images) - 6.47M params, mAP 0.697 - Labels: bag, bottom, dress, hat, shoes, outer, top - Runs on CPU via torch.no_grad() - Swap ultralytics dep for transformers + torch in requirements Co-authored-by: Cursor <cursoragent@cursor.com>147c5f0 -
feat(ui): add capture mode selector (single/multi/video WIP)
Add a Radio selector in the Capture tab with three modes: - Single garment: skips YOLO, sends photo directly to VLM with single-garment prompt (ideal for close-up photos) - Multiple garments: full pipeline (YOLO + crops + VLM per crop, fallback to multi-garment VLM analysis) - Video stream: placeholder showing "coming soon" message New vision.extract_single_from_path() for direct single-garment extraction without YOLO detection step. Co-authored-by: Cursor <cursoragent@cursor.com>ba65fe9 -
fix(detector): lower confidence threshold to 0.15
The previous threshold (0.35) caused YOLO to miss garments in flat lay photos. Lowering to 0.15 improves detection on product-style images while the fallback handles any remaining misses. Co-authored-by: Cursor <cursoragent@cursor.com>12e8038 -
fix(detector): download YOLO model from HuggingFace before loading
YOLO() does not accept HuggingFace repo IDs directly. Use hf_hub_download() to fetch the .pt file first, then pass the local path to YOLO(). The model file is 'best.pt' (standard ultralytics fine-tune convention). Co-authored-by: Cursor <cursoragent@cursor.com>a2fc99b -
fix(catalog): ensure data persists across app restarts
- Use Path.resolve() for all data paths to avoid symlink/CWD issues - Call _format_catalog_stats() with parens at Gradio build time so the stats Markdown evaluates immediately (not deferred) - Add startup log confirming catalog load count - Add debug logging to load_catalog() for troubleshooting Co-authored-by: Cursor <cursoragent@cursor.com>913537b -
fix(ui): improve wardrobe tab layout, scroll, labels and images
- Fix images not showing: use gr.update(value=None) for explicit clearing, show "Sin imagen disponible" text for old entries - Add fixed height (420px) with vertical scroll to garment list - Remove garment_id from list labels, show only description or "Color Type (pattern)" as fallback - Reorganize detail panel as horizontal 2-column layout (image beside attributes) to avoid vertical scrolling Co-authored-by: Cursor <cursoragent@cursor.com>07b8319 -
refactor(vision): use detector crops for per-garment extraction
Rewrite the vision pipeline to use YOLO-detected crops: - Each crop is sent individually to the VLM (focused single-garment prompt yields better results than multi-garment from full image) - extract_garments() now returns list[tuple[dict, bytes]] where each garment has its own unique crop bytes - catalog.add_garments() updated to accept per-garment image bytes - Falls back to full-image analysis when YOLO detects nothing - Add single-object JSON parsing to handle VLM responses for crops Co-authored-by: Cursor <cursoragent@cursor.com>226ca6c -
feat(detector): add YOLOv8n garment detection and cropping
New module src/detector.py that uses YOLOv8 Nano (fine-tuned on Fashionpedia) to detect garment bounding boxes in images. Runs on CPU to avoid VRAM contention with the VLM. Each detection is cropped with PIL and returned as JPEG bytes for individual garment analysis. Adds ultralytics dependency to requirements.txt. Co-authored-by: Cursor <cursoragent@cursor.com>73c2744 -
feat(ui): redesign wardrobe tab with list + detail panel
Replace the Markdown table with a 2-column layout: - Left: clickable radio list with short descriptions per garment - Right: detail panel showing photo + full attributes table Selecting a garment shows its image and structured metadata. Fixes the broken gr.State() output wiring from analyze_images. Co-authored-by: Cursor <cursoragent@cursor.com>fdbde02 -
feat(ui): add Tinder-style outfit combination tab
New "Combina" tab in Gradio with: - Card layout showing top + bottom garment images side by side - Like/dislike buttons to approve or reject combinations - Progress counter showing position in the queue - "Ver outfits guardados" section showing liked combinations - Queue auto-excludes previously disliked pairs Co-authored-by: Cursor <cursoragent@cursor.com>f54fb4b -
feat(combinations): add outfit combination engine
New module src/combinations.py with: - Garment classification into tops/bottoms categories - Rules-based filtering (season + formality compatibility) - LLM ranking prompt generation for style scoring - Outfit preference persistence (like/dislike in data/outfits.json) - Disliked combinations excluded from future suggestions Co-authored-by: Cursor <cursoragent@cursor.com>727dd4f -
feat(vision): add verbose description to garment extraction
- Extend VLM prompt to request a 1-2 sentence natural language description per garment (style, fit, notable details) - Include description field in garment normalization - Update get_catalog_summary() to show descriptions in LLM context, improving outfit recommendation quality Co-authored-by: Cursor <cursoragent@cursor.com>6ca17ee -
feat(catalog): add image persistence per garment
- vision.py now returns (garments, image_bytes) from extract_garments() - catalog.add_garments() accepts image_bytes and saves a thumbnail per garment via the storage layer - Each garment gets an image_ref field pointing to its stored image - clear_catalog() now also removes associated images - app.py passes image bytes through the full pipeline Co-authored-by: Cursor <cursoragent@cursor.com>14e7ce6 -
feat(storage): add dual storage abstraction (local/S3)
Add src/storage.py with two backends: - local: writes to data/garments/ (default for development) - s3: uses HF Spaces S3 bucket (for production persistence) Backend is selected via STORAGE_BACKEND env var. Includes .env.example with all configurable variables documented. Co-authored-by: Cursor <cursoragent@cursor.com>edbf640 -
feat(wardrobe): implement vision pipeline, catalog and assistant
- Add VLM-based garment extraction with Gemma 3 4B (src/vision.py) - Add JSON catalog storage with search and stats (src/catalog.py) - Add context-injected assistant with streaming (src/assistant.py) - Add singleton model loader with VRAM management (src/model_loader.py) - Implement 3-tab Gradio UI (Capture, Wardrobe, Chat) - Update shootout script for Gemma 3 4B handler Co-authored-by: Cursor <cursoragent@cursor.com>75e0882
-
feat (wardrobe): prepare project structure and basic gradio ui
cb7a01c -
initial commit
4865627