chatbot / src /models.py
jawadsaghir12's picture
new update
8c77cd6
"""Data models and schemas for the application."""
from pydantic import BaseModel, Field, EmailStr, validator
from typing import Optional
from datetime import datetime
# ===== USER SCHEMAS =====
class UserCreate(BaseModel):
"""What we need to create a user."""
email: EmailStr
name: str = Field(..., min_length=1, max_length=100)
password: str = Field(..., min_length=8)
class UserLogin(BaseModel):
"""What we need to login."""
email: EmailStr
password: str
class UserResponse(BaseModel):
"""What we return about a user."""
id: int
email: str
name: str
created_at: datetime
class Config:
from_attributes = True
class UserUpdate(BaseModel):
"""What can be updated."""
name: Optional[str] = Field(None, min_length=1, max_length=100)
# ===== AUTH SCHEMAS =====
class Token(BaseModel):
"""JWT token response."""
access_token: str
token_type: str = "bearer"
class TokenData(BaseModel):
"""Data encoded in the token."""
user_id: int
email: str
# ===== CHAT SCHEMAS =====
class Message(BaseModel):
"""A chat message."""
id: Optional[int] = None
conversation_id: int
sender_id: int
content: str
created_at: Optional[datetime] = None
class Conversation(BaseModel):
"""A conversation thread."""
id: Optional[int] = None
user_id: int
title: str
created_at: Optional[datetime] = None
# ===== AI QUERY SCHEMAS =====
class QueryRequest(BaseModel):
"""Request for AI query."""
conversation_id: Optional[str] = Field(
default=None,
max_length=128,
description="Optional conversation/session id used for chat memory and per-thread RAG"
)
query: str = Field(
...,
min_length=1,
max_length=1000,
description="The question or prompt to send to the AI"
)
@validator('query')
def validate_query(cls, v):
if not v.strip():
raise ValueError("Query cannot be empty")
# Basic sanitization - remove potential script tags
v = v.replace("<script", "").replace("</script>", "")
return v.strip()
@validator('conversation_id')
def validate_conversation_id(cls, v):
if v is None:
return None
v = str(v).strip()
return v or None
class QueryResponse(BaseModel):
"""Response from AI query."""
success: bool
response: Optional[str] = None
error: Optional[str] = None
timestamp: datetime = Field(default_factory=datetime.utcnow)
requires_auth: bool = False # True if Google authentication is needed
auth_url: Optional[str] = None # Google OAuth URL if authentication is required
class HealthCheckResponse(BaseModel):
"""Health check response."""
status: str # "healthy", "degraded", "unhealthy"
timestamp: datetime = Field(default_factory=datetime.utcnow)
version: str = "1.0.0"
components: dict = {}
# ===== CONVERSATION MANAGEMENT SCHEMAS =====
class MessageResponse(BaseModel):
"""Response format for a single message."""
id: int
sender_id: int
content: str
created_at: datetime
class Config:
from_attributes = True
class ConversationListResponse(BaseModel):
"""Brief conversation info for listing."""
id: int
title: Optional[str] = None
created_at: datetime
last_message_at: datetime
message_count: int
class Config:
from_attributes = True
class ConversationDetailResponse(BaseModel):
"""Full conversation with all messages."""
id: int
title: Optional[str] = None
created_at: datetime
last_message_at: datetime
messages: list[MessageResponse]
class Config:
from_attributes = True
class ChatRequest(BaseModel):
"""Chat message request."""
conversation_id: Optional[int] = Field(
None,
description="Existing conversation ID, or None to create new conversation"
)
query: str = Field(
...,
min_length=1,
max_length=2000,
description="User's message or query"
)
@validator('query')
def validate_query(cls, v):
if not v.strip():
raise ValueError("Query cannot be empty")
return v.strip()
class ChatResponse(BaseModel):
"""Chat message response."""
conversation_id: int
response: str
timestamp: datetime = Field(default_factory=datetime.utcnow)
class Config:
from_attributes = True
class PaginatedConversationsResponse(BaseModel):
"""Paginated list of conversations."""
conversations: list[ConversationListResponse]
total: int
skip: int
limit: int
class Config:
from_attributes = True