Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

440 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GET YOUR FIT — GYF

Closed-beta AI fashion stylist. Deterministic styling authority today,
behavior-trained personalization when the data matures.


Project Overview

Get Your Fit (GYF) is a closed-beta AI stylist product. A user describes what they want — body type, skin tone, occasion, weather, budget, style preference — and GYF returns ranked outfits and items with explicit reasoning.

Canonical runtime split:

Layer Path Status
Backend API backend/app (FastAPI) live
Frontend GYF_APP/web-app (React/Vite/Zustand) live
Styling engine src/gyf (deterministic ranker) live
CLIP BPR personalization src/gyf/clip_bpr_ranker.py live_assistive
NCF reranker src/gyf/ncf_ranker.py shadow_only
Shadow reranker src/gyf/shadow_reranker.py shadow_only
Compatibility ML src/gyf/compatibility_ml.py shadow_only
VTON preview backend/app/routers/vton.py preview_composite
Legacy reference api/server.py internal only
Deprecated beta_finale/ not used

Current Capabilities

Recommendation engine

  • Deterministic stylist engine: retrieval → candidate generation → BM25 ranking → score breakdown → explanation copy
  • 6-path CLIP boost map: text→text (0.33), text→image (0.21), item-similarity-text (0.17), item-similarity-vision (0.12), occasion-vibe-anchor (0.10), BPR-preference-vector (0.07)
  • Loom occasion anchors (arXiv:2605.09830): rich semantic vibe/anti-vibe anchor texts per occasion, lambda-weighted penalty to suppress style clashes
  • Outfit color clash penalty: P_color = 0.1 × max(0, n_non_neutral − 2) (Loom §4.3)
  • Feature-aware BPR (arXiv:1205.2618): user preference vector in 512-dim CLIP space updated via gradient ascent on positive–negative impression pairs
  • NCF reranker (arXiv:1708.05031): NeuMF — GMF branch (element-wise product) + MLP branch (1024→512→256→128→32) fused to a sigmoid compatibility score; runs shadow-only
  • Impression-based LTR negatives: items shown in RecommendationSnapshot but not acted on positively become weak negative labels (relevance=0.05)
  • Counterfactual explanation engine: aligns outfit explanations to non-zero ranking components only (arXiv:2203.01310)
  • Rich explanations via rich_explanation field in recommendation responses
  • Wardrobe gap analysis: missing outfit roles, underrepresented occasions, thin color coverage

Platform

  • Full FastAPI product backend: health, liveness, readiness, operator status, feed/catalog, auth/profile, favorites, cart intent, wardrobe state, recommendation snapshots, social interaction, VTON preview, recommendation endpoints
  • React/Vite/Zustand frontend: onboarding, studio, recommendations, try-on preview, profile, saved-look surfaces
  • BM25 posting-list retrieval eliminates O(N) scan; precomputed IDF across full catalog
  • PostgreSQL-backed state: saved items, cart intent, owned wardrobe, interaction audit events, recommendation snapshots
  • Auth-scoped recommendation context: saved and wardrobe state optionally wired into request context (deterministic, not trained personalization)
  • Operator surfaces: /ops/status, /ops/catalog-quality, /ops/data-quality-scorecard, /ml/status
  • Data-quality scorecard: catalog role coverage, image truth, label truth, runtime truth — offline-only promotion blockers
  • Frontend API contract validator derived by static analysis of React normalizer chains
  • Confidence calibration harness: ECE/MCE/Brier scoring
  • Shadow pairwise logistic reranker with _FORBIDDEN_FEATURES leakage guard and leave-one-case-out CV
  • 63,873-item merged catalog (14k Myntra + 50k Zappos UT-Zappos50k footwear), 49k with local-verified images

ML / DL Intelligence

GYF follows the principle of promotion by evidence: each ML component starts in shadow_only and advances only after measurable offline gains over the deterministic baseline.

Component Algorithm Promotion State
CLIP retrieval CLIP ViT-B/32 text+image dual-tower via fastembed live_assistive
BPR personalization Bayesian Personalized Ranking preference vector in CLIP space live_assistive
Occasion vibe anchors Rich semantic anchor/anti-anchor retrieval with λ-weighted penalty live_assistive
MMR diversity reranker Maximal Marginal Relevance on CLIP embeddings live_assistive
NCF reranker NeuMF (GMF element-wise + MLP 1024→512→256→128→32) fused to sigmoid shadow_only
Shadow logistic reranker Pairwise logistic LTR with forbidden-feature leakage guard shadow_only
Compatibility ML Color-graph harmony + occasion alignment + price coherence shadow_only
Counterfactual explanation engine Non-zero component alignment prevents phantom styling claims live
VTON Preview composite preview_composite

