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

updates 9.0

Browse files
Files changed (1) hide show
  1. app.py +142 -72
app.py CHANGED
@@ -69,7 +69,8 @@ class GPTOSSSizeRecommender:
69
  self.tokenizer = AutoTokenizer.from_pretrained(
70
  self.model_name,
71
  trust_remote_code=True,
72
- use_fast=False
 
73
  )
74
 
75
  # Add padding token if not present
@@ -93,7 +94,8 @@ class GPTOSSSizeRecommender:
93
  # Load model with 8-bit
94
  self.model = AutoModelForCausalLM.from_pretrained(
95
  self.model_name,
96
- **model_kwargs
 
97
  )
98
  print("βœ… Model loaded with 8-bit quantization")
99
  except Exception as e:
@@ -107,7 +109,8 @@ class GPTOSSSizeRecommender:
107
  }
108
  self.model = AutoModelForCausalLM.from_pretrained(
109
  self.model_name,
110
- **model_kwargs
 
111
  )
112
  print("βœ… Model loaded with bfloat16")
113
  else:
@@ -118,7 +121,8 @@ class GPTOSSSizeRecommender:
118
  # Load model
119
  self.model = AutoModelForCausalLM.from_pretrained(
120
  self.model_name,
121
- **model_kwargs
 
122
  )
123
 
124
  if self.device == "cpu":
@@ -242,83 +246,66 @@ class GPTOSSSizeRecommender:
242
  gender = user_data.get('gender', 'unisex')
243
  estimated_measurements = self.estimate_missing_measurements(user_data, gender)
244
 
245
- prompt = f"""You are an expert AI clothing size recommendation system with advanced reasoning capabilities. Your task is to recommend the perfect garment size based on available body measurements and garment specifications.
246
-
247
- **CUSTOMER PROFILE:**
248
- Gender/Body Type: {user_data.get('body_type', 'Not specified')} / {gender}
249
- Height: {estimated_measurements.get('height', 'Not provided')} inches
250
- Weight: {estimated_measurements.get('weight', 'Not provided')} lbs
251
-
252
- **BODY MEASUREMENTS (in inches):**
253
- - Chest/Bust: {estimated_measurements.get('chest', 0):.1f} {'(estimated)' if user_data.get('chest', 0) == 0 and estimated_measurements.get('chest', 0) > 0 else ''}
254
- - Shoulder Width: {estimated_measurements.get('shoulder_width', 0):.1f} {'(estimated)' if user_data.get('shoulder_width', 0) == 0 and estimated_measurements.get('shoulder_width', 0) > 0 else ''}
255
- - Sleeve Length: {estimated_measurements.get('sleeve_length', 0):.1f} {'(estimated)' if user_data.get('sleeve_length', 0) == 0 and estimated_measurements.get('sleeve_length', 0) > 0 else ''}
256
- - Neck Circumference: {estimated_measurements.get('neck_circumference', 0):.1f} {'(estimated)' if user_data.get('neck_circumference', 0) == 0 and estimated_measurements.get('neck_circumference', 0) > 0 else ''}
257
- - Shirt Length: {estimated_measurements.get('shirt_length', 0):.1f} {'(estimated)' if user_data.get('shirt_length', 0) == 0 and estimated_measurements.get('shirt_length', 0) > 0 else ''}
258
- - Armhole Size: {estimated_measurements.get('armhole_size', 0):.1f} {'(estimated)' if user_data.get('armhole_size', 0) == 0 and estimated_measurements.get('armhole_size', 0) > 0 else ''}
259
- - Waist: {estimated_measurements.get('waist', 0):.1f} {'(estimated)' if user_data.get('waist', 0) == 0 and estimated_measurements.get('waist', 0) > 0 else ''}
260
- - Inseam: {estimated_measurements.get('inseam', 0):.1f} {'(estimated)' if user_data.get('inseam', 0) == 0 and estimated_measurements.get('inseam', 0) > 0 else ''}
261
- - Thigh Circumference: {estimated_measurements.get('thigh_circumference', 0):.1f} {'(estimated)' if user_data.get('thigh_circumference', 0) == 0 and estimated_measurements.get('thigh_circumference', 0) > 0 else ''}
262
-
263
- **GARMENT DETAILS:**
264
- - Product: {garment_data.get('product_name', 'Not specified')}
265
- - Brand: {garment_data.get('brand', 'Not specified')}
266
- - Category: {garment_data.get('category', 'Not specified')}
267
- - Available Sizes: {', '.join(garment_data.get('available_sizes', []))}
268
-
269
- **GARMENT SIZE SPECIFICATIONS (in inches):**"""
270
-
271
- # Add size measurements for each available size
272
  for size in garment_data.get('available_sizes', []):
273
  measurements = garment_data.get(f'{size.lower()}_measurements', {})
