Spaces:
Paused
Paused
Ali Mohsin
commited on
Commit
Β·
25ea1c9
1
Parent(s):
ac45468
last changes final deployment, hopefully
Browse files- inference.py +50 -29
inference.py
CHANGED
|
@@ -387,8 +387,8 @@ class InferenceService:
|
|
| 387 |
|
| 388 |
# 2) Candidate generation with outfit templates
|
| 389 |
rng = np.random.default_rng(int(context.get("seed", 42)))
|
| 390 |
-
num_outfits = int(context.get("num_outfits",
|
| 391 |
-
min_size, max_size =
|
| 392 |
ids = list(range(len(proc_items)))
|
| 393 |
|
| 394 |
# Outfit templates for cohesive styling
|
|
@@ -569,7 +569,7 @@ class InferenceService:
|
|
| 569 |
print(f"π DEBUG: Will use flexible outfit generation with available items")
|
| 570 |
|
| 571 |
candidates: List[List[int]] = []
|
| 572 |
-
num_samples = max(num_outfits *
|
| 573 |
print(f"π DEBUG: Generating {num_samples} candidate outfits...")
|
| 574 |
|
| 575 |
def has_category_diversity(subset: List[int]) -> bool:
|
|
@@ -607,17 +607,18 @@ class InferenceService:
|
|
| 607 |
outfit_length = rng.choice([2, 3, 4, 5], p=[0.1, 0.4, 0.4, 0.1]) # Prefer 3-4 items
|
| 608 |
|
| 609 |
# Strategy 1: Core outfit (shirt + pants + shoes) + accessories
|
| 610 |
-
if rng.random() < 0.
|
| 611 |
# Core outfit: exactly 1 of each required slot
|
| 612 |
subset.append(int(rng.choice(uppers)))
|
| 613 |
subset.append(int(rng.choice(bottoms)))
|
| 614 |
subset.append(int(rng.choice(shoes)))
|
| 615 |
|
| 616 |
-
#
|
| 617 |
remaining_slots = outfit_length - len(subset)
|
| 618 |
if accs and remaining_slots > 0:
|
| 619 |
max_accs = min(template["accessory_limit"], remaining_slots, len(accs))
|
| 620 |
-
|
|
|
|
| 621 |
available_accs = [i for i in accs if i not in subset]
|
| 622 |
if available_accs and num_accs > 0:
|
| 623 |
selected_accs = rng.choice(available_accs, size=min(num_accs, len(available_accs)), replace=False)
|
|
@@ -632,29 +633,12 @@ class InferenceService:
|
|
| 632 |
selected_others = rng.choice(available_others, size=num_others, replace=False)
|
| 633 |
subset.extend(selected_others.tolist())
|
| 634 |
|
| 635 |
-
# Strategy 2:
|
| 636 |
-
elif rng.random() < 0.3:
|
| 637 |
-
# Randomly select items from all categories
|
| 638 |
-
all_items = list(ids)
|
| 639 |
-
rng.shuffle(all_items)
|
| 640 |
-
|
| 641 |
-
# Select items ensuring diversity
|
| 642 |
-
selected_categories = set()
|
| 643 |
-
for item in all_items:
|
| 644 |
-
if len(subset) >= outfit_length:
|
| 645 |
-
break
|
| 646 |
-
item_category = get_category_type(cat_str(item))
|
| 647 |
-
if item_category not in selected_categories or len(subset) < 2:
|
| 648 |
-
subset.append(item)
|
| 649 |
-
selected_categories.add(item_category)
|
| 650 |
-
|
| 651 |
-
# Strategy 3: Accessory-focused outfit (for small wardrobes)
|
| 652 |
-
else:
|
| 653 |
# Start with accessories if available
|
| 654 |
-
|
| 655 |
-
|
| 656 |
-
|
| 657 |
-
subset.extend(selected_accs.tolist())
|
| 658 |
|
| 659 |
# Fill remaining with other categories
|
| 660 |
remaining_slots = outfit_length - len(subset)
|
|
@@ -671,6 +655,22 @@ class InferenceService:
|
|
| 671 |
selected_others = rng.choice(available_others, size=num_others, replace=False)
|
| 672 |
subset.extend(selected_others.tolist())
|
| 673 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 674 |
# Remove duplicates and validate
|
| 675 |
subset = list(set(subset))
|
| 676 |
if len(subset) >= 2 and len(subset) <= max_size and has_category_diversity(subset):
|
|
@@ -768,6 +768,11 @@ class InferenceService:
|
|
| 768 |
if style_score > 0.6: # Good style match
|
| 769 |
bonus += 0.2
|
| 770 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 771 |
return base_score + penalty + bonus
|
| 772 |
|
| 773 |
# Score and filter valid outfits with penalty adjustment
|
|
@@ -786,6 +791,22 @@ class InferenceService:
|
|
| 786 |
# Sort by penalty-adjusted score with randomization
|
| 787 |
scored.sort(key=lambda x: x[1], reverse=True)
|
| 788 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 789 |
# Add randomization to prevent identical recommendations
|
| 790 |
if len(scored) > num_outfits:
|
| 791 |
# Take top 50% and randomly sample from them
|
|
@@ -795,7 +816,7 @@ class InferenceService:
|
|
| 795 |
else:
|
| 796 |
# If we have fewer candidates than requested, shuffle them
|
| 797 |
rng.shuffle(scored)
|
| 798 |
-
|
| 799 |
|
| 800 |
results = []
|
| 801 |
for subset, adjusted_score, base_score in topk:
|
|
|
|
| 387 |
|
| 388 |
# 2) Candidate generation with outfit templates
|
| 389 |
rng = np.random.default_rng(int(context.get("seed", 42)))
|
| 390 |
+
num_outfits = int(context.get("num_outfits", 5)) # Increased default from 3 to 5
|
| 391 |
+
min_size, max_size = 2, 6 # Allow smaller outfits (2 items minimum)
|
| 392 |
ids = list(range(len(proc_items)))
|
| 393 |
|
| 394 |
# Outfit templates for cohesive styling
|
|
|
|
| 569 |
print(f"π DEBUG: Will use flexible outfit generation with available items")
|
| 570 |
|
| 571 |
candidates: List[List[int]] = []
|
| 572 |
+
num_samples = max(num_outfits * 25, 50) # Further increased for more variety
|
| 573 |
print(f"π DEBUG: Generating {num_samples} candidate outfits...")
|
| 574 |
|
| 575 |
def has_category_diversity(subset: List[int]) -> bool:
|
|
|
|
| 607 |
outfit_length = rng.choice([2, 3, 4, 5], p=[0.1, 0.4, 0.4, 0.1]) # Prefer 3-4 items
|
| 608 |
|
| 609 |
# Strategy 1: Core outfit (shirt + pants + shoes) + accessories
|
| 610 |
+
if rng.random() < 0.5 and uppers and bottoms and shoes:
|
| 611 |
# Core outfit: exactly 1 of each required slot
|
| 612 |
subset.append(int(rng.choice(uppers)))
|
| 613 |
subset.append(int(rng.choice(bottoms)))
|
| 614 |
subset.append(int(rng.choice(shoes)))
|
| 615 |
|
| 616 |
+
# Prioritize accessories - higher chance of including them
|
| 617 |
remaining_slots = outfit_length - len(subset)
|
| 618 |
if accs and remaining_slots > 0:
|
| 619 |
max_accs = min(template["accessory_limit"], remaining_slots, len(accs))
|
| 620 |
+
# Higher probability of including accessories
|
| 621 |
+
num_accs = rng.integers(1, max_accs + 1) if rng.random() < 0.8 else 0
|
| 622 |
available_accs = [i for i in accs if i not in subset]
|
| 623 |
if available_accs and num_accs > 0:
|
| 624 |
selected_accs = rng.choice(available_accs, size=min(num_accs, len(available_accs)), replace=False)
|
|
|
|
| 633 |
selected_others = rng.choice(available_others, size=num_others, replace=False)
|
| 634 |
subset.extend(selected_others.tolist())
|
| 635 |
|
| 636 |
+
# Strategy 2: Accessory-focused outfit (prioritize accessories)
|
| 637 |
+
elif rng.random() < 0.3 and accs:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 638 |
# Start with accessories if available
|
| 639 |
+
num_accs = min(outfit_length, len(accs))
|
| 640 |
+
selected_accs = rng.choice(accs, size=num_accs, replace=False)
|
| 641 |
+
subset.extend(selected_accs.tolist())
|
|
|
|
| 642 |
|
| 643 |
# Fill remaining with other categories
|
| 644 |
remaining_slots = outfit_length - len(subset)
|
|
|
|
| 655 |
selected_others = rng.choice(available_others, size=num_others, replace=False)
|
| 656 |
subset.extend(selected_others.tolist())
|
| 657 |
|
| 658 |
+
# Strategy 3: Flexible combination (no strict slot requirements)
|
| 659 |
+
else:
|
| 660 |
+
# Randomly select items from all categories
|
| 661 |
+
all_items = list(ids)
|
| 662 |
+
rng.shuffle(all_items)
|
| 663 |
+
|
| 664 |
+
# Select items ensuring diversity
|
| 665 |
+
selected_categories = set()
|
| 666 |
+
for item in all_items:
|
| 667 |
+
if len(subset) >= outfit_length:
|
| 668 |
+
break
|
| 669 |
+
item_category = get_category_type(cat_str(item))
|
| 670 |
+
if item_category not in selected_categories or len(subset) < 2:
|
| 671 |
+
subset.append(item)
|
| 672 |
+
selected_categories.add(item_category)
|
| 673 |
+
|
| 674 |
# Remove duplicates and validate
|
| 675 |
subset = list(set(subset))
|
| 676 |
if len(subset) >= 2 and len(subset) <= max_size and has_category_diversity(subset):
|
|
|
|
| 768 |
if style_score > 0.6: # Good style match
|
| 769 |
bonus += 0.2
|
| 770 |
|
| 771 |
+
# Accessory inclusion bonus
|
| 772 |
+
categories = [get_category_type(cat_str(i)) for i in subset]
|
| 773 |
+
if "accessory" in categories:
|
| 774 |
+
bonus += 0.3 # Bonus for including accessories
|
| 775 |
+
|
| 776 |
return base_score + penalty + bonus
|
| 777 |
|
| 778 |
# Score and filter valid outfits with penalty adjustment
|
|
|
|
| 791 |
# Sort by penalty-adjusted score with randomization
|
| 792 |
scored.sort(key=lambda x: x[1], reverse=True)
|
| 793 |
|
| 794 |
+
# Remove duplicate outfits (same items, different order)
|
| 795 |
+
def normalize_outfit(subset):
|
| 796 |
+
"""Normalize outfit by sorting item IDs for duplicate detection"""
|
| 797 |
+
return tuple(sorted(subset))
|
| 798 |
+
|
| 799 |
+
seen_outfits = set()
|
| 800 |
+
unique_scored = []
|
| 801 |
+
for subset, adjusted_score, base_score in scored:
|
| 802 |
+
normalized = normalize_outfit(subset)
|
| 803 |
+
if normalized not in seen_outfits:
|
| 804 |
+
seen_outfits.add(normalized)
|
| 805 |
+
unique_scored.append((subset, adjusted_score, base_score))
|
| 806 |
+
|
| 807 |
+
print(f"π DEBUG: Removed {len(scored) - len(unique_scored)} duplicate outfits")
|
| 808 |
+
scored = unique_scored
|
| 809 |
+
|
| 810 |
# Add randomization to prevent identical recommendations
|
| 811 |
if len(scored) > num_outfits:
|
| 812 |
# Take top 50% and randomly sample from them
|
|
|
|
| 816 |
else:
|
| 817 |
# If we have fewer candidates than requested, shuffle them
|
| 818 |
rng.shuffle(scored)
|
| 819 |
+
topk = scored[:num_outfits]
|
| 820 |
|
| 821 |
results = []
|
| 822 |
for subset, adjusted_score, base_score in topk:
|