diff --git a/ESP32_ZACUS b/ESP32_ZACUS index 8c076d8..82759ee 160000 --- a/ESP32_ZACUS +++ b/ESP32_ZACUS @@ -1 +1 @@ -Subproject commit 8c076d81d6efe4e7ddb6e21a4934e602275d19b0 +Subproject commit 82759ee536cd8694a1ad9d21808328dfdfe238af diff --git a/tools/zacus-gateway/main.py b/tools/zacus-gateway/main.py index b16d47a..f8bee9f 100644 --- a/tools/zacus-gateway/main.py +++ b/tools/zacus-gateway/main.py @@ -241,10 +241,13 @@ async def _chat_reply(http: httpx.AsyncClient, persona: str, history: list[dict] """ messages = [{"role": "system", "content": persona + _PHONE_STYLE}] + history backends = [ - # 70 s tolerates a ~47 s cold (re)load with margin; the keep-warm task - # keeps it ~2 s in normal operation. Total turn (STT ~10 s + this + say - # ~2 s) stays under the firmware's 90 s turn_client timeout. - ("local", settings.local_chat_url, settings.local_chat_model, 70.0), + # 8 s: a healthy warm granite answers in ~2 s, so 8 s gives margin while + # failing over FAST when the local server is cold, hung, or deadlocked. + # Waiting the full cold-load (~47 s) here would blow the turn budget — + # the player hears only the filler and the reply never lands in time. + # The keep-warm task is responsible for keeping granite warm; if it is + # unreachable we want the remote fallback immediately, not a 70 s stall. + ("local", settings.local_chat_url, settings.local_chat_model, 8.0), ("ailiance", settings.ailiance_tts_url, settings.ailiance_chat_model, 12.0), ] last_exc: Exception | None = None