Santhakumar Ramesh
feat: initial deploy to HF Space
3872518
Raw
History Blame Contribute Delete
4.07 kB
"""
Centralized configuration management using environment variables.
"""
import os
import secrets
from dotenv import load_dotenv
from loguru import logger
load_dotenv()
class Config:
# OpenAI
OPENAI_API_KEY: str = os.getenv("OPENAI_API_KEY", "")
OPENAI_MODEL: str = os.getenv("OPENAI_MODEL", "gpt-4o-mini")
NVIDIA_API_KEY: str = os.getenv("NVIDIA_API_KEY", "")
NVIDIA_MODEL: str = os.getenv("NVIDIA_MODEL", "meta/llama-3.1-405b-instruct")
NVIDIA_RERANK_MODEL: str = os.getenv("NVIDIA_RERANK_MODEL", "nvidia/llama-nemotron-rerank-1b-v2")
# Embeddings
# Default: S-BioBERT — medical-domain sentence embeddings (PubMed + SNLI trained)
# Fallback set via env var to any sentence-transformers model or OpenAI
EMBEDDING_MODEL: str = os.getenv(
"EMBEDDING_MODEL", "pritamdeka/S-BioBert-snli-multinli-stsb"
)
# Vector Store
FAISS_INDEX_PATH: str = os.getenv("FAISS_INDEX_PATH", "./vectorstore/faiss_index")
VECTOR_STORE_TYPE: str = os.getenv("VECTOR_STORE_TYPE", "faiss")
# Pinecone (optional)
PINECONE_API_KEY: str = os.getenv("PINECONE_API_KEY", "")
PINECONE_INDEX_NAME: str = os.getenv("PINECONE_INDEX_NAME", "healthcare-rag")
PINECONE_ENVIRONMENT: str = os.getenv("PINECONE_ENVIRONMENT", "us-east-1")
# Tavily web search (optional)
TAVILY_API_KEY: str = os.getenv("TAVILY_API_KEY", "")
# Retrieval
MAX_RETRIEVED_DOCS: int = int(os.getenv("MAX_RETRIEVED_DOCS", "5"))
EVAL_SAMPLE_SIZE: int = 20
# Hybrid Search
RRF_K: int = 60
RERANK_TOP_K: int = int(os.getenv("RERANK_TOP_K", "3"))
CONFIDENCE_THRESHOLD: float = float(os.getenv("CONFIDENCE_THRESHOLD", "0.6"))
# Local LLM (AirLLM privacy mode)
LOCAL_MODE: bool = os.getenv("LOCAL_MODE", "false").lower() == "true"
LOCAL_MODEL_ID: str = os.getenv(
"LOCAL_MODEL_ID",
"mlx-community/Meta-Llama-3-8B-Instruct-4bit"
)
# API
API_HOST: str = os.getenv("API_HOST", "0.0.0.0")
# Render sets PORT; local .env might set API_PORT.
# We prioritize PORT to ensure Render's load balancer can reach the app.
API_PORT: int = int(os.getenv("PORT") or os.getenv("API_PORT") or "8000")
# Logging
LOG_LEVEL: str = os.getenv("LOG_LEVEL", "INFO")
APP_ENV: str = os.getenv("APP_ENV", "development")
# Security
# JWT secret key — defaults to a random value if not set (tokens won't survive restarts).
# Set a stable value via env var in production.
JWT_SECRET_KEY: str = os.getenv("JWT_SECRET_KEY") or secrets.token_urlsafe(32)
# Comma-separated allowed CORS origins.
# Use "*" only for local dev; always restrict in production.
CORS_ORIGINS: str = os.getenv("CORS_ORIGINS", "*")
# Error monitoring (optional)
SENTRY_DSN: str = os.getenv("SENTRY_DSN", "")
# 0.0 disables tracing; set to 0.1 or similar if you want performance traces.
SENTRY_TRACES_SAMPLE_RATE: float = float(os.getenv("SENTRY_TRACES_SAMPLE_RATE", "0.0"))
@classmethod
def validate(cls):
# Check if keys are non-empty AND not placeholders
def is_placeholder(key):
return not key or "your-" in key.lower() or "sk-" == key or "nvapi-" == key
if is_placeholder(cls.OPENAI_API_KEY):
logger.warning("OPENAI_API_KEY is missing or using a placeholder!")
# Mask keys for logging
def mask(key: str): return f"{key[:8]}...{key[-4:]}" if len(key) > 8 else "****"
logger.info("Config status:")
logger.info(f" - OpenAI Model: {cls.OPENAI_MODEL}")
logger.info(f" - Vector Store: {cls.VECTOR_STORE_TYPE}")
if not is_placeholder(cls.NVIDIA_API_KEY):
logger.info(f" - NVIDIA Engine: {cls.NVIDIA_MODEL} (Key: {mask(cls.NVIDIA_API_KEY)})")
else:
logger.info(" - NVIDIA Engine: INACTIVE (Missing API Key)")
if is_placeholder(cls.OPENAI_API_KEY):
logger.info(" - OpenAI Status: INACTIVE (Missing API Key)")
else:
logger.info(" - OpenAI Status: ACTIVE")
config = Config()