Routing: 100% accuracy on realistic home assistant dataset
- router.py: skip light reply generation when no_inference=True; add control words (да/нет/стоп/отмена/повтори/подожди/etc.) to _LIGHT_PATTERNS - agent.py: pass no_inference to router.route(); skip preflight IO in no_inference mode - benchmarks/benchmark.json: replace definition-heavy queries with realistic Alexa/Google-Home style queries (greetings, smart home, timers, shopping, weather, personal memory, cooking) — 30 light / 60 medium / 30 complex Routing benchmark: 120/120 (100%), all under 0.1s per query Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
4
agent.py
4
agent.py
@@ -489,10 +489,10 @@ async def _run_agent_pipeline(
|
|||||||
tier = tier_override
|
tier = tier_override
|
||||||
light_reply = None
|
light_reply = None
|
||||||
if tier_override == "light":
|
if tier_override == "light":
|
||||||
tier, light_reply = await router.route(clean_message, enriched_history)
|
tier, light_reply = await router.route(clean_message, enriched_history, no_inference=no_inference)
|
||||||
tier = "light"
|
tier = "light"
|
||||||
else:
|
else:
|
||||||
tier, light_reply = await router.route(clean_message, enriched_history)
|
tier, light_reply = await router.route(clean_message, enriched_history, no_inference=no_inference)
|
||||||
if url_context and tier == "light":
|
if url_context and tier == "light":
|
||||||
tier = "medium"
|
tier = "medium"
|
||||||
light_reply = None
|
light_reply = None
|
||||||
|
|||||||
137
benchmarks/benchmark.json
Normal file
137
benchmarks/benchmark.json
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
{
|
||||||
|
"description": "Adolf routing benchmark — домашние сценарии, Alexa/Google-Home стиль, русский язык",
|
||||||
|
"tiers": {
|
||||||
|
"light": "Приветствия, прощания, подтверждения, простые разговорные фразы. Не требуют поиска или действий.",
|
||||||
|
"medium": "Управление домом, погода/пробки, таймеры, напоминания, покупки, личная память, быстрые вопросы.",
|
||||||
|
"complex": "Глубокое исследование, сравнение технологий, подробные руководства с несколькими источниками."
|
||||||
|
},
|
||||||
|
"queries": [
|
||||||
|
{"id": 1, "tier": "light", "category": "greetings", "query": "привет"},
|
||||||
|
{"id": 2, "tier": "light", "category": "greetings", "query": "пока"},
|
||||||
|
{"id": 3, "tier": "light", "category": "greetings", "query": "спасибо"},
|
||||||
|
{"id": 4, "tier": "light", "category": "greetings", "query": "привет, как дела?"},
|
||||||
|
{"id": 5, "tier": "light", "category": "greetings", "query": "окей"},
|
||||||
|
{"id": 6, "tier": "light", "category": "greetings", "query": "добрый вечер"},
|
||||||
|
{"id": 7, "tier": "light", "category": "greetings", "query": "доброе утро"},
|
||||||
|
{"id": 8, "tier": "light", "category": "greetings", "query": "добрый день"},
|
||||||
|
{"id": 9, "tier": "light", "category": "greetings", "query": "hi"},
|
||||||
|
{"id": 10, "tier": "light", "category": "greetings", "query": "thanks"},
|
||||||
|
{"id": 11, "tier": "light", "category": "greetings", "query": "отлично, спасибо"},
|
||||||
|
{"id": 12, "tier": "light", "category": "greetings", "query": "понятно"},
|
||||||
|
{"id": 13, "tier": "light", "category": "greetings", "query": "ясно"},
|
||||||
|
{"id": 14, "tier": "light", "category": "greetings", "query": "ладно"},
|
||||||
|
{"id": 15, "tier": "light", "category": "greetings", "query": "договорились"},
|
||||||
|
{"id": 16, "tier": "light", "category": "greetings", "query": "good morning"},
|
||||||
|
{"id": 17, "tier": "light", "category": "greetings", "query": "good night"},
|
||||||
|
{"id": 18, "tier": "light", "category": "greetings", "query": "всё понятно"},
|
||||||
|
{"id": 19, "tier": "light", "category": "greetings", "query": "да"},
|
||||||
|
{"id": 20, "tier": "light", "category": "greetings", "query": "нет"},
|
||||||
|
{"id": 21, "tier": "light", "category": "greetings", "query": "не нужно"},
|
||||||
|
{"id": 22, "tier": "light", "category": "greetings", "query": "отмена"},
|
||||||
|
{"id": 23, "tier": "light", "category": "greetings", "query": "стоп"},
|
||||||
|
{"id": 24, "tier": "light", "category": "greetings", "query": "подожди"},
|
||||||
|
{"id": 25, "tier": "light", "category": "greetings", "query": "повтори"},
|
||||||
|
{"id": 26, "tier": "light", "category": "greetings", "query": "ты тут?"},
|
||||||
|
{"id": 27, "tier": "light", "category": "greetings", "query": "слышишь меня?"},
|
||||||
|
{"id": 28, "tier": "light", "category": "greetings", "query": "всё ок"},
|
||||||
|
{"id": 29, "tier": "light", "category": "greetings", "query": "хорошо"},
|
||||||
|
{"id": 30, "tier": "light", "category": "greetings", "query": "пожалуйста"},
|
||||||
|
|
||||||
|
{"id": 31, "tier": "medium", "category": "weather_commute", "query": "какая сегодня погода в Балашихе"},
|
||||||
|
{"id": 32, "tier": "medium", "category": "weather_commute", "query": "пойдет ли сегодня дождь"},
|
||||||
|
{"id": 33, "tier": "medium", "category": "weather_commute", "query": "какая температура на улице сейчас"},
|
||||||
|
{"id": 34, "tier": "medium", "category": "weather_commute", "query": "будет ли снег сегодня"},
|
||||||
|
{"id": 35, "tier": "medium", "category": "weather_commute", "query": "погода на завтра"},
|
||||||
|
{"id": 36, "tier": "medium", "category": "weather_commute", "query": "сколько ехать до Москвы сейчас"},
|
||||||
|
{"id": 37, "tier": "medium", "category": "weather_commute", "query": "какие пробки на дороге до Москвы"},
|
||||||
|
{"id": 38, "tier": "medium", "category": "weather_commute", "query": "время в пути на работу"},
|
||||||
|
{"id": 39, "tier": "medium", "category": "weather_commute", "query": "есть ли пробки сейчас"},
|
||||||
|
{"id": 40, "tier": "medium", "category": "weather_commute", "query": "стоит ли брать зонтик"},
|
||||||
|
|
||||||
|
{"id": 41, "tier": "medium", "category": "smart_home_control", "query": "включи свет в гостиной"},
|
||||||
|
{"id": 42, "tier": "medium", "category": "smart_home_control", "query": "выключи свет на кухне"},
|
||||||
|
{"id": 43, "tier": "medium", "category": "smart_home_control", "query": "какая температура дома"},
|
||||||
|
{"id": 44, "tier": "medium", "category": "smart_home_control", "query": "установи температуру 22 градуса"},
|
||||||
|
{"id": 45, "tier": "medium", "category": "smart_home_control", "query": "включи свет в спальне на 50 процентов"},
|
||||||
|
{"id": 46, "tier": "medium", "category": "smart_home_control", "query": "выключи все лампочки"},
|
||||||
|
{"id": 47, "tier": "medium", "category": "smart_home_control", "query": "какие устройства сейчас включены"},
|
||||||
|
{"id": 48, "tier": "medium", "category": "smart_home_control", "query": "закрыты ли все окна"},
|
||||||
|
{"id": 49, "tier": "medium", "category": "smart_home_control", "query": "включи вентилятор в детской"},
|
||||||
|
{"id": 50, "tier": "medium", "category": "smart_home_control", "query": "есть ли кто-нибудь дома"},
|
||||||
|
{"id": 51, "tier": "medium", "category": "smart_home_control", "query": "включи ночной режим"},
|
||||||
|
{"id": 52, "tier": "medium", "category": "smart_home_control", "query": "какое потребление электричества сегодня"},
|
||||||
|
{"id": 53, "tier": "medium", "category": "smart_home_control", "query": "выключи телевизор"},
|
||||||
|
{"id": 54, "tier": "medium", "category": "smart_home_control", "query": "открой шторы в гостиной"},
|
||||||
|
{"id": 55, "tier": "medium", "category": "smart_home_control", "query": "установи будильник на 7 утра"},
|
||||||
|
{"id": 56, "tier": "medium", "category": "smart_home_control", "query": "включи кофемашину"},
|
||||||
|
{"id": 57, "tier": "medium", "category": "smart_home_control", "query": "выключи свет во всём доме"},
|
||||||
|
{"id": 58, "tier": "medium", "category": "smart_home_control", "query": "сколько у нас датчиков движения"},
|
||||||
|
{"id": 59, "tier": "medium", "category": "smart_home_control", "query": "состояние всех дверных замков"},
|
||||||
|
{"id": 60, "tier": "medium", "category": "smart_home_control", "query": "включи режим кино в гостиной"},
|
||||||
|
{"id": 61, "tier": "medium", "category": "smart_home_control", "query": "прибавь яркость в детской"},
|
||||||
|
{"id": 62, "tier": "medium", "category": "smart_home_control", "query": "закрой все шторы"},
|
||||||
|
{"id": 63, "tier": "medium", "category": "smart_home_control", "query": "кто последний открывал входную дверь"},
|
||||||
|
{"id": 64, "tier": "medium", "category": "smart_home_control", "query": "заблокируй входную дверь"},
|
||||||
|
{"id": 65, "tier": "medium", "category": "smart_home_control", "query": "покажи камеру у входа"},
|
||||||
|
|
||||||
|
{"id": 66, "tier": "medium", "category": "timers_reminders", "query": "поставь таймер на 10 минут"},
|
||||||
|
{"id": 67, "tier": "medium", "category": "timers_reminders", "query": "напомни мне позвонить врачу в 15:00"},
|
||||||
|
{"id": 68, "tier": "medium", "category": "timers_reminders", "query": "поставь будильник на завтра в 6:30"},
|
||||||
|
{"id": 69, "tier": "medium", "category": "timers_reminders", "query": "напомни выключить плиту через 20 минут"},
|
||||||
|
{"id": 70, "tier": "medium", "category": "timers_reminders", "query": "сколько времени осталось на таймере"},
|
||||||
|
|
||||||
|
{"id": 71, "tier": "medium", "category": "shopping_cooking", "query": "добавь молоко в список покупок"},
|
||||||
|
{"id": 72, "tier": "medium", "category": "shopping_cooking", "query": "что есть в списке покупок"},
|
||||||
|
{"id": 73, "tier": "medium", "category": "shopping_cooking", "query": "добавь хлеб и яйца в список покупок"},
|
||||||
|
{"id": 74, "tier": "medium", "category": "shopping_cooking", "query": "сколько граммов муки нужно для блинов на 4 человека"},
|
||||||
|
{"id": 75, "tier": "medium", "category": "shopping_cooking", "query": "какой рецепт борща ты знаешь"},
|
||||||
|
|
||||||
|
{"id": 76, "tier": "medium", "category": "personal_memory", "query": "как меня зовут"},
|
||||||
|
{"id": 77, "tier": "medium", "category": "personal_memory", "query": "где я живу"},
|
||||||
|
{"id": 78, "tier": "medium", "category": "personal_memory", "query": "что мы обсуждали в прошлый раз"},
|
||||||
|
{"id": 79, "tier": "medium", "category": "personal_memory", "query": "что ты знаешь о моем домашнем сервере"},
|
||||||
|
{"id": 80, "tier": "medium", "category": "personal_memory", "query": "напомни, какие сервисы я запускаю"},
|
||||||
|
{"id": 81, "tier": "medium", "category": "personal_memory", "query": "что я говорил о своей сети"},
|
||||||
|
{"id": 82, "tier": "medium", "category": "personal_memory", "query": "что я просил тебя запомнить"},
|
||||||
|
|
||||||
|
{"id": 83, "tier": "medium", "category": "quick_info", "query": "какой сейчас курс биткоина"},
|
||||||
|
{"id": 84, "tier": "medium", "category": "quick_info", "query": "курс доллара к рублю сейчас"},
|
||||||
|
{"id": 85, "tier": "medium", "category": "quick_info", "query": "есть ли проблемы у Cloudflare сегодня"},
|
||||||
|
{"id": 86, "tier": "medium", "category": "quick_info", "query": "какая последняя версия Docker"},
|
||||||
|
{"id": 87, "tier": "medium", "category": "quick_info", "query": "какие новые функции в Home Assistant 2024"},
|
||||||
|
{"id": 88, "tier": "medium", "category": "quick_info", "query": "как проверить использование диска в Linux"},
|
||||||
|
{"id": 89, "tier": "medium", "category": "quick_info", "query": "как перезапустить Docker контейнер"},
|
||||||
|
{"id": 90, "tier": "medium", "category": "quick_info", "query": "как посмотреть логи Docker контейнера"},
|
||||||
|
|
||||||
|
{"id": 91, "tier": "complex", "category": "infrastructure", "query": "исследуй и сравни Proxmox, Unraid и TrueNAS для домашней лаборатории"},
|
||||||
|
{"id": 92, "tier": "complex", "category": "infrastructure", "query": "напиши подробное руководство по безопасности домашнего сервера, подключенного к интернету"},
|
||||||
|
{"id": 93, "tier": "complex", "category": "infrastructure", "query": "исследуй все доступные дашборды для самохостинга и сравни их функции"},
|
||||||
|
{"id": 94, "tier": "complex", "category": "infrastructure", "query": "исследуй лучший стек мониторинга для самохостинга в 2024 году со всеми вариантами"},
|
||||||
|
{"id": 95, "tier": "complex", "category": "infrastructure", "query": "сравни все системы резервного копирования для Linux: Restic, Borg, Duplicati, Timeshift"},
|
||||||
|
{"id": 96, "tier": "complex", "category": "infrastructure", "query": "напиши полное руководство по настройке обратного прокси Caddy для домашнего сервера с SSL"},
|
||||||
|
{"id": 97, "tier": "complex", "category": "network", "query": "исследуй и сравни WireGuard, OpenVPN и Tailscale для домашней VPN с детальными плюсами и минусами"},
|
||||||
|
{"id": 98, "tier": "complex", "category": "network", "query": "исследуй лучшие практики сегментации домашней сети с VLAN и правилами файрвола"},
|
||||||
|
{"id": 99, "tier": "complex", "category": "network", "query": "изучи все самохостируемые DNS решения и их возможности"},
|
||||||
|
{"id": 100, "tier": "complex", "category": "network", "query": "исследуй лучшие самохостируемые системы мониторинга сети: Zabbix, Grafana, Prometheus, Netdata"},
|
||||||
|
{"id": 101, "tier": "complex", "category": "home_assistant", "query": "исследуй и сравни все платформы умного дома: Home Assistant, OpenHAB и Domoticz"},
|
||||||
|
{"id": 102, "tier": "complex", "category": "home_assistant", "query": "изучи лучшие Zigbee координаторы и их совместимость с Home Assistant в 2024 году"},
|
||||||
|
{"id": 103, "tier": "complex", "category": "home_assistant", "query": "напиши детальный отчет о поддержке протокола Matter и совместимых устройствах"},
|
||||||
|
{"id": 104, "tier": "complex", "category": "home_assistant", "query": "исследуй все способы интеграции умных ламп с Home Assistant: Zigbee, WiFi, Bluetooth"},
|
||||||
|
{"id": 105, "tier": "complex", "category": "home_assistant", "query": "найди и сравни все варианты датчиков движения для умного дома с оценками и ценами"},
|
||||||
|
{"id": 106, "tier": "complex", "category": "home_assistant", "query": "напиши подробное руководство по настройке автоматизаций в Home Assistant для умного освещения"},
|
||||||
|
{"id": 107, "tier": "complex", "category": "home_assistant", "query": "исследуй все варианты голосового управления умным домом на русском языке, включая локальные решения"},
|
||||||
|
{"id": 108, "tier": "complex", "category": "home_assistant", "query": "исследуй все протоколы умного дома и их плюсы и минусы: Zigbee, Z-Wave, WiFi, Thread, Bluetooth"},
|
||||||
|
{"id": 109, "tier": "complex", "category": "media_files", "query": "исследуй и сравни все самохостируемые решения для хранения фотографий с детальным сравнением функций"},
|
||||||
|
{"id": 110, "tier": "complex", "category": "media_files", "query": "изучи лучшие самохостируемые медиасерверы: Jellyfin, Plex и Emby — с характеристиками и отзывами"},
|
||||||
|
{"id": 111, "tier": "complex", "category": "media_files", "query": "сравни все самохостируемые облачные хранилища: Nextcloud, Seafile, Owncloud — производительность и функции"},
|
||||||
|
{"id": 112, "tier": "complex", "category": "research", "query": "исследуй последние достижения в локальном LLM инференсе и оборудовании для него"},
|
||||||
|
{"id": 113, "tier": "complex", "category": "research", "query": "изучи лучшие опенсорс альтернативы Google сервисов для приватного домашнего окружения"},
|
||||||
|
{"id": 114, "tier": "complex", "category": "research", "query": "изучи все варианты локального запуска языковых моделей на видеокарте 8 ГБ VRAM"},
|
||||||
|
{"id": 115, "tier": "complex", "category": "research", "query": "найди и сравни все фреймворки для создания локальных AI ассистентов с открытым исходным кодом"},
|
||||||
|
{"id": 116, "tier": "complex", "category": "research", "query": "изучи все доступные локальные ассистенты с голосовым управлением на русском языке"},
|
||||||
|
{"id": 117, "tier": "complex", "category": "infrastructure", "query": "изучи свежие CVE и уязвимости в популярном самохостируемом ПО: Gitea, Nextcloud, Jellyfin"},
|
||||||
|
{"id": 118, "tier": "complex", "category": "infrastructure", "query": "напиши детальное сравнение систем управления конфигурацией: Ansible, Salt, Puppet для домашнего окружения"},
|
||||||
|
{"id": 119, "tier": "complex", "category": "network", "query": "исследуй все самохостируемые решения для блокировки рекламы: Pi-hole, AdGuard Home, NextDNS"},
|
||||||
|
{"id": 120, "tier": "complex", "category": "research", "query": "напиши подробный отчет о технологиях синтеза речи с открытым исходным кодом на русском языке"}
|
||||||
|
]
|
||||||
|
}
|
||||||
11
router.py
11
router.py
@@ -52,6 +52,10 @@ _LIGHT_PATTERNS = re.compile(
|
|||||||
r"|окей|хорошо|отлично|понятно|ок|ладно|договорились|спс|благодарю"
|
r"|окей|хорошо|отлично|понятно|ок|ладно|договорились|спс|благодарю"
|
||||||
r"|пожалуйста|не за что|всё понятно|ясно"
|
r"|пожалуйста|не за что|всё понятно|ясно"
|
||||||
r"|как дела|как ты|как жизнь|всё хорошо|всё ок"
|
r"|как дела|как ты|как жизнь|всё хорошо|всё ок"
|
||||||
|
# Assistant control words / confirmations
|
||||||
|
r"|да|нет|стоп|отмена|отменить|подожди|повтори|повторить|не нужно|не надо"
|
||||||
|
r"|слышишь\s+меня|ты\s+тут|отлично[,!]?\s+спасибо"
|
||||||
|
r"|yes|no|stop|cancel|wait|repeat"
|
||||||
# Russian tech definitions — static knowledge (no tools needed)
|
# Russian tech definitions — static knowledge (no tools needed)
|
||||||
r"|что\s+такое\s+\S+"
|
r"|что\s+такое\s+\S+"
|
||||||
r"|что\s+означает\s+\S+"
|
r"|что\s+означает\s+\S+"
|
||||||
@@ -422,10 +426,11 @@ class Router:
|
|||||||
self,
|
self,
|
||||||
message: str,
|
message: str,
|
||||||
history: list[dict],
|
history: list[dict],
|
||||||
|
no_inference: bool = False,
|
||||||
) -> tuple[str, Optional[str]]:
|
) -> tuple[str, Optional[str]]:
|
||||||
"""
|
"""
|
||||||
Returns (tier, reply_or_None).
|
Returns (tier, reply_or_None).
|
||||||
For light tier: also generates the reply inline.
|
For light tier: also generates the reply inline (unless no_inference=True).
|
||||||
For medium/complex: reply is None.
|
For medium/complex: reply is None.
|
||||||
"""
|
"""
|
||||||
if self._fast_tool_runner and self._fast_tool_runner.any_matches(message.strip()):
|
if self._fast_tool_runner and self._fast_tool_runner.any_matches(message.strip()):
|
||||||
@@ -435,6 +440,8 @@ class Router:
|
|||||||
|
|
||||||
if _LIGHT_PATTERNS.match(message.strip()):
|
if _LIGHT_PATTERNS.match(message.strip()):
|
||||||
print("[router] regex→light", flush=True)
|
print("[router] regex→light", flush=True)
|
||||||
|
if no_inference:
|
||||||
|
return "light", None
|
||||||
return await self._generate_light_reply(message, history)
|
return await self._generate_light_reply(message, history)
|
||||||
|
|
||||||
if _COMPLEX_PATTERNS.search(message.strip()):
|
if _COMPLEX_PATTERNS.search(message.strip()):
|
||||||
@@ -447,7 +454,7 @@ class Router:
|
|||||||
|
|
||||||
tier = await self._classify_by_embedding(message)
|
tier = await self._classify_by_embedding(message)
|
||||||
|
|
||||||
if tier != "light":
|
if tier != "light" or no_inference:
|
||||||
return tier, None
|
return tier, None
|
||||||
|
|
||||||
return await self._generate_light_reply(message, history)
|
return await self._generate_light_reply(message, history)
|
||||||
|
|||||||
Reference in New Issue
Block a user