miniature-businessperson-21934
02/14/2026, 6:39 AMtall-airline-16756
02/14/2026, 6:39 AMtall-airline-16756
02/14/2026, 6:40 AMimport hashlib
import json
import redis
import time
r = redis.Redis(host='REDIS_HOST', port=6379, db=0, password='REDIS_PASS')
def make_cache_key(input_text: str, model: str, params: dict) -> str:
normal = input_text.strip().lower()
key_src = f"{model}|{json.dumps(params, sort_keys=True)}|{normal}"
return "inference:" + hashlib.sha256(key_src.encode()).hexdigest()
def cached_inference(input_text, model, params, compute_fn, ttl=3600):
key = make_cache_key(input_text, model, params)
cached = r.get(key)
if cached:
return json.loads(cached)
lock_key = key + ":lock"
# simple lock to avoid stampede
if r.set(lock_key, "1", nx=True, ex=30):
try:
result = compute_fn(input_text, model, params)
r.set(key, json.dumps(result), ex=ttl)
return result
finally:
r.delete(lock_key)
else:
# Another worker is computing — wait and retry a few times
for _ in range(10):
time.sleep(0.2)
cached = r.get(key)
if cached:
return json.loads(cached)
# fallback: compute locally
return compute_fn(input_text, model, params)
When to store blobs vs references
• Small TTS or audio snippets (< 1–2 MB): you can store in Redis as binary or base64.
• Larger files: upload to object storage (S3/GCS) and store the URL/metadata in Redis.
Operational tips
• Provision Redis in same region/zone as your agents to avoid cross‑region latency.
• Use Redis clusters for scale and high availability.
• Monitor Redis latency and memory usage; tune eviction policy and maxmemory.
• If you need pub/sub or queueing semantics (e.g., coordinating egress jobs), Redis supports those patterns as well.
Next steps I can help with
• Provide a more targeted example for caching STT/LLM responses, TTS audio, or auth tokens — which do you want?
• Help design cache keys and TTL strategy for your exact agent workflow.
• Show how to combine Redis with S3 for larger assets and provide a code example.
Tell me which data you plan to cache and I’ll give a focused implementation you can drop into your Python LiveKit agent.
Sources: Universal Egress | Server-side | livekit/livekit_composite | DeepWiki | How can I reduce latency in voice agents using STT, TTS and LLM? | LiveKit | Introducing LiveKit Inference: A unified model interface for voice AI | Introducing LiveKit Inference: A unified model interface for voice AIminiature-businessperson-21934
02/14/2026, 6:44 AMtall-airline-16756
02/14/2026, 6:44 AMcompute_stt and call_llm with your actual calls to the STT and LLM endpoints (LiveKit Inference or third-party).
1) Install:
• pip install redis
2) Example code:
import hashlib
import json
import redis
import time
from typing import Callable
# Configure Redis connection (update host/port/password)
r = redis.Redis(host='REDIS_HOST', port=6379, db=0, password='REDIS_PASS', decode_responses=True)
def sha256_hex(data: bytes) -> str:
return hashlib.sha256(data).hexdigest()
def make_key(prefix: str, parts: list) -> str:
# parts should be strings already normalized
joined = "|".join(parts)
return f"{prefix}:" + sha256_hex(joined.encode())
def json_dumps_canonical(obj):
return json.dumps(obj, sort_keys=True, separators=(',', ':'))
def cached_compute(key: str, compute_fn: Callable, ttl: int = 3600):
"""
Generic cache wrapper with simple lock to avoid stampedes.
compute_fn should return JSON-serializable result.
"""
cached = r.get(key)
if cached:
return json.loads(cached)
lock_key = key + ":lock"
lock_acquired = r.set(lock_key, "1", nx=True, ex=30) # lock expires in 30s
if lock_acquired:
try:
result = compute_fn()
r.set(key, json.dumps(result), ex=ttl)
return result
finally:
r.delete(lock_key)
else:
# Wait for the result to appear
for _ in range(20):
time.sleep(0.1)
cached = r.get(key)
if cached:
return json.loads(cached)
# Fallback: compute locally to avoid long waits
result = compute_fn()
# best-effort cache
try:
r.set(key, json.dumps(result), ex=ttl)
except Exception:
pass
return result
# Example: caching STT
def compute_stt_from_audio(audio_bytes: bytes, stt_model: str, stt_params: dict):
# Replace this with actual STT call to LiveKit Inference or your STT service.
# Should return a dict, e.g., {"text": "...", "confidence": 0.98}
raise NotImplementedError
def get_stt(audio_bytes: bytes, stt_model: str, stt_params: dict, ttl=1800):
# Normalize audio: ensure consistent sample rate/encoding outside this snippet
audio_hash = sha256_hex(audio_bytes)
params_hash = sha256_hex(json_dumps_canonical(stt_params).encode())
key = f"stt:{audio_hash}:{stt_model}:{params_hash}"
return cached_compute(key, lambda: compute_stt_from_audio(audio_bytes, stt_model, stt_params), ttl=ttl)
# Example: caching LLM responses
def compute_llm_response(prompt_text: str, llm_model: str, llm_params: dict):
# Replace this with actual LLM call (LiveKit Inference or external provider).
# Return JSON-serializable dict like {"text": "...", "tokens": [...], ...}
raise NotImplementedError
def get_llm(prompt_text: str, llm_model: str, llm_params: dict, ttl=3600):
prompt_norm = " ".join(prompt_text.strip().split()) # simple normalization
params_hash = sha256_hex(json_dumps_canonical(llm_params).encode())
key = f"llm:{sha256_hex(prompt_norm.encode())}:{llm_model}:{params_hash}"
return cached_compute(key, lambda: compute_llm_response(prompt_norm, llm_model, llm_params), ttl=ttl)
Integrating with your LiveKit agent
• In your agent flow: when you receive audio, call get_stt(...). If STT result exists, proceed directly to LLM; otherwise STT will be computed and cached.
• For LLM calls, call get_llm(...) with normalized prompt and reused model params.
• If you perform STT→LLM pipeline often with the same transcript and prompt template, consider composing a combined cache key for the final LLM output as well (e.g., hash of transcript + prompt template + model).
Advanced improvements you can add
• Use Redis Hashes to store additional metadata (timestamp, model_version, source_url).
• Use Redis streams or task queue patterns if you want async background population of cache.
• Implement versioned keys (e.g., include app version or model-version tag) so you can invalidate broad sets of keys after upgrades.
• Use Redis Bloom / LFU counters to identify hot keys and tune TTLs.
• Use Redis Cluster and connection pooling for production scale.
Next steps I can help with
• Provide a concrete snippet that wires compute_stt_from_audio to your actual LiveKit Inference STT API or to your STT provider — tell me which provider or paste the code you currently use.
• Show an example that uploads audio to S3 and stores references in Redis for larger assets.
• Help decide TTL values based on your usage patterns (streaming live audio vs repeated identical clips).
Which of these would you like next: a LiveKit-specific STT/LLM wiring example, or wiring to a third-party STT/LLM provider you already use?