# Ручные кейсы для регрессии Чеклист для прогонов в Песочнице. **Не автоматизирован** — это `markdown`-чеклист, по которому оператор/разработчик прогоняет сценарии руками. Полная подсистема прогона (`eval/run.py`) — Спринт 8. Раздел A — конверсионные кейсы Спринта 7.6 (новые). Раздел B — регрессия 8 ручных сценариев из блока H Спринта 6b (должны проходить как раньше). --- ## A · Конверсионные кейсы (Спринт 7.6) Все 5 кейсов — про оптимизацию воронки `new_booking` до 4 шагов: `intro → qualify → book → close`. Цель проверки — сжатие воронки и содержательность первого ответа. ### Что проверяем на каждом кейсе **Структура первого ответа бота на жалобу пациента** (5-пунктовый шаблон, см. `prompts/intents/new_booking/steps/qualify.md`): - [ ] **Эмпатия** — одна короткая фраза (одна, не больше). - [ ] **Гипотеза** — 2–3 ЛОР-причины формулировкой «может быть связано с…», без диагноза. Если в RAG-выдержках причин нет — пункт допустимо пропустить. - [ ] **Специалист** — рекомендация по профилю (зафиксирован в слот `specialist`). - [ ] **Услуга и цена** — формулировкой «при необходимости назначит». Если в RAG нет — пункт пропускается. - [ ] **CTA** — бинарный вопрос «записать?». **Сжатие воронки:** - [ ] До запроса телефона — **≤ 3 реплики бота** (раньше было 5–6). - [ ] Имя на `intro` **не спрашивается** — спрашивается на `book` вместе с телефоном. - [ ] Граф работает по `intro → qualify → book → close`. На `present` модель не попадает (в Песочнице бейдж шага не показывает `present`). **RAG:** - [ ] В отладочной панели «Найденные фрагменты» видно, что чанки пришли из подписанных документов ветки `new_booking`. - [ ] Если ветка не подписана ни на один документ — гипотеза/услуга/цена пропускаются (5-пунктовый шаблон деградирует до эмпатия + специалист + CTA). ### Кейсы #### A.1 · «Очень сильно храплю, иногда закладывает уши» Контрольный кейс из `docs/OPTIMIZATION_CONVERSION_v1.md` §1 (сравнение с конкурентом «Александра»). - Ожидаемый специалист: ЛОР. - Ожидаемые гипотезы (из вики): искривление перегородки, аденоиды, ринит. - Ожидаемая услуга: эндоскопия, 1 000 ₽ (если в подписанных документах есть). - Слоты после `qualify`: `reason="храп + заложенность ушей"`, `specialist="ЛОР"`. #### A.2 · «Болит горло уже неделю, не проходит» - Ожидаемый специалист: ЛОР. - Ожидаемые гипотезы: тонзиллит, фарингит. - Слоты: `reason="боль в горле, неделя"`, `specialist="ЛОР"`. #### A.3 · «Стал плохо слышать на одно ухо, и звон» Особая ситуация 3 (`needs_surgologist_first`). - Ожидаемое поведение: сначала уточнить «вас уже обследовал сурдолог?», при первичном — `specialist=ЛОР`, `needs_surgologist_first=true`. - Объяснение: «обычно начинают с ЛОР-врача, при необходимости направит к сурдологу». #### A.4 · «Насморк больше месяца, не проходит» - Ожидаемый специалист: ЛОР. - Ожидаемые гипотезы: хронический ринит, синусит. #### A.5 · «Звон в ушах, какой-то непонятный» Аналог A.3, проверка устойчивости. - Ожидаемое поведение: уточнение «были у сурдолога?», при первичном — ЛОР с пометкой про сурдолога. --- ## B · Регрессия 8 ручных сценариев (блок H Спринта 6b) После переписки воронки в Спринте 7.6 — все 8 сценариев должны продолжать работать. Сравниваем с разобранными примерами в `docs/examples/*_v2.md`. ### B.1 · Базовая запись к ЛОР-врачу - См. `docs/examples/01_basic_booking_v2.md`. - Ожидание: путь `intro → qualify → book → close` (3 реплики бота до телефона), без особых ситуаций. ### B.2 · Soft-insertion цена в середине записи - См. `docs/examples/02_price_during_booking_v2.md` Вариант A. - Ожидание: на короткое «а сколько стоит?» — ответ в-line, шаг не меняется, `soft_insertion_count++`. ### B.3 · Hard-handoff в `reschedule` и возврат - См. `docs/examples/02_price_during_booking_v2.md` Вариант B (там `price_question`, для reschedule аналогично). - Ожидание: `suspended_intent=new_booking`, после возврата — восстановление `current_step_code` и `slots`. ### B.4 · Возврат из `suspended_intent` - Подразумевается в B.3. - Ожидание: при возврате `handoff_count` сбрасывается в 0. ### B.5 · Упоминание хирургии → escalate с `reason=surgery` - Пациент в любом месте говорит «у меня уже была операция, надо перенести» — должен сработать `[INTENT_CHANGE: escalate_human]` с `reason=surgery`. ### B.6 · Петля роутера → автоэскалация с `reason=routing_loop` - Искусственно: чередовать `new_booking ↔ price_question` 4+ раза. - Ожидание: на 4-м переключении автоматически уйти в `escalate_human` с `reason=routing_loop` без вызова LLM. ### B.7 · Запись ребёнка с защитным условием `require_legal_rep` - См. `docs/examples/03_child_patient_guard_v2.md`. - Ожидание: при `is_child=true` и пустых `legal_rep_*` валидатор блокирует переход `qualify → book`. **Внимание:** в Спринте 7.6 переход теперь `qualify → book` (раньше было `qualify → present`). Защитное условие должно продолжать работать на новом переходе. ### B.8 · Конкретный врач → лист ожидания - Пациент: «хочу к доктору Иванову». - Ожидание: `requested_doctor="Иванов"`, `waitlist_flag=true`, фраза «администратор свяжется для уточнения даты». --- ## Как прогонять 1. Открой Песочницу (`http://localhost:8000/sandbox.html`). 2. Создай новый тред для каждого кейса (чтобы счётчики `handoff_count` и `soft_insertion_count` были чистыми). 3. Веди диалог как пациент, проставляй галочки в чеклисте по факту. 4. Если что-то не так — отметь словесно, приложи скрин/реплику. Возвращаемся в код, правим, прогоняем снова. ## Что НЕ делает этот документ - Не запускается автоматически. Для автозапуска — Спринт 8 (`eval/run.py`). - Не покрывает все возможные граничные случаи маршрутизатора. Для них есть `eval/router_cases_*.jsonl` (тоже к Спринту 8). - Не сравнивает с baseline по метрикам. Это всё прогоны «глазами».