From 9e1cff460a342a478841d62dd8a5c77cf843866f Mon Sep 17 00:00:00 2001 From: ValueOn AG Date: Sat, 18 Oct 2025 00:33:28 +0200 Subject: [PATCH] UI Communication fixed --- app.py | 4 +- .../processing/adaptive/intentAnalyzer.py | 44 +++++++------------ .../workflows/processing/core/taskPlanner.py | 24 ++-------- .../processing/shared/placeholderFactory.py | 26 +++++++++++ .../shared/promptGenerationTaskplan.py | 3 +- .../workflows/processing/workflowProcessor.py | 3 ++ 6 files changed, 51 insertions(+), 53 deletions(-) diff --git a/app.py b/app.py index fc29fe5b..c4b77472 100644 --- a/app.py +++ b/app.py @@ -422,5 +422,5 @@ app.include_router(voiceGoogleRouter) from modules.routes.routeSecurityAdmin import router as adminSecurityRouter app.include_router(adminSecurityRouter) -from modules.routes.routeChatbot import router as chatbotRouter -app.include_router(chatbotRouter) +# from modules.routes.routeChatbot import router as chatbotRouter +# app.include_router(chatbotRouter) diff --git a/modules/workflows/processing/adaptive/intentAnalyzer.py b/modules/workflows/processing/adaptive/intentAnalyzer.py index f5fd5616..b1512e18 100644 --- a/modules/workflows/processing/adaptive/intentAnalyzer.py +++ b/modules/workflows/processing/adaptive/intentAnalyzer.py @@ -39,6 +39,7 @@ Analyze the user's intent and determine: 2. What format they expect (raw data, formatted, structured, visual, etc.) 3. What quality requirements they have (accuracy, completeness, format) 4. What specific success criteria define completion +5. What language the user is communicating in (detect from the user request) CRITICAL: Respond with ONLY the JSON object below. Do not include any explanatory text, analysis, or other content before or after the JSON. @@ -52,6 +53,7 @@ CRITICAL: Respond with ONLY the JSON object below. Do not include any explanator "formatRequirement": "any|formatted|raw|structured" }}, "successCriteria": ["specific criterion 1", "specific criterion 2"], + "languageUserDetected": "en", "confidenceScore": 0.0-1.0 }} """ @@ -108,6 +110,18 @@ CRITICAL: Respond with ONLY the JSON object below. Do not include any explanator try: aiResult = json.loads(result) logger.info("AI intent analysis JSON parsed successfully") + + # Set language only if currentUserLanguage is empty + detected_lang = (aiResult.get('languageUserDetected') or '').strip() + if detected_lang and detected_lang.lower() != 'unknown' and self.services.currentUserLanguage == "": + self.services.currentUserLanguage = detected_lang + logger.info(f"Set currentUserLanguage from intent: {detected_lang}") + + # Also set services.user.language if it's empty + if self.services.user and not self.services.user.language: + self.services.user.language = detected_lang + logger.info(f"Set services.user.language from intent: {detected_lang}") + return aiResult except json.JSONDecodeError as json_error: @@ -121,35 +135,7 @@ CRITICAL: Respond with ONLY the JSON object below. Do not include any explanator logger.error(f"AI intent analysis failed: {str(e)}") return None - def _createBasicIntentAnalysis(self, userPrompt: str) -> Dict[str, Any]: - """Creates basic intent analysis without AI""" - return { - "primaryGoal": userPrompt.strip(), - "dataType": "unknown", - "expectedFormat": "unknown", - "qualityRequirements": { - "accuracyThreshold": 0.8, - "completenessThreshold": 0.8, - "formatRequirement": "any" - }, - "successCriteria": ["Delivers what the user requested"], - "confidenceScore": 0.5 - } - - def _createDefaultIntentAnalysis(self, userPrompt: str) -> Dict[str, Any]: - """Creates a default intent analysis when analysis fails""" - return { - "primaryGoal": userPrompt, - "dataType": "unknown", - "expectedFormat": "unknown", - "qualityRequirements": { - "accuracyThreshold": 0.8, - "completenessThreshold": 0.8, - "formatRequirement": "any" - }, - "successCriteria": ["Delivers what the user requested"], - "confidenceScore": 0.1 - } + def _isValidJsonResponse(self, response: str) -> bool: """Checks if response contains valid JSON structure""" diff --git a/modules/workflows/processing/core/taskPlanner.py b/modules/workflows/processing/core/taskPlanner.py index dc7c992f..5feb1137 100644 --- a/modules/workflows/processing/core/taskPlanner.py +++ b/modules/workflows/processing/core/taskPlanner.py @@ -146,26 +146,11 @@ class TaskPlanner: if not taskPlanDict.get('tasks'): raise ValueError("Task plan contains no tasks") - # LANGUAGE DETECTION: Determine user language once for the entire workflow - # Priority: 1. languageUserDetected from AI response, 2. service.user.language, 3. "en" - detectedLanguage = taskPlanDict.get('languageUserDetected', '').strip() - serviceUserLanguage = getattr(self.services.user, 'language', '') if self.services and self.services.user else '' - - if detectedLanguage and len(detectedLanguage) == 2: # Valid language code like "en", "de", "fr" - userLanguage = detectedLanguage - logger.info(f"Using detected language from AI response: {userLanguage}") - elif serviceUserLanguage and len(serviceUserLanguage) == 2: - userLanguage = serviceUserLanguage - logger.info(f"Using language from service user object: {userLanguage}") - else: - userLanguage = "en" - logger.info(f"Using default language: {userLanguage}") - - # Set the detected language in the service for use throughout the workflow - if self.services and self.services.user: - self.services.user.language = userLanguage - logger.info(f"Set workflow user language to: {userLanguage}") + # Use already detected language from services; do not detect here + userLanguage = self.services.currentUserLanguage or 'en' + logger.info(f"Task planning using user language: {userLanguage}") + tasks = [] for i, taskDict in enumerate(taskPlanDict.get('tasks', [])): if not isinstance(taskDict, dict): @@ -193,7 +178,6 @@ class TaskPlanner: ) logger.info(f"Task plan generated successfully with {len(tasks)} tasks") - logger.info(f"Workflow user language set to: {userLanguage}") return taskPlan except Exception as e: diff --git a/modules/workflows/processing/shared/placeholderFactory.py b/modules/workflows/processing/shared/placeholderFactory.py index e45e560c..0e6d73f1 100644 --- a/modules/workflows/processing/shared/placeholderFactory.py +++ b/modules/workflows/processing/shared/placeholderFactory.py @@ -11,6 +11,7 @@ NAMING CONVENTION: MAPPING TABLE (keys → function) with usage [taskplan | actionplan | react]: {{KEY:USER_PROMPT}} -> extractUserPrompt() [taskplan, actionplan, react] {{KEY:USER_LANGUAGE}} -> extractUserLanguage() [actionplan, react] +{{KEY:LANGUAGE_USER_DETECTED}} -> extractLanguageUserDetected() [taskplan] {{KEY:WORKFLOW_HISTORY}} -> extractWorkflowHistory() [taskplan, actionplan, react] {{KEY:AVAILABLE_CONNECTIONS_INDEX}} -> extractAvailableConnectionsIndex() [actionplan, react] {{KEY:AVAILABLE_CONNECTIONS_SUMMARY}} -> extractAvailableConnectionsSummary() [] @@ -421,3 +422,28 @@ def extractAvailableConnectionsIndex(service: Any) -> str: except Exception as e: logger.error(f"Error getting connection index: {str(e)}") return "No connections available" + +def extractLanguageUserDetected(context: Any) -> str: + """Extract the detected user language from intent analysis or context.""" + try: + # Try to get language from intent analysis if available + if hasattr(context, 'intent_analysis') and context.intent_analysis: + language = context.intent_analysis.get('languageUserDetected', '') + if language and language != 'unknown': + return language + + # Try to get language from workflow context + if hasattr(context, 'workflow') and hasattr(context.workflow, 'intent_analysis'): + language = context.workflow.intent_analysis.get('languageUserDetected', '') if context.workflow.intent_analysis else '' + if language and language != 'unknown': + return language + + # Try to get language from user service + if hasattr(context, 'services') and hasattr(context.services, 'user') and hasattr(context.services.user, 'language'): + return context.services.user.language + + # Default fallback + return 'en' + except Exception as e: + logger.error(f"Error extracting user language: {str(e)}") + return 'en' diff --git a/modules/workflows/processing/shared/promptGenerationTaskplan.py b/modules/workflows/processing/shared/promptGenerationTaskplan.py index f5fb3407..6da51e1c 100644 --- a/modules/workflows/processing/shared/promptGenerationTaskplan.py +++ b/modules/workflows/processing/shared/promptGenerationTaskplan.py @@ -71,8 +71,7 @@ Break down user requests into logical, executable task steps. ```json { "overview": "Brief description of the overall plan", - "languageUserDetected": "en", - "userMessage": "User-friendly message explaining the task plan", + "userMessage": "User-friendly message explaining the task plan (use the user's detected language from intent)", "tasks": [ { "id": "task_1", diff --git a/modules/workflows/processing/workflowProcessor.py b/modules/workflows/processing/workflowProcessor.py index 7de1e114..1b46a72c 100644 --- a/modules/workflows/processing/workflowProcessor.py +++ b/modules/workflows/processing/workflowProcessor.py @@ -51,6 +51,9 @@ class WorkflowProcessor: # Check workflow status before generating task plan self._checkWorkflowStopped(workflow) + # Initialize currentUserLanguage to empty at workflow start + self.services.currentUserLanguage = "" + logger.info(f"=== STARTING TASK PLAN GENERATION ===") logger.info(f"Workflow ID: {workflow.id}") logger.info(f"User Input: {userInput}")