Refactored workflow modes to the standard Dynamic (default), Actionplan (option), Template (future)
This commit is contained in:
parent
53bfe06dbe
commit
46fcd089c4
17 changed files with 156 additions and 82 deletions
|
|
@ -263,6 +263,23 @@ registerModelLabels(
|
|||
)
|
||||
|
||||
|
||||
class WorkflowModeEnum(str, Enum):
|
||||
WORKFLOW_ACTIONPLAN = "Actionplan"
|
||||
WORKFLOW_DYNAMIC = "Dynamic"
|
||||
WORKFLOW_TEMPLATE = "Template"
|
||||
|
||||
|
||||
registerModelLabels(
|
||||
"WorkflowModeEnum",
|
||||
{"en": "Workflow Mode", "fr": "Mode de workflow"},
|
||||
{
|
||||
"WORKFLOW_ACTIONPLAN": {"en": "Actionplan", "fr": "Actionplan"},
|
||||
"WORKFLOW_DYNAMIC": {"en": "Dynamic", "fr": "Dynamique"},
|
||||
"WORKFLOW_TEMPLATE": {"en": "Template", "fr": "Modèle"},
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class ChatWorkflow(BaseModel):
|
||||
id: str = Field(
|
||||
default_factory=lambda: str(uuid.uuid4()),
|
||||
|
|
@ -372,18 +389,25 @@ class ChatWorkflow(BaseModel):
|
|||
frontend_readonly=True,
|
||||
frontend_required=False,
|
||||
)
|
||||
workflowMode: str = Field(
|
||||
default="Actionplan",
|
||||
workflowMode: WorkflowModeEnum = Field(
|
||||
default=WorkflowModeEnum.WORKFLOW_DYNAMIC,
|
||||
description="Workflow mode selector",
|
||||
frontend_type="select",
|
||||
frontend_readonly=False,
|
||||
frontend_required=False,
|
||||
frontend_options=[
|
||||
{
|
||||
"value": "Actionplan",
|
||||
"label": {"en": "Action Plan", "fr": "Plan d'actions"},
|
||||
"value": WorkflowModeEnum.WORKFLOW_ACTIONPLAN.value,
|
||||
"label": {"en": "Actionplan", "fr": "Actionplan"},
|
||||
},
|
||||
{
|
||||
"value": WorkflowModeEnum.WORKFLOW_DYNAMIC.value,
|
||||
"label": {"en": "Dynamic", "fr": "Dynamique"},
|
||||
},
|
||||
{
|
||||
"value": WorkflowModeEnum.WORKFLOW_TEMPLATE.value,
|
||||
"label": {"en": "Template", "fr": "Modèle"},
|
||||
},
|
||||
{"value": "React", "label": {"en": "React", "fr": "Réactif"}},
|
||||
],
|
||||
)
|
||||
maxSteps: int = Field(
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ import logging
|
|||
from typing import Optional
|
||||
|
||||
from modules.datamodels.datamodelUam import User
|
||||
from modules.datamodels.datamodelChat import ChatWorkflow, UserInputRequest
|
||||
from modules.datamodels.datamodelChat import ChatWorkflow, UserInputRequest, WorkflowModeEnum
|
||||
from modules.workflows.workflowManager import WorkflowManager
|
||||
from modules.services import getInterface as getServices
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
async def chatStart(interfaceDbChat, currentUser: User, userInput: UserInputRequest, workflowId: Optional[str] = None, workflowMode: str = "Actionplan") -> ChatWorkflow:
|
||||
async def chatStart(interfaceDbChat, currentUser: User, userInput: UserInputRequest, workflowId: Optional[str] = None, workflowMode: WorkflowModeEnum = WorkflowModeEnum.WORKFLOW_ACTIONPLAN) -> ChatWorkflow:
|
||||
"""
|
||||
Starts a new chat or continues an existing one, then launches processing asynchronously.
|
||||
|
||||
|
|
@ -17,10 +17,10 @@ async def chatStart(interfaceDbChat, currentUser: User, userInput: UserInputRequ
|
|||
currentUser: Current user
|
||||
userInput: User input request
|
||||
workflowId: Optional workflow ID to continue existing workflow
|
||||
workflowMode: "Actionplan" for traditional task planning, "React" for iterative react-style processing
|
||||
workflowMode: "Actionplan" for traditional task planning, "Dynamic" for iterative dynamic-style processing, "Template" for template-based processing
|
||||
|
||||
Example usage for React mode:
|
||||
workflow = await chatStart(interfaceDbChat, currentUser, userInput, workflowMode="React")
|
||||
Example usage for Dynamic mode:
|
||||
workflow = await chatStart(interfaceDbChat, currentUser, userInput, workflowMode=WorkflowModeEnum.WORKFLOW_DYNAMIC)
|
||||
"""
|
||||
try:
|
||||
services = getServices(currentUser, None)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ from modules.datamodels.datamodelChat import (
|
|||
ChatStat,
|
||||
ChatLog,
|
||||
ChatMessage,
|
||||
ChatWorkflow
|
||||
ChatWorkflow,
|
||||
WorkflowModeEnum
|
||||
)
|
||||
from modules.datamodels.datamodelUam import User
|
||||
|
||||
|
|
@ -367,7 +368,7 @@ class ChatObjects:
|
|||
messages=[],
|
||||
stats=[],
|
||||
mandateId=created.get("mandateId", self.currentUser.mandateId),
|
||||
workflowMode=created.get("workflowMode", "Actionplan"),
|
||||
workflowMode=created.get("workflowMode", WorkflowModeEnum.WORKFLOW_DYNAMIC),
|
||||
maxSteps=created.get("maxSteps", 1)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from modules.security.auth import limiter, getCurrentUser
|
|||
import modules.interfaces.interfaceDbChatObjects as interfaceDbChatObjects
|
||||
|
||||
# Import models
|
||||
from modules.datamodels.datamodelChat import ChatWorkflow, UserInputRequest
|
||||
from modules.datamodels.datamodelChat import ChatWorkflow, UserInputRequest, WorkflowModeEnum
|
||||
from modules.datamodels.datamodelUam import User
|
||||
|
||||
# Import workflow control functions
|
||||
|
|
@ -39,7 +39,7 @@ def getServiceChat(currentUser: User):
|
|||
async def start_workflow(
|
||||
request: Request,
|
||||
workflowId: Optional[str] = Query(None, description="Optional ID of the workflow to continue"),
|
||||
workflowMode: str = Query("Actionplan", description="Workflow mode: 'Actionplan' or 'React'"),
|
||||
workflowMode: WorkflowModeEnum = Query(WorkflowModeEnum.WORKFLOW_DYNAMIC, description="Workflow mode: 'Actionplan', 'Dynamic', or 'Template'"),
|
||||
userInput: UserInputRequest = Body(...),
|
||||
currentUser: User = Depends(getCurrentUser)
|
||||
) -> ChatWorkflow:
|
||||
|
|
@ -48,7 +48,7 @@ async def start_workflow(
|
|||
Corresponds to State 1 in the state machine documentation.
|
||||
|
||||
Args:
|
||||
workflowMode: "Actionplan" for traditional task planning, "React" for iterative react-style processing
|
||||
workflowMode: "Actionplan" for traditional task planning, "Dynamic" for iterative dynamic-style processing, "Template" for template-based processing
|
||||
"""
|
||||
try:
|
||||
# Get service center
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# adaptive module for React mode
|
||||
# adaptive module for Dynamic mode
|
||||
# Provides adaptive learning capabilities
|
||||
|
||||
from .intentAnalyzer import IntentAnalyzer
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# contentValidator.py
|
||||
# Content validation for adaptive React mode
|
||||
# Content validation for adaptive Dynamic mode
|
||||
# Generic, document-aware validation system
|
||||
|
||||
import logging
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# intentAnalyzer.py
|
||||
# Intent analysis for adaptive React mode - AI-based, language-agnostic
|
||||
# Intent analysis for adaptive Dynamic mode - AI-based, language-agnostic
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# learningEngine.py
|
||||
# Learning engine for adaptive React mode
|
||||
# Learning engine for adaptive Dynamic mode
|
||||
|
||||
import logging
|
||||
from typing import Dict, Any, List
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# progressTracker.py
|
||||
# Progress tracking for adaptive React mode
|
||||
# Progress tracking for adaptive Dynamic mode
|
||||
|
||||
import logging
|
||||
from typing import Dict, Any, List
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ class ActionplanMode(BaseMode):
|
|||
taskIndex, actionNumber, totalActions)
|
||||
actionResults.append(result)
|
||||
|
||||
# Enhanced validation: Content validation after each action (like React mode)
|
||||
# Enhanced validation: Content validation after each action (like Dynamic mode)
|
||||
if getattr(self, 'workflowIntent', None) and result.documents:
|
||||
# Pass ALL documents to validator - validator decides what to validate (generic approach)
|
||||
# Pass taskStep so validator can use task.objective and format fields
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# modeReact.py
|
||||
# React mode implementation for workflows
|
||||
# modeDynamic.py
|
||||
# Dynamic mode implementation for workflows
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
|
@ -14,10 +14,10 @@ from modules.datamodels.datamodelChat import (
|
|||
from modules.datamodels.datamodelChat import ChatWorkflow
|
||||
from modules.workflows.processing.modes.modeBase import BaseMode
|
||||
from modules.workflows.processing.shared.executionState import TaskExecutionState, shouldContinue
|
||||
from modules.workflows.processing.shared.promptGenerationActionsReact import (
|
||||
generateReactPlanSelectionPrompt,
|
||||
generateReactParametersPrompt,
|
||||
generateReactRefinementPrompt
|
||||
from modules.workflows.processing.shared.promptGenerationActionsDynamic import (
|
||||
generateDynamicPlanSelectionPrompt,
|
||||
generateDynamicParametersPrompt,
|
||||
generateDynamicRefinementPrompt
|
||||
)
|
||||
from modules.workflows.processing.shared.placeholderFactory import extractReviewContent
|
||||
from modules.workflows.processing.adaptive import IntentAnalyzer, ContentValidator, LearningEngine, ProgressTracker
|
||||
|
|
@ -25,8 +25,8 @@ from modules.workflows.processing.adaptive.adaptiveLearningEngine import Adaptiv
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class ReactMode(BaseMode):
|
||||
"""React mode implementation - iterative plan-act-observe-refine loop"""
|
||||
class DynamicMode(BaseMode):
|
||||
"""Dynamic mode implementation - iterative plan-act-observe-refine loop"""
|
||||
|
||||
def __init__(self, services, workflow):
|
||||
super().__init__(services, workflow)
|
||||
|
|
@ -41,13 +41,13 @@ class ReactMode(BaseMode):
|
|||
|
||||
async def generateActionItems(self, taskStep: TaskStep, workflow: ChatWorkflow,
|
||||
previousResults: List = None, enhancedContext: TaskContext = None) -> List[ActionItem]:
|
||||
"""React mode doesn't use batch action generation - actions are generated iteratively"""
|
||||
# React mode generates actions one at a time in the execution loop
|
||||
"""Dynamic mode doesn't use batch action generation - actions are generated iteratively"""
|
||||
# Dynamic mode generates actions one at a time in the execution loop
|
||||
return []
|
||||
|
||||
async def executeTask(self, taskStep: TaskStep, workflow: ChatWorkflow, context: TaskContext,
|
||||
taskIndex: int = None, totalTasks: int = None) -> TaskResult:
|
||||
"""Execute task using React mode - iterative plan-act-observe-refine loop"""
|
||||
"""Execute task using Dynamic mode - iterative plan-act-observe-refine loop"""
|
||||
logger.info(f"=== STARTING TASK {taskIndex or '?'}: {taskStep.objective} ===")
|
||||
|
||||
# Use workflow-level intent from planning phase (stored in workflow object)
|
||||
|
|
@ -79,9 +79,9 @@ class ReactMode(BaseMode):
|
|||
await self.messageCreator.createTaskStartMessage(taskStep, workflow, taskIndex, totalTasks)
|
||||
|
||||
state = TaskExecutionState(taskStep)
|
||||
# React mode uses max_steps instead of max_retries
|
||||
# Dynamic mode uses max_steps instead of max_retries
|
||||
state.max_steps = max(1, int(getattr(workflow, 'maxSteps', 5)))
|
||||
logger.info(f"Using React mode execution with max_steps: {state.max_steps}")
|
||||
logger.info(f"Using Dynamic mode execution with max_steps: {state.max_steps}")
|
||||
|
||||
step = 1
|
||||
decision = None
|
||||
|
|
@ -95,7 +95,7 @@ class ReactMode(BaseMode):
|
|||
try:
|
||||
t0 = time.time()
|
||||
selection = await self._planSelect(context)
|
||||
logger.info(f"React step {step}: Selected action: {selection}")
|
||||
logger.info(f"Dynamic step {step}: Selected action: {selection}")
|
||||
|
||||
# Create user-friendly message BEFORE action execution
|
||||
# Action intention message is now handled by the standard message creator in _actExecute
|
||||
|
|
@ -154,7 +154,7 @@ class ReactMode(BaseMode):
|
|||
# Action completion message is now handled by the standard message creator in _actExecute
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"React step {step} error: {e}")
|
||||
logger.error(f"Dynamic step {step} error: {e}")
|
||||
break
|
||||
|
||||
# NEW: Use adaptive stopping logic
|
||||
|
|
@ -168,7 +168,7 @@ class ReactMode(BaseMode):
|
|||
break
|
||||
step += 1
|
||||
|
||||
# Summarize task result for react mode
|
||||
# Summarize task result for dynamic mode
|
||||
status = TaskStatus.COMPLETED
|
||||
success = True
|
||||
# Get feedback from last decision if available
|
||||
|
|
@ -199,7 +199,7 @@ class ReactMode(BaseMode):
|
|||
|
||||
async def _planSelect(self, context: TaskContext) -> Dict[str, Any]:
|
||||
"""Plan: select exactly one action. Returns {"action": {method, name}}"""
|
||||
bundle = generateReactPlanSelectionPrompt(self.services, context, self.adaptiveLearningEngine)
|
||||
bundle = generateDynamicPlanSelectionPrompt(self.services, context, self.adaptiveLearningEngine)
|
||||
promptTemplate = bundle.prompt
|
||||
placeholders = bundle.placeholders
|
||||
|
||||
|
|
@ -297,7 +297,7 @@ class ReactMode(BaseMode):
|
|||
stage2Context.taskStep = getattr(context, 'taskStep', None)
|
||||
stage2Context.workflowId = getattr(context, 'workflowId', None)
|
||||
|
||||
# Set Stage 1 data directly on the permissive context (snake_case for promptGenerationActionsReact compatibility)
|
||||
# Set Stage 1 data directly on the permissive context (snake_case for promptGenerationActionsDynamic compatibility)
|
||||
if isinstance(selection, dict):
|
||||
stage2Context.action_objective = selection.get('actionObjective', '')
|
||||
stage2Context.parameters_context = selection.get('parametersContext', '')
|
||||
|
|
@ -308,7 +308,7 @@ class ReactMode(BaseMode):
|
|||
stage2Context.learnings = []
|
||||
|
||||
# Build and send the Stage 2 parameters prompt (always)
|
||||
bundle = generateReactParametersPrompt(self.services, stage2Context, compoundActionName, self.adaptiveLearningEngine)
|
||||
bundle = generateDynamicParametersPrompt(self.services, stage2Context, compoundActionName, self.adaptiveLearningEngine)
|
||||
promptTemplate = bundle.prompt
|
||||
placeholders = bundle.placeholders
|
||||
|
||||
|
|
@ -596,7 +596,7 @@ class ReactMode(BaseMode):
|
|||
reviewContext = ReviewContext(
|
||||
taskStep=context.taskStep,
|
||||
taskActions=[],
|
||||
actionResults=[], # React mode doesn't have action results in this context
|
||||
actionResults=[], # Dynamic mode doesn't have action results in this context
|
||||
stepResult={'observation': observationDict},
|
||||
workflowId=context.workflowId,
|
||||
previousResults=[]
|
||||
|
|
@ -640,7 +640,7 @@ class ReactMode(BaseMode):
|
|||
# Update placeholders with enhanced review content
|
||||
placeholders["REVIEW_CONTENT"] = enhancedReviewContent
|
||||
|
||||
bundle = generateReactRefinementPrompt(self.services, context, enhancedReviewContent)
|
||||
bundle = generateDynamicRefinementPrompt(self.services, context, enhancedReviewContent)
|
||||
promptTemplate = bundle.prompt
|
||||
placeholders = bundle.placeholders
|
||||
|
||||
|
|
@ -707,10 +707,10 @@ class ReactMode(BaseMode):
|
|||
qualityScore=5.0
|
||||
)
|
||||
|
||||
async def _createReactActionMessage(self, workflow: ChatWorkflow, selection: Dict[str, Any],
|
||||
async def _createDynamicActionMessage(self, workflow: ChatWorkflow, selection: Dict[str, Any],
|
||||
step: int, maxSteps: int, taskIndex: int, messageType: str,
|
||||
result: ActionResult = None, observation: Observation = None):
|
||||
"""Create user-friendly messages for React workflow actions"""
|
||||
"""Create user-friendly messages for Dynamic workflow actions"""
|
||||
try:
|
||||
action = selection.get('action', {})
|
||||
method = action.get('method', '')
|
||||
|
|
@ -757,7 +757,7 @@ class ReactMode(BaseMode):
|
|||
self.services.workflow.storeMessageWithDocuments(workflow, messageData, [])
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error creating React action message: {str(e)}")
|
||||
logger.error(f"Error creating Dynamic action message: {str(e)}")
|
||||
|
||||
async def _generateActionIntentionMessage(self, method: str, actionName: str, userLanguage: str):
|
||||
"""Generate user-friendly message explaining what action will do"""
|
||||
|
|
@ -817,7 +817,7 @@ Return only the user-friendly message, no technical details."""
|
|||
return f"{method}.{actionName} action completed"
|
||||
|
||||
def _createActionItem(self, actionData: Dict[str, Any]) -> ActionItem:
|
||||
"""Creates a new task action for React mode"""
|
||||
"""Creates a new task action for Dynamic mode"""
|
||||
try:
|
||||
import uuid
|
||||
|
||||
|
|
@ -908,7 +908,7 @@ Return only the user-friendly message, no technical details."""
|
|||
logger.error(f"Error updating workflow before executing action: {str(e)}")
|
||||
|
||||
def _createActionItem(self, actionData: Dict[str, Any]) -> ActionItem:
|
||||
"""Creates a new task action for React mode"""
|
||||
"""Creates a new task action for Dynamic mode"""
|
||||
try:
|
||||
import uuid
|
||||
|
||||
41
modules/workflows/processing/modes/modeTemplate.py
Normal file
41
modules/workflows/processing/modes/modeTemplate.py
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# modeTemplate.py
|
||||
# Template mode implementation for workflows (placeholder for future use)
|
||||
|
||||
import logging
|
||||
from typing import List, Dict, Any
|
||||
from modules.datamodels.datamodelChat import (
|
||||
TaskStep, TaskContext, TaskResult, ActionItem, TaskStatus
|
||||
)
|
||||
from modules.datamodels.datamodelChat import ChatWorkflow
|
||||
from modules.workflows.processing.modes.modeBase import BaseMode
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class TemplateMode(BaseMode):
|
||||
"""Template mode implementation - placeholder for future template-based workflow execution"""
|
||||
|
||||
def __init__(self, services, workflow):
|
||||
super().__init__(services, workflow)
|
||||
logger.warning("TemplateMode is not yet implemented - using placeholder implementation")
|
||||
|
||||
async def generateActionItems(self, taskStep: TaskStep, workflow: ChatWorkflow,
|
||||
previousResults: List = None, enhancedContext: TaskContext = None) -> List[ActionItem]:
|
||||
"""Generate actions for a given task step using template-based approach"""
|
||||
logger.warning("TemplateMode.generateActionItems not yet implemented")
|
||||
# TODO: Implement template-based action generation
|
||||
return []
|
||||
|
||||
async def executeTask(self, taskStep: TaskStep, workflow: ChatWorkflow, context: TaskContext,
|
||||
taskIndex: int = None, totalTasks: int = None) -> TaskResult:
|
||||
"""Execute task using Template mode - placeholder implementation"""
|
||||
logger.warning("TemplateMode.executeTask not yet implemented - returning placeholder result")
|
||||
|
||||
# Return placeholder task result
|
||||
return TaskResult(
|
||||
taskId=taskStep.id,
|
||||
status=TaskStatus.COMPLETED,
|
||||
success=False,
|
||||
feedback="Template mode is not yet implemented",
|
||||
error="Template mode is not yet implemented"
|
||||
)
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ class TaskExecutionState:
|
|||
self.current_action_index = 0
|
||||
self.retry_count = 0
|
||||
self.max_retries = 3
|
||||
# Iterative loop (react mode)
|
||||
# Iterative loop (dynamic mode)
|
||||
self.current_step = 0
|
||||
self.max_steps = 5
|
||||
|
||||
|
|
|
|||
|
|
@ -8,22 +8,22 @@ NAMING CONVENTION:
|
|||
- Placeholder names are in UPPER_CASE with underscores
|
||||
- Function names are in camelCase
|
||||
|
||||
MAPPING TABLE (keys → function) with usage [taskplan | actionplan | react]:
|
||||
{{KEY:USER_PROMPT}} -> extractUserPrompt() [taskplan, actionplan, react]
|
||||
{{KEY:USER_LANGUAGE}} -> extractUserLanguage() [actionplan, react]
|
||||
MAPPING TABLE (keys → function) with usage [taskplan | actionplan | dynamic]:
|
||||
{{KEY:USER_PROMPT}} -> extractUserPrompt() [taskplan, actionplan, dynamic]
|
||||
{{KEY:USER_LANGUAGE}} -> extractUserLanguage() [actionplan, dynamic]
|
||||
{{KEY:LANGUAGE_USER_DETECTED}} -> extractLanguageUserDetected() [taskplan]
|
||||
{{KEY:WORKFLOW_HISTORY}} -> extractWorkflowHistory() [taskplan, actionplan, react]
|
||||
{{KEY:AVAILABLE_CONNECTIONS_INDEX}} -> extractAvailableConnectionsIndex() [actionplan, react]
|
||||
{{KEY:WORKFLOW_HISTORY}} -> extractWorkflowHistory() [taskplan, actionplan, dynamic]
|
||||
{{KEY:AVAILABLE_CONNECTIONS_INDEX}} -> extractAvailableConnectionsIndex() [actionplan, dynamic]
|
||||
{{KEY:AVAILABLE_CONNECTIONS_SUMMARY}} -> extractAvailableConnectionsSummary() []
|
||||
{{KEY:AVAILABLE_DOCUMENTS_SUMMARY}} -> extractAvailableDocumentsSummary() [taskplan, actionplan, react]
|
||||
{{KEY:AVAILABLE_DOCUMENTS_INDEX}} -> extractAvailableDocumentsIndex() [react]
|
||||
{{KEY:AVAILABLE_METHODS}} -> extractAvailableMethods() [actionplan, react]
|
||||
{{KEY:REVIEW_CONTENT}} -> extractReviewContent() [actionplan, react]
|
||||
{{KEY:PREVIOUS_ACTION_RESULTS}} -> extractPreviousActionResults() [react]
|
||||
{{KEY:LEARNINGS_AND_IMPROVEMENTS}} -> extractLearningsAndImprovements() [react]
|
||||
{{KEY:LATEST_REFINEMENT_FEEDBACK}} -> extractLatestRefinementFeedback() [react]
|
||||
{{KEY:AVAILABLE_DOCUMENTS_SUMMARY}} -> extractAvailableDocumentsSummary() [taskplan, actionplan, dynamic]
|
||||
{{KEY:AVAILABLE_DOCUMENTS_INDEX}} -> extractAvailableDocumentsIndex() [dynamic]
|
||||
{{KEY:AVAILABLE_METHODS}} -> extractAvailableMethods() [actionplan, dynamic]
|
||||
{{KEY:REVIEW_CONTENT}} -> extractReviewContent() [actionplan, dynamic]
|
||||
{{KEY:PREVIOUS_ACTION_RESULTS}} -> extractPreviousActionResults() [dynamic]
|
||||
{{KEY:LEARNINGS_AND_IMPROVEMENTS}} -> extractLearningsAndImprovements() [dynamic]
|
||||
{{KEY:LATEST_REFINEMENT_FEEDBACK}} -> extractLatestRefinementFeedback() [dynamic]
|
||||
|
||||
Following placeholders are populated directly by prompt builders with according context in promptGenerationActionsReact module:
|
||||
Following placeholders are populated directly by prompt builders with according context in promptGenerationActionsDynamic module:
|
||||
- ACTION_OBJECTIVE,
|
||||
- SELECTED_ACTION,
|
||||
- ACTION_SIGNATURE
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"""
|
||||
React Mode Prompt Generation
|
||||
Handles prompt templates for react mode action handling.
|
||||
Dynamic Mode Prompt Generation
|
||||
Handles prompt templates for dynamic mode action handling.
|
||||
"""
|
||||
|
||||
import json
|
||||
|
|
@ -20,7 +20,7 @@ from modules.workflows.processing.shared.placeholderFactory import (
|
|||
)
|
||||
from modules.workflows.processing.shared.methodDiscovery import methods, getActionParameterList
|
||||
|
||||
def generateReactPlanSelectionPrompt(services, context: Any, learningEngine=None) -> PromptBundle:
|
||||
def generateDynamicPlanSelectionPrompt(services, context: Any, learningEngine=None) -> PromptBundle:
|
||||
"""Define placeholders first, then the template; return PromptBundle."""
|
||||
placeholders: List[PromptPlaceholder] = [
|
||||
PromptPlaceholder(label="USER_PROMPT", content=extractUserPrompt(context), summaryAllowed=False),
|
||||
|
|
@ -113,7 +113,7 @@ RULES:
|
|||
|
||||
return PromptBundle(prompt=template, placeholders=placeholders)
|
||||
|
||||
def generateReactParametersPrompt(services, context: Any, compoundActionName: str, learningEngine=None) -> PromptBundle:
|
||||
def generateDynamicParametersPrompt(services, context: Any, compoundActionName: str, learningEngine=None) -> PromptBundle:
|
||||
"""Define placeholders first, then the template; return PromptBundle.
|
||||
|
||||
Minimal Stage 2 (no fallback): consumes actionObjective, selectedAction, parametersContext only.
|
||||
|
|
@ -265,7 +265,7 @@ RULES:
|
|||
|
||||
return PromptBundle(prompt=template, placeholders=placeholders)
|
||||
|
||||
def generateReactRefinementPrompt(services, context: Any, reviewContent: str) -> PromptBundle:
|
||||
def generateDynamicRefinementPrompt(services, context: Any, reviewContent: str) -> PromptBundle:
|
||||
"""Define placeholders first, then the template; return PromptBundle."""
|
||||
placeholders: List[PromptPlaceholder] = [
|
||||
PromptPlaceholder(label="USER_PROMPT", content=extractUserPrompt(context), summaryAllowed=False),
|
||||
|
|
@ -4,10 +4,11 @@
|
|||
import logging
|
||||
from typing import Dict, Any, Optional, List
|
||||
from modules.datamodels.datamodelChat import TaskStep, TaskContext, TaskPlan, TaskResult
|
||||
from modules.datamodels.datamodelChat import ChatWorkflow
|
||||
from modules.datamodels.datamodelChat import ChatWorkflow, WorkflowModeEnum
|
||||
from modules.workflows.processing.modes.modeBase import BaseMode
|
||||
from modules.workflows.processing.modes.modeActionplan import ActionplanMode
|
||||
from modules.workflows.processing.modes.modeReact import ReactMode
|
||||
from modules.workflows.processing.modes.modeDynamic import DynamicMode
|
||||
from modules.workflows.processing.modes.modeTemplate import TemplateMode
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -21,15 +22,18 @@ class WorkflowProcessor:
|
|||
def __init__(self, services, workflow=None):
|
||||
self.services = services
|
||||
self.workflow = workflow
|
||||
self.mode = self._createMode(workflow.workflowMode if workflow else "Actionplan")
|
||||
self.mode = self._createMode(workflow.workflowMode if workflow else WorkflowModeEnum.WORKFLOW_DYNAMIC)
|
||||
|
||||
def _createMode(self, workflowMode: str) -> BaseMode:
|
||||
def _createMode(self, workflowMode: WorkflowModeEnum) -> BaseMode:
|
||||
"""Create the appropriate mode implementation based on workflow mode"""
|
||||
if workflowMode == "React":
|
||||
return ReactMode(self.services, self.workflow)
|
||||
else:
|
||||
if workflowMode == WorkflowModeEnum.WORKFLOW_DYNAMIC:
|
||||
return DynamicMode(self.services, self.workflow)
|
||||
elif workflowMode == WorkflowModeEnum.WORKFLOW_ACTIONPLAN:
|
||||
return ActionplanMode(self.services, self.workflow)
|
||||
|
||||
elif workflowMode == WorkflowModeEnum.WORKFLOW_TEMPLATE:
|
||||
return TemplateMode(self.services, self.workflow)
|
||||
else:
|
||||
raise ValueError(f"Invalid workflow mode: {workflowMode}")
|
||||
def _checkWorkflowStopped(self, workflow):
|
||||
"""Check if workflow has been stopped by user and raise exception if so"""
|
||||
try:
|
||||
|
|
@ -61,7 +65,7 @@ class WorkflowProcessor:
|
|||
operationId,
|
||||
"Workflow Planning",
|
||||
"Task Plan Generation",
|
||||
f"Mode: {workflow.workflowMode}"
|
||||
f"Mode: {workflow.workflowMode.value if hasattr(workflow.workflowMode, 'value') else workflow.workflowMode}"
|
||||
)
|
||||
|
||||
# Initialize currentUserLanguage to empty at workflow start
|
||||
|
|
@ -70,7 +74,8 @@ class WorkflowProcessor:
|
|||
logger.info(f"=== STARTING TASK PLAN GENERATION ===")
|
||||
logger.info(f"Workflow ID: {workflow.id}")
|
||||
logger.info(f"User Input: {userInput}")
|
||||
logger.info(f"Workflow Mode: {workflow.workflowMode}")
|
||||
modeValue = workflow.workflowMode.value if hasattr(workflow.workflowMode, 'value') else workflow.workflowMode
|
||||
logger.info(f"Workflow Mode: {modeValue}")
|
||||
|
||||
# Update progress - generating task plan
|
||||
self.services.workflow.progressLogUpdate(operationId, 0.3, "Analyzing input")
|
||||
|
|
@ -116,7 +121,8 @@ class WorkflowProcessor:
|
|||
|
||||
logger.info(f"=== STARTING TASK EXECUTION ===")
|
||||
logger.info(f"Task: {taskStep.objective}")
|
||||
logger.info(f"Mode: {workflow.workflowMode}")
|
||||
modeValue = workflow.workflowMode.value if hasattr(workflow.workflowMode, 'value') else workflow.workflowMode
|
||||
logger.info(f"Mode: {modeValue}")
|
||||
|
||||
# Update progress - executing task
|
||||
self.services.workflow.progressLogUpdate(operationId, 0.2, "Executing")
|
||||
|
|
@ -143,7 +149,8 @@ class WorkflowProcessor:
|
|||
|
||||
logger.info(f"=== STARTING ACTION GENERATION ===")
|
||||
logger.info(f"Task: {taskStep.objective}")
|
||||
logger.info(f"Mode: {workflow.workflowMode}")
|
||||
modeValue = workflow.workflowMode.value if hasattr(workflow.workflowMode, 'value') else workflow.workflowMode
|
||||
logger.info(f"Mode: {modeValue}")
|
||||
|
||||
# Delegate to the appropriate mode
|
||||
return await self.mode.generateActionItems(taskStep, workflow, previousResults, enhancedContext)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ from modules.datamodels.datamodelChat import (
|
|||
UserInputRequest,
|
||||
ChatMessage,
|
||||
ChatWorkflow,
|
||||
ChatDocument
|
||||
ChatDocument,
|
||||
WorkflowModeEnum
|
||||
)
|
||||
from modules.datamodels.datamodelChat import TaskContext
|
||||
from modules.workflows.processing.workflowProcessor import WorkflowProcessor, WorkflowStoppedException
|
||||
|
|
@ -25,7 +26,7 @@ class WorkflowManager:
|
|||
|
||||
# Exported functions
|
||||
|
||||
async def workflowStart(self, userInput: UserInputRequest, workflowId: Optional[str] = None, workflowMode: str = "React") -> ChatWorkflow:
|
||||
async def workflowStart(self, userInput: UserInputRequest, workflowId: Optional[str] = None, workflowMode: WorkflowModeEnum = WorkflowModeEnum.WORKFLOW_DYNAMIC) -> ChatWorkflow:
|
||||
"""Starts a new workflow or continues an existing one, then launches processing."""
|
||||
try:
|
||||
# Debug log to check workflowMode parameter
|
||||
|
|
@ -90,7 +91,7 @@ class WorkflowManager:
|
|||
"mandateId": self.services.user.mandateId,
|
||||
"messageIds": [],
|
||||
"workflowMode": workflowMode,
|
||||
"maxSteps": 5 if workflowMode == "React" else 1, # Set maxSteps for React mode
|
||||
"maxSteps": 5 if workflowMode == WorkflowModeEnum.WORKFLOW_DYNAMIC else 1, # Set maxSteps for Dynamic mode
|
||||
}
|
||||
|
||||
workflow = self.services.workflow.createWorkflow(workflowData)
|
||||
|
|
@ -320,7 +321,7 @@ class WorkflowManager:
|
|||
task_plan = await handling.generateTaskPlan(userInput.prompt, workflow)
|
||||
if not task_plan or not task_plan.tasks:
|
||||
raise Exception("No tasks generated in task plan.")
|
||||
workflow_mode = getattr(workflow, 'workflowMode', 'Actionplan')
|
||||
workflow_mode = getattr(workflow, 'workflowMode', WorkflowModeEnum.WORKFLOW_DYNAMIC)
|
||||
logger.info(f"Workflow object attributes: {workflow.__dict__ if hasattr(workflow, '__dict__') else 'No __dict__'}")
|
||||
logger.info(f"Executing workflow mode={workflow_mode} with {len(task_plan.tasks)} tasks")
|
||||
return task_plan
|
||||
|
|
|
|||
Loading…
Reference in a new issue