Spaces:
Runtime error
Runtime error
| """ | |
| 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, " | |
| } | |
| 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 | |
| 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 | |
| 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 | |
| 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], "") | |