- Fix 71 invalid-syntax files (class-body newline-broken assignments) - Add from/None chain to 307 B904 raise-without-from sites - Add B008 ignore to ruff.toml (already in pyproject.toml) - Noqa F401 on __init__.py re-exports (137 sites) - Noqa E402 on deferred imports (63 sites) - Bulk-add stdlib/FastAPI/project imports for F821 (127 sites) - Replace ×→x, –→-, …→... in docstrings (4093 chars) - Manual refactor of 5 SIM103/SIM116 patterns Tests: 791 passed (66 deselected due to pre-existing Redis issues in test_rag.py) Co-authored-by: opencode <opencode@rugmunch.io>
49 lines
1.3 KiB
Python
49 lines
1.3 KiB
Python
"""Semantic LLM Cache for DataBus - caches identical + similar prompts. Redis-backed."""
|
|
|
|
import hashlib
|
|
import json
|
|
import os
|
|
|
|
REDIS_URL = os.getenv("REDIS_CACHE_URL", "redis://localhost:6379/1")
|
|
CACHE_TTL = int(os.getenv("LLM_CACHE_TTL", "3600"))
|
|
|
|
|
|
def _cache_key(prompt: str, model: str) -> str:
|
|
return f"llm_cache:{hashlib.sha256(f'{model}:{prompt}'.encode()).hexdigest()[:16]}"
|
|
|
|
|
|
def get_cached(prompt: str, model: str) -> dict | None:
|
|
"""Check if prompt+model result is cached."""
|
|
import redis
|
|
|
|
try:
|
|
r = redis.from_url(REDIS_URL, decode_responses=True)
|
|
data = r.get(_cache_key(prompt, model))
|
|
if data:
|
|
return json.loads(data)
|
|
except Exception:
|
|
pass
|
|
return None
|
|
|
|
|
|
def set_cached(prompt: str, model: str, result: dict, ttl: int = CACHE_TTL):
|
|
"""Cache a prompt result."""
|
|
import redis
|
|
|
|
try:
|
|
r = redis.from_url(REDIS_URL, decode_responses=True)
|
|
r.setex(_cache_key(prompt, model), ttl, json.dumps(result))
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
def get_cache_stats() -> dict:
|
|
"""Get cache statistics."""
|
|
import redis
|
|
|
|
try:
|
|
r = redis.from_url(REDIS_URL, decode_responses=True)
|
|
keys = r.keys("llm_cache:*")
|
|
return {"cached_prompts": len(keys)}
|
|
except Exception:
|
|
return {"cached_prompts": 0, "error": "redis unavailable"}
|