59 lines
2.2 KiB
Python
59 lines
2.2 KiB
Python
"""Deterministic routing hints for background voice tasks."""
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
# Gemma is a small model and will sometimes promise to do work without actually
|
|
# calling dispatch_task. Force that tool for high-confidence background intents;
|
|
# the main prompt remains responsible for less obvious cases.
|
|
_BACKGROUND_TASK_RE = re.compile(
|
|
r"\b(?:"
|
|
r"latest|news|current events?|headlines?|prices?|scores?|"
|
|
r"research|look\s+up|search(?:\s+for)?|find\s+out|investigate|"
|
|
r"compare|comparison|pros\s+and\s+cons|"
|
|
r"plan|itinerary|schedule|"
|
|
r"write|draft|compose|rewrite|"
|
|
r"summari[sz]e|summary|analy[sz]e|analysis|review|report|"
|
|
r"recommend|recommendation|options?|developments?"
|
|
r")\b",
|
|
re.IGNORECASE,
|
|
)
|
|
_MEMORY_INTENT_RE = re.compile(
|
|
r"\b(?:remember|memory|memories|forget|write down|my name|"
|
|
r"what do you know about me|preference|preferences)\b",
|
|
re.IGNORECASE,
|
|
)
|
|
_DIRECT_WEATHER_TIME_RE = re.compile(
|
|
r"\b(?:weather|temperature|forecast|what time|current time|what day|today's date)\b",
|
|
re.IGNORECASE,
|
|
)
|
|
|
|
|
|
def should_force_background_task(text: str) -> bool:
|
|
"""Return whether a fresh user turn should be forced through dispatch_task.
|
|
|
|
This deliberately favors precise intent signals over trying to classify every
|
|
possible request. Memory stays on its authenticated MCP and straightforward
|
|
weather/time requests stay on their purpose-built tools.
|
|
"""
|
|
normalized = " ".join((text or "").split())
|
|
if not normalized or _MEMORY_INTENT_RE.search(normalized):
|
|
return False
|
|
if re.search(r"\b(?:my|saved)\s+notes?\b", normalized, re.IGNORECASE):
|
|
return False
|
|
|
|
match = _BACKGROUND_TASK_RE.search(normalized)
|
|
if not match:
|
|
return bool(re.search(r"\b(?:tell me about|give me an overview of)\b", normalized, re.I))
|
|
|
|
# Straightforward weather/time requests stay on the fast dedicated MCP.
|
|
# Comparisons, research, plans, and written reports still go background.
|
|
if _DIRECT_WEATHER_TIME_RE.search(normalized) and not re.search(
|
|
r"\b(?:compare|comparison|research|investigate|plan|write|draft|"
|
|
r"summari[sz]e|analy[sz]e|review|report)\b",
|
|
normalized,
|
|
re.IGNORECASE,
|
|
):
|
|
return False
|
|
return True
|