Training data for NCF/BPR is derived from real RecommendationSnapshot payloads — impression-based negatives (shown but not acted on) combined with explicit like/dislike/save interaction events.


Live API Surface

Canonical FastAPI — Recommendations

Endpoint Description
POST /recommendations Combined items + outfits response
POST /recommendations/items Ranked items with full reasoning
POST /recommendations/outfits Ranked outfits: slots, total price, breakdown
GET /recommendations Contract/default response (not a stub)
POST /recommendations/actions Record item/outfit feedback signals
GET /recommendations/history Authenticated snapshot history
GET /state/summary Auth-scoped state transparency

Canonical FastAPI — Platform

Endpoint Description
GET /health Process health check
GET /live Fast liveness probe (no DB/ML dependency)
GET /ready Traffic readiness: DB, catalog, stylist engine
GET /ops/status Operator status with AI/VTON truth
GET /ops/catalog-quality Catalog role counts, image status, repair hints
GET /ops/data-quality-scorecard Offline promotion gates for ML/DL work
GET /ml/status Honest AI/model/VTON runtime status
GET /catalog (/feed/catalog) Beta catalog/feed listing
POST /GET/DELETE /cart/items Auth-scoped cart intent (not checkout)
POST /GET/DELETE /wardrobe/items Auth-scoped owned wardrobe state
POST /wardrobe/gap-analysis Missing roles, thin occasion/color coverage
POST /catalog/ingest-json Ingest catalog rows for beta/testing

Canonical VTON

Endpoint Description
POST /vton/try-on Create try-on preview job (labeled composite unless real provider active)
GET /vton/jobs/{job_id} Read VTON job state and preview truth

Legacy / Internal Reference (api/server.py)

These surfaces exist for internal tooling and older evaluation flows. They are not the canonical product runtime.

  • POST /recommend — legacy deterministic recommendation reference
  • POST /preferences/recommend — legacy preference recommendation with optional saved/wardrobe reuse
  • POST /sessions/recommend — legacy session recommendation used by older tests and evaluation flows
  • POST /recommendation/compare — legacy comparison endpoint for recommendation snapshots
  • GET /history/preferences — legacy preference history inspection
  • GET /state/conflicts — legacy state conflict inspection
  • POST /recommendation/action — legacy explicit action mutation
  • GET /capabilities — legacy machine-readable product truth
  • GET /catalog/item/{item_id}/image — legacy verified local catalog-image serving

Example canonical request:

curl -X POST http://127.0.0.1:8000/recommendations/outfits \
  -H 'Content-Type: application/json' \
  -H 'X-GYF-User-Id: beta-user' \
  -d '{
    "preferred_occasions": ["date"],
    "preferred_styles": ["premium casual"],
    "budget_max": 180,
    "body_type": "rectangle",
    "skin_tone": "warm",
    "weather": {
      "temperature_c": 29,
      "condition": "humid",
      "humidity": 74,
      "time_of_day": "night"
    },
    "limit": 4
  }'

The X-GYF-User-Id header scopes saved items, wardrobe, sessions, and recommendation actions to an explicit user identity.


Data Status

  • Catalog: 63,873 merged items (Myntra 14k + Zappos UT-Zappos50k 50k footwear); 49k with local-verified images
  • Qdrant: fashion_embeddings (63,901 CLIP text vectors), fashion_image_embeddings (50,025 CLIP image vectors)
  • Interaction labels: captured via RecommendationSnapshot and explicit action events; behavior-driven ranking ML remains blocked until enough verified data exists
  • Image truth: demo placeholder assets are local/dev/test fallback; production-grade images require affiliate/licensed/user-owned sources; remote URLs stored as references only
  • Trained artifacts: no trained model artifacts are committed; all ML components load from runtime-configured paths or fall back gracefully

Known limitations:

  • Local integration tests require reachable PostgreSQL; make dev brings up local Postgres on host port 55432
  • Visual embeddings are inactive for live recommendation authority unless a verified Qdrant index is present
  • behavior-driven ranking ML is capture-only until enough verified end-user action data exists
  • VTON is preview_composite by default; no photorealistic provider is active unless runtime status says active_provider
  • Photo analysis is heuristic unless a trained body/skin model is explicitly wired in
  • Cart and wardrobe represent intent and state only — not checkout, payment, or retailer integration

