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}")