issues fixing in chat workflow
This commit is contained in:
parent
46fcd089c4
commit
6060d74eb2
9 changed files with 111 additions and 97 deletions
|
|
@ -8,30 +8,29 @@ from modules.services import getInterface as getServices
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
async def chatStart(interfaceDbChat, currentUser: User, userInput: UserInputRequest, workflowId: Optional[str] = None, workflowMode: WorkflowModeEnum = WorkflowModeEnum.WORKFLOW_ACTIONPLAN) -> ChatWorkflow:
|
||||
async def chatStart(currentUser: User, userInput: UserInputRequest, workflowMode: WorkflowModeEnum, workflowId: Optional[str] = None) -> ChatWorkflow:
|
||||
"""
|
||||
Starts a new chat or continues an existing one, then launches processing asynchronously.
|
||||
|
||||
Args:
|
||||
interfaceDbChat: Chat interface instance
|
||||
currentUser: Current user
|
||||
userInput: User input request
|
||||
workflowId: Optional workflow ID to continue existing workflow
|
||||
workflowMode: "Actionplan" for traditional task planning, "Dynamic" for iterative dynamic-style processing, "Template" for template-based processing
|
||||
|
||||
Example usage for Dynamic mode:
|
||||
workflow = await chatStart(interfaceDbChat, currentUser, userInput, workflowMode=WorkflowModeEnum.WORKFLOW_DYNAMIC)
|
||||
workflow = await chatStart(currentUser, userInput, workflowMode=WorkflowModeEnum.WORKFLOW_DYNAMIC)
|
||||
"""
|
||||
try:
|
||||
services = getServices(currentUser, None)
|
||||
workflowManager = WorkflowManager(services)
|
||||
workflow = await workflowManager.workflowStart(userInput, workflowId, workflowMode)
|
||||
workflow = await workflowManager.workflowStart(userInput, workflowMode, workflowId)
|
||||
return workflow
|
||||
except Exception as e:
|
||||
logger.error(f"Error starting chat: {str(e)}")
|
||||
raise
|
||||
|
||||
async def chatStop(interfaceDbChat, currentUser: User, workflowId: str) -> ChatWorkflow:
|
||||
async def chatStop(currentUser: User, workflowId: str) -> ChatWorkflow:
|
||||
"""Stops a running chat."""
|
||||
try:
|
||||
services = getServices(currentUser, None)
|
||||
|
|
|
|||
|
|
@ -368,7 +368,7 @@ class ChatObjects:
|
|||
messages=[],
|
||||
stats=[],
|
||||
mandateId=created.get("mandateId", self.currentUser.mandateId),
|
||||
workflowMode=created.get("workflowMode", WorkflowModeEnum.WORKFLOW_DYNAMIC),
|
||||
workflowMode=created["workflowMode"],
|
||||
maxSteps=created.get("maxSteps", 1)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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: WorkflowModeEnum = Query(WorkflowModeEnum.WORKFLOW_DYNAMIC, description="Workflow mode: 'Actionplan', 'Dynamic', or 'Template'"),
|
||||
workflowMode: WorkflowModeEnum = Query(..., description="Workflow mode: 'Actionplan', 'Dynamic', or 'Template' (mandatory)"),
|
||||
userInput: UserInputRequest = Body(...),
|
||||
currentUser: User = Depends(getCurrentUser)
|
||||
) -> ChatWorkflow:
|
||||
|
|
@ -51,11 +51,8 @@ async def start_workflow(
|
|||
workflowMode: "Actionplan" for traditional task planning, "Dynamic" for iterative dynamic-style processing, "Template" for template-based processing
|
||||
"""
|
||||
try:
|
||||
# Get service center
|
||||
interfaceDbChat = getServiceChat(currentUser)
|
||||
|
||||
# Start or continue workflow using playground controller
|
||||
workflow = await chatStart(interfaceDbChat, currentUser, userInput, workflowId, workflowMode)
|
||||
workflow = await chatStart(currentUser, userInput, workflowMode, workflowId)
|
||||
|
||||
return workflow
|
||||
|
||||
|
|
@ -76,11 +73,8 @@ async def stop_workflow(
|
|||
) -> ChatWorkflow:
|
||||
"""Stops a running workflow."""
|
||||
try:
|
||||
# Get service center
|
||||
interfaceDbChat = getServiceChat(currentUser)
|
||||
|
||||
# Stop workflow using playground controller
|
||||
workflow = await chatStop(interfaceDbChat, currentUser, workflowId)
|
||||
workflow = await chatStop(currentUser, workflowId)
|
||||
|
||||
return workflow
|
||||
|
||||
|
|
|
|||
|
|
@ -156,6 +156,10 @@ async def login(
|
|||
error_msg = str(e)
|
||||
logger.warning(f"Authentication failed for user {formData.username}: {error_msg}")
|
||||
|
||||
# Check if user is disabled and provide specific message
|
||||
if error_msg == "User is disabled":
|
||||
error_msg = "Your account is disabled. Please send an email to p.motsch@valueon.ch to get access to the PowerOn center."
|
||||
|
||||
# Log failed login attempt
|
||||
try:
|
||||
from modules.shared.auditLogger import audit_logger
|
||||
|
|
@ -209,6 +213,7 @@ async def register_user(
|
|||
|
||||
# Create user with local authentication
|
||||
# Set safe default privilege level for new registrations
|
||||
# New users are disabled by default and require admin approval
|
||||
from modules.datamodels.datamodelUam import UserPrivilege
|
||||
user = appInterface.createUser(
|
||||
username=userData.username,
|
||||
|
|
@ -216,7 +221,7 @@ async def register_user(
|
|||
email=userData.email,
|
||||
fullName=userData.fullName,
|
||||
language=userData.language,
|
||||
enabled=userData.enabled,
|
||||
enabled=False, # New users are disabled by default
|
||||
privilege=UserPrivilege.USER, # Always set to USER for new registrations
|
||||
authenticationAuthority=AuthAuthority.LOCAL
|
||||
)
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ class WorkflowService:
|
|||
logger.error(f"Error getting workflow context: {str(e)}")
|
||||
return {'currentRound': 0, 'currentTask': 0, 'currentAction': 0}
|
||||
|
||||
def setWorkflowContext(self, round_number: int = None, task_number: int = None, action_number: int = None):
|
||||
def setWorkflowContext(self, roundNumber: int = None, taskNumber: int = None, actionNumber: int = None):
|
||||
"""Set current workflow context for document generation and routing"""
|
||||
try:
|
||||
workflow = self.services.currentWorkflow
|
||||
|
|
@ -383,15 +383,15 @@ class WorkflowService:
|
|||
# Prepare update data
|
||||
update_data = {}
|
||||
|
||||
if round_number is not None:
|
||||
workflow.currentRound = round_number
|
||||
update_data["currentRound"] = round_number
|
||||
if task_number is not None:
|
||||
workflow.currentTask = task_number
|
||||
update_data["currentTask"] = task_number
|
||||
if action_number is not None:
|
||||
workflow.currentAction = action_number
|
||||
update_data["currentAction"] = action_number
|
||||
if roundNumber is not None:
|
||||
workflow.currentRound = roundNumber
|
||||
update_data["currentRound"] = roundNumber
|
||||
if taskNumber is not None:
|
||||
workflow.currentTask = taskNumber
|
||||
update_data["currentTask"] = taskNumber
|
||||
if actionNumber is not None:
|
||||
workflow.currentAction = actionNumber
|
||||
update_data["currentAction"] = actionNumber
|
||||
|
||||
# Persist changes to database if any updates were made
|
||||
if update_data:
|
||||
|
|
@ -863,8 +863,8 @@ class WorkflowService:
|
|||
logger.error(f"Error getting connection reference list: {str(e)}")
|
||||
return []
|
||||
|
||||
def setWorkflowContext(self, workflow):
|
||||
"""Set the current workflow context for this service"""
|
||||
def setCurrentWorkflow(self, workflow):
|
||||
"""Set the current workflow reference for this service"""
|
||||
self.workflow = workflow
|
||||
# Reset progress logger for new workflow
|
||||
self._progressLogger = None
|
||||
|
|
|
|||
|
|
@ -176,6 +176,23 @@ def getModelAttributeDefinitions(modelClass: Type[BaseModel] = None, userLanguag
|
|||
else str(field.annotation)
|
||||
)
|
||||
)
|
||||
|
||||
# Extract default value from field
|
||||
# In Pydantic v2, FieldInfo has a 'default' attribute
|
||||
field_default = None
|
||||
if hasattr(field_info, 'default'):
|
||||
default_value = field_info.default
|
||||
# Handle default_factory (callable that generates default)
|
||||
if hasattr(field_info, 'default_factory') and callable(field_info.default_factory):
|
||||
# Don't call it here - it's meant to be called per-instance
|
||||
# Instead, store a marker that indicates it exists
|
||||
field_default = None # Frontend should use first option or specific logic
|
||||
elif default_value is not ...: # Ellipsis means no default
|
||||
# Convert enum to its value if it's an enum
|
||||
if hasattr(default_value, 'value'):
|
||||
field_default = default_value.value
|
||||
else:
|
||||
field_default = default_value
|
||||
|
||||
attributes.append(
|
||||
{
|
||||
|
|
@ -192,6 +209,7 @@ def getModelAttributeDefinitions(modelClass: Type[BaseModel] = None, userLanguag
|
|||
"order": len(attributes),
|
||||
"readonly": frontend_readonly,
|
||||
"options": frontend_options,
|
||||
"default": field_default,
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ class ActionplanMode(BaseMode):
|
|||
|
||||
# Update workflow context for this task
|
||||
if taskIndex is not None:
|
||||
self.services.workflow.setWorkflowContext(task_number=taskIndex)
|
||||
self.services.workflow.setWorkflowContext(taskNumber=taskIndex)
|
||||
|
||||
# Create task start message
|
||||
await self.messageCreator.createTaskStartMessage(taskStep, workflow, taskIndex, totalTasks)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class WorkflowProcessor:
|
|||
def __init__(self, services, workflow=None):
|
||||
self.services = services
|
||||
self.workflow = workflow
|
||||
self.mode = self._createMode(workflow.workflowMode if workflow else WorkflowModeEnum.WORKFLOW_DYNAMIC)
|
||||
self.mode = self._createMode(workflow.workflowMode)
|
||||
|
||||
def _createMode(self, workflowMode: WorkflowModeEnum) -> BaseMode:
|
||||
"""Create the appropriate mode implementation based on workflow mode"""
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class WorkflowManager:
|
|||
|
||||
# Exported functions
|
||||
|
||||
async def workflowStart(self, userInput: UserInputRequest, workflowId: Optional[str] = None, workflowMode: WorkflowModeEnum = WorkflowModeEnum.WORKFLOW_DYNAMIC) -> ChatWorkflow:
|
||||
async def workflowStart(self, userInput: UserInputRequest, workflowMode: WorkflowModeEnum, workflowId: Optional[str] = None) -> ChatWorkflow:
|
||||
"""Starts a new workflow or continues an existing one, then launches processing."""
|
||||
try:
|
||||
# Debug log to check workflowMode parameter
|
||||
|
|
@ -142,7 +142,7 @@ class WorkflowManager:
|
|||
self.services.currentUserPrompt = userInput.prompt
|
||||
|
||||
# Update the workflow service with the current workflow context
|
||||
self.services.workflow.setWorkflowContext(workflow)
|
||||
self.services.workflow.setCurrentWorkflow(workflow)
|
||||
|
||||
self.workflowProcessor = WorkflowProcessor(self.services, workflow)
|
||||
await self._sendFirstMessage(userInput, workflow)
|
||||
|
|
@ -165,10 +165,8 @@ class WorkflowManager:
|
|||
|
||||
# Create initial message using interface
|
||||
# For first user message, include round info in the user context label
|
||||
round_num = workflow.currentRound
|
||||
task_num = 0
|
||||
action_num = 0
|
||||
context_label = f"round{round_num}_usercontext"
|
||||
roundNum = workflow.currentRound
|
||||
contextLabel = f"round{roundNum}_usercontext"
|
||||
|
||||
messageData = {
|
||||
"workflowId": workflow.id,
|
||||
|
|
@ -177,7 +175,7 @@ class WorkflowManager:
|
|||
"status": "first",
|
||||
"sequenceNr": 1,
|
||||
"publishedAt": self.services.utils.timestampGetUtc(),
|
||||
"documentsLabel": context_label,
|
||||
"documentsLabel": contextLabel,
|
||||
"documents": [],
|
||||
# Add workflow context fields
|
||||
"roundNumber": workflow.currentRound,
|
||||
|
|
@ -189,7 +187,7 @@ class WorkflowManager:
|
|||
}
|
||||
|
||||
# Analyze the user's input to detect language, normalize request, extract intent, and offload bulky context into documents
|
||||
created_docs = []
|
||||
createdDocs = []
|
||||
|
||||
try:
|
||||
analyzerPrompt = (
|
||||
|
|
@ -271,28 +269,28 @@ class WorkflowManager:
|
|||
mimeType = (mime or "text/plain").strip()
|
||||
|
||||
# Neutralize content before storing if neutralization is enabled
|
||||
content_bytes = content.encode('utf-8')
|
||||
content_bytes = await self._neutralizeContentIfEnabled(content_bytes, mimeType)
|
||||
contentBytes = content.encode('utf-8')
|
||||
contentBytes = await self._neutralizeContentIfEnabled(contentBytes, mimeType)
|
||||
|
||||
# Create file in component storage
|
||||
file_item = self.services.interfaceDbComponent.createFile(
|
||||
fileItem = self.services.interfaceDbComponent.createFile(
|
||||
name=fileName,
|
||||
mimeType=mimeType,
|
||||
content=content_bytes
|
||||
content=contentBytes
|
||||
)
|
||||
# Persist file data
|
||||
self.services.interfaceDbComponent.createFileData(file_item.id, content_bytes)
|
||||
|
||||
self.services.interfaceDbComponent.createFileData(fileItem.id, contentBytes)
|
||||
|
||||
# Collect file info
|
||||
file_info = self.services.workflow.getFileInfo(file_item.id)
|
||||
fileInfo = self.services.workflow.getFileInfo(fileItem.id)
|
||||
from modules.datamodels.datamodelChat import ChatDocument
|
||||
doc = ChatDocument(
|
||||
fileId=file_item.id,
|
||||
fileName=file_info.get("fileName", fileName) if file_info else fileName,
|
||||
fileSize=file_info.get("size", len(content_bytes)) if file_info else len(content_bytes),
|
||||
mimeType=file_info.get("mimeType", mimeType) if file_info else mimeType
|
||||
fileId=fileItem.id,
|
||||
fileName=fileInfo.get("fileName", fileName) if fileInfo else fileName,
|
||||
fileSize=fileInfo.get("size", len(contentBytes)) if fileInfo else len(contentBytes),
|
||||
mimeType=fileInfo.get("mimeType", mimeType) if fileInfo else mimeType
|
||||
)
|
||||
created_docs.append(doc)
|
||||
createdDocs.append(doc)
|
||||
except Exception:
|
||||
continue
|
||||
except Exception as e:
|
||||
|
|
@ -301,14 +299,14 @@ class WorkflowManager:
|
|||
# Process user-uploaded documents (fileIds) and combine with context documents
|
||||
if userInput.listFileId:
|
||||
try:
|
||||
user_docs = await self._processFileIds(userInput.listFileId, None)
|
||||
if user_docs:
|
||||
created_docs.extend(user_docs)
|
||||
userDocs = await self._processFileIds(userInput.listFileId, None)
|
||||
if userDocs:
|
||||
createdDocs.extend(userDocs)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to process user fileIds: {e}")
|
||||
|
||||
# Finally, persist and bind the first message with combined documents (context + user)
|
||||
self.services.workflow.storeMessageWithDocuments(workflow, messageData, created_docs)
|
||||
self.services.workflow.storeMessageWithDocuments(workflow, messageData, createdDocs)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error sending first message: {str(e)}")
|
||||
|
|
@ -318,33 +316,33 @@ class WorkflowManager:
|
|||
"""Generate task plan for workflow execution"""
|
||||
handling = self.workflowProcessor
|
||||
# Generate task plan first (shared for both modes)
|
||||
task_plan = await handling.generateTaskPlan(userInput.prompt, workflow)
|
||||
if not task_plan or not task_plan.tasks:
|
||||
taskPlan = await handling.generateTaskPlan(userInput.prompt, workflow)
|
||||
if not taskPlan or not taskPlan.tasks:
|
||||
raise Exception("No tasks generated in task plan.")
|
||||
workflow_mode = getattr(workflow, 'workflowMode', WorkflowModeEnum.WORKFLOW_DYNAMIC)
|
||||
workflowMode = getattr(workflow, 'workflowMode')
|
||||
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
|
||||
logger.info(f"Executing workflow mode={workflowMode} with {len(taskPlan.tasks)} tasks")
|
||||
return taskPlan
|
||||
|
||||
async def _executeTasks(self, task_plan, workflow: ChatWorkflow) -> None:
|
||||
async def _executeTasks(self, taskPlan, workflow: ChatWorkflow) -> None:
|
||||
"""Execute all tasks in the task plan and update workflow status."""
|
||||
handling = self.workflowProcessor
|
||||
total_tasks = len(task_plan.tasks)
|
||||
all_task_results: List = []
|
||||
previous_results: List[str] = []
|
||||
totalTasks = len(taskPlan.tasks)
|
||||
allTaskResults: List = []
|
||||
previousResults: List[str] = []
|
||||
|
||||
for idx, task_step in enumerate(task_plan.tasks):
|
||||
current_task_index = idx + 1
|
||||
logger.info(f"Task {current_task_index}/{total_tasks}: {task_step.objective}")
|
||||
for idx, taskStep in enumerate(taskPlan.tasks):
|
||||
currentTaskIndex = idx + 1
|
||||
logger.info(f"Task {currentTaskIndex}/{totalTasks}: {taskStep.objective}")
|
||||
|
||||
# Build TaskContext (mode-specific behavior is inside WorkflowProcessor)
|
||||
task_context = TaskContext(
|
||||
taskStep=task_step,
|
||||
taskContext = TaskContext(
|
||||
taskStep=taskStep,
|
||||
workflow=workflow,
|
||||
workflowId=workflow.id,
|
||||
availableDocuments=None,
|
||||
availableConnections=None,
|
||||
previousResults=previous_results,
|
||||
previousResults=previousResults,
|
||||
previousHandover=None,
|
||||
improvements=[],
|
||||
retryCount=0,
|
||||
|
|
@ -361,15 +359,15 @@ class WorkflowManager:
|
|||
}
|
||||
)
|
||||
|
||||
task_result = await handling.executeTask(task_step, workflow, task_context, current_task_index, total_tasks)
|
||||
handover_data = await handling.prepareTaskHandover(task_step, [], task_result, workflow)
|
||||
all_task_results.append({
|
||||
'task_step': task_step,
|
||||
'task_result': task_result,
|
||||
'handover_data': handover_data
|
||||
taskResult = await handling.executeTask(taskStep, workflow, taskContext, currentTaskIndex, totalTasks)
|
||||
handoverData = await handling.prepareTaskHandover(taskStep, [], taskResult, workflow)
|
||||
allTaskResults.append({
|
||||
'taskStep': taskStep,
|
||||
'taskResult': taskResult,
|
||||
'handoverData': handoverData
|
||||
})
|
||||
if task_result.success and task_result.feedback:
|
||||
previous_results.append(task_result.feedback)
|
||||
if taskResult.success and taskResult.feedback:
|
||||
previousResults.append(taskResult.feedback)
|
||||
|
||||
# Mark workflow as completed; error/stop cases update status elsewhere
|
||||
workflow.status = "completed"
|
||||
|
|
@ -384,7 +382,7 @@ class WorkflowManager:
|
|||
logger.info(f"Workflow {workflow.id} was stopped during result processing")
|
||||
|
||||
# Create final stopped message
|
||||
stopped_message = {
|
||||
stoppedMessage = {
|
||||
"workflowId": workflow.id,
|
||||
"role": "assistant",
|
||||
"message": "🛑 Workflow stopped by user",
|
||||
|
|
@ -401,7 +399,7 @@ class WorkflowManager:
|
|||
"taskProgress": "stopped",
|
||||
"actionProgress": "stopped"
|
||||
}
|
||||
self.services.workflow.storeMessageWithDocuments(workflow, stopped_message, [])
|
||||
self.services.workflow.storeMessageWithDocuments(workflow, stoppedMessage, [])
|
||||
|
||||
# Update workflow status to stopped
|
||||
workflow.status = "stopped"
|
||||
|
|
@ -431,7 +429,7 @@ class WorkflowManager:
|
|||
"taskProgress": "stopped",
|
||||
"actionProgress": "stopped"
|
||||
}
|
||||
self.services.workflow.storeMessageWithDocuments(workflow, stopped_message, [])
|
||||
self.services.workflow.storeMessageWithDocuments(workflow, stoppedMessage, [])
|
||||
|
||||
# Update workflow status to stopped
|
||||
workflow.status = "stopped"
|
||||
|
|
@ -453,7 +451,7 @@ class WorkflowManager:
|
|||
return
|
||||
elif workflow.status == 'failed':
|
||||
# Create error message
|
||||
error_message = {
|
||||
errorMessage = {
|
||||
"workflowId": workflow.id,
|
||||
"role": "assistant",
|
||||
"message": f"Workflow failed: {'Unknown error'}",
|
||||
|
|
@ -470,7 +468,7 @@ class WorkflowManager:
|
|||
"taskProgress": "fail",
|
||||
"actionProgress": "fail"
|
||||
}
|
||||
self.services.workflow.storeMessageWithDocuments(workflow, error_message, [])
|
||||
self.services.workflow.storeMessageWithDocuments(workflow, errorMessage, [])
|
||||
|
||||
# Update workflow status to failed
|
||||
workflow.status = "failed"
|
||||
|
|
@ -514,7 +512,7 @@ class WorkflowManager:
|
|||
"taskProgress": "fail",
|
||||
"actionProgress": "fail"
|
||||
}
|
||||
self.services.workflow.storeMessageWithDocuments(workflow, error_message, [])
|
||||
self.services.workflow.storeMessageWithDocuments(workflow, errorMessage, [])
|
||||
|
||||
# Update workflow status to failed
|
||||
workflow.status = "failed"
|
||||
|
|
@ -587,12 +585,12 @@ class WorkflowManager:
|
|||
self.workflowProcessor._checkWorkflowStopped(workflow)
|
||||
|
||||
# Count messages by role
|
||||
user_messages = [msg for msg in workflow.messages if msg.role == 'user']
|
||||
assistant_messages = [msg for msg in workflow.messages if msg.role == 'assistant']
|
||||
userMessages = [msg for msg in workflow.messages if msg.role == 'user']
|
||||
assistantMessages = [msg for msg in workflow.messages if msg.role == 'assistant']
|
||||
|
||||
# Generate summary feedback
|
||||
feedback = f"Workflow completed.\n\n"
|
||||
feedback += f"Processed {len(user_messages)} user inputs and generated {len(assistant_messages)} responses.\n"
|
||||
feedback += f"Processed {len(userMessages)} user inputs and generated {len(assistantMessages)} responses.\n"
|
||||
|
||||
# Add final status
|
||||
if workflow.status == "completed":
|
||||
|
|
@ -724,45 +722,45 @@ class WorkflowManager:
|
|||
"""Set user language for the service center"""
|
||||
self.services.user.language = language
|
||||
|
||||
async def _neutralizeContentIfEnabled(self, content_bytes: bytes, mimeType: str) -> bytes:
|
||||
async def _neutralizeContentIfEnabled(self, contentBytes: bytes, mimeType: str) -> bytes:
|
||||
"""Neutralize content if neutralization is enabled in user settings"""
|
||||
try:
|
||||
# Check if neutralization is enabled
|
||||
config = self.services.neutralization.getConfig()
|
||||
if not config or not config.enabled:
|
||||
return content_bytes
|
||||
return contentBytes
|
||||
|
||||
# Decode content to text for neutralization
|
||||
try:
|
||||
text_content = content_bytes.decode('utf-8')
|
||||
textContent = contentBytes.decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
# Try alternative encodings
|
||||
for enc in ['latin-1', 'cp1252', 'iso-8859-1']:
|
||||
try:
|
||||
text_content = content_bytes.decode(enc)
|
||||
textContent = contentBytes.decode(enc)
|
||||
break
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
else:
|
||||
# If unable to decode, return original bytes (binary content)
|
||||
logger.debug(f"Unable to decode content for neutralization, skipping: {mimeType}")
|
||||
return content_bytes
|
||||
return contentBytes
|
||||
|
||||
# Neutralize the text content
|
||||
# Note: The neutralization service should use names from config when processing
|
||||
result = self.services.neutralization.processText(text_content)
|
||||
result = self.services.neutralization.processText(textContent)
|
||||
if result and 'neutralized_text' in result:
|
||||
neutralized_text = result['neutralized_text']
|
||||
neutralizedText = result['neutralized_text']
|
||||
# Encode back to bytes using the same encoding
|
||||
try:
|
||||
return neutralized_text.encode('utf-8')
|
||||
return neutralizedText.encode('utf-8')
|
||||
except Exception as e:
|
||||
logger.warning(f"Error encoding neutralized text: {str(e)}")
|
||||
return content_bytes
|
||||
return contentBytes
|
||||
else:
|
||||
logger.warning("Neutralization did not return neutralized_text")
|
||||
return content_bytes
|
||||
return contentBytes
|
||||
except Exception as e:
|
||||
logger.error(f"Error during content neutralization: {str(e)}")
|
||||
# Return original content on error
|
||||
return content_bytes
|
||||
return contentBytes
|
||||
|
|
|
|||
Loading…
Reference in a new issue