Download app/utils/api_key_runtime.py from Himankpro/Sub: direct link, hf CLI and curl.
- Browser
- Download file 4.27 kB
-
https://huggingface.co/spaces/Himankpro/Sub/resolve/main/app/utils/api_key_runtime.py
- Command line
-
hf download hf://spaces/Himankpro/Sub/app/utils/api_key_runtime.py
-
curl -L -o api_key_runtime.py https://huggingface.co/spaces/Himankpro/Sub/resolve/main/app/utils/api_key_runtime.py
4.27 kB
| """ | |
| Shared LLM + Zep API key slot (same index for both) with rate-limit handling: | |
| try primary → on limit try secondary → on limit sleep 60s → retry from primary once more. | |
| """ | |
| from __future__ import annotations | |
| import contextvars | |
| import time | |
| from typing import Any, Callable, TypeVar | |
| from ..config import Config | |
| from ..utils.logger import get_logger | |
| logger = get_logger("mirofish.api_key_runtime") | |
| T = TypeVar("T") | |
| _key_slot: contextvars.ContextVar[int] = contextvars.ContextVar("miro_api_key_slot", default=0) | |
| def reset_pipeline_api_keys() -> None: | |
| """Call at the start of each full pipeline run (worker thread).""" | |
| _key_slot.set(0) | |
| def current_key_slot() -> int: | |
| return _key_slot.get() | |
| def _max_key_slots() -> int: | |
| lk = Config.get_llm_api_keys() | |
| zk = Config.get_zep_api_keys() | |
| n = max(len(lk or []), len(zk or []), 1) | |
| return n | |
| def set_key_slot(i: int) -> None: | |
| n = _max_key_slots() | |
| _key_slot.set(max(0, min(i, n - 1))) | |
| def get_llm_key() -> str | None: | |
| keys = Config.get_llm_api_keys() | |
| if not keys: | |
| return None | |
| i = min(_key_slot.get(), len(keys) - 1) | |
| return keys[i] | |
| def get_zep_key() -> str | None: | |
| keys = Config.get_zep_api_keys() | |
| if not keys: | |
| return None | |
| i = min(_key_slot.get(), len(keys) - 1) | |
| return keys[i] | |
| def is_rate_limit_error(exc: BaseException) -> bool: | |
| try: | |
| import openai | |
| if isinstance(exc, getattr(openai, "RateLimitError", ())): | |
| return True | |
| if isinstance(exc, getattr(openai, "APIStatusError", ())): | |
| if getattr(exc, "status_code", None) == 429: | |
| return True | |
| except Exception: | |
| pass | |
| st = getattr(exc, "status_code", None) | |
| if st == 429: | |
| return True | |
| msg = str(exc).lower() | |
| for phrase in ( | |
| "rate limit", | |
| "429", | |
| "too many requests", | |
| "quota", | |
| "resource_exhausted", | |
| "resource exhausted", | |
| "throttl", | |
| "over capacity", | |
| "capacity", | |
| ): | |
| if phrase in msg: | |
| return True | |
| return False | |
| def is_auth_or_invalid_key_error(exc: BaseException) -> bool: | |
| """401 / invalid API key — rotate to next paired slot when LLM_2/ZEP_2 exist.""" | |
| try: | |
| import openai | |
| if isinstance(exc, getattr(openai, "AuthenticationError", ())): | |
| return True | |
| if isinstance(exc, getattr(openai, "APIStatusError", ())): | |
| if getattr(exc, "status_code", None) == 401: | |
| return True | |
| except Exception: | |
| pass | |
| if getattr(exc, "status_code", None) == 401: | |
| return True | |
| msg = str(exc).lower() | |
| if "invalid api key" in msg or "invalid_api_key" in msg: | |
| return True | |
| if "401" in msg and ("unauthorized" in msg or "authentication" in msg): | |
| return True | |
| return False | |
| def should_rotate_api_key(exc: BaseException) -> bool: | |
| return is_rate_limit_error(exc) or is_auth_or_invalid_key_error(exc) | |
| def call_with_limit_rotation(op: Callable[[], T]) -> T: | |
| """ | |
| Run op() using keys at the current slot. On rate-limit: | |
| advance to next key slot if available; else sleep 60s, reset to slot 0, try again; | |
| if still rate-limited after that full cycle, re-raise. | |
| """ | |
| cooldown_used = False | |
| last_exc: BaseException | None = None | |
| while True: | |
| try: | |
| return op() | |
| except BaseException as e: | |
| if not should_rotate_api_key(e): | |
| raise | |
| last_exc = e | |
| idx = current_key_slot() | |
| n = _max_key_slots() | |
| if idx + 1 < n: | |
| set_key_slot(idx + 1) | |
| logger.warning( | |
| "Rate limit hit; switching API key slot to %s (LLM+Zep)", current_key_slot() | |
| ) | |
| continue | |
| if not cooldown_used: | |
| logger.warning("Rate limit on all API key slots; sleeping 60s then retrying from slot 0") | |
| time.sleep(60) | |
| cooldown_used = True | |
| set_key_slot(0) | |
| continue | |
| raise last_exc from None | |