# Copyright (c) 2025 Patrick Motsch # All rights reserved. """ Chatbot constants and helper functions. """ import logging from typing import Optional from modules.datamodels.datamodelAi import AiCallRequest, AiCallOptions, OperationTypeEnum, PriorityEnum, ProcessingModeEnum logger = logging.getLogger(__name__) async def generate_conversation_name( services, prompt: str, user_language: Optional[str] = None ) -> str: """ Generate a conversation name from the user's prompt using AI. Creates a concise, informative summary name in German based on the user input. Args: services: Services object with AI service prompt: User's input prompt (always in German) user_language: User's language preference (not used, always German) Returns: A short, informative conversation name in German """ if not prompt or not prompt.strip(): return "Neue Unterhaltung" try: # Check if AI service is available if not hasattr(services, 'ai') or services.ai is None: logger.warning("AI service not available, generating name from prompt") return generate_name_from_prompt(prompt) # Ensure AI service is initialized before use await services.ai.ensureAiObjectsInitialized() # Create AI prompt - very explicit that answer must be in German ai_prompt = f"""Du bist ein deutscher Assistent. Der Benutzer hat folgende Anfrage auf Deutsch gestellt: "{prompt.strip()}" Erstelle einen kurzen, zusammenfassenden Titel für diese Unterhaltung. Der Titel muss: - Auf Deutsch sein (KEIN Englisch!) - Maximal 50 Zeichen lang sein - Das Hauptthema zusammenfassen - Informativ sein Beispiele für gute deutsche Titel: - "LED-Artikel Suche" - "Lagerbestandsabfrage" - "Produktinformationen" - "Artikel-Suche" Antworte NUR mit dem deutschen Titel, ohne Anführungszeichen oder Erklärungen.""" # Create AI request request = AiCallRequest( prompt=ai_prompt, context="", options=AiCallOptions( operationType=OperationTypeEnum.DATA_GENERATE, priority=PriorityEnum.SPEED, processingMode=ProcessingModeEnum.BASIC, compressPrompt=False, compressContext=False, temperature=0.3 # Lower temperature for more consistent German output ) ) # Call AI service logger.info(f"Calling AI to generate conversation name for prompt: {prompt[:50]}...") response = await services.ai.callAi(request) if not response or not hasattr(response, 'content') or not response.content: logger.warning("AI response invalid, generating name from prompt") return generate_name_from_prompt(prompt) logger.info(f"AI response received: {response.content[:100]}...") # Clean up the AI response name = str(response.content).strip() name = name.strip('"\'') # Remove markdown code blocks if present if name.startswith('```'): lines = name.split('\n') if len(lines) > 1: name = '\n'.join(lines[1:-1]) if lines[-1].strip() == '```' else '\n'.join(lines[1:]) # Remove newlines and extra spaces name = " ".join(name.split()) # Check if name contains English words - if so, generate from prompt instead name_lower = name.lower() english_words = ["search", "find", "show", "display", "query", "article", "product", "item", "led articles", "product search"] if any(word in name_lower for word in english_words): logger.warning(f"AI generated English name '{name}', generating from prompt instead") return generate_name_from_prompt(prompt) # Limit to 50 characters if len(name) > 50: name = name[:47] + "..." # If we got a valid name, return it if name and len(name) >= 3: logger.info(f"Successfully generated conversation name via AI: '{name}'") return name else: logger.warning(f"Generated name is too short: '{name}', generating from prompt") return generate_name_from_prompt(prompt) except Exception as e: logger.error(f"Error generating conversation name with AI: {e}", exc_info=True) return generate_name_from_prompt(prompt) def generate_name_from_prompt(prompt: str) -> str: """ Generate a conversation name directly from the German prompt. Creates a concise title by extracting key words and formatting them. Args: prompt: User's input prompt in German Returns: A short conversation name in German """ if not prompt or not prompt.strip(): return "Neue Unterhaltung" # Clean up the prompt name = prompt.strip() # Remove newlines and extra spaces name = " ".join(name.split()) # Remove common question words and phrases question_words = ["wie", "was", "wo", "wann", "wer", "welche", "welcher", "welches"] words = name.split() filtered_words = [w for w in words if w.lower() not in question_words] if filtered_words: name = " ".join(filtered_words) # Capitalize first letter if name: name = name[0].upper() + name[1:] if len(name) > 1 else name.upper() # Limit to 50 characters if len(name) > 50: # Try to cut at word boundary truncated = name[:47] last_space = truncated.rfind(' ') if last_space > 20: # Only cut at word boundary if reasonable name = truncated[:last_space] + "..." else: name = truncated + "..." # If name is empty or too short, use default if not name or len(name) < 3: return "Neue Unterhaltung" return name