File size: 48,106 Bytes
595e0a5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
import random
import hashlib
import numpy as np
import sqlite3
import re
import traceback
from typing import List, Dict, Tuple, Optional, Any
from dataclasses import dataclass
from sentence_transformers import SentenceTransformer
import torch
from sklearn.metrics.pairwise import cosine_similarity
from dog_database import get_dog_description
from breed_health_info import breed_health_info
from breed_noise_info import breed_noise_info
from scoring_calculation_system import UserPreferences, calculate_compatibility_score, UnifiedScoringSystem, calculate_unified_breed_scores
from query_understanding import QueryUnderstandingEngine, analyze_user_query
from constraint_manager import ConstraintManager, apply_breed_constraints
from multi_head_scorer import MultiHeadScorer, score_breed_candidates, BreedScore
from score_calibrator import ScoreCalibrator, calibrate_breed_scores
from config_manager import get_config_manager, get_standardized_breed_data

class MatchingScoreCalculator:
    """
    匹配評分計算器
    處理多維度匹配計算、約束條件過濾和評分校準
    """

    def __init__(self, breed_list: List[str]):
        """初始化匹配評分計算器"""
        self.breed_list = breed_list

    def apply_size_distribution_correction(self, recommendations: List[Dict]) -> List[Dict]:
        """應用尺寸分佈修正以防止大型品種偏差"""
        if len(recommendations) < 10:
            return recommendations

        # 分析尺寸分佈
        size_counts = {'toy': 0, 'small': 0, 'medium': 0, 'large': 0, 'giant': 0}

        for rec in recommendations:
            breed_info = get_dog_description(rec['breed'])
            if breed_info:
                size = self._normalize_breed_size(breed_info.get('Size', 'Medium'))
                size_counts[size] += 1

        total_recs = len(recommendations)
        large_giant_ratio = (size_counts['large'] + size_counts['giant']) / total_recs

        # 如果超過 70% 是大型/巨型品種,應用修正
        if large_giant_ratio > 0.7:
            corrected_recommendations = []
            size_quotas = {'toy': 2, 'small': 4, 'medium': 6, 'large': 2, 'giant': 1}
            current_counts = {'toy': 0, 'small': 0, 'medium': 0, 'large': 0, 'giant': 0}

            # 第一輪:在配額內添加品種
            for rec in recommendations:
                breed_info = get_dog_description(rec['breed'])
                if breed_info:
                    size = self._normalize_breed_size(breed_info.get('Size', 'Medium'))
                    if current_counts[size] < size_quotas[size]:
                        corrected_recommendations.append(rec)
                        current_counts[size] += 1

            # 第二輪:用最佳剩餘候選品種填滿剩餘位置
            remaining_slots = 15 - len(corrected_recommendations)
            remaining_breeds = [rec for rec in recommendations if rec not in corrected_recommendations]

            corrected_recommendations.extend(remaining_breeds[:remaining_slots])
            return corrected_recommendations

        return recommendations

    def _normalize_breed_size(self, size: str) -> str:
        """標準化品種尺寸到標準分類"""
        if not isinstance(size, str):
            return 'medium'

        size_lower = size.lower()
        if any(term in size_lower for term in ['toy', 'tiny']):
            return 'toy'
        elif 'small' in size_lower:
            return 'small'
        elif 'medium' in size_lower:
            return 'medium'
        elif 'large' in size_lower:
            return 'large'
        elif any(term in size_lower for term in ['giant', 'extra large']):
            return 'giant'
        else:
            return 'medium'

    def apply_hard_constraints(self, breed: str, user_input: str, breed_characteristics: Dict[str, Any]) -> float:
        """增強硬約束,具有更嚴格的懲罰"""
        penalty = 0.0
        user_text_lower = user_input.lower()

        # 獲取品種信息
        breed_info = get_dog_description(breed)
        if not breed_info:
            return 0.0

        breed_size = breed_info.get('Size', '').lower()
        exercise_needs = breed_info.get('Exercise Needs', '').lower()

        # 公寓居住約束 - 更嚴格
        if any(term in user_text_lower for term in ['apartment', 'flat', 'studio', 'small space']):
            if 'giant' in breed_size:
                return -2.0  # 完全淘汰
            elif 'large' in breed_size:
                if any(term in exercise_needs for term in ['high', 'very high']):
                    return -2.0  # 完全淘汰
                else:
                    penalty -= 0.5  # 仍有顯著懲罰
            elif 'medium' in breed_size and 'very high' in exercise_needs:
                penalty -= 0.6

        # 運動不匹配約束
        if "don't exercise much" in user_text_lower or "low exercise" in user_text_lower:
            if any(term in exercise_needs for term in ['very high', 'extreme', 'intense']):
                return -2.0  # 完全淘汰
            elif 'high' in exercise_needs:
                penalty -= 0.8

        # 中等生活方式檢測
        if any(term in user_text_lower for term in ['moderate', 'balanced', '30 minutes', 'half hour']):
            # 懲罰極端情況
            if 'giant' in breed_size:
                penalty -= 0.7  # 對巨型犬的強懲罰
            elif 'very high' in exercise_needs:
                penalty -= 0.5

        # 兒童安全(現有邏輯保持但增強)
        if any(term in user_text_lower for term in ['child', 'kids', 'family', 'baby']):
            good_with_children = breed_info.get('Good with Children', '').lower()
            if good_with_children == 'no':
                return -2.0  # 為了安全完全淘汰

        return penalty

    def calculate_lifestyle_bonus(self, breed_characteristics: Dict[str, Any],
                                 lifestyle_keywords: Dict[str, List[str]]) -> float:
        """增強生活方式匹配獎勵計算"""
        bonus = 0.0
        penalties = 0.0

        # 增強尺寸匹配
        breed_size = breed_characteristics.get('size', '').lower()
        size_prefs = lifestyle_keywords.get('size_preference', [])
        for pref in size_prefs:
            if pref in breed_size:
                bonus += 0.25  # 尺寸匹配的強獎勵
            elif (pref == 'small' and 'large' in breed_size) or \
                 (pref == 'large' and 'small' in breed_size):
                penalties += 0.15  # 尺寸不匹配的懲罰

        # 增強活動水平匹配
        breed_exercise = breed_characteristics.get('exercise_needs', '').lower()
        activity_prefs = lifestyle_keywords.get('activity_level', [])

        if 'high' in activity_prefs:
            if 'high' in breed_exercise or 'very high' in breed_exercise:
                bonus += 0.2
            elif 'low' in breed_exercise:
                penalties += 0.2
        elif 'low' in activity_prefs:
            if 'low' in breed_exercise:
                bonus += 0.2
            elif 'high' in breed_exercise or 'very high' in breed_exercise:
                penalties += 0.25
        elif 'moderate' in activity_prefs:
            if 'moderate' in breed_exercise:
                bonus += 0.15

        # 增強家庭情況匹配
        good_with_children = breed_characteristics.get('good_with_children', 'Yes')
        family_prefs = lifestyle_keywords.get('family_situation', [])

        if 'children' in family_prefs:
            if good_with_children == 'Yes':
                bonus += 0.15
            else:
                penalties += 0.3  # 對非兒童友好品種的強懲罰

        # 增強居住空間匹配
        living_prefs = lifestyle_keywords.get('living_space', [])
        if 'apartment' in living_prefs:
            if 'small' in breed_size:
                bonus += 0.2
            elif 'medium' in breed_size and 'low' in breed_exercise:
                bonus += 0.1
            elif 'large' in breed_size or 'giant' in breed_size:
                penalties += 0.2  # 公寓中大型犬的懲罰

        # 噪音偏好匹配
        noise_prefs = lifestyle_keywords.get('noise_preference', [])
        temperament = breed_characteristics.get('temperament', '').lower()

        if 'low' in noise_prefs:
            # 獎勵安靜品種
            if any(term in temperament for term in ['gentle', 'calm', 'quiet']):
                bonus += 0.1

        # 照護水平匹配
        grooming_needs = breed_characteristics.get('grooming_needs', '').lower()
        care_prefs = lifestyle_keywords.get('care_level', [])

        if 'low' in care_prefs and 'low' in grooming_needs:
            bonus += 0.1
        elif 'high' in care_prefs and 'high' in grooming_needs:
            bonus += 0.1
        elif 'low' in care_prefs and 'high' in grooming_needs:
            penalties += 0.15

        # 特殊需求匹配
        special_needs = lifestyle_keywords.get('special_needs', [])

        if 'guard' in special_needs:
            if any(term in temperament for term in ['protective', 'alert', 'watchful']):
                bonus += 0.1
        elif 'companion' in special_needs:
            if any(term in temperament for term in ['affectionate', 'gentle', 'loyal']):
                bonus += 0.1

        # 計算包含懲罰的最終獎勵
        final_bonus = bonus - penalties
        return max(-0.3, min(0.5, final_bonus))  # 允許負獎勵但限制範圍

    def apply_intelligent_trait_matching(self, recommendations: List[Dict], user_input: str) -> List[Dict]:
        """基於增強關鍵字提取和數據庫挖掘應用智能特徵匹配"""
        try:
            # 從用戶輸入提取增強關鍵字
            extracted_keywords = self._extract_enhanced_lifestyle_keywords(user_input)

            # 對每個推薦應用智能特徵匹配
            enhanced_recommendations = []

            for rec in recommendations:
                breed_name = rec['breed'].replace(' ', '_')

                # 獲取品種數據庫信息
                breed_info = get_dog_description(breed_name) or {}

                # 計算智能特徵獎勵
                intelligence_bonus = 0.0
                trait_match_details = {}

                # 1. 智力匹配
                if extracted_keywords.get('intelligence_preference'):
                    intelligence_pref = extracted_keywords['intelligence_preference'][0]
                    breed_desc = breed_info.get('Description', '').lower()

                    if intelligence_pref == 'high':
                        if any(word in breed_desc for word in ['intelligent', 'smart', 'clever', 'quick to learn', 'trainable']):
                            intelligence_bonus += 0.05
                            trait_match_details['intelligence_match'] = 'High intelligence match detected'
                        elif any(word in breed_desc for word in ['stubborn', 'independent', 'difficult']):
                            intelligence_bonus -= 0.02
                            trait_match_details['intelligence_warning'] = 'May be challenging to train'

                    elif intelligence_pref == 'independent':
                        if any(word in breed_desc for word in ['independent', 'stubborn', 'strong-willed']):
                            intelligence_bonus += 0.03
                            trait_match_details['independence_match'] = 'Independent nature match'

                # 2. 美容偏好匹配
                if extracted_keywords.get('grooming_preference'):
                    grooming_pref = extracted_keywords['grooming_preference'][0]
                    breed_grooming = breed_info.get('Grooming Needs', '').lower()

                    if grooming_pref == 'low' and 'low' in breed_grooming:
                        intelligence_bonus += 0.03
                        trait_match_details['grooming_match'] = 'Low maintenance grooming match'
                    elif grooming_pref == 'high' and 'high' in breed_grooming:
                        intelligence_bonus += 0.03
                        trait_match_details['grooming_match'] = 'High maintenance grooming match'
                    elif grooming_pref == 'low' and 'high' in breed_grooming:
                        intelligence_bonus -= 0.04
                        trait_match_details['grooming_mismatch'] = 'High grooming needs may not suit preferences'

                # 3. 氣質偏好匹配
                if extracted_keywords.get('temperament_preference'):
                    temp_prefs = extracted_keywords['temperament_preference']
                    breed_temperament = breed_info.get('Temperament', '').lower()
                    breed_desc = breed_info.get('Description', '').lower()

                    temp_text = (breed_temperament + ' ' + breed_desc).lower()

                    for temp_pref in temp_prefs:
                        if temp_pref == 'gentle' and any(word in temp_text for word in ['gentle', 'calm', 'peaceful', 'mild']):
                            intelligence_bonus += 0.04
                            trait_match_details['temperament_match'] = f'Gentle temperament match: {temp_pref}'
                        elif temp_pref == 'playful' and any(word in temp_text for word in ['playful', 'energetic', 'lively', 'fun']):
                            intelligence_bonus += 0.04
                            trait_match_details['temperament_match'] = f'Playful temperament match: {temp_pref}'
                        elif temp_pref == 'protective' and any(word in temp_text for word in ['protective', 'guard', 'alert', 'watchful']):
                            intelligence_bonus += 0.04
                            trait_match_details['temperament_match'] = f'Protective temperament match: {temp_pref}'
                        elif temp_pref == 'friendly' and any(word in temp_text for word in ['friendly', 'social', 'outgoing', 'people']):
                            intelligence_bonus += 0.04
                            trait_match_details['temperament_match'] = f'Friendly temperament match: {temp_pref}'

                # 4. 經驗水平匹配
                if extracted_keywords.get('experience_level'):
                    exp_level = extracted_keywords['experience_level'][0]
                    breed_desc = breed_info.get('Description', '').lower()

                    if exp_level == 'beginner':
                        # 為初學者偏愛易於處理的品種
                        if any(word in breed_desc for word in ['easy', 'gentle', 'good for beginners', 'family', 'calm']):
                            intelligence_bonus += 0.06
                            trait_match_details['beginner_friendly'] = 'Good choice for first-time owners'
                        elif any(word in breed_desc for word in ['challenging', 'dominant', 'requires experience', 'strong-willed']):
                            intelligence_bonus -= 0.08
                            trait_match_details['experience_warning'] = 'May be challenging for first-time owners'

                    elif exp_level == 'advanced':
                        # 高級用戶可以處理更具挑戰性的品種
                        if any(word in breed_desc for word in ['working', 'requires experience', 'intelligent', 'strong']):
                            intelligence_bonus += 0.03
                            trait_match_details['advanced_suitable'] = 'Good match for experienced owners'

                # 5. 壽命偏好匹配
                if extracted_keywords.get('lifespan_preference'):
                    lifespan_pref = extracted_keywords['lifespan_preference'][0]
                    breed_lifespan = breed_info.get('Lifespan', '10-12 years')

                    try:
                        import re
                        years = re.findall(r'\d+', breed_lifespan)
                        if years:
                            avg_years = sum(int(y) for y in years) / len(years)
                            if lifespan_pref == 'long' and avg_years >= 13:
                                intelligence_bonus += 0.02
                                trait_match_details['longevity_match'] = f'Long lifespan match: {breed_lifespan}'
                            elif lifespan_pref == 'healthy' and avg_years >= 12:
                                intelligence_bonus += 0.02
                                trait_match_details['health_match'] = f'Healthy lifespan: {breed_lifespan}'
                    except:
                        pass

                # 將智力獎勵應用到總分
                original_score = rec['overall_score']
                enhanced_score = min(1.0, original_score + intelligence_bonus)

                # 創建包含特徵匹配詳細信息的增強推薦
                enhanced_rec = rec.copy()
                enhanced_rec['overall_score'] = enhanced_score
                enhanced_rec['intelligence_bonus'] = intelligence_bonus
                enhanced_rec['trait_match_details'] = trait_match_details

                # 如果發生顯著增強,添加詳細說明
                if abs(intelligence_bonus) > 0.02:
                    enhancement_explanation = []
                    for detail_key, detail_value in trait_match_details.items():
                        enhancement_explanation.append(detail_value)

                    if enhancement_explanation:
                        current_explanation = enhanced_rec.get('explanation', '')
                        enhanced_explanation = current_explanation + f" Enhanced matching: {'; '.join(enhancement_explanation)}"
                        enhanced_rec['explanation'] = enhanced_explanation

                enhanced_recommendations.append(enhanced_rec)

            # 按增強總分重新排序
            enhanced_recommendations.sort(key=lambda x: x['overall_score'], reverse=True)

            # 更新排名
            for i, rec in enumerate(enhanced_recommendations):
                rec['rank'] = i + 1

            print(f"Applied intelligent trait matching with average bonus: {sum(r['intelligence_bonus'] for r in enhanced_recommendations) / len(enhanced_recommendations):.3f}")

            return enhanced_recommendations

        except Exception as e:
            print(f"Error in intelligent trait matching: {str(e)}")
            # 如果特徵匹配失敗,返回原始推薦
            return recommendations

    def _extract_enhanced_lifestyle_keywords(self, user_input: str) -> Dict[str, List[str]]:
        """提取增強的生活方式關鍵字(用於智能特徵匹配)"""
        keywords = {
            'intelligence_preference': [],
            'grooming_preference': [],
            'temperament_preference': [],
            'experience_level': [],
            'lifespan_preference': []
        }

        text = user_input.lower()

        # 智力偏好檢測
        smart_terms = ['smart', 'intelligent', 'clever', 'bright', 'quick learner', 'easy to train', 'trainable', 'genius', 'brilliant']
        independent_terms = ['independent', 'stubborn', 'strong-willed', 'less trainable', 'thinks for themselves']

        if any(term in text for term in smart_terms):
            keywords['intelligence_preference'].append('high')
        if any(term in text for term in independent_terms):
            keywords['intelligence_preference'].append('independent')

        # 美容偏好檢測
        low_grooming_terms = ['low grooming', 'minimal grooming', 'easy care', 'wash and wear', 'no grooming', 'simple coat']
        high_grooming_terms = ['high grooming', 'professional grooming', 'lots of care', 'high maintenance coat', 'daily brushing', 'regular grooming']

        if any(term in text for term in low_grooming_terms):
            keywords['grooming_preference'].append('low')
        if any(term in text for term in high_grooming_terms):
            keywords['grooming_preference'].append('high')

        # 氣質偏好檢測
        gentle_terms = ['gentle', 'calm', 'peaceful', 'laid back', 'chill', 'mellow', 'docile']
        playful_terms = ['playful', 'energetic', 'fun', 'active personality', 'lively', 'spirited', 'bouncy']
        protective_terms = ['protective', 'guard', 'watchdog', 'alert', 'vigilant', 'defensive']
        friendly_terms = ['friendly', 'social', 'outgoing', 'loves people', 'sociable', 'gregarious']

        if any(term in text for term in gentle_terms):
            keywords['temperament_preference'].append('gentle')
        if any(term in text for term in playful_terms):
            keywords['temperament_preference'].append('playful')
        if any(term in text for term in protective_terms):
            keywords['temperament_preference'].append('protective')
        if any(term in text for term in friendly_terms):
            keywords['temperament_preference'].append('friendly')

        # 經驗水平檢測
        beginner_terms = ['first time', 'beginner', 'new to dogs', 'never had', 'novice', 'inexperienced']
        advanced_terms = ['experienced', 'advanced', 'dog expert', 'many dogs before', 'professional', 'seasoned']

        if any(term in text for term in beginner_terms):
            keywords['experience_level'].append('beginner')
        if any(term in text for term in advanced_terms):
            keywords['experience_level'].append('advanced')

        # 壽命偏好檢測
        long_lived_terms = ['long lived', 'long lifespan', 'live long', 'many years', '15+ years', 'longevity']
        healthy_terms = ['healthy breed', 'few health issues', 'robust', 'hardy', 'strong constitution']

        if any(term in text for term in long_lived_terms):
            keywords['lifespan_preference'].append('long')
        if any(term in text for term in healthy_terms):
            keywords['lifespan_preference'].append('healthy')

        return keywords

    def calculate_enhanced_matching_score(self, breed: str, breed_info: dict, user_description: str, base_similarity: float) -> dict:
        """計算增強的匹配分數,基於用戶描述和品種特性"""
        try:
            user_desc = user_description.lower()

            # 分析用戶需求
            space_requirements = self._analyze_space_requirements(user_desc)
            exercise_requirements = self._analyze_exercise_requirements(user_desc)
            noise_requirements = self._analyze_noise_requirements(user_desc)
            size_requirements = self._analyze_size_requirements(user_desc)
            family_requirements = self._analyze_family_requirements(user_desc)

            # 獲取品種特性
            breed_size = breed_info.get('Size', '').lower()
            breed_exercise = breed_info.get('Exercise Needs', '').lower()
            breed_noise = breed_noise_info.get(breed, {}).get('noise_level', 'moderate').lower()
            breed_temperament = breed_info.get('Temperament', '').lower()
            breed_good_with_children = breed_info.get('Good with Children', '').lower()

            # 計算各維度匹配分數
            dimension_scores = {}

            # 空間匹配 (30% 權重)
            space_score = self._calculate_space_compatibility(space_requirements, breed_size, breed_exercise)
            dimension_scores['space'] = space_score

            # 運動需求匹配 (25% 權重)
            exercise_score = self._calculate_exercise_compatibility(exercise_requirements, breed_exercise)
            dimension_scores['exercise'] = exercise_score

            # 噪音匹配 (20% 權重)
            noise_score = self._calculate_noise_compatibility(noise_requirements, breed_noise)
            dimension_scores['noise'] = noise_score

            # 體型匹配 (15% 權重)
            size_score = self._calculate_size_compatibility(size_requirements, breed_size)
            dimension_scores['grooming'] = min(0.9, base_similarity + 0.1)  # 美容需求基於語意相似度

            # 家庭相容性 (10% 權重)
            family_score = self._calculate_family_compatibility(family_requirements, breed_good_with_children, breed_temperament)
            dimension_scores['family'] = family_score
            dimension_scores['experience'] = min(0.9, base_similarity + 0.05)  # 經驗需求基於語意相似度

            # 應用硬約束過濾
            constraint_penalty = self._apply_hard_constraints_enhanced(user_desc, breed_info)

            # 計算加權總分 - 精確化維度權重配置
            # 根據指導建議重新平衡維度權重
            weighted_score = (
                space_score * 0.30 +      # 空間相容性(降低5%)
                exercise_score * 0.28 +   # 運動需求匹配(降低2%)
                noise_score * 0.18 +      # 噪音控制(提升3%)
                family_score * 0.12 +     # 家庭相容性(提升2%)
                size_score * 0.08 +       # 體型匹配(降低2%)
                min(0.9, base_similarity + 0.1) * 0.04  # 護理需求(新增獨立權重)
            )

            # 優化完美匹配獎勵機制 - 降低觸發門檻並增加層次
            perfect_match_bonus = 0.0
            if space_score >= 0.88 and exercise_score >= 0.88 and noise_score >= 0.85:
                perfect_match_bonus = 0.08  # 卓越匹配獎勵
            elif space_score >= 0.82 and exercise_score >= 0.82 and noise_score >= 0.75:
                perfect_match_bonus = 0.04  # 優秀匹配獎勵
            elif space_score >= 0.75 and exercise_score >= 0.75:
                perfect_match_bonus = 0.02  # 良好匹配獎勵

            # 結合語意相似度與維度匹配 - 調整為75%維度匹配 25%語義相似度
            base_combined_score = (weighted_score * 0.75 + base_similarity * 0.25) + perfect_match_bonus

            # 應用漸進式約束懲罰,但確保基礎分數保障
            raw_final_score = base_combined_score + constraint_penalty

            # 實施動態分數保障機制 - 提升至40-42%基礎分數
            # 根據品種特性動態調整基礎分數
            base_guaranteed_score = 0.42  # 提升基礎保障分數

            # 特殊品種基礎分數調整
            high_adaptability_breeds = ['French_Bulldog', 'Pug', 'Golden_Retriever', 'Labrador_Retriever']
            if any(breed in breed for breed in high_adaptability_breeds):
                base_guaranteed_score = 0.45  # 高適應性品種更高基礎分數

            # 動態分數分佈優化
            if raw_final_score >= base_guaranteed_score:
                # 對於高分品種,實施適度壓縮避免過度集中
                if raw_final_score > 0.85:
                    compression_factor = 0.92  # 輕度壓縮高分
                    final_score = 0.85 + (raw_final_score - 0.85) * compression_factor
                else:
                    final_score = raw_final_score
                final_score = min(0.93, final_score)  # 降低最高分數限制
            else:
                # 對於低分品種,使用改進的保障機制
                normalized_raw_score = max(0.15, raw_final_score)
                # 基礎保障75% + 實際計算25%,保持一定區分度
                final_score = base_guaranteed_score * 0.75 + normalized_raw_score * 0.25
                final_score = max(base_guaranteed_score, min(0.93, final_score))

            lifestyle_bonus = max(0.0, weighted_score - base_similarity)

            return {
                'final_score': final_score,
                'weighted_score': weighted_score,
                'lifestyle_bonus': lifestyle_bonus,
                'dimension_scores': dimension_scores,
                'constraint_penalty': constraint_penalty
            }

        except Exception as e:
            print(f"Error in enhanced matching calculation for {breed}: {str(e)}")
            return {
                'final_score': base_similarity,
                'weighted_score': base_similarity,
                'lifestyle_bonus': 0.0,
                'dimension_scores': {
                    'space': base_similarity * 0.9,
                    'exercise': base_similarity * 0.85,
                    'grooming': base_similarity * 0.8,
                    'experience': base_similarity * 0.75,
                    'noise': base_similarity * 0.7,
                    'family': base_similarity * 0.65
                },
                'constraint_penalty': 0.0
            }

    def _analyze_space_requirements(self, user_desc: str) -> dict:
        """分析空間需求 - 增強中等活動量識別"""
        requirements = {'type': 'unknown', 'size': 'medium', 'importance': 0.5}

        if any(word in user_desc for word in ['apartment', 'small apartment', 'small space', 'condo', 'flat']):
            requirements['type'] = 'apartment'
            requirements['size'] = 'small'
            requirements['importance'] = 0.95  # 提高重要性
        elif any(word in user_desc for word in ['medium-sized house', 'medium house', 'townhouse']):
            requirements['type'] = 'medium_house'
            requirements['size'] = 'medium'
            requirements['importance'] = 0.8  # 中等活動量用戶的特殊標記
        elif any(word in user_desc for word in ['large house', 'big house', 'yard', 'garden', 'large space', 'backyard']):
            requirements['type'] = 'house'
            requirements['size'] = 'large'
            requirements['importance'] = 0.7

        return requirements

    def _analyze_exercise_requirements(self, user_desc: str) -> dict:
        """分析運動需求 - 增強中等活動量識別"""
        requirements = {'level': 'moderate', 'importance': 0.5}

        # 低運動量識別
        if any(word in user_desc for word in ["don't exercise", "don't exercise much", "low exercise", "minimal", "lazy", "not active"]):
            requirements['level'] = 'low'
            requirements['importance'] = 0.95
        # 中等運動量的精確識別
        elif any(phrase in user_desc for phrase in ['30 minutes', 'half hour', 'moderate', 'balanced', 'walk about']):
            if 'walk' in user_desc or 'daily' in user_desc:
                requirements['level'] = 'moderate'
                requirements['importance'] = 0.85  # 中等活動量的特殊標記
        # 高運動量識別
        elif any(word in user_desc for word in ['active', 'hiking', 'outdoor activities', 'running', 'outdoors', 'love hiking']):
            requirements['level'] = 'high'
            requirements['importance'] = 0.9

        return requirements

    def _analyze_noise_requirements(self, user_desc: str) -> dict:
        """分析噪音需求"""
        requirements = {'tolerance': 'medium', 'importance': 0.5}

        if any(word in user_desc for word in ['quiet', 'no bark', "won't bark", "doesn't bark", 'silent', 'peaceful']):
            requirements['tolerance'] = 'low'
            requirements['importance'] = 0.9
        elif any(word in user_desc for word in ['loud', 'barking ok', 'noise ok']):
            requirements['tolerance'] = 'high'
            requirements['importance'] = 0.7

        return requirements

    def _analyze_size_requirements(self, user_desc: str) -> dict:
        """分析體型需求"""
        requirements = {'preferred': 'any', 'importance': 0.5}

        if any(word in user_desc for word in ['small', 'tiny', 'little', 'lap dog', 'compact']):
            requirements['preferred'] = 'small'
            requirements['importance'] = 0.8
        elif any(word in user_desc for word in ['large', 'big', 'giant']):
            requirements['preferred'] = 'large'
            requirements['importance'] = 0.8

        return requirements

    def _analyze_family_requirements(self, user_desc: str) -> dict:
        """分析家庭需求"""
        requirements = {'children': False, 'importance': 0.3}

        if any(word in user_desc for word in ['children', 'kids', 'family', 'child']):
            requirements['children'] = True
            requirements['importance'] = 0.8

        return requirements

    def _calculate_space_compatibility(self, space_req: dict, breed_size: str, breed_exercise: str) -> float:
        """計算空間相容性分數 - 增強中等活動量處理"""
        if space_req['type'] == 'apartment':
            if 'small' in breed_size or 'toy' in breed_size:
                base_score = 0.95
            elif 'medium' in breed_size:
                if 'low' in breed_exercise:
                    base_score = 0.75
                else:
                    base_score = 0.45  # 降低中型犬在公寓的分數
            elif 'large' in breed_size:
                base_score = 0.05  # 大型犬極度不適合公寓
            elif 'giant' in breed_size:
                base_score = 0.01  # 超大型犬完全不適合公寓
            else:
                base_score = 0.7
        elif space_req['type'] == 'medium_house':
            # 中型房屋的特殊處理 - 適合中等活動量用戶
            if 'small' in breed_size or 'toy' in breed_size:
                base_score = 0.9
            elif 'medium' in breed_size:
                base_score = 0.95  # 中型犬在中型房屋很適合
            elif 'large' in breed_size:
                if 'moderate' in breed_exercise or 'low' in breed_exercise:
                    base_score = 0.8  # 低運動量大型犬還可以
                else:
                    base_score = 0.6  # 高運動量大型犬不太適合
            elif 'giant' in breed_size:
                base_score = 0.3  # 超大型犬在中型房屋不太適合
            else:
                base_score = 0.85
        else:
            # 大型房屋的情況
            if 'small' in breed_size or 'toy' in breed_size:
                base_score = 0.85
            elif 'medium' in breed_size:
                base_score = 0.9
            elif 'large' in breed_size or 'giant' in breed_size:
                base_score = 0.95
            else:
                base_score = 0.8

        return min(0.95, base_score)

    def _calculate_exercise_compatibility(self, exercise_req: dict, breed_exercise: str) -> float:
        """計算運動需求相容性分數 - 增強中等活動量處理"""
        if exercise_req['level'] == 'low':
            if 'low' in breed_exercise or 'minimal' in breed_exercise:
                return 0.95
            elif 'moderate' in breed_exercise:
                return 0.5  # 降低不匹配分數
            elif 'high' in breed_exercise:
                return 0.1  # 進一步降低高運動需求的匹配
            else:
                return 0.7
        elif exercise_req['level'] == 'high':
            if 'high' in breed_exercise:
                return 0.95
            elif 'moderate' in breed_exercise:
                return 0.8
            elif 'low' in breed_exercise:
                return 0.6
            else:
                return 0.7
        else:  # moderate - 中等活動量的精確處理
            if 'moderate' in breed_exercise:
                return 0.95  # 完美匹配
            elif 'low' in breed_exercise:
                return 0.85  # 低運動需求的品種對中等活動量用戶也不錯
            elif 'high' in breed_exercise:
                return 0.5  # 中等活動量用戶不太適合高運動需求品種
            else:
                return 0.75

        return 0.6

    def _calculate_noise_compatibility(self, noise_req: dict, breed_noise: str) -> float:
        """計算噪音相容性分數,更好處理複合等級"""
        breed_noise_lower = breed_noise.lower()

        if noise_req['tolerance'] == 'low':
            if 'low' in breed_noise_lower and 'moderate' not in breed_noise_lower:
                return 0.95  # 純低噪音
            elif 'low-moderate' in breed_noise_lower or 'low to moderate' in breed_noise_lower:
                return 0.8   # 低到中等噪音,還可接受
            elif breed_noise_lower in ['moderate']:
                return 0.4   # 中等噪音有些問題
            elif 'high' in breed_noise_lower:
                return 0.1   # 高噪音不適合
            else:
                return 0.6   # 未知噪音水平,保守估計
        elif noise_req['tolerance'] == 'high':
            if 'high' in breed_noise_lower:
                return 0.9
            elif 'moderate' in breed_noise_lower:
                return 0.85
            elif 'low' in breed_noise_lower:
                return 0.8   # 安靜犬對高容忍度的人也很好
            else:
                return 0.8
        else:  # moderate tolerance
            if 'moderate' in breed_noise_lower:
                return 0.9
            elif 'low' in breed_noise_lower:
                return 0.85
            elif 'high' in breed_noise_lower:
                return 0.6
            else:
                return 0.75

        return 0.7

    def _calculate_size_compatibility(self, size_req: dict, breed_size: str) -> float:
        """計算體型相容性分數"""
        if size_req['preferred'] == 'small':
            if any(word in breed_size for word in ['small', 'toy', 'tiny']):
                return 0.9
            elif 'medium' in breed_size:
                return 0.6
            else:
                return 0.3
        elif size_req['preferred'] == 'large':
            if any(word in breed_size for word in ['large', 'giant']):
                return 0.9
            elif 'medium' in breed_size:
                return 0.7
            else:
                return 0.4

        return 0.7  # 無特別偏好

    def _calculate_family_compatibility(self, family_req: dict, good_with_children: str, temperament: str) -> float:
        """計算家庭相容性分數"""
        if family_req['children']:
            if 'yes' in good_with_children.lower():
                return 0.9
            elif any(word in temperament for word in ['gentle', 'patient', 'friendly']):
                return 0.8
            elif 'no' in good_with_children.lower():
                return 0.2
            else:
                return 0.6

        return 0.7

    def _apply_hard_constraints_enhanced(self, user_desc: str, breed_info: dict) -> float:
        """應用品種特性感知的動態懲罰機制"""
        penalty = 0.0

        # 建立懲罰衰減係數和補償機制
        penalty_decay_factor = 0.7
        breed_adaptability_bonus = 0.0
        breed_size = breed_info.get('Size', '').lower()
        breed_exercise = breed_info.get('Exercise Needs', '').lower()
        breed_name = breed_info.get('Breed', '').replace(' ', '_')

        # 公寓空間約束 - 品種特性感知懲罰機制
        if 'apartment' in user_desc or 'small apartment' in user_desc:
            if 'giant' in breed_size:
                base_penalty = -0.35  # 減少基礎懲罰
                # 特定品種適應性補償
                adaptable_giants = ['Mastiff', 'Great Dane']  # 相對安靜的巨型犬
                if any(adapt_breed in breed_name for adapt_breed in adaptable_giants):
                    breed_adaptability_bonus += 0.08
                penalty += base_penalty * penalty_decay_factor
            elif 'large' in breed_size:
                base_penalty = -0.25  # 減少大型犬懲罰
                # 適合公寓的大型犬補償
                apartment_friendly_large = ['Greyhound', 'Great_Dane']
                if any(apt_breed in breed_name for apt_breed in apartment_friendly_large):
                    breed_adaptability_bonus += 0.06
                penalty += base_penalty * penalty_decay_factor
            elif 'medium' in breed_size and 'high' in breed_exercise:
                penalty += -0.15 * penalty_decay_factor  # 進一步減少懲罰

        # 運動需求不匹配 - 品種特性感知懲罰機制
        if any(phrase in user_desc for phrase in ["don't exercise", "not active", "low exercise", "don't exercise much"]):
            if 'high' in breed_exercise:
                base_penalty = -0.28  # 減少基礎懲罰
                # 低維護高運動犬種補償
                adaptable_high_energy = ['Greyhound', 'Whippet']  # 運動爆發型,平時安靜
                if any(adapt_breed in breed_name for adapt_breed in adaptable_high_energy):
                    breed_adaptability_bonus += 0.10
                penalty += base_penalty * penalty_decay_factor
            elif 'moderate' in breed_exercise:
                penalty += -0.08 * penalty_decay_factor  # 進一步減少懲罰

        # 噪音控制需求不匹配 - 品種特性感知懲罰機制
        if any(phrase in user_desc for phrase in ['quiet', "won't bark", "doesn't bark", "silent"]):
            breed_noise = breed_noise_info.get(breed_name, {}).get('noise_level', 'moderate').lower()
            if 'high' in breed_noise:
                base_penalty = -0.18  # 減少基礎懲罰
                # 訓練性良好的高噪音品種補償
                trainable_vocal_breeds = ['German_Shepherd', 'Golden_Retriever']
                if any(train_breed in breed_name for train_breed in trainable_vocal_breeds):
                    breed_adaptability_bonus += 0.05
                penalty += base_penalty * penalty_decay_factor
            elif 'moderate' in breed_noise and 'low' not in breed_noise:
                penalty += -0.05 * penalty_decay_factor

        # 體型偏好不匹配 - 漸進式懲罰
        if any(phrase in user_desc for phrase in ['small', 'tiny', 'little']):
            if 'giant' in breed_size:
                penalty -= 0.35  # 超大型犬懲罰
            elif 'large' in breed_size:
                penalty -= 0.20  # 大型犬懲罰

        # 中等活動量用戶的特殊約束處理 - 漸進式懲罰
        moderate_activity_terms = ['30 minutes', 'half hour', 'moderate', 'balanced', 'medium-sized house']
        if any(term in user_desc for term in moderate_activity_terms):
            # 超大型犬對中等活動量用戶的適度懲罰
            giant_breeds = ['Saint Bernard', 'Tibetan Mastiff', 'Great Dane', 'Mastiff', 'Newfoundland']
            if any(giant in breed_name for giant in giant_breeds) or 'giant' in breed_size:
                penalty -= 0.35  # 適度懲罰,不完全排除

            # 中型房屋 + 超大型犬的額外考量
            if 'medium-sized house' in user_desc and any(giant in breed_name for giant in giant_breeds):
                if not any(high_activity in user_desc for high_activity in ['hiking', 'running', 'active', 'outdoor activities']):
                    penalty -= 0.15  # 輕度額外懲罰

        # 30分鐘散步對極高運動需求品種的懲罰
        if any(term in user_desc for term in ['30 minutes', 'half hour']) and 'walk' in user_desc:
            high_energy_breeds = ['Siberian Husky', 'Border Collie', 'Jack Russell Terrier', 'Weimaraner']
            if any(he_breed in breed_name for he_breed in high_energy_breeds) and 'high' in breed_exercise:
                penalty -= 0.25  # 適度懲罰極高運動需求品種

        # 添加特殊品種適應性補償機制
        # 對於邊界適配品種,給予適度補償
        boundary_adaptable_breeds = {
            'Italian_Greyhound': 0.08,  # 安靜、低維護的小型犬
            'Boston_Bull': 0.06,        # 適應性強的小型犬
            'Havanese': 0.05,           # 友好適應的小型犬
            'Silky_terrier': 0.04,      # 安靜的玩具犬
            'Basset': 0.07              # 低能量但友好的中型犬
        }

        if breed_name in boundary_adaptable_breeds:
            breed_adaptability_bonus += boundary_adaptable_breeds[breed_name]

        # 應用品種適應性補償並設置懲罰上限
        final_penalty = penalty + breed_adaptability_bonus
        # 限制最大懲罰,避免單一約束主導評分
        final_penalty = max(-0.4, final_penalty)

        return final_penalty

    def get_breed_characteristics_enhanced(self, breed: str) -> Dict[str, Any]:
        """獲取品種特徵"""
        breed_info = get_dog_description(breed)
        if not breed_info:
            return {}

        characteristics = {
            'size': breed_info.get('Size', 'Unknown'),
            'temperament': breed_info.get('Temperament', ''),
            'exercise_needs': breed_info.get('Exercise Needs', 'Moderate'),
            'grooming_needs': breed_info.get('Grooming Needs', 'Moderate'),
            'good_with_children': breed_info.get('Good with Children', 'Unknown'),
            'lifespan': breed_info.get('Lifespan', '10-12 years'),
            'description': breed_info.get('Description', '')
        }

        # 添加噪音資訊
        noise_info = breed_noise_info.get(breed, {})
        characteristics['noise_level'] = noise_info.get('noise_level', 'moderate')

        return characteristics

    def get_breed_info_from_standardized(self, standardized_info) -> Dict[str, Any]:
        """將標準化品種信息轉換為字典格式"""
        try:
            size_map = {1: 'Tiny', 2: 'Small', 3: 'Medium', 4: 'Large', 5: 'Giant'}
            exercise_map = {1: 'Low', 2: 'Moderate', 3: 'High', 4: 'Very High'}
            care_map = {1: 'Low', 2: 'Moderate', 3: 'High'}

            return {
                'Size': size_map.get(standardized_info.size_category, 'Medium'),
                'Exercise Needs': exercise_map.get(standardized_info.exercise_level, 'Moderate'),
                'Grooming Needs': care_map.get(standardized_info.care_complexity, 'Moderate'),
                'Good with Children': 'Yes' if standardized_info.child_compatibility >= 0.8 else
                                     'No' if standardized_info.child_compatibility <= 0.2 else 'Unknown',
                'Temperament': 'Varies by individual',
                'Lifespan': '10-12 years',
                'Description': f'A {size_map.get(standardized_info.size_category, "medium")} sized breed'
            }
        except Exception as e:
            print(f"Error converting standardized info: {str(e)}")
            return {}

    def get_fallback_recommendations(self, top_k: int = 15) -> List[Dict[str, Any]]:
        """當增強系統失敗時獲取備用推薦"""
        try:
            safe_breeds = [
                ('Labrador Retriever', 0.85),
                ('Golden Retriever', 0.82),
                ('Cavalier King Charles Spaniel', 0.80),
                ('French Bulldog', 0.78),
                ('Boston Terrier', 0.76),
                ('Bichon Frise', 0.74),
                ('Pug', 0.72),
                ('Cocker Spaniel', 0.70)
            ]

            recommendations = []
            for i, (breed, score) in enumerate(safe_breeds[:top_k]):
                breed_info = get_dog_description(breed.replace(' ', '_')) or {}

                recommendation = {
                    'breed': breed,
                    'rank': i + 1,
                    'overall_score': score,
                    'final_score': score,
                    'semantic_score': score * 0.8,
                    'comparative_bonus': 0.0,
                    'lifestyle_bonus': 0.0,
                    'size': breed_info.get('Size', 'Unknown'),
                    'temperament': breed_info.get('Temperament', ''),
                    'exercise_needs': breed_info.get('Exercise Needs', 'Moderate'),
                    'grooming_needs': breed_info.get('Grooming Needs', 'Moderate'),
                    'good_with_children': breed_info.get('Good with Children', 'Yes'),
                    'lifespan': breed_info.get('Lifespan', '10-12 years'),
                    'description': breed_info.get('Description', ''),
                    'search_type': 'fallback'
                }
                recommendations.append(recommendation)

            return recommendations

        except Exception as e:
            print(f"Error generating fallback recommendations: {str(e)}")
            return []