gateway/modules/interfaces/lucydomModel.py
2025-05-21 19:38:06 +02:00

246 lines
12 KiB
Python

"""
LucyDOM model classes for the workflow and document system.
"""
from pydantic import BaseModel, Field
from typing import List, Dict, Any, Optional
from datetime import datetime
import uuid
# Get all attributes of the model
def getModelAttributes(modelClass):
return [attr for attr in dir(modelClass)
if not callable(getattr(modelClass, attr))
and not attr.startswith('_')
and attr not in ('metadata', 'query', 'query_class', 'label', 'field_labels')]
# CORE MODELS
class Label(BaseModel):
"""Label for an attribute or a class with support for multiple languages"""
default: str = Field(..., description="Default label text")
translations: Dict[str, str] = Field(default_factory=dict, description="Translations for different languages")
class Config:
title = "Label"
description = "A label with support for multiple languages"
schema_extra = {
"example": {
"default": "Document",
"translations": {
"en": "Document",
"fr": "Document"
}
}
}
def getLabel(self, language: str = None):
"""Returns the label in the specified language, or the default value if not available"""
if language and language in self.translations:
return self.translations[language]
return self.default
class Prompt(BaseModel):
"""Data model for a prompt"""
id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique ID of the prompt")
content: str = Field(description="Content of the prompt")
name: str = Field(description="Display name of the prompt")
mandateId: str = Field(description="ID of the mandate this prompt belongs to")
label: Label = Field(
default=Label(default="Prompt", translations={"en": "Prompt", "fr": "Invite"}),
description="Label for the class"
)
# Labels for attributes
fieldLabels: Dict[str, Label] = {
"id": Label(default="ID", translations={}),
"content": Label(default="Content", translations={"en": "Content", "fr": "Contenu"}),
"name": Label(default="Name", translations={"en": "Label", "fr": "Nom"}),
"mandateId": Label(default="Mandate ID", translations={"en": "Mandate ID", "fr": "ID de mandat"})
}
class FileItem(BaseModel):
"""Data model for a file"""
id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique ID of the data object")
mimeType: str = Field(description="Type of the file MIME type")
fileName: str = Field(description="Name of the file")
fileSize: int = Field(description="Size of the file in bytes")
fileHash: str = Field(description="Hash code for deduplication")
workflowId: Optional[str] = Field(None, description="ID of the associated workflow, if any")
mandateId: str = Field(description="ID of the mandate this file belongs to")
label: Label = Field(
default=Label(default="Data Object", translations={"en": "Data Object", "fr": "Objet de données"}),
description="Label for the class"
)
# Labels for attributes
fieldLabels: Dict[str, Label] = {
"id": Label(default="ID", translations={}),
"mimeType": Label(default="Type", translations={"en": "Type", "fr": "Type"}),
"fileName": Label(default="Filename", translations={"en": "fileName", "fr": "Nom de fichier"}),
"fileSize": Label(default="Size", translations={"en": "Size", "fr": "Taille"}),
"fileHash": Label(default="File Hash", translations={"en": "Hash", "fr": "Hash"}),
"workflowId": Label(default="Workflow ID", translations={"en": "Workflow ID", "fr": "ID du workflow"}),
"mandateId": Label(default="Mandate ID", translations={"en": "Mandate ID", "fr": "ID de mandat"})
}
class FileData(BaseModel):
"""Data model for file content"""
id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique ID of the data object")
data: str = Field(description="content of the file, text or base64 encoded based on base64Encoded flag")
base64Encoded: bool = Field(description="Flag indicating whether the data is base64 encoded")
workflowId: Optional[str] = Field(None, description="ID of the associated workflow, if any")
# WORKFLOW MODELS
class ChatContent(BaseModel):
"""Content of a document in the chat"""
sequenceNr: int = Field(1, description="Sequence number of the content in the source document")
name: str = Field(description="Designation")
mimeType: str = Field(description="MIME type")
data: str = Field(description="Actual content")
metadata: Dict[str, Any] = Field(default_factory=dict, description="Metadata about the content")
class ChatDocument(BaseModel):
"""Document in the chat workflow"""
id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique ID of the document")
fileId: str = Field(description="ID of the referenced file in the database")
fileName: str = Field(description="Name of the file")
fileSize: int = Field(description="Size of the file in bytes")
mimeType: str = Field(description="MIME type")
contents: List[ChatContent] = Field(default=[], description="Document contents")
class ChatStat(BaseModel):
"""Statistics for performance and data usage"""
id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique ID of the stats")
workflowId: str = Field(description="ID of the associated workflow")
processingTime: Optional[float] = Field(None, description="Processing time in seconds")
tokenCount: Optional[int] = Field(None, description="Token count (for AI models)")
bytesSent: Optional[int] = Field(None, description="Bytes sent")
bytesReceived: Optional[int] = Field(None, description="Bytes received")
label: Label = Field(
default=Label(default="Chat Statistics", translations={"en": "Chat Statistics", "fr": "Statistiques de chat"}),
description="Label for the class"
)
# Labels for attributes
fieldLabels: Dict[str, Label] = {
"id": Label(default="ID", translations={}),
"workflowId": Label(default="Workflow ID", translations={"en": "Workflow ID", "fr": "ID du workflow"}),
"processingTime": Label(default="Processing Time", translations={"en": "Processing Time", "fr": "Temps de traitement"}),
"tokenCount": Label(default="Token Count", translations={"en": "Token Count", "fr": "Nombre de tokens"}),
"bytesSent": Label(default="Bytes Sent", translations={"en": "Bytes Sent", "fr": "Octets envoyés"}),
"bytesReceived": Label(default="Bytes Received", translations={"en": "Bytes Received", "fr": "Octets reçus"})
}
class ChatMessage(BaseModel):
"""Message object in the chat workflow"""
id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique ID of the message")
workflowId: str = Field(description="Reference to the parent workflow")
parentMessageId: Optional[str] = Field(None, description="Reference to the replied message")
agentName: Optional[str] = Field(None, description="Name of the agent used")
documents: Optional[List[ChatDocument]] = Field(None, description="Documents in this message")
message: Optional[str] = Field(None, description="Text content of the message")
role: str = Field(description="Role of the sender ('system', 'user', 'assistant')")
status: str = Field(description="Status of the message ('first', 'step', 'last')")
sequenceNr: int = Field(description="Sequence number for sorting")
startedAt: datetime = Field(description="Timestamp for message creation")
finishedAt: Optional[datetime] = Field(None, description="Timestamp for message completion")
stats: Optional[ChatStat] = Field(None, description="Statistics")
class ChatLog(BaseModel):
"""Log entry for a chat workflow"""
id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique ID of the log entry")
workflowId: str = Field(description="ID of the associated workflow")
message: str = Field(description="Log message content")
type: str = Field(description="Type of log ('info', 'warning', 'error')")
timestamp: str = Field(description="Timestamp of the log entry")
agentName: str = Field(description="Name of the agent that created the log")
status: str = Field(description="Status of the workflow at log time")
progress: Optional[int] = Field(None, description="Progress value (0-100)")
class ChatWorkflow(BaseModel):
"""Chat workflow object for multi-agent system"""
id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique ID of the chat workflow")
status: str = Field(description="Status of the chat workflow")
name: Optional[str] = Field(None, description="Name of the chat workflow")
currentRound: int = Field(default=1, description="Current round/iteration")
lastActivity: str = Field(description="Timestamp of the last activity")
startedAt: str = Field(description="Start timestamp")
logs: List[ChatLog] = Field(default=[], description="Log entries")
messages: List[ChatMessage] = Field(default=[], description="Message history")
stats: Optional[ChatStat] = Field(None, description="Statistics")
mandateId: str = Field(description="ID of the mandate this workflow belongs to")
label: Label = Field(
default=Label(default="Chat Workflow", translations={"en": "Chat Workflow", "fr": "Workflow de chat"}),
description="Label for the class"
)
# Labels for attributes
fieldLabels: Dict[str, Label] = {
"id": Label(default="ID", translations={}),
"status": Label(default="Status", translations={"en": "Status", "fr": "Statut"}),
"name": Label(default="Name", translations={"en": "Name", "fr": "Nom"}),
"currentRound": Label(default="Current Round", translations={"en": "Current Round", "fr": "Tour actuel"}),
"lastActivity": Label(default="Last Activity", translations={"en": "Last Activity", "fr": "Dernière activité"}),
"startedAt": Label(default="Started At", translations={"en": "Started At", "fr": "Démarré à"}),
"logs": Label(default="Logs", translations={"en": "Logs", "fr": "Journaux"}),
"messages": Label(default="Messages", translations={"en": "Messages", "fr": "Messages"}),
"stats": Label(default="Statistics", translations={"en": "Statistics", "fr": "Statistiques"}),
"mandateId": Label(default="Mandate ID", translations={"en": "Mandate ID", "fr": "ID de mandat"})
}
# AGENT AND TASK MODELS
class Agent(BaseModel):
"""Data model for an agent"""
id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique ID of the agent")
name: str = Field(description="Name of the agent")
description: str = Field(description="Description of the agent's functionality")
capabilities: List[str] = Field(default=[], description="List of agent capabilities")
class AgentResponse(BaseModel):
"""Response structure returned by agent processing"""
response: str = Field(description="Text response from the agent")
documents: List[ChatDocument] = Field(default=[], description="List of document objects created by the agent")
class TaskItem(BaseModel):
"""Individual task in the workplan"""
sequenceNr: int = Field(description="Sequence number of the task")
agentName: str = Field(description="Name of an available agent")
prompt: str = Field(description="Specific instructions to the agent")
userLanguage: str = Field(description="Language code of the user's request")
filesInput: List[str] = Field(default=[], description="List of input files in format 'fileName[;documentId]'")
filesOutput: List[str] = Field(default=[], description="List of output files in format 'fileName'")
class TaskPlan(BaseModel):
"""Work plan created by project manager"""
fileList: List[str] = Field(default=[], description="List of required result documents in format 'fileName'")
taskItems: List[TaskItem] = Field(default=[], description="Plan for executing agents")
userResponse: str = Field(description="Response to the user explaining the plan")
userLanguage: str = Field(default="en", description="Language code of the user's request")
class UserInputRequest(BaseModel):
"""Request for user input to a running workflow"""
prompt: str = Field(description="Message from the user")
listFileId: List[str] = Field(default=[], description="List of FileItem IDs")
metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata for the request")