1111 CONFUSION_PATTERNS , TOPIC_KEYWORDS , TOPIC_REQUEST_PATTERNS ,
1212 PRACTICE_REQUEST_PATTERNS , HELP_PATTERNS , TOPIC_MATCH_THRESHOLD ,
1313 BEGINNER_PATTERNS , QUESTION_PATTERNS , NEGATION_WORDS ,
14- UNCERTAIN_RESPONSES , REPEAT_REQUEST_PATTERNS , CLARIFICATION_PATTERNS ,
14+ UNCERTAIN_RESPONSES , REPEAT_REQUEST_PATTERNS , CLARIFICATION_PATTERNS ,
15+ DEFER_PATTERNS , # ADD THIS
1516 COMMON_SINGLE_WORDS , generic_python_patterns
1617)
1718
3132
3233YES_EXAMPLES_SET = {p .lower () for p in YES_EXAMPLES_RESPONSES }
3334NO_EXAMPLES_SET = {p .lower () for p in NO_EXAMPLES_RESPONSES }
34-
35+
36+ DEFER_SET = {p .lower () for p in DEFER_PATTERNS }
37+
3538# Single-word negation list (for fast lookup)
3639SINGLE_WORD_NEGATIONS = {w for w in NEGATION_WORDS if ' ' not in w }
3740MULTI_WORD_NEGATIONS = {p for p in NEGATION_WORDS if ' ' in p }
@@ -47,33 +50,40 @@ def get_global_valid_input(prompt):
4750 - If 'no' or 'exit' is the highest score and above threshold, returns those accordingly.
4851 - If no clear match, prompts user to try again.
4952 """
50-
53+
5154 while True :
5255 raw_input = input (prompt ).strip ().lower ()
53-
56+
5457 # Exact matches (fast path)
5558 if raw_input in YES_SET :
5659 return 'yes'
5760 if raw_input in NO_SET :
5861 return 'no'
5962 if raw_input in EXIT_SET :
6063 return 'exit'
61-
64+ if raw_input in DEFER_SET :
65+ return 'defer'
66+
6267 # Extract intent keywords from user input once, reused across all comparisons
6368 w1 = _extract_keywords (raw_input )
64-
65- # Max similarity scores for yes/no/exit using smart_validators
69+
70+ # Max similarity scores for yes/no/exit/defer using smart_validators
6671 best_yes = max ((smart_validators (raw_input , phrase , w1 , _extract_keywords (phrase )) for phrase in YES_SET ), default = 0.0 )
6772 best_no = max ((smart_validators (raw_input , phrase , w1 , _extract_keywords (phrase )) for phrase in NO_SET ), default = 0.0 )
6873 best_exit = max ((smart_validators (raw_input , phrase , w1 , _extract_keywords (phrase )) for phrase in EXIT_SET ), default = 0.0 )
69-
74+ best_defer = max ((smart_validators (raw_input , phrase , w1 , _extract_keywords (phrase )) for phrase in DEFER_SET ), default = 0.0 )
75+
7076 THRESHOLD = 0.75
7177
7278 words = set (raw_input .split ())
7379 user_negated = any (w in words for w in SINGLE_WORD_NEGATIONS ) or any (
7480 phrase in raw_input for phrase in MULTI_WORD_NEGATIONS
7581 )
7682
83+ # Check defer first (highest priority for deferral phrases)
84+ if best_defer >= THRESHOLD and best_defer > best_yes and best_defer > best_no and best_defer > best_exit :
85+ return 'defer'
86+
7787 if best_yes >= THRESHOLD and best_no >= THRESHOLD and best_yes == best_no :
7888 if user_negated :
7989 return 'no'
@@ -89,7 +99,7 @@ def get_global_valid_input(prompt):
8999
90100 if best_exit >= THRESHOLD and best_exit > best_yes and best_exit > best_no :
91101 return 'exit'
92-
102+
93103 print ("🤔 I didn't quite get that. Please answer with 'yes', 'no', or 'exit'." )
94104
95105# ---- Specialized validation for menu choice input -------
@@ -441,11 +451,15 @@ def check_topic_request(user_text):
441451 if any (phrase in user_input_lower for phrase in UNCERTAIN_RESPONSES ):
442452 record ('uncertain' , 0.75 )
443453
444- # Scorer 13: Repeat request (say again, repeat that, etc.)
454+ # Scorer 13: Defer/Pause request (afk, brb, not now, pause, busy, maybe, etc.)
455+ if any (phrase in user_input_lower for phrase in DEFER_PATTERNS ):
456+ record ('defer' , 0.85 )
457+
458+ # Scorer 14: Repeat request (say again, repeat that, etc.)
445459 if any (phrase in user_input_lower for phrase in REPEAT_REQUEST_PATTERNS ):
446460 record ('repeat_request' , 0.85 )
447461
448- # Scorer 14 : Clarification request (define, explain more, etc.)
462+ # Scorer 15 : Clarification request (define, explain more, etc.)
449463 if any (phrase in user_input_lower for phrase in CLARIFICATION_PATTERNS ):
450464 record ('clarification' , 0.8 )
451465
@@ -472,7 +486,7 @@ def check_topic_request(user_text):
472486 del scores [social ]
473487
474488 # ---- Intent prioritization: prefer conversation intents over topic requests ----
475- CONVERSATION_INTENTS = {'greeting' , 'farewell' , 'gratitude' , 'confusion' , 'clarification' }
489+ CONVERSATION_INTENTS = {'greeting' , 'farewell' , 'gratitude' , 'confusion' , 'clarification' , 'defer' }
476490 if 'topic_request' in scores and CONVERSATION_INTENTS & scores .keys ():
477491
478492 # If both topic_request and conversation intents fired, prefer conversation
@@ -482,7 +496,7 @@ def check_topic_request(user_text):
482496 break
483497
484498 # ---- Additional prioritization: prefer gratitude/clarification/general_question over topic_request even if lower confidence ----
485- HIGH_PRIORITY_INTENTS = {'gratitude' , 'clarification' , 'general_question' }
499+ HIGH_PRIORITY_INTENTS = {'gratitude' , 'clarification' , 'general_question' , 'defer' }
486500 if 'topic_request' in scores and HIGH_PRIORITY_INTENTS & scores .keys ():
487501
488502 # Always prefer these intents over topic_request
0 commit comments