fix(fast-path): Voice-Befehle matchen wieder (GPS-Praefix, Umlaute, Kommas)
Voice-Nachrichten tragen den GPS-Hint-Praefix der Bridge
("[Stefans aktuelle GPS-Position: ...] nächstes lied bitte") und echte
Umlaute + Whisper-Kommas. Die ^...$-verankerten fast_patterns matchten damit
NIE — jeder Voice-Spotify-Befehl ging unnoetig an local/Claude (Tokens +
Latenz + TTS statt 0-Token-Fast-Path, was das Doppel-Ausfuehren mit anheizte).
_normalize_for_fast_match: fuehrende [ ... ]-Hint-Bloecke strippen, Umlaute
falten (ä→ae …), interne Satzzeichen (Komma/Punkt) raus. Pattern wird gleich
gefaltet. Router strippt den Praefix ebenfalls (Laengen-/Hint-Heuristik).
Wirkung: "nächstes lied bitte", "play", "nächster titel" -> Fast-Path
(instant, speak=False). "spiele auf duffy desktop weiter" bleibt Router-Sache.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+32
-3
@@ -1018,10 +1018,36 @@ META_TOOLS = [
|
||||
# Diese Logik ist generisch — ARIA deklariert die Patterns selbst beim
|
||||
# skill_create / skill_update, das Brain orchestriert nur.
|
||||
|
||||
def _strip_leading_hint_blocks(text: str) -> str:
|
||||
"""Entfernt fuehrende Hint-Bloecke `[ ... ]`, die die Bridge an
|
||||
Voice-Nachrichten haengt (GPS-Position, Barge-In-Hinweis). Ohne das matcht
|
||||
KEIN Voice-Befehl je den Fast-Path (Regex ist ^...$-verankert) — selbst
|
||||
'nächstes lied' landete unnoetig bei Claude statt beim 0-Token-Fast-Path."""
|
||||
s = (text or "").strip()
|
||||
prev = None
|
||||
while prev != s:
|
||||
prev = s
|
||||
s = re.sub(r"^\s*\[[^\]]*\]\s*", "", s)
|
||||
return s
|
||||
|
||||
|
||||
def _fold_umlauts(s: str) -> str:
|
||||
"""ä→ae, ö→oe, ü→ue, ß→ss (lowercase erwartet). Whisper liefert echte
|
||||
Umlaute ('Nächstes Lied'), viele Skill-fast_patterns sind aber in ae/oe/ue
|
||||
geschrieben — ohne Faltung matcht das nie."""
|
||||
return (s.replace("ä", "ae").replace("ö", "oe").replace("ü", "ue")
|
||||
.replace("ß", "ss"))
|
||||
|
||||
|
||||
def _normalize_for_fast_match(text: str) -> str:
|
||||
norm = (text or "").strip().lower()
|
||||
norm = re.sub(r"[.!?]+$", "", norm)
|
||||
norm = re.sub(r"\s+", " ", norm)
|
||||
norm = _strip_leading_hint_blocks(text).lower()
|
||||
norm = _fold_umlauts(norm)
|
||||
# Interne Satzzeichen raus, die Whisper einstreut ('Nächstes Lied, bitte.').
|
||||
# Kommas/Semikola/Doppelpunkte → Space, Punkt/!/? ganz weg. Sonst matcht das
|
||||
# ^...$-verankerte fast_pattern nie, weil das Komma dazwischenfunkt.
|
||||
norm = re.sub(r"[,;:]", " ", norm)
|
||||
norm = re.sub(r"[.!?]+", "", norm)
|
||||
norm = re.sub(r"\s+", " ", norm).strip()
|
||||
return norm
|
||||
|
||||
|
||||
@@ -1117,6 +1143,9 @@ class Agent:
|
||||
rx = pat.get("match") or ""
|
||||
if not rx:
|
||||
continue
|
||||
# Pattern GLEICH falten wie den Text — egal ob der Skill-Autor
|
||||
# 'naechstes' oder 'nächstes' geschrieben hat.
|
||||
rx = _fold_umlauts(rx)
|
||||
try:
|
||||
if not re.match(rx, norm, re.IGNORECASE):
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user