104 lines
6.4 KiB
Python
104 lines
6.4 KiB
Python
from pydantic import Field, field_validator
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
model_config = SettingsConfigDict(
|
|
env_file=".env",
|
|
env_file_encoding="utf-8",
|
|
extra="ignore",
|
|
populate_by_name=True,
|
|
)
|
|
|
|
app_env: str = Field(default="development", validation_alias="GEOINTEL_ENV")
|
|
app_version: str = Field(default="0.1.0")
|
|
api_prefix: str = Field(default="/api/v1", validation_alias="GEOINTEL_API_PREFIX")
|
|
database_url: str = Field(
|
|
default="postgresql+psycopg://geointel:geointel@localhost:5432/geointel?connect_timeout=1",
|
|
validation_alias="DATABASE_URL",
|
|
)
|
|
storage_root: str = Field(default="./storage", validation_alias="STORAGE_ROOT")
|
|
max_upload_mb: int = Field(default=500, validation_alias="MAX_UPLOAD_MB")
|
|
orthophoto_enabled: bool = Field(default=True, validation_alias="ORTHOPHOTO_ENABLED")
|
|
orthophoto_wms_url: str = Field(
|
|
default="https://geo.api.vlaanderen.be/OMWRGBMRVL/wms",
|
|
validation_alias="ORTHOPHOTO_WMS_URL",
|
|
)
|
|
orthophoto_wms_layer: str = Field(default="Ortho", validation_alias="ORTHOPHOTO_WMS_LAYER")
|
|
orthophoto_resolution_m: float = Field(default=1.0, gt=0, validation_alias="ORTHOPHOTO_RESOLUTION_M")
|
|
orthophoto_min_side_m: float = Field(default=128.0, gt=0, validation_alias="ORTHOPHOTO_MIN_SIDE_M")
|
|
orthophoto_max_side_m: float = Field(default=1024.0, gt=0, validation_alias="ORTHOPHOTO_MAX_SIDE_M")
|
|
orthophoto_timeout_seconds: int = Field(default=120, ge=1, validation_alias="ORTHOPHOTO_TIMEOUT_SECONDS")
|
|
orthophoto_max_response_mb: int = Field(default=32, ge=1, validation_alias="ORTHOPHOTO_MAX_RESPONSE_MB")
|
|
orthophoto_cache_ttl_hours: int = Field(default=24, ge=0, validation_alias="ORTHOPHOTO_CACHE_TTL_HOURS")
|
|
dhmv_enabled: bool = Field(default=True, validation_alias="DHMV_ENABLED")
|
|
dhmv_wcs_url: str = Field(
|
|
default="https://geo.api.vlaanderen.be/DHMV/wcs",
|
|
validation_alias="DHMV_WCS_URL",
|
|
)
|
|
dhmv_resolution_m: float = Field(default=5.0, ge=1.0, le=10.0, validation_alias="DHMV_RESOLUTION_M")
|
|
dhmv_min_side_m: float = Field(default=10.0, gt=0, validation_alias="DHMV_MIN_SIDE_M")
|
|
dhmv_max_side_m: float = Field(default=20_000.0, gt=0, validation_alias="DHMV_MAX_SIDE_M")
|
|
dhmv_max_pixels: int = Field(default=12_000_000, ge=1, validation_alias="DHMV_MAX_PIXELS")
|
|
dhmv_timeout_seconds: int = Field(default=300, ge=1, validation_alias="DHMV_TIMEOUT_SECONDS")
|
|
dhmv_max_response_mb: int = Field(default=160, ge=1, validation_alias="DHMV_MAX_RESPONSE_MB")
|
|
flood_hazard_enabled: bool = Field(default=True, validation_alias="FLOOD_HAZARD_ENABLED")
|
|
flood_hazard_wcs_url: str = Field(
|
|
default="https://geoservice.waterinfo.be/OGRK/wcs",
|
|
validation_alias="FLOOD_HAZARD_WCS_URL",
|
|
)
|
|
flood_hazard_resolution_m: float = Field(default=5.0, ge=2.0, le=20.0, validation_alias="FLOOD_HAZARD_RESOLUTION_M")
|
|
flood_hazard_min_side_m: float = Field(default=10.0, gt=0, validation_alias="FLOOD_HAZARD_MIN_SIDE_M")
|
|
flood_hazard_max_side_m: float = Field(default=20_000.0, gt=0, validation_alias="FLOOD_HAZARD_MAX_SIDE_M")
|
|
flood_hazard_max_pixels: int = Field(default=12_000_000, ge=1, validation_alias="FLOOD_HAZARD_MAX_PIXELS")
|
|
flood_hazard_timeout_seconds: int = Field(default=300, ge=1, validation_alias="FLOOD_HAZARD_TIMEOUT_SECONDS")
|
|
flood_hazard_max_response_mb: int = Field(default=160, ge=1, validation_alias="FLOOD_HAZARD_MAX_RESPONSE_MB")
|
|
redis_url: str | None = Field(default=None, validation_alias="REDIS_URL")
|
|
log_level: str = Field(default="INFO", validation_alias="GEOINTEL_LOG_LEVEL")
|
|
database_statement_timeout_ms: int = Field(default=5_000, validation_alias="DATABASE_STATEMENT_TIMEOUT_MS")
|
|
yolo_enabled: bool = Field(default=False, validation_alias="YOLO_ENABLED")
|
|
yolo_models_dir: str = Field(default="/app/models", validation_alias="YOLO_MODELS_DIR")
|
|
yolo_model_path: str | None = Field(default=None, validation_alias="YOLO_MODEL_PATH")
|
|
yolo_model_id: str = Field(default="yolo-configured", validation_alias="YOLO_MODEL_ID")
|
|
yolo_model_display_name: str = Field(default="Configured YOLO detector", validation_alias="YOLO_MODEL_DISPLAY_NAME")
|
|
yolo_model_version: str | None = Field(default=None, validation_alias="YOLO_MODEL_VERSION")
|
|
yolo_device: str = Field(default="cpu", validation_alias="YOLO_DEVICE")
|
|
yolo_image_size: int = Field(default=640, validation_alias="YOLO_IMAGE_SIZE")
|
|
yolo_max_tiles: int = Field(default=100, validation_alias="YOLO_MAX_TILES")
|
|
yolo_max_detections: int = Field(default=1000, validation_alias="YOLO_MAX_DETECTIONS")
|
|
yolo_duplicate_iou_threshold: float = Field(default=0.5, ge=0.0, le=1.0, validation_alias="YOLO_DUPLICATE_IOU_THRESHOLD")
|
|
yolo_batch_size: int = Field(default=1, validation_alias="YOLO_BATCH_SIZE")
|
|
ollama_enabled: bool = Field(default=False, validation_alias="OLLAMA_ENABLED")
|
|
ollama_base_url: str = Field(default="http://127.0.0.1:11434", validation_alias="OLLAMA_BASE_URL")
|
|
ollama_default_model: str = Field(default="qwen3.5:9b", validation_alias="OLLAMA_DEFAULT_MODEL")
|
|
ollama_timeout_seconds: int = Field(default=120, ge=5, le=600, validation_alias="OLLAMA_TIMEOUT_SECONDS")
|
|
ollama_max_output_tokens: int = Field(default=700, ge=100, le=4_000, validation_alias="OLLAMA_MAX_OUTPUT_TOKENS")
|
|
ollama_context_tokens: int = Field(default=16_384, ge=4_096, le=131_072, validation_alias="OLLAMA_CONTEXT_TOKENS")
|
|
cors_origins: list[str] | str = Field(
|
|
default=["http://localhost:5173", "http://127.0.0.1:5173"],
|
|
validation_alias="CORS_ORIGINS",
|
|
)
|
|
|
|
@field_validator("cors_origins", mode="before")
|
|
@classmethod
|
|
def parse_cors_origins(cls, value: object) -> list[str]:
|
|
if isinstance(value, str):
|
|
return [item.strip() for item in value.split(",") if item.strip()]
|
|
if isinstance(value, list):
|
|
return value
|
|
if value is None:
|
|
return ["http://localhost:5173", "http://127.0.0.1:5173"]
|
|
return [str(value)]
|
|
|
|
@field_validator("ollama_base_url")
|
|
@classmethod
|
|
def validate_ollama_base_url(cls, value: str) -> str:
|
|
normalized = value.strip().rstrip("/")
|
|
if not normalized.startswith(("http://", "https://")):
|
|
raise ValueError("OLLAMA_BASE_URL must use http or https")
|
|
return normalized
|
|
|
|
|
|
def get_settings() -> Settings:
|
|
return Settings()
|