"""Runtime configuration loaded from environment variables. Required: HY_API_KEY API key for the upstream OpenAI-compatible endpoint. HY_BASE_URL OpenAI-compatible base URL of the upstream endpoint. HY_MODEL Model name passed to chat.completions.create. Optional: HY_LOG_LEVEL One of DEBUG / INFO / WARNING / ERROR (default: WARNING). """ from __future__ import annotations import logging import os from openai import OpenAI API_KEY = os.environ.get("HY_API_KEY", "").strip() BASE_URL = os.environ.get("HY_BASE_URL", "").strip() MODEL = os.environ.get("HY_MODEL", "").strip() LOG_LEVEL = os.environ.get("HY_LOG_LEVEL", "WARNING").upper() # Configure logging once at import time. Kept module-level (rather than # behind ``if __name__ == "__main__"``) because every module in the # project does ``logging.getLogger(__name__)`` and expects the format / # level to already be set up. The handler is only installed if no other # handler exists — embedders that have already configured logging are # left untouched. if not logging.getLogger().handlers: logging.basicConfig( level=getattr(logging, LOG_LEVEL, logging.WARNING), format="%(asctime)s %(levelname)s %(name)s: %(message)s", ) logger = logging.getLogger("Hy3") # Surface missing required env vars loudly at import time. We don't # raise — that would prevent the Gradio server from even starting up # (and HuggingFace Spaces would just show a blank build-failed page), # making it harder to debug. Instead: warn now, and the per-request # code paths will still fail cleanly with the upstream API's own # error message. _missing = [ name for name, val in ( ("HY_API_KEY", API_KEY), ("HY_BASE_URL", BASE_URL), ("HY_MODEL", MODEL), ) if not val ] if _missing: logger.warning( "Required env var(s) not set: %s. " "The app will boot but every chat request will fail until they are " "configured (e.g. as HuggingFace Space secrets / variables).", ", ".join(_missing), ) # ``base_url=""`` would be passed through to httpx and produce undefined # request URLs. ``None`` makes the OpenAI SDK fall back to its default # (api.openai.com), which is at least a well-defined behaviour. client = OpenAI( api_key=API_KEY or "missing-api-key", base_url=BASE_URL or None, )