""" Unified Tone System - Ensures consistent personality across all agents Makes the AI feel like ONE knowledgeable assistant, not multiple people """ class UnifiedTone: """ Provides consistent tone and personality across all agents The AI is ONE medical professional with multiple specialties """ # Base personality - applies to ALL agents BASE_PERSONALITY = """ Bạn là một trợ lý sức khỏe AI thông minh và đa năng. QUAN TRỌNG - Tính nhất quán: - Bạn là MỘT NGƯỜI duy nhất với nhiều chuyên môn - KHÔNG tự giới thiệu là "chuyên gia dinh dưỡng" hay "huấn luyện viên" - Chỉ nói "Tôi sẽ tư vấn về [lĩnh vực]" khi cần - Giữ giọng điệu nhất quán xuyên suốt SMART GREETING - Câu đầu tiên: - Nếu user CHỈ chào (vd: "chào", "hello") → Chào đầy đủ + giới thiệu - Nếu user VÀO THẲNG VẤN ĐỀ (vd: "đau lưng", "tôi muốn giảm cân") → Chào ngắn gọn + trả lời luôn * Ví dụ: "Chào bạn! Để giúp bạn về vấn đề đau lưng..." * KHÔNG greeting dài dòng khi user đã có vấn đề cụ thể Phong cách chung: - Thân thiện nhưng chuyên nghiệp - Rõ ràng, súc tích, dễ hiểu - Quan tâm nhưng không quá emotional - Thực tế, có căn cứ khoa học - Tránh emoji quá nhiều (chỉ dùng khi cần thiết) """ # Smooth transitions between specialties TRANSITION_PHRASES = { 'to_nutrition': "Về mặt dinh dưỡng, ", 'to_exercise': "Về vận động và tập luyện, ", 'to_symptom': "Về triệu chứng bạn đang gặp, ", 'to_mental': "Về mặt tinh thần và cảm xúc, ", 'general': "Dựa trên thông tin bạn cung cấp, " } @staticmethod def apply_unified_tone(response: str, agent_type: str) -> str: """ Apply unified tone to agent response Ensures consistency across all agents """ # Remove agent-specific introductions replacements = [ ("Tôi là chuyên gia dinh dưỡng", "Về dinh dưỡng"), ("Tôi là huấn luyện viên", "Về tập luyện"), ("Với tư cách bác sĩ", "Theo y học"), ("Là chuyên gia tâm lý", "Về mặt tâm lý"), ] for old, new in replacements: response = response.replace(old, new) # Moderate emoji usage if agent_type == 'symptom': # Remove excessive medical emojis response = response.replace('🏥', '').replace('💊', '') elif agent_type == 'exercise': # Keep motivational but not excessive response = response.replace('💪💪💪', '💪') response = response.replace('🔥🔥🔥', '🔥') return response @staticmethod def create_smooth_handoff(from_agent: str, to_agent: str, context: str) -> str: """ Create smooth transition between agent specialties Makes it feel like one person switching topics, not different people """ transition = UnifiedTone.TRANSITION_PHRASES.get(f'to_{to_agent}', '') # Don't say "I'm handing you over to..." # Instead, smoothly transition topics handoff_message = f"{context}\n\n{transition}" return handoff_message @staticmethod def check_information_before_asking(chat_history: list, field: str) -> bool: """ Check if information already exists in chat history Prevents duplicate questions across agents """ import re # Patterns to check for each field patterns = { 'age': r'\d+\s*tuổi', 'gender': r'(nam|nữ|male|female)', 'weight': r'\d+\s*kg', 'height': r'\d+\s*cm', 'goal': r'(giảm cân|tăng cân|tăng cơ|khỏe mạnh)', 'condition': r'(tiểu đường|huyết áp|tim mạch|dị ứng)' } if field not in patterns: return False # Check all messages in history for user_msg, bot_msg in chat_history: if user_msg and re.search(patterns[field], user_msg.lower()): return True # Information already provided if bot_msg and "không biết" in bot_msg.lower(): return True # User already declined to provide return False @staticmethod def generate_smart_question(needed_info: list, chat_history: list) -> str: """ Generate intelligent questions that don't repeat Groups multiple needs into one natural question """ # Filter out already known information actually_needed = [] for info in needed_info: if not UnifiedTone.check_information_before_asking(chat_history, info): actually_needed.append(info) if not actually_needed: return "" # Don't ask anything # Group related questions if len(actually_needed) > 2: # Ask for multiple things naturally return "Để tư vấn chính xác, bạn có thể cho tôi biết tuổi, giới tính, cân nặng và mục tiêu của bạn được không?" elif len(actually_needed) == 2: field_names = { 'age': 'tuổi', 'gender': 'giới tính', 'weight': 'cân nặng', 'height': 'chiều cao', 'goal': 'mục tiêu' } fields = ' và '.join([field_names.get(f, f) for f in actually_needed]) return f"Bạn có thể cho tôi biết {fields} của bạn không?" else: # Single question questions = { 'age': "Bạn bao nhiêu tuổi?", 'gender': "Giới tính của bạn là gì?", 'weight': "Cân nặng hiện tại của bạn là bao nhiêu?", 'height': "Chiều cao của bạn là bao nhiêu?", 'goal': "Mục tiêu sức khỏe của bạn là gì?" } return questions.get(actually_needed[0], "")