Files
2025-09-05 17:50:16 +00:00

119 lines
4.0 KiB
Python

# services/history_manager.py
import time
import httpx
from config import settings
from services import redis_service
MAX_HISTORY_TURNS = 10
SUMMARY_TRIGGER_TURNS = 20
# -------------------------
# STATISTICHE LM STUDIO
# -------------------------
# services/history_manager.py
def track_lm_call(model_name: str, elapsed_seconds: float):
"""
Aggiorna le statistiche di utilizzo LM Studio in Redis, sia globali che per modello.
"""
model_key = model_name.replace(" ", "_") # per sicurezza nelle chiavi Redis
pipe = redis_service.r.pipeline()
# --- Globali ---
pipe.incr("lm:calls:total")
pipe.incr("lm:calls:last_hour")
pipe.expire("lm:calls:last_hour", 3600)
pipe.incr("lm:calls:last_24h")
pipe.expire("lm:calls:last_24h", 86400)
pipe.incrbyfloat("lm:processing_time:total", elapsed_seconds)
# --- Per modello ---
pipe.sadd("lm:models:loaded", model_name)
# Chiamate
pipe.incr(f"lm:model:{model_key}:calls:last_hour")
pipe.expire(f"lm:model:{model_key}:calls:last_hour", 3600)
pipe.incr(f"lm:model:{model_key}:calls:last_24h")
pipe.expire(f"lm:model:{model_key}:calls:last_24h", 86400)
# Tempo totale
pipe.incrbyfloat(f"lm:model:{model_key}:time:total", elapsed_seconds)
pipe.execute()
def get_lm_stats():
"""
Restituisce statistiche globali e per modello.
"""
models = list(redis_service.r.smembers("lm:models:loaded"))
stats_per_model = []
for m in models:
model_key = m.replace(" ", "_")
calls_last_hour = int(redis_service.r.get(f"lm:model:{model_key}:calls:last_hour") or 0)
calls_last_24h = int(redis_service.r.get(f"lm:model:{model_key}:calls:last_24h") or 0)
total_time = float(redis_service.r.get(f"lm:model:{model_key}:time:total") or 0.0)
avg_time = (total_time / calls_last_24h) if calls_last_24h > 0 else 0.0
stats_per_model.append({
"model": m,
"calls_last_hour": calls_last_hour,
"calls_last_24h": calls_last_24h,
"total_time_sec": total_time,
"avg_time_sec": avg_time
})
return {
"global": {
"calls_total": int(redis_service.r.get("lm:calls:total") or 0),
"calls_last_hour": int(redis_service.r.get("lm:calls:last_hour") or 0),
"calls_last_24h": int(redis_service.r.get("lm:calls:last_24h") or 0),
"total_processing_time_sec": float(redis_service.r.get("lm:processing_time:total") or 0.0)
},
"per_model": stats_per_model
}
# -------------------------
# HISTORY
# -------------------------
async def summarize_messages(messages):
prompt = [
{"role": "system", "content": "Riassumi la seguente conversazione in forma di elenco puntato, mantenendo solo i fatti chiave e le informazioni rilevanti per continuare il dialogo."},
*messages
]
async with httpx.AsyncClient(timeout=settings.REQUEST_TIMEOUT) as client:
resp = await client.post(
settings.LM_STUDIO_URL,
json={"model": settings.MODEL_NAME, "messages": prompt}
)
resp.raise_for_status()
data = resp.json()
return data["choices"][0]["message"]["content"]
async def prepare_history(user_id: str, session_id: str):
full_history = redis_service.get_chat(user_id, session_id, limit=1000)
if len(full_history) > SUMMARY_TRIGGER_TURNS:
old_messages = full_history[:-MAX_HISTORY_TURNS]
last_messages = full_history[-MAX_HISTORY_TURNS:]
summary_text = await summarize_messages(old_messages)
condensed_history = [{"role": "system", "content": f"Riassunto conversazione: {summary_text}"}]
condensed_history.extend(last_messages)
# Salva la nuova history condensata
redis_service.clear_chat(user_id, session_id)
for msg in condensed_history:
redis_service.save_chat(user_id, session_id, msg)
return condensed_history
else:
# Solo windowing
return full_history[-MAX_HISTORY_TURNS:]