File size: 3,059 Bytes
ed37502
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
"""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()