File size: 4,742 Bytes
aeb3f7c
 
 
 
 
 
 
 
 
 
d7f7508
 
 
 
 
 
 
 
 
 
aeb3f7c
 
 
 
 
 
d7f7508
 
aeb3f7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f277022
 
 
 
aeb3f7c
f277022
aeb3f7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
aec570d
aeb3f7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
"""Configuration management using Pydantic settings."""

import os
from typing import List, Literal

from pydantic import Field, field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    """
    Application settings with environment variable support.

    Settings are loaded from (in order of precedence):
    1. Environment variables
    2. .env file (if present)
    3. Default values

    Works without .env file for HuggingFace Spaces and containerized deployments.
    """

    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        case_sensitive=False,
        extra="ignore",
        # Don't error if .env file is missing (for HF Spaces, Docker, etc.)
        env_ignore_empty=True,
    )

    # Application Settings
    app_name: str = Field(default="AI Writing Studio", description="Application name")
    app_version: str = Field(default="1.0.0", description="Application version")
    environment: Literal["development", "staging", "production"] = Field(
        default="development", description="Runtime environment"
    )
    debug: bool = Field(default=False, description="Enable debug mode")

    # Server Configuration
    host: str = Field(default="0.0.0.0", description="Server host")
    port: int = Field(default=7860, ge=1, le=65535, description="Server port")
    server_workers: int = Field(default=4, ge=1, description="Number of worker processes")

    # Model Configuration
    default_model: str = Field(
        default="google/flan-t5-base",
        description="Default HuggingFace model (instruction-tuned for revision)"
    )
    max_model_length: int = Field(default=512, ge=1, description="Maximum model input length")
    default_max_length: int = Field(default=512, ge=1, description="Default generation length")
    default_num_sequences: int = Field(default=1, ge=1, description="Number of sequences")

    # Security
    allowed_origins: str = Field(
        default="http://localhost:7860,http://127.0.0.1:7860",
        description="Comma-separated CORS origins",
    )
    rate_limit_per_minute: int = Field(default=10, ge=1, description="Rate limit per minute")
    max_text_length: int = Field(
        default=10000, ge=1, description="Maximum input text length"
    )
    enable_auth: bool = Field(default=False, description="Enable authentication")
    secret_key: str = Field(default="", description="Secret key for sessions")

    # Logging
    log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] = Field(
        default="INFO", description="Logging level"
    )
    log_format: Literal["json", "text"] = Field(default="json", description="Log format")
    log_file_path: str = Field(default="./logs/app.log", description="Log file path")
    log_max_bytes: int = Field(default=10485760, ge=1, description="Max log file size")
    log_backup_count: int = Field(default=5, ge=0, description="Number of log backups")

    # Monitoring
    enable_metrics: bool = Field(default=True, description="Enable Prometheus metrics")
    metrics_port: int = Field(default=8000, ge=1, le=65535, description="Metrics port")

    # Cache Configuration
    enable_cache: bool = Field(default=True, description="Enable caching")
    cache_ttl: int = Field(default=3600, ge=1, description="Cache TTL in seconds")
    cache_max_size: int = Field(default=100, ge=1, description="Maximum cache entries")

    # Feature Flags
    enable_diff_highlighting: bool = Field(default=True, description="Enable diff view")
    enable_rubric_scoring: bool = Field(default=True, description="Enable rubric scoring")
    enable_prompt_packs: bool = Field(default=True, description="Enable prompt packs")

    @field_validator("allowed_origins")
    @classmethod
    def parse_origins(cls, v: str) -> List[str]:
        """Parse comma-separated origins into a list."""
        if isinstance(v, str):
            return [origin.strip() for origin in v.split(",") if origin.strip()]
        return v

    @field_validator("log_file_path")
    @classmethod
    def ensure_directory_exists(cls, v: str) -> str:
        """Ensure directory exists for file paths."""
        directory = os.path.dirname(v) if os.path.splitext(v)[1] else v
        if directory and not os.path.exists(directory):
            os.makedirs(directory, exist_ok=True)
        return v

    @property
    def is_production(self) -> bool:
        """Check if running in production."""
        return self.environment == "production"

    @property
    def is_development(self) -> bool:
        """Check if running in development."""
        return self.environment == "development"


# Global settings instance
settings = Settings()