DawnC commited on
Commit
fc63763
1 Parent(s): 34ac181

Update breed_recommendation.py

Browse files
Files changed (1) hide show
  1. breed_recommendation.py +1 -560
breed_recommendation.py CHANGED
@@ -122,10 +122,6 @@ def create_recommendation_tab(UserPreferences, get_breed_recommendations, format
122
  get_recommendations_btn = gr.Button("Find My Perfect Match! 🔍", variant="primary")
123
  recommendation_output = gr.HTML(label="Breed Recommendations")
124
 
125
- with gr.Tab("Find by Description"):
126
- description_input, description_search_btn, description_output, loading_msg = create_description_search_tab()
127
-
128
-
129
  def on_find_match_click(*args):
130
  try:
131
  user_prefs = UserPreferences(
@@ -181,549 +177,6 @@ def create_recommendation_tab(UserPreferences, get_breed_recommendations, format
181
  import traceback
182
  print(traceback.format_exc())
183
  return "Error getting recommendations"
184
-
185
-
186
- # def on_description_search(description: str):
187
- # try:
188
- # # 初始化匹配器
189
- # matcher = SmartBreedMatcher(dog_data)
190
- # breed_recommendations = matcher.match_user_preference(description, top_n=10)
191
-
192
- # # 從描述中提取用戶偏好
193
- # user_prefs = UserPreferences(
194
- # living_space="apartment" if any(word in description.lower()
195
- # for word in ["apartment", "flat", "condo"]) else "house_small",
196
- # yard_access="no_yard" if any(word in description.lower()
197
- # for word in ["apartment", "flat", "condo"]) else "private_yard",
198
- # exercise_time=120 if any(word in description.lower()
199
- # for word in ["active", "exercise", "running", "athletic", "high energy"]) else 60,
200
- # exercise_type="active_training" if any(word in description.lower()
201
- # for word in ["training", "running", "jogging", "hiking"]) else "moderate_activity",
202
- # grooming_commitment="high" if any(word in description.lower()
203
- # for word in ["grooming", "brush", "maintain"]) else "medium",
204
- # experience_level="experienced" if any(word in description.lower()
205
- # for word in ["experienced", "trained", "professional"]) else "intermediate",
206
- # time_availability="flexible" if any(word in description.lower()
207
- # for word in ["time", "available", "flexible", "home"]) else "moderate",
208
- # has_children=any(word in description.lower()
209
- # for word in ["children", "kids", "family", "child"]),
210
- # children_age="school_age" if any(word in description.lower()
211
- # for word in ["school", "elementary"]) else "teenager" if any(word in description.lower()
212
- # for word in ["teen", "teenager"]) else "toddler" if any(word in description.lower()
213
- # for word in ["baby", "toddler"]) else None,
214
- # noise_tolerance="low" if any(word in description.lower()
215
- # for word in ["quiet", "peaceful", "silent"]) else "medium",
216
- # space_for_play=any(word in description.lower()
217
- # for word in ["yard", "garden", "outdoor", "space"]),
218
- # other_pets=any(word in description.lower()
219
- # for word in ["other pets", "cats", "dogs"]),
220
- # climate="moderate",
221
- # health_sensitivity="high" if any(word in description.lower()
222
- # for word in ["health", "medical", "sensitive"]) else "medium",
223
- # barking_acceptance="low" if any(word in description.lower()
224
- # for word in ["quiet", "no barking"]) else "medium"
225
- # )
226
-
227
- # final_recommendations = []
228
-
229
- # for smart_rec in breed_recommendations:
230
- # breed_name = smart_rec['breed']
231
- # breed_info = get_dog_description(breed_name)
232
- # if not isinstance(breed_info, dict):
233
- # continue
234
-
235
- # # 獲取基礎分數
236
- # base_score = smart_rec.get('base_score', 0.7)
237
- # similarity = smart_rec.get('similarity', 0)
238
- # is_preferred = smart_rec.get('is_preferred', False)
239
-
240
- # bonus_reasons = []
241
- # bonus_score = 0
242
-
243
- # # 1. 尺寸評估
244
- # size = breed_info.get('Size', '')
245
- # if size in ['Small', 'Tiny']:
246
- # if "apartment" in description.lower():
247
- # bonus_score += 0.05
248
- # bonus_reasons.append("Suitable size for apartment (+5%)")
249
- # else:
250
- # bonus_score -= 0.25
251
- # bonus_reasons.append("Size too small (-25%)")
252
- # elif size == 'Medium':
253
- # bonus_score += 0.15
254
- # bonus_reasons.append("Ideal size (+15%)")
255
- # elif size == 'Large':
256
- # if "apartment" in description.lower():
257
- # bonus_score -= 0.05
258
- # bonus_reasons.append("May be too large for apartment (-5%)")
259
- # elif size == 'Giant':
260
- # bonus_score -= 0.20
261
- # bonus_reasons.append("Size too large (-20%)")
262
-
263
- # # 2. 運動需求評估
264
- # exercise_needs = breed_info.get('Exercise_Needs', '')
265
- # if any(word in description.lower() for word in ['active', 'energetic', 'running']):
266
- # if exercise_needs in ['High', 'Very High']:
267
- # bonus_score += 0.20
268
- # bonus_reasons.append("Exercise needs match (+20%)")
269
- # elif exercise_needs == 'Low':
270
- # bonus_score -= 0.15
271
- # bonus_reasons.append("Insufficient exercise level (-15%)")
272
- # else:
273
- # if exercise_needs == 'Moderate':
274
- # bonus_score += 0.10
275
- # bonus_reasons.append("Moderate exercise needs (+10%)")
276
-
277
- # # 3. 美容需求評估
278
- # grooming = breed_info.get('Grooming_Needs', '')
279
- # if user_prefs.grooming_commitment == "high":
280
- # if grooming == 'High':
281
- # bonus_score += 0.10
282
- # bonus_reasons.append("High grooming match (+10%)")
283
- # else:
284
- # if grooming == 'High':
285
- # bonus_score -= 0.15
286
- # bonus_reasons.append("High grooming needs (-15%)")
287
- # elif grooming == 'Low':
288
- # bonus_score += 0.10
289
- # bonus_reasons.append("Low grooming needs (+10%)")
290
-
291
- # # 4. 家庭適應性評估
292
- # if user_prefs.has_children:
293
- # if breed_info.get('Good_With_Children'):
294
- # bonus_score += 0.15
295
- # bonus_reasons.append("Excellent with children (+15%)")
296
- # temperament = breed_info.get('Temperament', '').lower()
297
- # if any(trait in temperament for trait in ['gentle', 'patient', 'friendly']):
298
- # bonus_score += 0.05
299
- # bonus_reasons.append("Family-friendly temperament (+5%)")
300
-
301
- # # 5. 噪音評估
302
- # if user_prefs.noise_tolerance == "low":
303
- # noise_level = breed_noise_info.get(breed_name, {}).get('noise_level', 'Unknown')
304
- # if noise_level == 'High':
305
- # bonus_score -= 0.10
306
- # bonus_reasons.append("High noise level (-10%)")
307
- # elif noise_level == 'Low':
308
- # bonus_score += 0.10
309
- # bonus_reasons.append("Low noise level (+10%)")
310
-
311
- # # 6. 健康考慮
312
- # if user_prefs.health_sensitivity == "high":
313
- # health_score = smart_rec.get('health_score', 0.5)
314
- # if health_score > 0.8:
315
- # bonus_score += 0.10
316
- # bonus_reasons.append("Excellent health score (+10%)")
317
- # elif health_score < 0.5:
318
- # bonus_score -= 0.10
319
- # bonus_reasons.append("Health concerns (-10%)")
320
-
321
- # # 7. 品種偏好獎勵
322
- # if is_preferred:
323
- # bonus_score += 0.15
324
- # bonus_reasons.append("Directly mentioned breed (+15%)")
325
- # elif similarity > 0.8:
326
- # bonus_score += 0.10
327
- # bonus_reasons.append("Very similar to preferred breed (+10%)")
328
-
329
- # # 計算最終分數
330
- # final_score = min(0.95, base_score + bonus_score)
331
-
332
- # space_score = _calculate_space_compatibility(
333
- # breed_info.get('Size', 'Medium'),
334
- # user_prefs.living_space
335
- # )
336
-
337
- # exercise_score = _calculate_exercise_compatibility(
338
- # breed_info.get('Exercise_Needs', 'Moderate'),
339
- # user_prefs.exercise_time
340
- # )
341
-
342
- # grooming_score = _calculate_grooming_compatibility(
343
- # breed_info.get('Grooming_Needs', 'Moderate'),
344
- # user_prefs.grooming_commitment
345
- # )
346
-
347
- # experience_score = _calculate_experience_compatibility(
348
- # breed_info.get('Care_Level', 'Moderate'),
349
- # user_prefs.experience_level
350
- # )
351
-
352
- # scores = {
353
- # 'overall': final_score,
354
- # 'space': space_score,
355
- # 'exercise': exercise_score,
356
- # 'grooming': grooming_score,
357
- # 'experience': experience_score,
358
- # 'noise': smart_rec.get('scores', {}).get('noise', 0.0),
359
- # 'health': smart_rec.get('health_score', 0.5),
360
- # 'temperament': smart_rec.get('scores', {}).get('temperament', 0.0)
361
- # }
362
-
363
-
364
- # final_recommendations.append({
365
- # 'rank': 0,
366
- # 'breed': breed_name,
367
- # 'scores': scores,
368
- # 'base_score': round(base_score, 4),
369
- # 'bonus_score': round(bonus_score, 4),
370
- # 'final_score': round(final_score, 4),
371
- # 'match_reason': ' • '.join(bonus_reasons) if bonus_reasons else "Standard match",
372
- # 'info': breed_info,
373
- # 'noise_info': breed_noise_info.get(breed_name, {}),
374
- # 'health_info': breed_health_info.get(breed_name, {})
375
- # })
376
-
377
- # # 根據最終分數排序
378
- # final_recommendations.sort(key=lambda x: (-x['final_score'], x['breed']))
379
-
380
- # # 更新排名
381
- # for i, rec in enumerate(final_recommendations, 1):
382
- # rec['rank'] = i
383
-
384
- # # 保存到歷史記錄
385
- # history_results = [{
386
- # 'breed': rec['breed'],
387
- # 'rank': rec['rank'],
388
- # 'final_score': rec['final_score']
389
- # } for rec in final_recommendations[:10]]
390
-
391
- # history_component.save_search(
392
- # user_preferences=None,
393
- # results=history_results,
394
- # search_type="description",
395
- # description=description
396
- # )
397
-
398
- # result = format_recommendation_html(final_recommendations, is_description_search=True)
399
- # return [gr.update(value=result), gr.update(visible=False)]
400
-
401
- # except Exception as e:
402
- # error_msg = f"Error processing your description. Details: {str(e)}"
403
- # return [gr.update(value=error_msg), gr.update(visible=False)]
404
-
405
-
406
- def on_description_search(description: str):
407
- try:
408
- # 初始化匹配器
409
- matcher = SmartBreedMatcher(dog_data)
410
- breed_recommendations = matcher.match_user_preference(description, top_n=10)
411
-
412
- # 從描述中提取用戶偏好
413
- user_prefs = UserPreferences(
414
- living_space="apartment" if any(word in description.lower()
415
- for word in ["apartment", "flat", "condo"]) else "house_small",
416
- yard_access="no_yard" if any(word in description.lower()
417
- for word in ["apartment", "flat", "condo"]) else "private_yard",
418
- exercise_time=120 if any(word in description.lower()
419
- for word in ["active", "exercise", "running", "athletic", "high energy"]) else 60,
420
- exercise_type="active_training" if any(word in description.lower()
421
- for word in ["training", "running", "jogging", "hiking"]) else "moderate_activity",
422
- grooming_commitment="high" if any(word in description.lower()
423
- for word in ["grooming", "brush", "maintain"]) else "medium",
424
- experience_level="experienced" if any(word in description.lower()
425
- for word in ["experienced", "trained", "professional"]) else "intermediate",
426
- time_availability="flexible" if any(word in description.lower()
427
- for word in ["time", "available", "flexible", "home"]) else "moderate",
428
- has_children=any(word in description.lower()
429
- for word in ["children", "kids", "family", "child"]),
430
- children_age="school_age" if any(word in description.lower()
431
- for word in ["school", "elementary"]) else "teenager" if any(word in description.lower()
432
- for word in ["teen", "teenager"]) else "toddler" if any(word in description.lower()
433
- for word in ["baby", "toddler"]) else None,
434
- noise_tolerance="low" if any(word in description.lower()
435
- for word in ["quiet", "peaceful", "silent"]) else "medium",
436
- space_for_play=any(word in description.lower()
437
- for word in ["yard", "garden", "outdoor", "space"]),
438
- other_pets=any(word in description.lower()
439
- for word in ["other pets", "cats", "dogs"]),
440
- climate="moderate",
441
- health_sensitivity="high" if any(word in description.lower()
442
- for word in ["health", "medical", "sensitive"]) else "medium",
443
- barking_acceptance="low" if any(word in description.lower()
444
- for word in ["quiet", "no barking"]) else "medium"
445
- )
446
-
447
- final_recommendations = []
448
-
449
- if not breed_recommendations:
450
- print("No direct matches found, applying fallback logic")
451
- # 使用 criteria 搜索的邏輯作為後備
452
- recommendations = get_breed_recommendations(user_prefs, top_n=10)
453
- if recommendations:
454
- final_recommendations.extend(recommendations)
455
- else:
456
- # 保持原有的詳細評分系統
457
- for smart_rec in breed_recommendations:
458
- breed_name = smart_rec['breed']
459
- breed_info = get_dog_description(breed_name)
460
-
461
- if not isinstance(breed_info, dict):
462
- continue
463
-
464
- # 獲取基礎分數
465
- base_score = smart_rec.get('base_score', 0.7)
466
- similarity = smart_rec.get('similarity', 0)
467
- is_preferred = smart_rec.get('is_preferred', False)
468
-
469
- bonus_reasons = []
470
- bonus_score = 0
471
-
472
- # 1. 尺寸評估
473
- size = breed_info.get('Size', '')
474
- if size in ['Small', 'Tiny']:
475
- if "apartment" in description.lower():
476
- bonus_score += 0.05
477
- bonus_reasons.append("Suitable size for apartment (+5%)")
478
- else:
479
- bonus_score -= 0.25
480
- bonus_reasons.append("Size too small (-25%)")
481
- elif size == 'Medium':
482
- bonus_score += 0.15
483
- bonus_reasons.append("Ideal size (+15%)")
484
- elif size == 'Large':
485
- if "apartment" in description.lower():
486
- bonus_score -= 0.05
487
- bonus_reasons.append("May be too large for apartment (-5%)")
488
- elif size == 'Giant':
489
- bonus_score -= 0.20
490
- bonus_reasons.append("Size too large (-20%)")
491
-
492
- # 2. 運動需求評估
493
- exercise_needs = breed_info.get('Exercise_Needs', '')
494
- if any(word in description.lower() for word in ['active', 'energetic', 'running']):
495
- if exercise_needs in ['High', 'Very High']:
496
- bonus_score += 0.20
497
- bonus_reasons.append("Exercise needs match (+20%)")
498
- elif exercise_needs == 'Low':
499
- bonus_score -= 0.15
500
- bonus_reasons.append("Insufficient exercise level (-15%)")
501
- else:
502
- if exercise_needs == 'Moderate':
503
- bonus_score += 0.10
504
- bonus_reasons.append("Moderate exercise needs (+10%)")
505
-
506
- # 3. 美容需求評估
507
- grooming = breed_info.get('Grooming_Needs', '')
508
- if user_prefs.grooming_commitment == "high":
509
- if grooming == 'High':
510
- bonus_score += 0.10
511
- bonus_reasons.append("High grooming match (+10%)")
512
- else:
513
- if grooming == 'High':
514
- bonus_score -= 0.15
515
- bonus_reasons.append("High grooming needs (-15%)")
516
- elif grooming == 'Low':
517
- bonus_score += 0.10
518
- bonus_reasons.append("Low grooming needs (+10%)")
519
-
520
- # 4. 家庭適應性評估
521
- if user_prefs.has_children:
522
- if breed_info.get('Good_With_Children'):
523
- bonus_score += 0.15
524
- bonus_reasons.append("Excellent with children (+15%)")
525
- temperament = breed_info.get('Temperament', '').lower()
526
- if any(trait in temperament for trait in ['gentle', 'patient', 'friendly']):
527
- bonus_score += 0.05
528
- bonus_reasons.append("Family-friendly temperament (+5%)")
529
-
530
- # 5. 噪音評估
531
- if user_prefs.noise_tolerance == "low":
532
- noise_level = breed_noise_info.get(breed_name, {}).get('noise_level', 'Unknown')
533
- if noise_level == 'High':
534
- bonus_score -= 0.10
535
- bonus_reasons.append("High noise level (-10%)")
536
- elif noise_level == 'Low':
537
- bonus_score += 0.10
538
- bonus_reasons.append("Low noise level (+10%)")
539
-
540
- # 6. 健康考慮
541
- if user_prefs.health_sensitivity == "high":
542
- health_score = smart_rec.get('health_score', 0.5)
543
- if health_score > 0.8:
544
- bonus_score += 0.10
545
- bonus_reasons.append("Excellent health score (+10%)")
546
- elif health_score < 0.5:
547
- bonus_score -= 0.10
548
- bonus_reasons.append("Health concerns (-10%)")
549
-
550
- # 7. 品種偏好獎勵
551
- if is_preferred:
552
- bonus_score += 0.15
553
- bonus_reasons.append("Directly mentioned breed (+15%)")
554
- elif similarity > 0.8:
555
- bonus_score += 0.10
556
- bonus_reasons.append("Very similar to preferred breed (+10%)")
557
-
558
- # 計算最終分數
559
- final_score = min(0.95, base_score + bonus_score)
560
-
561
- scores = {
562
- 'overall': final_score,
563
- 'space': _calculate_space_compatibility(
564
- breed_info.get('Size', 'Medium'),
565
- user_prefs.living_space
566
- ),
567
- 'exercise': _calculate_exercise_compatibility(
568
- breed_info.get('Exercise_Needs', 'Moderate'),
569
- user_prefs.exercise_time
570
- ),
571
- 'grooming': _calculate_grooming_compatibility(
572
- breed_info.get('Grooming_Needs', 'Moderate'),
573
- user_prefs.grooming_commitment
574
- ),
575
- 'experience': _calculate_experience_compatibility(
576
- breed_info.get('Care_Level', 'Moderate'),
577
- user_prefs.experience_level
578
- ),
579
- 'noise': smart_rec.get('scores', {}).get('noise', 0.0),
580
- 'health': smart_rec.get('health_score', 0.5),
581
- 'temperament': smart_rec.get('scores', {}).get('temperament', 0.0)
582
- }
583
-
584
- final_recommendations.append({
585
- 'rank': 0,
586
- 'breed': breed_name,
587
- 'scores': scores,
588
- 'base_score': round(base_score, 4),
589
- 'bonus_score': round(bonus_score, 4),
590
- 'final_score': round(final_score, 4),
591
- 'match_reason': ' • '.join(bonus_reasons) if bonus_reasons else "Standard match",
592
- 'info': breed_info,
593
- 'noise_info': breed_noise_info.get(breed_name, {}),
594
- 'health_info': breed_health_info.get(breed_name, {})
595
- })
596
-
597
- # 排序並更新排名
598
- if final_recommendations:
599
- final_recommendations.sort(key=lambda x: (-x['final_score'], x['breed']))
600
- for i, rec in enumerate(final_recommendations, 1):
601
- rec['rank'] = i
602
-
603
- # 保存搜索歷史
604
- history_results = [{
605
- 'breed': rec['breed'],
606
- 'rank': rec['rank'],
607
- 'overall_score': rec['final_score'],
608
- 'base_score': rec['base_score'],
609
- 'bonus_score': rec['bonus_score'],
610
- 'scores': rec['scores']
611
- } for rec in final_recommendations[:10]]
612
-
613
- # 保存到歷史記錄
614
- history_component.save_search(
615
- user_preferences={'description': description},
616
- results=history_results,
617
- search_type="description"
618
- )
619
-
620
- # 返回結果
621
- result = format_recommendation_html(final_recommendations, is_description_search=True)
622
- return result
623
-
624
- return "No matching breeds found. Please try a different description."
625
-
626
- except Exception as e:
627
- print(f"Error in description search: {str(e)}")
628
- import traceback
629
- print(traceback.format_exc())
630
- return "Error processing your description"
631
-
632
-
633
- def _calculate_space_compatibility(size: str, living_space: str) -> float:
634
- """住宿空間適應性評分"""
635
- if living_space == "apartment":
636
- scores = {
637
- 'Tiny': 0.6,
638
- 'Small': 0.8,
639
- 'Medium': 1.0,
640
- 'Medium-Large': 0.6,
641
- 'Large': 0.4,
642
- 'Giant': 0.2
643
- }
644
- else: # house
645
- scores = {
646
- 'Tiny': 0.4,
647
- 'Small': 0.6,
648
- 'Medium': 0.8,
649
- 'Medium-Large': 1.0,
650
- 'Large': 0.9,
651
- 'Giant': 0.7
652
- }
653
- return scores.get(size, 0.5)
654
-
655
- def _calculate_exercise_compatibility(exercise_needs: str, exercise_time: int) -> float:
656
- """運動需求相容性評分"""
657
- # 轉換運動時間到評分標準
658
- if exercise_time >= 120: # 高運動量
659
- scores = {
660
- 'Very High': 1.0,
661
- 'High': 0.8,
662
- 'Moderate': 0.5,
663
- 'Low': 0.2
664
- }
665
- elif exercise_time >= 60: # 中等運動量
666
- scores = {
667
- 'Very High': 0.5,
668
- 'High': 0.7,
669
- 'Moderate': 1.0,
670
- 'Low': 0.8
671
- }
672
- else: # 低運動量
673
- scores = {
674
- 'Very High': 0.2,
675
- 'High': 0.4,
676
- 'Moderate': 0.7,
677
- 'Low': 1.0
678
- }
679
- return scores.get(exercise_needs, 0.5)
680
-
681
- def _calculate_grooming_compatibility(grooming_needs: str, grooming_commitment: str) -> float:
682
- """美容需求相容性評分"""
683
- if grooming_commitment == "high":
684
- scores = {
685
- 'High': 1.0,
686
- 'Moderate': 0.8,
687
- 'Low': 0.5
688
- }
689
- elif grooming_commitment == "medium":
690
- scores = {
691
- 'High': 0.6,
692
- 'Moderate': 1.0,
693
- 'Low': 0.8
694
- }
695
- else: # low
696
- scores = {
697
- 'High': 0.3,
698
- 'Moderate': 0.6,
699
- 'Low': 1.0
700
- }
701
- return scores.get(grooming_needs, 0.5)
702
-
703
- def _calculate_experience_compatibility(care_level: str, experience_level: str) -> float:
704
- if experience_level == "experienced":
705
- care_scores = {
706
- 'High': 1.0,
707
- 'Moderate': 0.8,
708
- 'Low': 0.6
709
- }
710
- elif experience_level == "intermediate":
711
- care_scores = {
712
- 'High': 0.6,
713
- 'Moderate': 1.0,
714
- 'Low': 0.8
715
- }
716
- else: # beginner
717
- care_scores = {
718
- 'High': 0.3,
719
- 'Moderate': 0.7,
720
- 'Low': 1.0
721
- }
722
- return care_scores.get(care_level, 0.7)
723
-
724
- def show_loading():
725
- return [gr.update(value=""), gr.update(visible=True)]
726
-
727
 
728
  get_recommendations_btn.click(
729
  fn=on_find_match_click,
@@ -742,15 +195,6 @@ def create_recommendation_tab(UserPreferences, get_breed_recommendations, format
742
  outputs=recommendation_output
743
  )
744
 
745
- description_search_btn.click(
746
- fn=show_loading, # 先顯示加載消息
747
- outputs=[description_output, loading_msg]
748
- ).then( # 然後執行搜索
749
- fn=on_description_search,
750
- inputs=[description_input],
751
- outputs=[description_output, loading_msg]
752
- )
753
-
754
  return {
755
  'living_space': living_space,
756
  'exercise_time': exercise_time,
@@ -760,7 +204,4 @@ def create_recommendation_tab(UserPreferences, get_breed_recommendations, format
760
  'noise_tolerance': noise_tolerance,
761
  'get_recommendations_btn': get_recommendations_btn,
762
  'recommendation_output': recommendation_output,
763
- 'description_input': description_input,
764
- 'description_search_btn': description_search_btn,
765
- 'description_output': description_output
766
- }
 
122
  get_recommendations_btn = gr.Button("Find My Perfect Match! 🔍", variant="primary")
123
  recommendation_output = gr.HTML(label="Breed Recommendations")
124
 
 
 
 
 
125
  def on_find_match_click(*args):
126
  try:
127
  user_prefs = UserPreferences(
 
177
  import traceback
178
  print(traceback.format_exc())
179
  return "Error getting recommendations"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
 
181
  get_recommendations_btn.click(
182
  fn=on_find_match_click,
 
195
  outputs=recommendation_output
196
  )
197
 
 
 
 
 
 
 
 
 
 
198
  return {
199
  'living_space': living_space,
200
  'exercise_time': exercise_time,
 
204
  'noise_tolerance': noise_tolerance,
205
  'get_recommendations_btn': get_recommendations_btn,
206
  'recommendation_output': recommendation_output,
207
+ }