Spaces:
Build error
Build error
| """Settings for the Chattr app.""" | |
| from enum import Enum | |
| from logging import CRITICAL, DEBUG, ERROR, INFO, NOTSET, WARNING | |
| from pathlib import Path | |
| from typing import Self | |
| from agno.utils.log import log_error, log_info | |
| from dotenv import load_dotenv | |
| from pydantic import ( | |
| BaseModel, | |
| DirectoryPath, | |
| Field, | |
| FilePath, | |
| HttpUrl, | |
| SecretStr, | |
| computed_field, | |
| model_validator, | |
| ) | |
| from pydantic_settings import BaseSettings, SettingsConfigDict | |
| from chattr.app.scheme import MCPScheme | |
| load_dotenv() | |
| class MemorySettings(BaseModel): | |
| """Settings for memory configuration.""" | |
| collection_name: str = Field(default="memories") | |
| embedding_dims: int = Field(default=384) | |
| class VectorDatabaseSettings(BaseModel): | |
| """Settings for vector database configuration.""" | |
| name: str = Field(default="chattr") | |
| url: HttpUrl = HttpUrl("http://localhost:6333") | |
| class MCPSettings(BaseModel): | |
| """Settings for MCP configuration.""" | |
| path: FilePath = Field(default_factory=lambda: Path.cwd() / "mcp.json") | |
| def is_valid(self) -> Self: | |
| """Validate that the MCP config file is a valid JSON file.""" | |
| if self.path: | |
| if self.path.suffix != ".json": | |
| msg = "MCP config file must be a JSON file" | |
| raise ValueError(msg) | |
| if self.path.stem != "mcp": | |
| msg = "MCP config file must be named 'mcp.json'" | |
| raise ValueError(msg) | |
| return self | |
| def is_valid_scheme(self) -> Self: | |
| """Validate that the MCP config file has a valid scheme.""" | |
| if self.path and self.path.exists(): | |
| _ = MCPScheme.model_validate_json(self.path.read_text()) | |
| return self | |
| class DirectorySettings(BaseModel): | |
| """Settings for application directories.""" | |
| base: DirectoryPath = Field(default_factory=Path.cwd, frozen=True) | |
| def assets(self) -> DirectoryPath: | |
| """Path to the assets directory.""" | |
| return self.base / "assets" | |
| def audio(self) -> DirectoryPath: | |
| """Path to the audio directory.""" | |
| return self.assets / "audio" | |
| def video(self) -> DirectoryPath: | |
| """Path to the video directory.""" | |
| return self.assets / "video" | |
| def prompts(self) -> DirectoryPath: | |
| """Path to the prompts directory.""" | |
| return self.assets / "prompts" | |
| def create_missing_dirs(self) -> Self: | |
| """ | |
| Ensure that all specified directories exist, creating them if necessary. | |
| Checks and creates any missing directories defined in the `DirectorySettings`. | |
| Returns: | |
| Self: The validated DirectorySettings instance. | |
| """ | |
| for directory in [self.base, self.assets, self.audio, self.video, self.prompts]: | |
| if not directory.exists(): | |
| try: | |
| directory.mkdir(parents=True, exist_ok=True) | |
| log_info(f"Created directory {directory}.") | |
| except OSError as e: | |
| log_error(f"Error creating directory {directory}: {e}") | |
| raise | |
| return self | |
| class ModelSettings(BaseModel): | |
| """Settings related to model execution.""" | |
| url: HttpUrl | None = Field(default=None) | |
| name: str | None = Field(default=None) | |
| api_key: SecretStr | None = Field(default=None) | |
| temperature: float = Field(default=0.0, ge=0.0, le=1.0) | |
| cache_response: bool = Field(default=True) | |
| def check_param_exist(self) -> Self: | |
| """Validate the existence of required credentials for the model provider.""" | |
| if self.url: | |
| if not self.api_key or not self.api_key.get_secret_value(): | |
| _msg: str = ( | |
| "You need to provide API Key for the Model provider: Set via `MODEL__API_KEY`" | |
| ) | |
| raise ValueError(_msg) | |
| if not self.name: | |
| _msg: str = ( | |
| "You need to provide Model name for the Model provider: Set via `MODEL__NAME`" | |
| ) | |
| raise ValueError(_msg) | |
| return self | |
| class CharacterSettings(BaseModel): | |
| """Settings related to character configuration.""" | |
| name: str | None = Field(default=None) | |
| class LogLevel(Enum): | |
| """Logging levels.""" | |
| CRITICAL = CRITICAL | |
| ERROR = ERROR | |
| WARNING = WARNING | |
| INFO = INFO | |
| DEBUG = DEBUG | |
| NOTSET = NOTSET | |
| class LoggerSettings(BaseModel): | |
| """Settings related to logger configuration.""" | |
| name: str = Field(default="chattr", frozen=True) | |
| level: LogLevel = Field(default=LogLevel.INFO) | |
| propagate: bool = Field(default=False) | |
| format: str = Field(default="%(name)s | %(process)d | %(message)s") | |
| class Settings(BaseSettings): | |
| """Configuration for the Chattr app.""" | |
| model_config = SettingsConfigDict( | |
| env_nested_delimiter="__", | |
| env_parse_none_str="None", | |
| env_file=".env", | |
| extra="ignore", | |
| ) | |
| directory: DirectorySettings = Field(default_factory=DirectorySettings, frozen=True) | |
| model: ModelSettings = Field(default_factory=ModelSettings) | |
| memory: MemorySettings = Field(default_factory=MemorySettings) | |
| vector_database: VectorDatabaseSettings = Field( | |
| default_factory=VectorDatabaseSettings, | |
| ) | |
| mcp: MCPSettings = Field(default_factory=MCPSettings) | |
| character: CharacterSettings = Field(default_factory=CharacterSettings) | |
| log: LoggerSettings = Field(default_factory=LoggerSettings) | |
| debug: bool = Field(default=False) | |
| timezone: str = Field(default="Africa/Cairo") | |
| if __name__ == "__main__": | |
| from rich import print as rprint | |
| rprint(Settings().model_dump_json(indent=4)) | |