119 lines
4.0 KiB
Python
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:]
|
|
|