108 lines
3.5 KiB
Python
108 lines
3.5 KiB
Python
from functools import lru_cache
|
|
from typing import Literal
|
|
|
|
from pydantic import Field, model_validator
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
model_config = SettingsConfigDict(
|
|
env_file=".env",
|
|
env_file_encoding="utf-8",
|
|
case_sensitive=False,
|
|
extra="ignore",
|
|
)
|
|
|
|
app_name: str = "AI模型内部安全测试平台"
|
|
app_env: Literal["test", "production"] = "test"
|
|
app_host: str = "0.0.0.0"
|
|
app_port: int = 8000
|
|
app_debug: bool = True
|
|
app_api_prefix: str = "/api/v1"
|
|
|
|
log_level_test: str = "INFO"
|
|
log_level_production: str = "WARNING"
|
|
log_json: bool = False
|
|
|
|
database_url: str = "sqlite:///./data/platform.db"
|
|
|
|
cors_allow_origins: str = "http://localhost:3000"
|
|
cors_allow_credentials: bool = True
|
|
cors_allow_methods: str = "*"
|
|
cors_allow_headers: str = "*"
|
|
|
|
target_api_type: str = "openai"
|
|
target_base_url: str
|
|
target_chat_path: str = "/chat/completions"
|
|
target_models_path: str = "/models"
|
|
target_model: str = ""
|
|
target_auth_type: str = "none"
|
|
target_api_key: str = ""
|
|
target_auth_header: str = "Authorization"
|
|
target_auth_prefix: str = "Bearer "
|
|
|
|
judge_api_type: str = "openai"
|
|
judge_base_url: str
|
|
judge_chat_path: str = "/chat/completions"
|
|
judge_models_path: str = "/models"
|
|
judge_model: str = ""
|
|
judge_auth_type: str = "bearer"
|
|
judge_api_key: str = ""
|
|
judge_auth_header: str = "Authorization"
|
|
judge_auth_prefix: str = "Bearer "
|
|
|
|
request_timeout_seconds: int = Field(default=180, gt=0)
|
|
request_retry_count: int = Field(default=5, ge=0, le=10)
|
|
request_retry_delay_seconds: int = Field(default=5, gt=0)
|
|
request_retry_max_delay_seconds: int = Field(default=60, ge=5, le=300)
|
|
request_verify_ssl: bool = True
|
|
|
|
auth_token_secret: str = ""
|
|
auth_token_ttl_seconds: int = Field(default=3600, ge=300, le=86400)
|
|
auth_token_refresh_window_seconds: int = Field(default=1800, ge=60, le=43200)
|
|
auth_refresh_token_ttl_seconds: int = Field(default=28800, ge=3600, le=31536000)
|
|
|
|
dataset_path: str = "data/dataset.json"
|
|
output_dir: str = "outputs"
|
|
|
|
@model_validator(mode="after")
|
|
def validate_auth_timing(self):
|
|
if self.auth_token_refresh_window_seconds >= self.auth_token_ttl_seconds:
|
|
raise ValueError(
|
|
"AUTH_TOKEN_REFRESH_WINDOW_SECONDS must be less than AUTH_TOKEN_TTL_SECONDS"
|
|
)
|
|
if self.auth_refresh_token_ttl_seconds < self.auth_token_ttl_seconds:
|
|
raise ValueError(
|
|
"AUTH_REFRESH_TOKEN_TTL_SECONDS must not be shorter than AUTH_TOKEN_TTL_SECONDS"
|
|
)
|
|
return self
|
|
|
|
@property
|
|
def log_level(self) -> str:
|
|
return self.log_level_production if self.app_env == "production" else self.log_level_test
|
|
|
|
@property
|
|
def cors_origins(self) -> list[str]:
|
|
return [x.strip() for x in self.cors_allow_origins.split(",") if x.strip()]
|
|
|
|
@property
|
|
def cors_methods(self) -> list[str]:
|
|
return (
|
|
["*"]
|
|
if self.cors_allow_methods.strip() == "*"
|
|
else [x.strip() for x in self.cors_allow_methods.split(",") if x.strip()]
|
|
)
|
|
|
|
@property
|
|
def cors_headers(self) -> list[str]:
|
|
return (
|
|
["*"]
|
|
if self.cors_allow_headers.strip() == "*"
|
|
else [x.strip() for x in self.cors_allow_headers.split(",") if x.strip()]
|
|
)
|
|
|
|
|
|
@lru_cache
|
|
def get_settings() -> Settings:
|
|
return Settings()
|