Ali Mohsin commited on
Commit
ab6d8ce
Β·
1 Parent(s): a13f0b7

faster version 10

Browse files
Files changed (1) hide show
  1. app.py +126 -64
app.py CHANGED
@@ -238,6 +238,77 @@ class GPTOSSSizeRecommender:
238
  estimated['inseam'] = estimated['height'] * ratios['inseam_height_ratio']
239
 
240
  return estimated
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
 
242
  def create_size_recommendation_prompt(self, user_data: Dict, garment_data: Dict) -> str:
243
  """Create a comprehensive prompt for size recommendation with estimation context"""
@@ -246,66 +317,36 @@ class GPTOSSSizeRecommender:
246
  gender = user_data.get('gender', 'unisex')
247
  estimated_measurements = self.estimate_missing_measurements(user_data, gender)
248
 
249
- # Build size comparison table
250
- size_comparisons = []
251
- for size in garment_data.get('available_sizes', []):
252
- measurements = garment_data.get(f'{size.lower()}_measurements', {})
253
- if measurements:
254
- size_comparisons.append(f"{size}: Chest={measurements.get('chest', 'N/A')}, Waist={measurements.get('waist', 'N/A')}, Length={measurements.get('length', 'N/A')}")
255
 
256
- prompt = f"""<system>You are a professional clothing size recommendation assistant. You must provide clear, structured recommendations following the exact format specified.</system>
257
-
258
- <task>Analyze the customer's measurements against the garment specifications and recommend the best size.</task>
259
 
260
- <customer_info>
261
- - Gender: {gender}
262
- - Body Type: {user_data.get('body_type', 'Regular')}
 
263
  - Height: {estimated_measurements.get('height', 0):.0f} inches
264
- - Weight: {estimated_measurements.get('weight', 0):.0f} lbs
265
- </customer_info>
266
-
267
- <customer_measurements>
268
- - Chest: {estimated_measurements.get('chest', 0):.0f}" (User Provided: {'Yes' if user_data.get('chest', 0) > 0 else 'No'})
269
- - Waist: {estimated_measurements.get('waist', 0):.0f}" (User Provided: {'Yes' if user_data.get('waist', 0) > 0 else 'No'})
270
- - Shoulder: {estimated_measurements.get('shoulder_width', 0):.0f}" (User Provided: {'Yes' if user_data.get('shoulder_width', 0) > 0 else 'No'})
271
- - Length Preference: {estimated_measurements.get('shirt_length', 0):.0f}" (User Provided: {'Yes' if user_data.get('shirt_length', 0) > 0 else 'No'})
272
- </customer_measurements>
273
 
274
- <garment_info>
275
- - Product: {garment_data.get('product_name', 'Not specified')}
276
- - Brand: {garment_data.get('brand', 'Not specified')}
277
- - Category: {garment_data.get('category', 'Not specified')}
278
- </garment_info>
279
 
280
- <available_sizes>
281
- {chr(10).join(size_comparisons)}
282
- </available_sizes>
283
 
284
- <instructions>
285
- 1. Compare customer measurements to each size
286
- 2. Find the best match considering chest as priority, then waist, then length
287
- 3. Calculate fit tolerance (2-3 inches for comfort)
288
- 4. Consider if estimated measurements affect confidence
289
- 5. Provide your response in EXACTLY this format:
290
-
291
- RECOMMENDED SIZE: [Choose one size]
292
- CONFIDENCE: [Number 1-100]%
293
- ALTERNATIVE: [Second best size or "None"]
294
 
295
  FIT ANALYSIS:
296
- βœ“ Chest fit: [Customer chest] vs Size [X] chest [Y] = [Perfect/Good/Tight/Loose]
297
- βœ“ Waist fit: [Customer waist] vs Size [X] waist [Y] = [Perfect/Good/Tight/Loose]
298
- βœ“ Length fit: [Assessment based on height and garment length]
299
 
300
  KEY POINTS:
301
- β€’ [Most important fit consideration]
302
- β€’ [Second important point]
303
- β€’ [Any concerns or adjustments needed]
304
-
305
- RECOMMENDATION: [One sentence summary, e.g. "Size M will provide the best overall fit with comfortable room in the chest and proper length."]
306
- </instructions>
307
 
308
- Provide your analysis now:"""
309
 
310
  return prompt
311
 
