"""Configuration loader using Pydantic Settings.""" from __future__ import annotations import os from pathlib import Path from typing import Any import yaml from pydantic import BaseModel, Field from pydantic_settings import BaseSettings # Detect if running on Hugging Face Spaces IS_HF_SPACES = os.environ.get("HF_SPACES") == "1" or os.environ.get("SPACE_ID") is not None # Base paths - use environment variables or defaults if IS_HF_SPACES: BASE_OUTPUT_DIR = Path(os.environ.get("OUTPUT_DIR", "/app/data/output")) BASE_DATA_DIR = Path(os.environ.get("DATA_DIR", "/app/data")) BASE_DB_PATH = os.environ.get("DB_PATH", "/app/data/db/content_engine.db") else: BASE_OUTPUT_DIR = Path("D:/AI automation/output") BASE_DATA_DIR = Path("D:/AI automation/data") BASE_DB_PATH = "D:/AI automation/data/catalog.db" class ComfyUIConfig(BaseModel): url: str = "http://127.0.0.1:8188" max_local_queue_depth: int = 3 min_vram_gb: float = 2.0 class PathsConfig(BaseModel): output_dir: Path = BASE_OUTPUT_DIR data_dir: Path = BASE_DATA_DIR lora_dir: Path = Path("D:/ComfyUI/Models/Lora") if not IS_HF_SPACES else Path("/app/data/loras") checkpoint_dir: Path = Path("D:/ComfyUI/Models/StableDiffusion") if not IS_HF_SPACES else Path("/app/data/models") class DatabaseConfig(BaseModel): url: str = f"sqlite+aiosqlite:///{BASE_DB_PATH}" jobs_url: str = f"sqlite+aiosqlite:///{BASE_DATA_DIR}/jobs.db" class GenerationConfig(BaseModel): default_checkpoint: str = "realisticVisionV51_v51VAE.safetensors" default_steps: int = 28 default_cfg: float = 7.0 default_sampler: str = "dpmpp_2m" default_scheduler: str = "karras" default_width: int = 832 default_height: int = 1216 class SchedulingConfig(BaseModel): posts_per_day: int = 3 peak_hours: list[int] = Field(default_factory=lambda: [10, 14, 20]) sfw_ratio: float = 0.4 class CloudProviderEntry(BaseModel): name: str api_key: str = "" priority: int = 1 class Settings(BaseSettings): comfyui: ComfyUIConfig = Field(default_factory=ComfyUIConfig) paths: PathsConfig = Field(default_factory=PathsConfig) database: DatabaseConfig = Field(default_factory=DatabaseConfig) generation: GenerationConfig = Field(default_factory=GenerationConfig) scheduling: SchedulingConfig = Field(default_factory=SchedulingConfig) cloud_providers: list[CloudProviderEntry] = Field(default_factory=list) def load_settings(config_path: Path | None = None) -> Settings: """Load settings from YAML config file, with env var overrides.""" if config_path is None: if IS_HF_SPACES: config_path = Path("/app/config/settings.yaml") else: config_path = Path("D:/AI automation/content_engine/config/settings.yaml") data: dict[str, Any] = {} if config_path.exists(): with open(config_path) as f: data = yaml.safe_load(f) or {} return Settings(**data) # Global singleton — initialized on import settings = load_settings()