""" Configuration module for the VLA Demo System. Loads settings from environment variables (with .env file support). All configuration is centralized here to avoid hardcoded values. """ import os import logging from pathlib import Path from dotenv import load_dotenv # Load .env from project root _PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent load_dotenv(_PROJECT_ROOT / ".env") logger = logging.getLogger(__name__) # --------------------------------------------------------------------------- # LLM Provider Configuration # --------------------------------------------------------------------------- # LLM_PROVIDER selects the language model backend: "openai" or "groq" LLM_PROVIDER: str = os.getenv("LLM_PROVIDER", "openai") # "openai" or "groq" OPENAI_API_KEY: str = os.getenv("OPENAI_API_KEY", "") OPENAI_MODEL: str = os.getenv("OPENAI_MODEL", "gpt-4o-mini") GROQ_API_KEY: str = os.getenv("GROQ_API_KEY", "") GROQ_MODEL: str = os.getenv("GROQ_MODEL", "llama-3.3-70b-versatile") # --------------------------------------------------------------------------- # Vision / Detection Configuration # --------------------------------------------------------------------------- DETECTION_MODEL: str = os.getenv("DETECTION_MODEL", "grounding_dino") # "yolo" or "grounding_dino" YOLO_MODEL: str = os.getenv("YOLO_MODEL", "yolov8n.pt") YOLO_CONFIDENCE: float = float(os.getenv("YOLO_CONFIDENCE", "0.25")) GROUNDING_DINO_MODEL: str = os.getenv( "GROUNDING_DINO_MODEL", "IDEA-Research/grounding-dino-tiny" ) GROUNDING_DINO_CONFIDENCE: float = float(os.getenv("GROUNDING_DINO_CONFIDENCE", "0.3")) # --------------------------------------------------------------------------- # Paths # --------------------------------------------------------------------------- ASSETS_DIR: Path = _PROJECT_ROOT / "assets" DEMO_IMAGES_DIR: Path = ASSETS_DIR / "demo_images" MODELS_DIR: Path = _PROJECT_ROOT / "models" # --------------------------------------------------------------------------- # Logging Setup # --------------------------------------------------------------------------- LOG_LEVEL: str = os.getenv("LOG_LEVEL", "INFO") def setup_logging() -> None: """Configure root logger with a consistent format.""" logging.basicConfig( level=getattr(logging, LOG_LEVEL.upper(), logging.INFO), format="%(asctime)s | %(levelname)-8s | %(name)s | %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) def validate_config() -> list[str]: """ Validate critical configuration values. Returns: List of warning messages for missing/invalid config values. """ warnings: list[str] = [] valid_providers = ("openai", "groq") if LLM_PROVIDER not in valid_providers: warnings.append( f"Unknown LLM_PROVIDER='{LLM_PROVIDER}'. " f"Valid values: {valid_providers}. Defaulting to 'openai'." ) if LLM_PROVIDER == "openai" and not OPENAI_API_KEY: warnings.append( "LLM_PROVIDER='openai' but OPENAI_API_KEY is not set. " "Language reasoning will use fallback mode." ) if LLM_PROVIDER == "groq" and not GROQ_API_KEY: warnings.append( "LLM_PROVIDER='groq' but GROQ_API_KEY is not set. " "Language reasoning will use fallback mode." ) valid_detectors = ("yolo", "grounding_dino") if DETECTION_MODEL not in valid_detectors: warnings.append( f"Unknown DETECTION_MODEL='{DETECTION_MODEL}'. " f"Valid values: {valid_detectors}. Defaulting to 'grounding_dino'." ) return warnings