system-prompts-and-models-o.../salesflow-saas/backend/dealix_gtm_os/ai/response_cache.py
Claude 503bf2e5d7
feat: AI Cost, Quality & Proof OS — complete
AI Layer:
- llm_router.py: routes cheap/mid/high models, enforces daily budget, caches
- token_counter.py: estimates tokens, truncates to budget
- response_cache.py: in-memory cache with TTL per agent
- prompt_registry.py: versioned prompts with stable prefix for caching
- ai_budget.yaml: model costs, agent budgets, daily limits (10 SAR/day)

Guardrails:
- output_validator.py: blocks fake claims + prohibited actions
- cost_guard.py: prevents runaway spending

Observability:
- trace.py: trace_id, cost, latency, steps per pipeline run

Tests: ALL PASS
- 30/30 evals (100%) — 9 sectors, 30 companies
- 10/10 prohibited actions blocked
- 4/4 allowed actions verified
- 3/3 forbidden claims blocked
- 3/3 message quality checks passed

https://claude.ai/code/session_01W1rJthWDkasijTdXCfxVHs
2026-04-26 17:42:47 +00:00

29 lines
934 B
Python

"""In-memory response cache — avoids re-analyzing the same company."""
import hashlib
import json
import time
from typing import Optional
_cache: dict[str, dict] = {}
def _key(agent_name: str, input_data: dict) -> str:
raw = f"{agent_name}:{json.dumps(input_data, sort_keys=True, ensure_ascii=False)}"
return hashlib.sha256(raw.encode()).hexdigest()[:16]
def get_cached(agent_name: str, input_data: dict, ttl_hours: float = 24) -> Optional[dict]:
k = _key(agent_name, input_data)
entry = _cache.get(k)
if not entry:
return None
if time.time() - entry["ts"] > ttl_hours * 3600:
del _cache[k]
return None
return entry["data"]
def set_cached(agent_name: str, input_data: dict, result: dict):
k = _key(agent_name, input_data)
_cache[k] = {"data": result, "ts": time.time()}
def cache_stats() -> dict:
return {"entries": len(_cache), "keys": list(_cache.keys())[:10]}