@@ -329,19 +370,16 @@ Provide your analysis now:"""
329
  # Move to device
330
  inputs = {k: v.to(self.device) for k, v in inputs.items()}
331
 
332
- # Generate response
333
  with torch.no_grad():
334
  outputs = self.model.generate(
335
  **inputs,
336
- max_new_tokens=400,
337
- temperature=0.3,
338
- do_sample=True,
339
- top_p=0.95,
340
- top_k=50,
341
  pad_token_id=self.tokenizer.eos_token_id,
342
  eos_token_id=self.tokenizer.eos_token_id,
343
- repetition_penalty=1.05,
344
- num_beams=1
345
  )
346
 
347
  # Decode response
@@ -415,13 +453,37 @@ Based on the analysis, size {sizes_found[0]} is recommended."""
415
  def recommend_size(self, user_data: Dict, garment_data: Dict, api_key: str = None) -> str:
416
  """Main function to get size recommendation"""
417
 
418
- # Create the prompt
419
- prompt = self.create_size_recommendation_prompt(user_data, garment_data)
420
-
421
- # Query the model
422
- response = self.query_model(prompt, api_key)
423
-
424
- return response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
425
 
426
  # Initialize the recommender
427
  recommender = GPTOSSSizeRecommender()
 
238
  estimated['inseam'] = estimated['height'] * ratios['inseam_height_ratio']
239
 
240
  return estimated
241
+
242
+ def calculate_best_size(self, user_measurements: Dict, garment_data: Dict) -> Tuple[str, int, str]:
243
+ """Calculate the best matching size based on measurements"""
244
+ available_sizes = garment_data.get('available_sizes', [])
245
+ best_size = "M"
246
+ best_score = float('inf')
247
+ analysis_parts = []
248
+
249
+ for size in available_sizes:
250
+ size_measurements = garment_data.get(f'{size.lower()}_measurements', {})
251
+ if not size_measurements:
252
+ continue
253
+
254
+ # Calculate differences for each measurement
255
+ chest_diff = abs(user_measurements.get('chest', 0) - size_measurements.get('chest', 0))
256
+ waist_diff = abs(user_measurements.get('waist', 0) - size_measurements.get('waist', 0))
257
+ shoulder_diff = abs(user_measurements.get('shoulder_width', 0) - size_measurements.get('shoulder', 0))
258
+
259
+ # Weighted score (chest is most important)
260
+ score = (chest_diff * 2) + waist_diff + (shoulder_diff * 0.5)
261
+
262
+ if score < best_score:
263
+ best_score = score
264
+ best_size = size
265
+
266
+ # Create analysis
267
+ chest_fit = self.assess_fit(user_measurements.get('chest', 0), size_measurements.get('chest', 0))
268
+ waist_fit = self.assess_fit(user_measurements.get('waist', 0), size_measurements.get('waist', 0))
269
+
270
+ analysis_parts = [
271
+ f"βœ“ Chest fit: {user_measurements.get('chest', 0):.0f}\" vs Size {size} chest {size_measurements.get('chest', 0)}\" = {chest_fit}",
272
+ f"βœ“ Waist fit: {user_measurements.get('waist', 0):.0f}\" vs Size {size} waist {size_measurements.get('waist', 0)}\" = {waist_fit}",
273
+ f"βœ“ Length fit: Appropriate for {user_measurements.get('height', 0):.0f}\" height"
274
+ ]
275
+
276
+ # Calculate confidence based on how well it matches
277
+ confidence = max(50, min(95, 100 - int(best_score * 2)))
278
+ analysis = "\n".join(analysis_parts)
279
+
280
+ return best_size, confidence, analysis
281
+
282
+ def assess_fit(self, user_measurement: float, garment_measurement: float) -> str:
283
+ """Assess how well a measurement fits"""
284
+ diff = garment_measurement - user_measurement
285
+
286
+ if abs(diff) <= 1:
287
+ return "Perfect"
288
+ elif 1 < diff <= 3:
289
+ return "Good (comfortable)"
290
+ elif -2 <= diff < 0:
291
+ return "Snug"
292
+ elif diff > 3:
293
+ return "Loose"
294
+ else:
295
+ return "Too tight"
296
+
297
+ def get_alternative_size(self, primary_size: str, garment_data: Dict) -> str:
298
+ """Get alternative size recommendation"""
299
+ size_order = ["XS", "S", "M", "L", "XL", "XXL", "XXXL"]
300
+ available_sizes = garment_data.get('available_sizes', [])
301
+
302
+ if primary_size in size_order:
303
+ idx = size_order.index(primary_size)
304
+ # Check one size up
305
+ if idx + 1 < len(size_order) and size_order[idx + 1] in available_sizes:
306
+ return size_order[idx + 1]
307
+ # Check one size down
308
+ if idx - 1 >= 0 and size_order[idx - 1] in available_sizes:
309
+ return size_order[idx - 1]
310
+
311
+ return "None"
312
 
