fix(chat): heartbeat SSE pendant la préparation + think=False sur les appels auxiliaires

Le déplacement de la préparation (plan, recall RAG) dans le flux SSE
laissait un silence total pendant le chargement d'un gros modèle : le
reverse proxy coupait la connexion (« Connexion interrompue pendant le
chargement du modèle »). Avec la réflexion active, l'appel de plan
laissait en plus le modèle penser — silence encore plus long.

- ping SSE toutes les 10 s pendant la préparation du contexte
- plan / auto-critique / résumé : think=False (repli automatique si le
  modèle refuse le paramètre) — un appel utilitaire ne réfléchit jamais

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MichaelandClaude Opus 4.8 committed 2026-07-19 01:01:49 +02:00
1 parent da76b8192d
commit a1380d0bf8
3 files changed
+61 -30

No files matched your search

+24 -14
View File
@@ -12,7 +12,7 @@ import re
import httpx
from .ollama_client import ollama
from .ollama_client import OllamaError, ollama
logger = logging.getLogger(__name__)
@@ -61,19 +61,29 @@ async def _ask(
principal : un appel avec des options divergentes force Ollama à recharger
le modèle en plein message.
"""
text = ""
async for chunk in ollama.chat(
model,
[{"role": "system", "content": system},
{"role": "user", "content": user}],
options={**(options or {}), "temperature": 0.2, "num_predict": num_predict},
keep_alive=keep_alive,
stream=True,
):
text += chunk.get("message", {}).get("content", "")
if chunk.get("done"):
break
return text.strip()
messages = [{"role": "system", "content": system},
{"role": "user", "content": user}]
opts = {**(options or {}), "temperature": 0.2, "num_predict": num_predict}
# think=False : un appel utilitaire (plan, critique) ne doit jamais
# « réfléchir » — sur un modèle thinking, la pensée dévore le budget et
# multiplie la latence. Repli sans le paramètre si le modèle le refuse.
think: bool | None = False
while True:
text = ""
try:
async for chunk in ollama.chat(
model, messages, options=opts, think=think,
keep_alive=keep_alive, stream=True,
):
text += chunk.get("message", {}).get("content", "")
if chunk.get("done"):
break
return text.strip()
except OllamaError as exc:
if think is False and "think" in str(exc).lower():
think = None
continue
raise
async def make_plan(