274
  if measurements:
275
- prompt += f"\n\n{size} Size:"
276
- for measurement, value in measurements.items():
277
- if value and value != 0:
278
- prompt += f"\n - {measurement.title()}: {value} inches"
279
 
280
- prompt += """
281
 
282
- **ANALYSIS REQUIREMENTS:**
283
- 1. **Smart Comparison**: Compare customer measurements (including estimated ones) with each available garment size
284
- 2. **Estimation Confidence**: Consider the reliability of estimated vs. provided measurements
285
- 3. **Fit Philosophy**: Account for garment category, brand typical sizing, and comfort requirements
286
- 4. **Multi-factor Analysis**: Consider all relevant measurements, not just chest/waist
287
- 5. **Gender/Body Type**: Factor in the customer's body type and proportions
288
- 6. **Tolerance Analysis**: Account for fabric stretch, fit preferences, and wearing comfort
289
 
290
- **RESPONSE FORMAT:**
291
- 🎯 **RECOMMENDED SIZE: [SIZE]**
292
- πŸ“Š **CONFIDENCE SCORE: [SCORE]/100**
293
- πŸ”„ **ALTERNATIVE SIZE: [ALT_SIZE]** (if confidence < 85)
 
 
294
 
295
- πŸ“‹ **DETAILED FIT ANALYSIS:**
 
 
 
 
296
 
297
- **Critical Measurements Match:**
298
- - Chest/Bust: [Analysis with specific numbers]
299
- - Waist: [Analysis with specific numbers]
300
- - Shoulder: [Analysis with specific numbers]
301
- - Length: [Analysis with specific numbers]
302
 
303
- **Estimated Measurements Impact:**
304
- [Discuss how estimated measurements affect confidence]
 
 
 
 
305
 
306
- **Fit Assessment:**
307
- - Overall Comfort: [Excellent/Good/Acceptable/Tight/Loose]
308
- - Movement Freedom: [Assessment]
309
- - Style Appropriateness: [Assessment]
310
 
311
- ⚠️ **POTENTIAL CONCERNS:**
312
- [List any fit issues or areas to watch]
 
 
313
 
314
- βœ… **FINAL RECOMMENDATION:**
315
- [Comprehensive summary with actionable advice]
 
 
316
 
317
- **Measurement Notes:**
318
- [Any important notes about sizing for this specific garment/brand]
319
 
320
- Reasoning: high
321
- """
322
 
323
  return prompt
324
 
@@ -346,13 +333,15 @@ Reasoning: high
346
  with torch.no_grad():
347
  outputs = self.model.generate(
348
  **inputs,
349
- max_new_tokens=600,
350
- temperature=0.7,
351
  do_sample=True,
352
- top_p=0.9,
 
353
  pad_token_id=self.tokenizer.eos_token_id,
354
  eos_token_id=self.tokenizer.eos_token_id,
355
- repetition_penalty=1.1
 
356
  )
357
 
358
  # Decode response
@@ -364,10 +353,64 @@ Reasoning: high
364
  else:
365
  response = generated_text.strip()
366
 
 
 
 
367
  return response if response else "No response generated"
368
 
369
  except Exception as e:
370
  return f"❌ Model Error: {str(e)}\nPlease try again or restart the application."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
 
372
  def recommend_size(self, user_data: Dict, garment_data: Dict, api_key: str = None) -> str:
373
  """Main function to get size recommendation"""
@@ -403,6 +446,14 @@ def predict_size(
403
  ) -> str:
404
  """Enhanced prediction function with robust input handling"""
405
 
 
 
 
 
 
 
 
 
406
  try:
407
  # Parse all measurements with units
408
  user_data = {
@@ -449,10 +500,29 @@ def predict_size(
449
  if total_measurements < 2:
450
  return "⚠️ Please provide at least 2 body measurements for accurate recommendations."
451
 
 
 
 
 
 
 
 
452
  # Get recommendation
453
  recommendation = recommender.recommend_size(user_data, garment_data)
454
 
455
- return recommendation
 
 
 
 
 
 
 
 
 
 
 
 
456
 
457
  except Exception as e:
458
  return f"❌ Processing Error: {str(e)}\nPlease check your inputs and try again."
 
69
  self.tokenizer = AutoTokenizer.from_pretrained(
70
  self.model_name,
71
  trust_remote_code=True,
72
+ use_fast=False,
73
+ cache_dir="/tmp/huggingface_cache"
74
  )
75
 
76
  # Add padding token if not present
 
94
  # Load model with 8-bit
95
  self.model = AutoModelForCausalLM.from_pretrained(
96
  self.model_name,
97
+ **model_kwargs,
98
+ cache_dir="/tmp/huggingface_cache"
99
  )
100
  print("βœ… Model loaded with 8-bit quantization")
101
  except Exception as e:
 
109
  }
110
  self.model = AutoModelForCausalLM.from_pretrained(
111
  self.model_name,
112
+ **model_kwargs,
113
+ cache_dir="/tmp/huggingface_cache"
114
  )
115
  print("βœ… Model loaded with bfloat16")
116
  else:
 
121
  # Load model
122
  self.model = AutoModelForCausalLM.from_pretrained(
123
  self.model_name,
124
+ **model_kwargs,
125
+ cache_dir="/tmp/huggingface_cache"
126
  )
127
 
128
  if self.device == "cpu":
 
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
 
 
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
 
353
  else:
354
  response = generated_text.strip()
355
 
356
+ # Format response
357
+ response = self.format_response(response)
358
+
359
  return response if response else "No response generated"
360
 
361
  except Exception as e:
362
  return f"❌ Model Error: {str(e)}\nPlease try again or restart the application."
363
+
364
+ def format_response(self, response: str) -> str:
365
+ """Format and clean up the model response"""
366
+ # Clean up common issues
367
+ response = response.strip()
368
+
369
+ # If response doesn't follow format, try to extract key information
370
+ if "RECOMMENDED SIZE:" not in response:
371
+ # Try to extract size recommendation from unstructured text
372
+ import re
373
+
374
+ # Look for size mentions
375
+ size_pattern = r'\b(XS|S|M|L|XL|XXL|XXXL)\b'
376
+ sizes_found = re.findall(size_pattern, response.upper())
377
+
378
+ if sizes_found:
379
+ # Create structured response
380
+ formatted = f"""🎯 **RECOMMENDED SIZE: {sizes_found[0]}**
381
+ πŸ“Š **CONFIDENCE: 75%**
382
+
383
+ πŸ“‹ **ANALYSIS:**
384
+ {response[:500]}...
385
+
386
+ βœ… **RECOMMENDATION:**
387
+ Based on the analysis, size {sizes_found[0]} is recommended."""
388
+ return formatted
389
+
390
+ # Clean up formatting
391
+ lines = response.split('\n')
392
+ cleaned_lines = []
393
+
394
+ for line in lines:
395
+ line = line.strip()
396
+ if line:
397
+ # Format headers
398
+ if line.startswith("RECOMMENDED SIZE:"):
399
+ line = f"🎯 **{line}**"
400
+ elif line.startswith("CONFIDENCE:"):
401
+ line = f"πŸ“Š **{line}**"
402
+ elif line.startswith("ALTERNATIVE:"):
403
+ line = f"πŸ”„ **{line}**"
404
+ elif line.startswith("FIT ANALYSIS:"):
405
+ line = f"\nπŸ“‹ **{line}**"
406
+ elif line.startswith("KEY POINTS:"):
407
+ line = f"\nπŸ”‘ **{line}**"
408
+ elif line.startswith("RECOMMENDATION:"):
409
+ line = f"\nβœ… **{line}**"
410
+
411
+ cleaned_lines.append(line)
412
+
413
+ return '\n'.join(cleaned_lines)
414
 
415
  def recommend_size(self, user_data: Dict, garment_data: Dict, api_key: str = None) -> str:
416
  """Main function to get size recommendation"""
 
446
  ) -> str:
447
  """Enhanced prediction function with robust input handling"""
448
 
449
+ # Check if model is loaded
450
+ if not recommender.model_loaded:
451
+ return """⏳ **AI Model is Loading...**
452
+
453
+ Please wait a moment while the AI model initializes. This may take 1-2 minutes on first use.
454
+
455
+ Once loaded, click 'Get My Perfect Size' again!"""
456
+
457
  try:
458
  # Parse all measurements with units
459
  user_data = {
 
500
  if total_measurements < 2:
501
  return "⚠️ Please provide at least 2 body measurements for accurate recommendations."
502
 
503
+ # Show processing message
504
+ processing_msg = """πŸ”„ **Analyzing your measurements...**
505
+
506
+ Our AI is comparing your measurements with the garment specifications to find your perfect fit.
507
+
508
+ This usually takes 5-10 seconds."""
509
+
510
  # Get recommendation
511
  recommendation = recommender.recommend_size(user_data, garment_data)
512
 
513
+ # Add visual separator
514
+ final_output = f"""
515
+ {recommendation}
516
+
517
+ ---
518
+
519
+ πŸ’‘ **Shopping Tips:**
520
+ - If between sizes, consider the fabric (stretchy vs rigid)
521
+ - Check the brand's return policy before ordering
522
+ - Save your measurements for future purchases
523
+ """
524
+
525
+ return final_output
526
 
527
  except Exception as e:
528
  return f"❌ Processing Error: {str(e)}\nPlease check your inputs and try again."