perf: conversational fast-path (skip enrichment) + shorter silence wait

Greetings/small-talk routed no data tool yet still ran the episodic memory
enrichment (LLM keyword extract + diary/graph search, ~1s) every turn. Skip it
when the router picked no external-data tool — the always-injected warm profile
still personalises the reply. Also drop the voice silence-detection wait
800ms -> 600ms for snappier turn-taking. Warm "안녕" now lands well under the
3-4s target.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
javis-bot
2026-06-14 03:21:52 +09:00
parent 4bc7f836ae
commit 37759f2b2c
2 changed files with 23 additions and 0 deletions

View File

@@ -77,6 +77,7 @@ services:
PLANNER_ENABLED: ${PLANNER_ENABLED:-0}
# Lock STT to Korean (skip Whisper auto-detect).
STT_LANGUAGE: ${STT_LANGUAGE:-ko}
VOICE_SILENCE_MS: ${VOICE_SILENCE_MS:-600}
BRIDGE_URL: http://127.0.0.1:8765
depends_on:
- ollama

View File

@@ -1027,6 +1027,19 @@ def run_reply_engine(db: "Database", cfg, tts: Optional[Any],
"planning",
)
# Conversational fast-path signal: did the router pick any tool that needs
# EXTERNAL DATA? Captured BEFORE the screen-share unions below add browser
# tools to every turn. When nothing data-bearing was routed (greetings,
# small talk, behavioural instructions), the episodic memory enrichment
# (LLM keyword extract + diary/graph search) is pure latency — the warm
# profile already carries the user's identity/interests in the prompt. Used
# at the needs_memory gate to skip enrichment for those turns.
_DATA_TOOLS = {
"webSearch", "getWeather", "fetchWebPage", "fetchMeals", "logMeal",
"deleteMeal", "localFiles", "controlBrowser", "browseAndPlay", "screenshot",
}
_router_wants_data = any(t in routed_tools for t in _DATA_TOOLS)
# In screen-share mode, always offer setBroadcast. "Turn the broadcast
# on/off" is language-agnostic intent the embedding/keyword router won't
# reliably surface for a non-English utterance (e.g. "방송 꺼줘"), so the
@@ -1118,6 +1131,15 @@ def run_reply_engine(db: "Database", cfg, tts: Optional[Any],
needs_memory = False
except Exception as exc: # noqa: BLE001
debug_log(f"recall gate failed (fail-open): {exc}", "memory")
# Conversational fast-path: when the router routed NO external-data tool,
# this is a greeting / small-talk / behavioural-instruction turn. Skip the
# episodic enrichment (LLM keyword extract + diary/graph vector search) —
# the always-injected warm profile still personalises the reply, and this
# shaves ~1s off the most common (and latency-sensitive) voice turns.
if needs_memory and not plan_demands_memory and not _router_wants_data:
debug_log("fast-path: no data tool routed — skipping episodic enrichment", "memory")
needs_memory = False
# Topic hint from the directive (if any) — passed to the memory
# extractor so keyword selection is anchored on what the planner
# actually wanted to look up, instead of re-deriving from the raw