147 lines
No EOL
5.7 KiB
Python
147 lines
No EOL
5.7 KiB
Python
from typing import Dict, Any
|
|
import logging
|
|
from datetime import datetime, UTC
|
|
import uuid
|
|
|
|
from modules.interfaces.serviceChatModel import (
|
|
AgentTask, AgentResult, TaskStatus, ChatMessage,
|
|
UserInputRequest, ChatWorkflow, ChatDocument
|
|
)
|
|
from modules.interfaces.serviceChatClass import ChatInterface
|
|
from modules.workflow.managerChat import ChatManager
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class WorkflowStoppedException(Exception):
|
|
"""Exception raised when workflow is stopped by user"""
|
|
pass
|
|
|
|
class WorkflowManager:
|
|
"""Manages workflow execution lifecycle"""
|
|
|
|
def __init__(self, chatInterface: ChatInterface):
|
|
self.workflow = None
|
|
self.isRunning = False
|
|
self.chatInterface = chatInterface
|
|
self.chatManager = ChatManager()
|
|
|
|
def _checkWorkflowStopped(self, workflow: ChatWorkflow) -> None:
|
|
if workflow.status == "stopped":
|
|
logger.info(f"Workflow {workflow.id} stopped by user")
|
|
raise WorkflowStoppedException("User stopped workflow")
|
|
|
|
async def workflowProcess(self, userInput: UserInputRequest, workflow: ChatWorkflow) -> None:
|
|
"""Main workflow execution process"""
|
|
try:
|
|
self.workflow = workflow
|
|
self.isRunning = True
|
|
|
|
# Process documents from userInput using ChatInterface's method
|
|
documents = []
|
|
if userInput.listFileId:
|
|
documents = await self.chatInterface.processFileIds(userInput.listFileId)
|
|
|
|
# Create initial ChatMessage from userInput
|
|
initialMessage = ChatMessage(
|
|
id=str(uuid.uuid4()),
|
|
workflowId=workflow.id,
|
|
role="user",
|
|
message=userInput.prompt,
|
|
status="first", # First message in workflow
|
|
documents=documents
|
|
)
|
|
|
|
# Add message to workflow
|
|
await self.chatInterface.createWorkflowMessage(initialMessage.dict())
|
|
|
|
# Create initial task
|
|
task = await self.chatInterface.createInitialTask(workflow, initialMessage)
|
|
if not task:
|
|
logger.error("Failed to create initial task")
|
|
workflow.status = "error"
|
|
workflow.error = "Failed to create initial task"
|
|
return
|
|
|
|
# Main workflow loop
|
|
while self.isRunning and workflow.status == "running":
|
|
|
|
self._checkWorkflowStopped(workflow)
|
|
|
|
# Execute task
|
|
result = AgentResult(
|
|
id=task.id,
|
|
status=TaskStatus.PENDING,
|
|
createdAt=datetime.now(UTC),
|
|
updatedAt=datetime.now(UTC)
|
|
)
|
|
|
|
# Execute each action
|
|
for action in task.actionList:
|
|
|
|
self._checkWorkflowStopped(workflow)
|
|
|
|
try:
|
|
# Execute action
|
|
actionResult = await action.execute()
|
|
|
|
# Update action status
|
|
action.status = TaskStatus.COMPLETED if actionResult.success else TaskStatus.FAILED
|
|
action.result = actionResult
|
|
|
|
# Check for failure
|
|
if not actionResult.success:
|
|
result.status = TaskStatus.FAILED
|
|
result.error = actionResult.error
|
|
break
|
|
|
|
except Exception as e:
|
|
logger.error(f"Action error: {str(e)}")
|
|
action.status = TaskStatus.FAILED
|
|
result.status = TaskStatus.FAILED
|
|
result.error = str(e)
|
|
break
|
|
|
|
# Update result status
|
|
if result.status != TaskStatus.FAILED:
|
|
result.status = TaskStatus.COMPLETED
|
|
|
|
result.updatedAt = datetime.now(UTC)
|
|
|
|
self._checkWorkflowStopped(workflow)
|
|
|
|
# Update workflow with result
|
|
await self.chatInterface.addTaskResult(workflow, result)
|
|
|
|
# Get next task
|
|
task = await self.chatInterface.getNextTask(workflow)
|
|
if not task:
|
|
break
|
|
|
|
# Check if should continue
|
|
if not await self.chatInterface.shouldContinue(workflow):
|
|
break
|
|
|
|
# Generate final feedback message using ChatManager
|
|
finalFeedback = await self.chatManager.generateWorkflowFeedback(workflow)
|
|
|
|
# Create final message with "last" status
|
|
self._checkWorkflowStopped(workflow)
|
|
finalMessage = ChatMessage(
|
|
id=str(uuid.uuid4()),
|
|
workflowId=workflow.id,
|
|
role="assistant",
|
|
message=finalFeedback,
|
|
status="last" # Last message in workflow
|
|
)
|
|
await self.chatInterface.createWorkflowMessage(finalMessage.dict())
|
|
|
|
# Complete workflow
|
|
if workflow.status != "failed":
|
|
workflow.status = "completed"
|
|
workflow.lastActivity = datetime.now(UTC).isoformat()
|
|
|
|
except Exception as e:
|
|
logger.error(f"Workflow error: {str(e)}")
|
|
if self.workflow:
|
|
self.workflow.status = "error"
|
|
self.workflow.error = str(e) |