Download rate_limit.py from Jindrich3/openajaj: direct link, hf CLI and curl.
- Browser
- Download file 2.51 kB
-
https://huggingface.co/spaces/Jindrich3/openajaj/resolve/main/rate_limit.py
- Command line
-
hf download hf://spaces/Jindrich3/openajaj/rate_limit.py
-
curl -L -o rate_limit.py https://huggingface.co/spaces/Jindrich3/openajaj/resolve/main/rate_limit.py
2.51 kB
| """Per-client request caps, in memory. | |
| Keys are exact paths, not prefixes. `"/api/stt"` used to match by prefix, which | |
| swallowed `/api/stt/check` and `/api/stt/usage` as well: a single /transcribe | |
| load spends three of those, so the fourth reload inside a minute was refused | |
| and the page reported the transcription service as down. The websocket it was | |
| written for never reaches this code at all — `BaseHTTPMiddleware` skips | |
| non-http scopes, so websocket limits live in `stt_budget` instead. | |
| """ | |
| import threading | |
| import time | |
| # exact path → (max_requests, window_seconds) | |
| LIMITS: dict[str, tuple[int, int]] = { | |
| "/api/chat": (15, 60), | |
| # Voice mode sends one request per sentence, prefetched as the answer | |
| # streams, so a low cap counts sentences rather than users: at 10 the | |
| # eleventh sentence of one answer was refused and the reply finished in the | |
| # browser's built-in voice. edge-tts is unmetered and the result is cached, | |
| # so this only exists to stop the Space being used as a free TTS proxy. | |
| "/api/tts": (60, 60), | |
| "/api/benchmark": (1, 300), | |
| # Every call makes an outbound request to Deepgram's auth endpoint, so it | |
| # cannot go uncapped. The chat page calls it once per load, /t after each | |
| # unexpected socket close: reconnect backoff (1 s doubling to 30 s) keeps | |
| # that to about seven in the first minute, then two a minute. | |
| "/api/stt/check": (30, 60), | |
| "/api/stt/usage": (30, 60), | |
| # /t asks once per socket, like the check; each call mints a Deepgram token | |
| "/api/stt/token": (30, 60), | |
| # /t reports its visit every 5 min and on hide: far under this | |
| "/api/stt/session": (30, 60), | |
| "/api/captcha/challenge": (10, 60), | |
| "/api/captcha/verify": (10, 60), | |
| } | |
| _buckets: dict[str, list[float]] = {} | |
| _lock = threading.Lock() | |
| def is_limited(client: str, path: str, now: float | None = None) -> bool: | |
| """True when this client has used up `path`'s allowance. Counts the call.""" | |
| limit_window = LIMITS.get(path) | |
| if limit_window is None: | |
| return False | |
| limit, window = limit_window | |
| now = time.time() if now is None else now | |
| key = f"{client}:{path}" | |
| with _lock: | |
| recent = [t for t in _buckets.get(key, ()) if t > now - window] | |
| if len(recent) >= limit: | |
| _buckets[key] = recent | |
| return True | |
| recent.append(now) | |
| _buckets[key] = recent | |
| return False | |
| def reset() -> None: | |
| """Drop all buckets. For tests.""" | |
| with _lock: | |
| _buckets.clear() | |