PlanMate / planmate /config.py
Memoona648's picture
Update planmate/config.py
fdabb60 verified
raw
history blame
3.95 kB
import os
import time
import requests
from itertools import cycle
# Try to load .env (local dev only, ignored in production)
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
pass
# Streamlit-safe logging
def log_message(msg, level="info"):
try:
import streamlit as st
if level == "error":
st.error(msg)
elif level == "warning":
st.warning(msg)
else:
st.info(msg)
except ImportError:
print(f"[{level.upper()}] {msg}")
APP_TITLE = "PlanMate"
APP_TAGLINE = "AI Powered smart trip planner"
THEME = {
"bg": "#fcfcfc",
"text": "#383838",
"label": "#153d15",
"border": "#153d15",
}
CURRENCY = "PKR"
UNITS = "metric"
LANGUAGE = "en"
# API Base URLs
AMADEUS_BASE = "https://test.api.amadeus.com"
OPENWEATHER_BASE = "https://api.openweathermap.org"
OPENTRIPMAP_BASE = "https://api.opentripmap.com/0.1/en"
# ---------- Hugging Face Secrets Configuration ----------
def get_secret(key, default=None):
"""
Get secret from environment first (production),
fallback to .env for local dev.
"""
value = os.getenv(key)
if value is None and default is not None:
return default
elif value is None:
log_message(f"Missing required secret: {key}", level="error")
raise RuntimeError(f"Missing required secret: {key}")
return value
def get_env(key: str) -> str:
val = os.getenv(key)
if not val:
raise RuntimeError(f"Missing required environment variable: {key}")
return val
# ---------- Gemini Key Rotation ----------
gemini_keys = os.getenv("GEMINI_API_KEYS", "").split(",")
gemini_keys = [k.strip() for k in gemini_keys if k.strip()]
if not gemini_keys:
raise RuntimeError("No GEMINI_API_KEYS found in environment!")
gemini_cycle = cycle(gemini_keys)
_current_gemini_key = next(gemini_cycle)
def get_gemini_key():
"""Get the current Gemini API key"""
return _current_gemini_key
def rotate_gemini_key():
"""Rotate to the next Gemini API key (when quota exceeded)"""
global _current_gemini_key
_current_gemini_key = next(gemini_cycle)
log_message(f"Rotated to new Gemini API key: {_current_gemini_key}", level="warning")
return _current_gemini_key
# ---------- Gemini Helper Function ----------
def make_gemini_request(prompt, model="gemini-2.0-flash-lite", max_retries=3):
"""
Make a Gemini API request with automatic key rotation on quota errors.
"""
import google.generativeai as genai
for attempt in range(max_retries):
try:
# Configure SDK with current key
genai.configure(api_key=get_gemini_key())
# Create the model
model_instance = genai.GenerativeModel(model)
# Generate response
response = model_instance.generate_content(prompt)
return response.text # or response.candidates, depending on usage
except Exception as e:
error_message = str(e)
# Case 1: Quota exceeded (429)
if "429" in error_message or "quota" in error_message.lower():
rotate_gemini_key()
time.sleep(2) # short delay before retry
continue
# Case 2: Network/HTTP error
elif isinstance(e, requests.exceptions.RequestException):
log_message(f"Network issue: {e}. Retrying...", level="warning")
time.sleep(2)
continue
# Any other error → stop immediately
raise e
raise RuntimeError("Gemini request failed after rotating all keys")
# ---------- Other API Keys ----------
def get_amadeus_credentials():
return get_secret("AMADEUS_CLIENT_ID"), get_secret("AMADEUS_CLIENT_SECRET")
def get_openweather_key():
return get_secret("OPENWEATHER_API_KEY")
def get_opentripmap_key():
return get_secret("OPENTRIPMAP_API_KEY")