System Truth

  • shadow-mode catalog-side AI sidecars and offline CLIP-style foundations exist in src/gyf; the canonical FastAPI recommendation endpoints expose deterministic_stylist_engine as the primary live recommendation authority
  • backend/app is the canonical backend; GYF_APP/web-app is the canonical frontend
  • api/server.py is legacy/internal reference; it is not the main closed-beta product runtime
  • Recommendation outputs are deterministic and heuristic by default; the BPR personalization path is live_assistive (small boost signal, not primary authority)
  • Body type and skin tone are accepted as assistive styling inputs; skin/tone reasoning does not claim undertone-accurate ML
  • Weather-aware ranking is deterministic product logic based on explicit/manual weather context, not an external API
  • VTON preview output is labeled preview/prototype unless a real model/provider is active and reported by runtime status
  • Feedback signals are captured; behavior-driven ranking ML remains blocked until sufficient verified data and promotion evaluation exist
  • The product avoids fake visual AI, fake aesthetic scores, fake checkout, and fake production try-on claims

Canonical Architecture

backend/app/          ← FastAPI product backend (canonical)
  routers/            ← recommendation, vton, catalog, auth, cart, wardrobe, ops
  services/           ← recommendation_service.py (6-path CLIP boost map, BPR, anchors)
  models/             ← SQLAlchemy ORM (CatalogItem, Interaction, Favorite, …)

src/gyf/              ← Packaged styling intelligence
  stylist.py          ← Deterministic ranker + BM25 retrieval
  clip_bpr_ranker.py  ← BPR preference vector in CLIP space (live_assistive)
  ncf_ranker.py       ← NeuMF NCF reranker (shadow_only)
  shadow_reranker.py  ← Pairwise logistic reranker (shadow_only)
  compatibility_ml.py ← Color-graph + occasion compatibility (shadow_only)
  interaction_labels.py ← LTR label extraction + impression negatives

GYF_APP/web-app/      ← React/Vite/Zustand frontend (canonical)

api/server.py         ← Legacy/internal reference (not canonical)
tools/                ← Dataset, training, evaluation, and operator CLI scripts
ml/                   ← ML experiment code (training, evaluation, serving)

How to Run

Backend

make setup
make prepare-datasets
make dev

make dev starts local PostgreSQL on port 55432, applies Alembic migrations, seeds the beta catalog, and launches the API at http://127.0.0.1:8000.

Frontend

make frontend-install
make frontend-dev

React app at http://127.0.0.1:5173.

Common Makefile targets

make help                          # All targets with descriptions
make bootstrap-live                # Full environment bootstrap
make db-migrate                    # Alembic upgrade head
make seed-beta-catalog             # Idempotent catalog seed
make build-real-image-manifest     # Build JSONL image metadata from local archives
make import-real-image-manifest    # Import verified image references into catalog
make data-quality-scorecard        # Offline promotion-gate scorecard
make shadow-reranker-eval          # NCF/shadow reranker offline eval
make validate-api-contract         # Frontend field-coverage check
make evaluate-confidence-calibration  # ECE/MCE/Brier calibration report
make test                          # Full test suite
make test-gyf                      # gyf library tests only (no DB)
make test-ml-slow                  # Slow ML training tests
make lint                          # Ruff check + format check
make smoke                         # FastAPI runtime smoke
make verify-release                # Release manifest + golden verification
make docker-build                  # Build Docker image
make docker-up                     # Start Docker stack
make docker-down                   # Stop Docker stack

Testing

make test

Current automated suite: 1131 tests.

Golden recommendation evaluation: 22 cases.

make test-gyf          # gyf library unit tests (no DB)
make test-ml-slow      # long-running ML training convergence tests
make lint              # ruff check + format check
make frontend-lint     # ESLint on the React app
make frontend-build    # production frontend build
make verify-release    # release-readiness gate
make smoke             # FastAPI runtime smoke (requires local DB)

