---
name: avtero_fastpath_singlepass
description: avtero ускорение подбора — fast-path (single-pass finalize когда pre-resolve покрыл всё); как проверить/откатить
metadata: 
  node_type: memory
  type: project
  originSessionId: 4eea915e-3b47-4cd5-8a0e-bfa29b78a87c
---

**2026-06-30: fast-path для скорости подбора.** Профиль показал: ~110с держат НЕ модель и НЕ раунды (cap=2 был медленнее И хуже OEM), а **последовательные раунды tool-loop** × медленные RU-сетевые тулзы (emex/autodoc/ddg). emex уже кешируется, валидация аналогов уже параллельна (gather) — там выигрыша нет.

**Что сделано (`app/services/orchestrator.py`, бэкап `orchestrator.py.bak-fastpath-*`):** `_pre_resolve_parts` уже тянет авторитетные OEM (autodoc-first→emex) + кроссы ДО LLM и вкладывает в промпт; и добавляет маркер `🚀 ОПТИМИЗАЦИЯ` РОВНО когда покрыты все required-категории. Правки:
1. call-site (~4510): `_pre_covered = bool(preresolved and "🚀 ОПТИМИЗАЦИЯ" in preresolved)`, передаётся `fast_finalize=_pre_covered` в `_llm_with_tools`.
2. `_llm_with_tools` (+параметр `fast_finalize`): перед циклом чейна — если `fast_finalize` и env `AVTERO_FAST_PATH≠0`, делает ОДИН tool-less `_force_final_call` (модель просто оформляет готовые OEM+аналоги из промпта в JSON), возвращает `meta.fast_path=True, tool_rounds=0`. Если JSON не вышел — проваливается в обычный loop. Post-LLM emex-валидация + фитмент-гейт идут как обычно → **качество сохраняется**.
Ожидание: типовые работы (колодки/диски/фильтры/масло) ~30-40с вместо ~110с; gap-кейсы (нет маркера) идут полным loop как раньше.

**ОТКАТ мгновенный:** env `AVTERO_FAST_PATH=0` в `~/Library/LaunchAgents/local.avtero.plist` → bootout+bootstrap (код не трогать). Либо вернуть бэкап `cp orchestrator.py.bak-fastpath-* orchestrator.py`.

**СТАТУС ПОСЛЕ ДЕПЛОЯ (2026-06-30):** задеплоено, прод СТАБИЛЕН и КАЧЕСТВЕНЕН (тест Kia Rio: OEM `58101-1RA00` верный, 9 аналогов). НО fast-path **НЕ сработал** (`_meta.fast_path=None`, rounds=3, 69.7с) — гейт слишком строгий: работа «колодки» раскрывается на колодки+смазки+направляющие, смазки/направляющие БЕЗ каталожного OEM, а маркер `🚀` требует `n_required_resolved==n_required` по ВСЕМ required → маркера нет → fast-path инертен (проваливается в обычный loop = текущее поведение, **регрессии нет**, по сути no-op пока гейт не выполнен).

**ИСТИННЫЙ ДИАГНОЗ 2026-06-30 (прежний «ослабить гейт» — НЕВЕРЕН).** Профилировка с реальными VIN показала:
1. **fast-path-код ИЗБЫТОЧЕН.** Когда пре-резолв покрыл работу, skip-hint в промпте уже заставляет LLM финализировать с **0 тул-раундов** (`_meta.tool_rounds=0`) — fast-path tool-less вызов не нужен (он к тому же не отрабатывал: `_force_final_call` не давал валидный JSON → провал в обычный loop, который и так делал 0 раундов). Оставлен как инертный no-op; можно удалить (но orchestrator.py правит и параллельная сессия — не трогать без нужды).
2. **Настоящий блокер был — МОРФОЛОГИЯ МАТЧИНГА `work_groups`.** `expand_work_group` матчил подстрокой: «замена ПЕРЕДНИХ тормозНЫХ колодОК» ≠ паттерн «тормозНЫЕ колодКИ» → тормоза (частейшая работа!) вообще не пре-резолвились → полный цикл ~110с. **ИСПРАВЛЕНО:** добавлен стем-фолбэк в `work_groups.py` (бэкап `*.bak-stemmatch-*`, sha `86b60ec9…`): `_stem_match` стеммит слова паттерна и требует префикс-совпадение со словами запроса; стоп-слова (замена/передних/задних/…), одиночное родовое слово (фильтр/масло/диск/ремень — `_GENERIC_STEMS`) в стем-проход НЕ идёт (иначе «то с фильтрами» цеплял любой фильтр). Точный матч работает как раньше, стем только ДОБАВЛЯет. Батарея 9/9 поз + 0 ложных + нет over-union (oil+filter→только oil_service); 50 unit passed.

**РЕЗУЛЬТАТ matcher-фикса (живьём, VIN KNAFW411…):** тормоза `замена передних тормозных колодок` → **rounds=0, 69.8с**, верные OEM колодки `583051MA00`+диск `517122H300`. Масло → rounds=0, 44.5с. Раньше тормоза = полный loop. Остаточная латентность при rounds=0 = генерация JSON головой + фитмент-валидация (растёт с числом деталей, не с раундами).

**FAST-FINALIZE РОУТИНГ — ПОСТРОЕН, НО ОТКЛЮЧЁН (env `AVTERO_FAST_PATH=0` в плисте, 2026-06-30).** Идея: для pre-covered работ переставлять быструю голову (`AVTERO_FAST_FINALIZE_MODEL`, дефолт `bynara/mimo-v2.5-pro-free`) в начало цепочки и пускать обычный цикл (orchestrator.py:~2122, бэкап `*.bak-fastfinalize-*`; мёртвый tool-less `_force_final_call`-блок заменён на stable-sort цепочки). **A/B на свежем mimo (Kia, 6 работ) показал 2.2× (18с vs 41с opus) при ИДЕНТИЧНЫХ primary OEM** (OEM из пре-резолва, не от модели). НО при включении в прод — рваные 18-235с: free-reseller головы (mimo И zyloo/opus) **троттлятся под нагрузкой** → откат на cerebras/glm, который уходит в полный тул-цикл (медленно). Частично артефакт тест-нагрузки (~25 запросов/час выжгли free-квоты), но риск безотказности реален. **Решение: держать выключенным** — безотказность > скорость (приоритет юзера). Включать `AVTERO_FAST_PATH=1` ТОЛЬКО когда будет быстрая+надёжная голова (не free-reseller). Код реверсивен, matcher-фикс работает независимо. См. [[avtero_omniroute_llm_bus]] [[avtero_llm_chain_incident]] [[risky_llm_provider_isolation]].
