ai-prof / ai_prof /config.py
pranavkarthik10's picture
Deploy AI Prof hackathon submission
81e3ca2 verified
Raw
History Blame Contribute Delete
3.15 kB
"""Runtime configuration for AI Prof.
Both models are reached over OpenAI-compatible HTTP, which is what the common
self-hosted runtimes expose:
- MiniCPM-V (eyes) -> llama.cpp ``llama-server`` with ``--mmproj``
- Nemotron (brain) -> vLLM / llama.cpp chat endpoint
If a base URL is left blank, that model falls back to MOCK mode so the whole
app still runs end-to-end with no weights — useful for UI work and demos.
"""
from __future__ import annotations
import os
from dataclasses import dataclass
from dotenv import load_dotenv
load_dotenv()
def _clean(value: str | None) -> str | None:
"""Treat blank / placeholder env values as unset."""
if value is None:
return None
value = value.strip()
return value or None
@dataclass(frozen=True)
class ModelConfig:
base_url: str | None
api_key: str
model: str
@property
def is_live(self) -> bool:
return self.base_url is not None
@property
def openai_base_url(self) -> str | None:
"""Return an OpenAI-compatible base URL ending in /v1."""
if self.base_url is None:
return None
base = self.base_url.rstrip("/")
return base if base.endswith("/v1") else f"{base}/v1"
@dataclass(frozen=True)
class Config:
vision: ModelConfig
brain: ModelConfig
tts: ModelConfig
stt: ModelConfig
slide_dpi: int
tts_voice: str
deck_cache_dir: str
hf_deck_cache_repo: str | None
hf_token: str | None
hf_deck_cache_write: bool
@property
def fully_mocked(self) -> bool:
return not self.vision.is_live and not self.brain.is_live
def load_config() -> Config:
return Config(
vision=ModelConfig(
base_url=_clean(os.getenv("VISION_BASE_URL")),
api_key=_clean(os.getenv("VISION_API_KEY")) or "sk-no-key-required",
model=_clean(os.getenv("VISION_MODEL")) or "minicpm-v",
),
brain=ModelConfig(
base_url=_clean(os.getenv("BRAIN_BASE_URL")),
api_key=_clean(os.getenv("BRAIN_API_KEY")) or "sk-no-key-required",
model=_clean(os.getenv("BRAIN_MODEL")) or "nemotron-3-nano",
),
tts=ModelConfig(
base_url=_clean(os.getenv("TTS_BASE_URL")),
api_key=_clean(os.getenv("TTS_API_KEY")) or "sk-no-key-required",
model=_clean(os.getenv("TTS_MODEL")) or "tts-1",
),
stt=ModelConfig(
base_url=_clean(os.getenv("STT_BASE_URL")),
api_key=_clean(os.getenv("STT_API_KEY")) or "sk-no-key-required",
model=_clean(os.getenv("STT_MODEL")) or "whisper-1",
),
slide_dpi=int(_clean(os.getenv("SLIDE_DPI")) or "150"),
tts_voice=_clean(os.getenv("TTS_VOICE")) or "default",
deck_cache_dir=_clean(os.getenv("DECK_CACHE_DIR")) or ".cache/ai-prof/decks",
hf_deck_cache_repo=_clean(os.getenv("HF_DECK_CACHE_REPO")),
hf_token=_clean(os.getenv("HF_TOKEN")),
hf_deck_cache_write=(
(_clean(os.getenv("HF_DECK_CACHE_WRITE")) or "").lower()
in {"1", "true", "yes", "on"}
),
)
CONFIG = load_config()