Recent Progress

  • NCF training pipeline (tools/train_ncf_ranker.py): end-to-end orchestrator — loads LTR labels → batch-fetches Qdrant embeddings → computes per-user BPR vectors → builds pairwise triples → trains NCF with early stopping → pairwise accuracy evaluation → saves model + JSON report. Promotion criteria logged (accuracy ≥ 0.60, pairs ≥ 500). make train-ncf / make train-ncf-dry
  • MMR diversity reranker (src/gyf/diversity_reranker.py): Maximal Marginal Relevance on CLIP embeddings balances relevance vs. embedding-space diversity (λ=0.7 default); falls back to role-based round-robin when embeddings unavailable; wired as live_assistive post-ranking pass; 18-test coverage
  • NCF shadow scoring in recommendation service: trained model loaded at warmup via NCF_MODEL_PATH env; scores annotated as ncf_shadow_score in every item's score_breakdown for offline NDCG evaluation; zero impact on live ranking order
  • NCF reranker (NeuMF GMF + MLP) on pre-trained CLIP embeddings; pairwise BCE training; save_ncf/load_ncf persistence; 15-test coverage; promotion state shadow_only
  • CLIP BPR personalization (arXiv:1205.2618): feature-aware BPR in 512-dim CLIP space; warm-start from positive embedding centroid; gradient ascent with L2 regularization; wired as 6th path (weight 0.07) in CLIP boost map
  • Impression-based LTR negatives: extract_impression_negatives() derives weak negative labels from RecommendationSnapshot items shown but not acted on; --no-impressions flag in tools/export_ltr_labels.py
  • Loom occasion anchors (arXiv:2605.09830): 8 occasions with vibe/anti-vibe anchor texts; lambda-weighted penalty S_occ = cos(e_i, v_o) − λ × max(0, cos(e_i, a_o) − cos(e_i, v_o)); wired as 5th CLIP path (weight 0.10)
  • Outfit color clash penalty: P_color = 0.1 × max(0, n_non_neutral − 2) applied in outfit scoring; neutral color set (black/white/gray/navy/beige/cream/tan/khaki/brown/silver/gold)
  • Real image ingest pipeline: Myntra images downloaded, background removal via rembg, CLIP image embeddings generated and upserted to Qdrant fashion_image_embeddings (50k vectors)
  • 63k merged catalog: Myntra 14k + Zappos UT-Zappos50k 50k; MD5-dedup with brand-aware fingerprinting; 49k local-verified images
  • BM25 retrieval: posting-list indexing with precomputed IDF eliminates O(N) scan across all recommendation paths
  • Counterfactual explanation engine (arXiv:2203.01310): aligns outfit explanations to non-zero ranking breakdown components; rich_explanation field in recommendation responses
  • Compatibility ML sidecar: color-graph harmony/tension edges, occasion alignment, price coherence, explicit clash rules; shadow_only, zero weight on live ranking
  • Shadow logistic reranker: pairwise logistic with _FORBIDDEN_FEATURES leakage guard, leave-one-case-out CV, make shadow-reranker-eval
  • Data-quality scorecard: catalog role coverage, image truth, label truth, runtime truth → offline-only ML promotion blockers; exposed at /ops/data-quality-scorecard and make data-quality-scorecard
  • Production data pipeline: scripts/_catalog_mappings.py SSOT (150+ role mappings, 6 canonical occasions, INR/USD price buckets); normalize_myntra_csv.py, normalize_zappos.py, merge_catalogs.py
  • Render/Vercel deployment: render.yaml + vercel.json one-click free-tier blueprint; requirements.backend.txt strips torch/transformers/diffusers (~1.5GB) for free-tier RAM budget
  • Wardrobe gap analysis: POST /wardrobe/gap-analysis — missing roles, underrepresented occasions, thin color coverage, actionable suggestions
  • Frontend API contract validator: static analysis of React normalizeRecommendationItem/normalizeRecommendationOutfit; make validate-api-contract
  • Confidence calibration harness: ECE/MCE/Brier scoring; make evaluate-confidence-calibration

Next Priorities

  • Collect interaction data → train NCF → promote: make export-ltr-labelsmake train-ncf → verify pairwise_accuracy ≥ 0.60 in report → set NCF_MODEL_PATH=models/ncf_ranker.ptmake shadow-reranker-eval → promote to live_assistive after measurable NDCG gain
  • Wire MMR diversity into item ranking: diversity_reranker.py is ready; activate by fetching item embeddings from Qdrant in _build_clip_boost_map() and passing them through _rank_items()diversify() post-pass
  • Deploy closed beta: set JWT_SECRET/DATABASE_URL/REDIS_URL in Render dashboard, use render.yaml + vercel.json blueprint, then make ingest-real-catalog to load 63k catalog
  • Wire real image manifest: make build-real-image-manifestmake import-real-image-manifest to replace demo placeholders with Myntra/Zappos-verified image references
  • Verify catalog role balance: make data-quality-scorecard + GET /ops/catalog-quality; footwear gap is common in Myntra datasets
  • TLS termination: nginx.conf HSTS header is commented out; uncomment after Certbot/Let's Encrypt volume or Cloudflare/AWS ALB routing
  • Promote behavior-driven ranking ML: keep capture-only until enough verified end-user action data exists for honest model training and baseline comparison
  • Promote compatibility ML and shadow reranker: keep shadow_only until leave-one-case-out CV shows measurable NDCG gain
  • Promote visual embeddings / VTON: only after real artifacts/providers, tests, evaluation, and rollback gates exist

Releases

Packages

Used by

Contributors

Languages