RavindranadhM's picture
Simplify deployed UX and remove surface gate flow
c36c5e5 verified
Raw
History Blame Contribute Delete
8.01 kB
import os
from dataclasses import dataclass, field
from pathlib import Path
from dotenv import load_dotenv
BASE_DIR = Path(__file__).resolve().parent.parent
load_dotenv(BASE_DIR / ".env")
def _resolve_path(env_name: str, default_relative_path: str) -> str:
raw_value = os.getenv(env_name)
path = Path(raw_value) if raw_value else BASE_DIR / default_relative_path
return str(path if path.is_absolute() else (BASE_DIR / path).resolve())
def _resolve_optional_path(
env_name: str,
default_relative_path: str | None = None,
) -> str | None:
raw_value = os.getenv(env_name)
if raw_value:
path = Path(raw_value)
return str(path if path.is_absolute() else (BASE_DIR / path).resolve())
if not default_relative_path:
return None
default_path = (BASE_DIR / default_relative_path).resolve()
if default_path.exists():
return str(default_path)
return None
def _parse_origins() -> tuple[str, ...]:
raw_origins = os.getenv(
"CORS_ORIGINS",
"http://127.0.0.1:5173,http://localhost:5173",
)
return tuple(
origin.strip()
for origin in raw_origins.split(",")
if origin.strip()
)
def _parse_bool(name: str, default: bool) -> bool:
raw_value = os.getenv(name)
if raw_value is None:
return default
return raw_value.strip().lower() in {"1", "true", "yes", "on"}
@dataclass(frozen=True)
class Settings:
"""
Central configuration for the inspection system.
"""
# -----------------------------
# PATHS
# -----------------------------
BASE_DIR: str = str(BASE_DIR)
MODEL_PATH: str = field(
default_factory=lambda: _resolve_path("MODEL_PATH", "models/steel_inspection.pt")
)
IMAGE_FOLDER: str = field(
default_factory=lambda: _resolve_path("IMAGE_FOLDER", "test_images")
)
REPORT_FOLDER: str = field(
default_factory=lambda: _resolve_path("REPORT_FOLDER", "reports")
)
FRONTEND_DIST: str = field(
default_factory=lambda: _resolve_path("FRONTEND_DIST", "dashboard/dist")
)
# -----------------------------
# DEMO / SIMULATION SETTINGS
# -----------------------------
IMAGE_REPEAT: int = field(default_factory=lambda: int(os.getenv("IMAGE_REPEAT", "5")))
BLANK_FRAMES: int = field(default_factory=lambda: int(os.getenv("BLANK_FRAMES", "3")))
# -----------------------------
# TRACKING / LIFECYCLE
# -----------------------------
MAX_MISSING_FRAMES: int = field(
default_factory=lambda: int(os.getenv("MAX_MISSING_FRAMES", "5"))
)
# -----------------------------
# MODEL / INFERENCE SETTINGS
# -----------------------------
CONF_THRESHOLD: float = field(default_factory=lambda: float(os.getenv("CONF_THRESHOLD", "0.20")))
SECONDARY_CONF_THRESHOLD: float = field(
default_factory=lambda: float(os.getenv("SECONDARY_CONF_THRESHOLD", "0.25"))
)
IMAGE_SIZE: int = field(default_factory=lambda: int(os.getenv("IMAGE_SIZE", "896")))
MIN_DEFECT_AREA: int = field(default_factory=lambda: int(os.getenv("MIN_DEFECT_AREA", "120")))
MAX_AREA_RATIO: float = field(default_factory=lambda: float(os.getenv("MAX_AREA_RATIO", "0.12")))
SURFACE_GATE_ENABLED: bool = field(
default_factory=lambda: _parse_bool("SURFACE_GATE_ENABLED", False)
)
SURFACE_DETECTOR_PATH: str | None = field(
default_factory=lambda: _resolve_optional_path(
"SURFACE_DETECTOR_PATH",
"models/steel_surface_detector.pt",
)
)
SURFACE_DETECTOR_CLASS_NAME: str = field(
default_factory=lambda: os.getenv("SURFACE_DETECTOR_CLASS_NAME", "steel_surface")
)
SURFACE_DETECTOR_CONFIDENCE: float = field(
default_factory=lambda: float(os.getenv("SURFACE_DETECTOR_CONFIDENCE", "0.40"))
)
SURFACE_DETECTOR_MIN_AREA_RATIO: float = field(
default_factory=lambda: float(os.getenv("SURFACE_DETECTOR_MIN_AREA_RATIO", "0.12"))
)
SURFACE_DETECTOR_EXPAND_RATIO: float = field(
default_factory=lambda: float(os.getenv("SURFACE_DETECTOR_EXPAND_RATIO", "0.04"))
)
SURFACE_DETECTOR_IMAGE_SIZE: int = field(
default_factory=lambda: int(os.getenv("SURFACE_DETECTOR_IMAGE_SIZE", "640"))
)
SURFACE_CLASSIFIER_PATH: str | None = field(
default_factory=lambda: _resolve_optional_path(
"SURFACE_CLASSIFIER_PATH",
"models/steel_surface_classifier.pt",
)
)
SURFACE_CLASSIFIER_STEEL_LABEL: str = field(
default_factory=lambda: os.getenv("SURFACE_CLASSIFIER_STEEL_LABEL", "steel")
)
SURFACE_MIN_STEEL_CONFIDENCE: float = field(
default_factory=lambda: float(os.getenv("SURFACE_MIN_STEEL_CONFIDENCE", "0.55"))
)
SURFACE_GRAY_DELTA: int = field(
default_factory=lambda: int(os.getenv("SURFACE_GRAY_DELTA", "16"))
)
SURFACE_MIN_GRAY_RATIO: float = field(
default_factory=lambda: float(os.getenv("SURFACE_MIN_GRAY_RATIO", "0.72"))
)
SURFACE_LOW_SAT_PIXEL_THRESHOLD: int = field(
default_factory=lambda: int(os.getenv("SURFACE_LOW_SAT_PIXEL_THRESHOLD", "45"))
)
SURFACE_MIN_LOW_SAT_RATIO: float = field(
default_factory=lambda: float(os.getenv("SURFACE_MIN_LOW_SAT_RATIO", "0.78"))
)
SURFACE_MAX_MEAN_SATURATION: float = field(
default_factory=lambda: float(os.getenv("SURFACE_MAX_MEAN_SATURATION", "40"))
)
SURFACE_MAX_COLORFULNESS: float = field(
default_factory=lambda: float(os.getenv("SURFACE_MAX_COLORFULNESS", "24"))
)
SURFACE_MAX_SKIN_RATIO: float = field(
default_factory=lambda: float(os.getenv("SURFACE_MAX_SKIN_RATIO", "0.16"))
)
SURFACE_MIN_TEXTURE_VARIANCE: float = field(
default_factory=lambda: float(os.getenv("SURFACE_MIN_TEXTURE_VARIANCE", "80"))
)
# -----------------------------
# API / UI
# -----------------------------
CORS_ORIGINS: tuple[str, ...] = field(default_factory=_parse_origins)
REPORT_FETCH_LIMIT: int = field(
default_factory=lambda: int(os.getenv("REPORT_FETCH_LIMIT", "50"))
)
MAX_UPLOAD_SIZE_MB: int = field(
default_factory=lambda: int(os.getenv("MAX_UPLOAD_SIZE_MB", "8"))
)
WEBSOCKET_HEARTBEAT_SECONDS: int = field(
default_factory=lambda: int(os.getenv("WEBSOCKET_HEARTBEAT_SECONDS", "20"))
)
ENABLE_LLM_REPORTS: bool = field(
default_factory=lambda: _parse_bool("ENABLE_LLM_REPORTS", True)
)
LLM_PROVIDER: str = field(
default_factory=lambda: os.getenv("LLM_PROVIDER", "auto")
)
OLLAMA_BASE_URL: str = field(
default_factory=lambda: os.getenv("OLLAMA_BASE_URL", "http://127.0.0.1:11434")
)
OLLAMA_MODEL: str = field(
default_factory=lambda: os.getenv("OLLAMA_MODEL", "llama3")
)
OLLAMA_TIMEOUT_SECONDS: float = field(
default_factory=lambda: float(os.getenv("OLLAMA_TIMEOUT_SECONDS", "6"))
)
HF_TOKEN: str | None = field(default_factory=lambda: os.getenv("HF_TOKEN"))
HF_CHAT_MODEL: str = field(
default_factory=lambda: os.getenv("HF_CHAT_MODEL", "meta-llama/Llama-3.1-8B-Instruct:cerebras")
)
HF_ROUTER_BASE_URL: str = field(
default_factory=lambda: os.getenv("HF_ROUTER_BASE_URL", "https://router.huggingface.co/v1")
)
OPENROUTER_API_KEY: str | None = field(default_factory=lambda: os.getenv("OPENROUTER_API_KEY"))
OPENROUTER_MODEL: str = field(
default_factory=lambda: os.getenv("OPENROUTER_MODEL", "openrouter/free")
)
OPENROUTER_BASE_URL: str = field(
default_factory=lambda: os.getenv("OPENROUTER_BASE_URL", "https://openrouter.ai/api/v1")
)
# -----------------------------
# DATABASE
# -----------------------------
DATABASE_URL: str | None = field(default_factory=lambda: os.getenv("DATABASE_URL"))
@property
def max_upload_bytes(self) -> int:
return self.MAX_UPLOAD_SIZE_MB * 1024 * 1024
settings = Settings()