313
  def create_size_recommendation_prompt(self, user_data: Dict, garment_data: Dict) -> str:
314
  """Create a comprehensive prompt for size recommendation with estimation context"""
 
317
  gender = user_data.get('gender', 'unisex')
318
  estimated_measurements = self.estimate_missing_measurements(user_data, gender)
319
 
320
+ # Find best matching size using actual logic
321
+ best_size, confidence, analysis = self.calculate_best_size(estimated_measurements, garment_data)
 
 
 
 
322
 
323
+ # Create a simpler prompt that guides the model to the right answer
324
+ prompt = f"""You are a size recommendation assistant. Based on this analysis, provide a formatted recommendation.
 
325
 
326
+ Customer measurements:
327
+ - Chest: {estimated_measurements.get('chest', 0):.0f} inches
328
+ - Waist: {estimated_measurements.get('waist', 0):.0f} inches
329
+ - Shoulder: {estimated_measurements.get('shoulder_width', 0):.0f} inches
330
  - Height: {estimated_measurements.get('height', 0):.0f} inches
 
 
 
 
 
 
 
 
 
331
 
332
+ Best matching size: {best_size}
333
+ Reason: {analysis}
 
 
 
334
 
335
+ Format your response EXACTLY as:
 
 
336
 
337
+ RECOMMENDED SIZE: {best_size}
338
+ CONFIDENCE: {confidence}%
339
+ ALTERNATIVE: {self.get_alternative_size(best_size, garment_data)}
 
 
 
 
 
 
 
340
 
341
  FIT ANALYSIS:
342
+ {analysis}
 
 
343
 
344
  KEY POINTS:
345
+ β€’ Primary recommendation based on chest and waist measurements
346
+ β€’ Consider ordering one size up if you prefer a looser fit
347
+ β€’ This brand's sizing runs true to measurements
 
 
 
348
 
349
+ RECOMMENDATION: Size {best_size} provides the best overall fit for your measurements."""
350
 
351
  return prompt
352
 
 
370
  # Move to device
371
  inputs = {k: v.to(self.device) for k, v in inputs.items()}
372
 
373
+ # Generate response with optimized parameters for speed
374
  with torch.no_grad():
375
  outputs = self.model.generate(
376
  **inputs,
377
+ max_new_tokens=150, # Reduced for faster generation
378
+ temperature=0.1, # Lower for more deterministic output
379
+ do_sample=False, # Greedy decoding for speed
 
 
380
  pad_token_id=self.tokenizer.eos_token_id,
381
  eos_token_id=self.tokenizer.eos_token_id,
382
+ repetition_penalty=1.0
 
383
  )
384
 
385
  # Decode response
 
453
  def recommend_size(self, user_data: Dict, garment_data: Dict, api_key: str = None) -> str:
454
  """Main function to get size recommendation"""
455
 
456
+ # For faster response, calculate the recommendation directly
457
+ gender = user_data.get('gender', 'unisex')
458
+ estimated_measurements = self.estimate_missing_measurements(user_data, gender)
459
+ best_size, confidence, analysis = self.calculate_best_size(estimated_measurements, garment_data)
460
+ alternative = self.get_alternative_size(best_size, garment_data)
461
+
462
+ # Format the response directly without calling the model for most cases
463
+ # Only use model for very uncertain cases
464
+ if confidence > 40:
465
+ # High confidence - return direct formatted response
466
+ response = f"""🎯 **RECOMMENDED SIZE: {best_size}**
467
+ πŸ“Š **CONFIDENCE: {confidence}%**
468
+ πŸ”„ **ALTERNATIVE: {alternative}**
469
+
470
+ πŸ“‹ **FIT ANALYSIS:**
471
+ {analysis}
472
+
473
+ πŸ”‘ **KEY POINTS:**
474
+ β€’ Primary recommendation based on chest and waist measurements
475
+ β€’ Size {best_size} provides optimal fit across all key measurements
476
+ β€’ {f"Consider {alternative} for an alternative fit" if alternative != "None" else "This size should fit comfortably"}
477
+
478
+ βœ… **RECOMMENDATION:**
479
+ Size {best_size} is your best match with {confidence}% confidence based on your measurements."""
480
+
481
+ return response
482
+ else:
483
+ # Lower confidence - use model for nuanced response
484
+ prompt = self.create_size_recommendation_prompt(user_data, garment_data)
485
+ response = self.query_model(prompt, api_key)
486
+ return response
487
 
488
  # Initialize the recommender
489
  recommender = GPTOSSSizeRecommender()