hyf-backend/th_agenter/models/message.py

70 lines
2.5 KiB
Python

"""Message model."""
from typing import Optional
from sqlalchemy import String, Integer, Text, Enum, JSON
from sqlalchemy.orm import Mapped, mapped_column
import enum
from ..db.base import BaseModel
class MessageRole(str, enum.Enum):
"""Message role enumeration."""
USER = "user"
ASSISTANT = "assistant"
SYSTEM = "system"
class MessageType(str, enum.Enum):
"""Message type enumeration."""
TEXT = "text"
IMAGE = "image"
FILE = "file"
AUDIO = "audio"
class Message(BaseModel):
"""Message model."""
__tablename__ = "messages"
conversation_id: Mapped[int] = mapped_column(Integer, nullable=False) # Removed ForeignKey("conversations.id")
role: Mapped[MessageRole] = mapped_column(Enum(MessageRole), nullable=False)
content: Mapped[str] = mapped_column(Text, nullable=False)
message_type: Mapped[MessageType] = mapped_column(Enum(MessageType), default=MessageType.TEXT, nullable=False)
message_metadata: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True) # Store additional data like file info, tokens used, etc.
# For knowledge base context
context_documents: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True) # Store retrieved document references
# Token usage tracking
prompt_tokens: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
completion_tokens: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
total_tokens: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
# Relationships removed to eliminate foreign key constraints
def __repr__(self):
content_preview = self.content[:50] + "..." if len(self.content) > 50 else self.content
return f"<Message(id={self.id}, role='{self.role}', content='{content_preview}')>"
def to_dict(self, include_metadata=True):
"""Convert to dictionary."""
data = super().to_dict()
if not include_metadata:
data.pop('message_metadata', None)
data.pop('context_documents', None)
data.pop('prompt_tokens', None)
data.pop('completion_tokens', None)
data.pop('total_tokens', None)
return data
@property
def is_from_user(self):
"""Check if message is from user."""
return self.role == MessageRole.USER
@property
def is_from_assistant(self):
"""Check if message is from assistant."""
return self.role == MessageRole.ASSISTANT