mirror of
https://github.com/Alkatrazz24/Funk-lab.git
synced 2026-07-08 05:34:43 +02:00
fix(stt-server): retry brain + timeout par tentative + log timing effectif (#21)
Suite au déploiement 0.2.0, deux points observés en pilotant l'app en direct : - Le log de timing (`ask … recall/gen/total`) n'émettait pas : uvicorn ne configure que ses propres loggers → on attache un handler INFO sur `stt_server`. - La chaîne LiteLLM→llama-server (ROCm gfx1031) se fige par à-coups (~1-2 min, 502 pour tous les appels, cf. incidents-llm-gpu.md). Résilience côté STT : brain tente 2× (fermeture du client httpx entre les essais → connexion neuve si le pool est vicié) et le timeout passe à 30s PAR tentative (≤ ~2× au pire). Un blip transitoire devient une requête récupérée au lieu d'un 502. bump serveur 0.2.0 → 0.2.1 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ced79658cf
commit
681b94e268
5 changed files with 32 additions and 5 deletions
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "stt-server"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
description = "STT-server — orchestrateur AI du homelab Funk (API pour les clients STT)"
|
||||
requires-python = ">=3.11"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
"""STT-server — orchestrateur AI in-cluster pour les clients STT."""
|
||||
|
||||
__version__ = "0.2.0"
|
||||
__version__ = "0.2.1"
|
||||
|
|
|
|||
|
|
@ -23,6 +23,14 @@ from stt_server.longterm import LongTermMemory
|
|||
from stt_server.memory import SessionStore
|
||||
|
||||
log = logging.getLogger("stt_server")
|
||||
# uvicorn ne configure que ses propres loggers : on attache notre handler en INFO
|
||||
# pour que les lignes de timing (`ask … recall/gen/total`) sortent dans les logs du pod.
|
||||
if not log.handlers:
|
||||
log.setLevel(logging.INFO)
|
||||
_h = logging.StreamHandler()
|
||||
_h.setFormatter(logging.Formatter("%(levelname)s: %(name)s: %(message)s"))
|
||||
log.addHandler(_h)
|
||||
log.propagate = False
|
||||
|
||||
sessions = SessionStore()
|
||||
longterm = LongTermMemory() if settings.memory_longterm else None
|
||||
|
|
|
|||
|
|
@ -59,8 +59,25 @@ async def ask(
|
|||
"temperature": settings.temperature,
|
||||
}
|
||||
headers = {"Authorization": f"Bearer {settings.litellm_key}"}
|
||||
r = await _get_client().post(settings.litellm_url, json=payload, headers=headers)
|
||||
r.raise_for_status()
|
||||
# Résilience : la chaîne LiteLLM→llama-server (ROCm) se fige par à-coups. Une 2ᵉ tentative
|
||||
# récupère un blip transitoire (ex. connexion keep-alive périmée) au lieu de renvoyer 502.
|
||||
# Timeout PAR tentative (`request_timeout`) → on ne dépasse pas ~2× ce budget au pire.
|
||||
last_exc: Exception | None = None
|
||||
for attempt in range(2):
|
||||
try:
|
||||
r = await _get_client().post(
|
||||
settings.litellm_url,
|
||||
json=payload,
|
||||
headers=headers,
|
||||
timeout=settings.request_timeout,
|
||||
)
|
||||
r.raise_for_status()
|
||||
break
|
||||
except httpx.HTTPError as e:
|
||||
last_exc = e
|
||||
await aclose() # repart sur une connexion neuve (pool potentiellement vicié)
|
||||
else:
|
||||
raise last_exc # type: ignore[misc]
|
||||
msg = r.json()["choices"][0]["message"]
|
||||
# Filet de sécurité : si un modèle « thinking » renvoie un content vide (tout parti
|
||||
# en reasoning_content), on récupère le raisonnement plutôt que de renvoyer "".
|
||||
|
|
|
|||
|
|
@ -30,7 +30,9 @@ class Settings:
|
|||
)
|
||||
max_tokens: int = int(os.getenv("STT_MAX_TOKENS", "200"))
|
||||
temperature: float = float(os.getenv("STT_TEMPERATURE", "0.7"))
|
||||
request_timeout: float = float(os.getenv("STT_REQUEST_TIMEOUT", "60"))
|
||||
# Timeout PAR tentative vers LiteLLM (brain fait jusqu'à 2 tentatives). Une réponse vocale
|
||||
# avec /no_think tient en quelques secondes → 30s suffit, et borne l'attente d'un blip backend.
|
||||
request_timeout: float = float(os.getenv("STT_REQUEST_TIMEOUT", "30"))
|
||||
# Qwen3 est un modèle « thinking » → ajoute `/no_think` pour désactiver le raisonnement
|
||||
# (sinon content vide / timeout). Inoffensif pour les modèles non-Qwen.
|
||||
disable_thinking: bool = os.getenv("STT_DISABLE_THINKING", "true").lower() == "true"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue