Spaces:
Sleeping
Sleeping
| """ | |
| Data models for analytics collections. | |
| """ | |
| import uuid | |
| from datetime import datetime | |
| from typing import Optional, Dict, Any | |
| from pydantic import BaseModel, Field, field_validator | |
| class Session(BaseModel): | |
| """Session analytics model""" | |
| session_id: str = Field(default_factory=lambda: str(uuid.uuid4())) | |
| start_time: datetime = Field(default_factory=datetime.utcnow) | |
| end_time: Optional[datetime] = None | |
| message_count: int = 0 | |
| search_used: bool = False | |
| user_agent: Optional[str] = None | |
| status: str = "active" # active, ended | |
| user_id: Optional[str] = None | |
| def validate_user_id(cls, v): | |
| """Validate user_id format""" | |
| if v is not None: | |
| if not isinstance(v, str): | |
| raise ValueError('user_id must be a string') | |
| if v.strip() == '': | |
| return None # Treat empty string as None (anonymous) | |
| if len(v) > 255: | |
| raise ValueError('user_id must be 255 characters or less') | |
| # Allow ASCII alphanumeric, hyphens, and underscores | |
| if not all((c.isascii() and c.isalnum()) or c in '-_' for c in v): | |
| raise ValueError('user_id can only contain alphanumeric characters, hyphens, and underscores') | |
| return v | |
| def to_dict(self) -> Dict[str, Any]: | |
| """Convert to dictionary for MongoDB insertion""" | |
| data = self.dict() | |
| data["_id"] = self.session_id | |
| return data | |
| def end_session(self): | |
| """Mark session as ended""" | |
| self.end_time = datetime.utcnow() | |
| self.status = "ended" | |
| def duration_seconds(self) -> Optional[int]: | |
| """Calculate session duration in seconds""" | |
| if self.end_time: | |
| return int((self.end_time - self.start_time).total_seconds()) | |
| return None | |
| class Message(BaseModel): | |
| """Message analytics model""" | |
| message_id: str = Field(default_factory=lambda: str(uuid.uuid4())) | |
| session_id: str | |
| timestamp: datetime = Field(default_factory=datetime.utcnow) | |
| prompt_length: int | |
| response_length: int | |
| used_search: bool = False | |
| response_time_ms: int | |
| max_tokens: int = 500 | |
| temperature: float = 0.7 | |
| success: bool = True | |
| error_message: Optional[str] = None | |
| user_id: Optional[str] = None | |
| def validate_user_id(cls, v): | |
| """Validate user_id format""" | |
| if v is not None: | |
| if not isinstance(v, str): | |
| raise ValueError('user_id must be a string') | |
| if v.strip() == '': | |
| return None # Treat empty string as None (anonymous) | |
| if len(v) > 255: | |
| raise ValueError('user_id must be 255 characters or less') | |
| # Allow ASCII alphanumeric, hyphens, and underscores | |
| if not all((c.isascii() and c.isalnum()) or c in '-_' for c in v): | |
| raise ValueError('user_id can only contain alphanumeric characters, hyphens, and underscores') | |
| return v | |
| def to_dict(self) -> Dict[str, Any]: | |
| """Convert to dictionary for MongoDB insertion""" | |
| data = self.dict() | |
| data["_id"] = self.message_id | |
| return data | |
| class SearchAnalytics(BaseModel): | |
| """Search analytics model""" | |
| search_id: str = Field(default_factory=lambda: str(uuid.uuid4())) | |
| message_id: str | |
| timestamp: datetime = Field(default_factory=datetime.utcnow) | |
| search_query: str | |
| search_terms: list[str] = [] | |
| brave_results: int = 0 | |
| duckduckgo_results: int = 0 | |
| total_unique_results: int = 0 | |
| brave_response_time_ms: int = 0 | |
| duckduckgo_response_time_ms: int = 0 | |
| search_engines_used: list[str] = [] | |
| search_success: bool = True | |
| fallback_used: bool = False | |
| user_id: Optional[str] = None | |
| def validate_user_id(cls, v): | |
| """Validate user_id format""" | |
| if v is not None: | |
| if not isinstance(v, str): | |
| raise ValueError('user_id must be a string') | |
| if v.strip() == '': | |
| return None # Treat empty string as None (anonymous) | |
| if len(v) > 255: | |
| raise ValueError('user_id must be 255 characters or less') | |
| # Allow ASCII alphanumeric, hyphens, and underscores | |
| if not all((c.isascii() and c.isalnum()) or c in '-_' for c in v): | |
| raise ValueError('user_id can only contain alphanumeric characters, hyphens, and underscores') | |
| return v | |
| def to_dict(self) -> Dict[str, Any]: | |
| """Convert to dictionary for MongoDB insertion""" | |
| data = self.dict() | |
| data["_id"] = self.search_id | |
| return data |