52b46bc53e
Спринт 6c — терминология и сверка документации с реальным кодом:
- Словарь терминов в static/docs.html: «маршрутизатор» вместо «роутер»,
«защитное условие» вместо «guard», «пошаговая ветка» вместо «многошаговая».
Разделены концепты «намерение» (intent) и «ветка» (branch) с пометкой,
что в коде они хранятся как одна сущность 1:1.
- Песочница: «Решение маршрутизатора» виден всегда (зелёный/жёлтый),
счётчик переключений «N из 3» отдельной плашкой, бейджи под словарь.
- Настройки: «Условия перехода» → «Защитные условия (guards, JSON)».
- GRAPH_ARCHITECTURE_v4.md: имена полей thread_state и слоты приведены
к реальной БД (db/models/thread_state.py) и таксономии промптов шагов
(prompts/intents/new_booking/steps/). Ссылки на *_v2 примеры. На v3
поставлена шапка «устарело».
- 4 примера переписаны как *_v2: реальные current_intent_code/
current_step_code/slots_json, реальные allowed_next без двойных переходов,
реальная таксономия слотов name/reason/specialist/preferred_time/confirmed.
Удалены вымышленные CRM tool calls и слоты, которых нет в коде.
- static/example.html — параметризованная страница с навигацией между
4 примерами; роут GET /api/docs/examples/{name} в main.py отдаёт
markdown без дублирования файлов.
- Редактирование документов в Отладке: GET/PUT /documents/{id}/raw,
textarea с переразметкой и обновлением Chroma при сохранении.
Спринт 7, часть A — мульти-RAG через подписку ветка↔документы:
- Миграция: таблица intent_documents (M:N), модель IntentDocument,
индекс по document_id для обратного поиска.
- API: GET/PUT /intents/{code}/documents и GET/PUT /documents/{id}/intents
с PUT-семантикой «полный список», атомарно. Сервис
services/intent_document_service.py.
- Retrieval-фильтр в chat_service: подтягивает document_ids активной
ветки и передаёт в vectorstore.query(). Дефолт пустой подписки —
document_ids=[] (= 0 чанков), не «вся коллекция»: пустая подписка
означает «ветка не настроена», подмешивать случайное хуже, чем
ничего. vectorstore.query() различает None (нет фильтра) и [] (0).
- UI Настроек: блок «Документы базы знаний» в правом сайдбаре,
всегда видим независимо от вкладки, сортировка по имени, счётчик
«N из M», PUT при сохранении.
- UI Отладки: третья кнопка «привязка» рядом с «удалить» —
раскрывашка со списком веток (галочки), быстрая привязка прямо
на странице загрузки.
- Песочница: блок «Срез RAG» с подпиской/найдено, ворнинг при пустой
подписке. Поле rag_subscription в QueryResponse и ChatResponse.
- Системный промпт страницы Отладки переехал в обычную ветку _debug
(«Страница отладки»). Удалён prompts/system_prompt.md и логика
DEFAULT_SYSTEM_PROMPT в llm_client. routers/query.py подтягивает
активный конфиг ветки _debug и её подписки. Дефолт пустой подписки
для _debug — None (вся коллекция), не [] как для пациентских — чтобы
Отладка работала «из коробки». На странице Отладки info-bar показывает
активную версию и счётчик подписок, ссылка → Настройки.
- Тест-блок «Тест-вопрос» в центре Настроек: расширил /query
параметрами intent_code (default _debug), system_prompt (override
для теста черновика из textarea), disable_rag (для _router).
Редактор промпта обёрнут в <details open> — можно свернуть до
одной строки. Под ним — три колонки результата (RAG / промпт /
ответ). Для _router показывается подсказка про отсутствие RAG.
Документы:
- data/datasets/*.md — наработки по 6 веткам (рабочие материалы оператора).
- docs/BRANCH_MAP_AND_PROMPTS_v1.md, docs/OPTIMIZATION_CONVERSION_v1.md,
docs/guides/state_machine_and_slots.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
190 lines
21 KiB
Markdown
190 lines
21 KiB
Markdown
---
|
||
intent: escalate_human
|
||
title: Передача оператору (датасет для ветки escalate_human)
|
||
purpose: |
|
||
Источник для РАГа в ветке escalate_human. Контент — это формулировки переключения на оператора в зависимости от reason (acute_pain, surgery, angry, explicit_request, routing_loop) и минимальный набор данных для саммари оператору.
|
||
sources_wiki:
|
||
- homepage/udalennyjj-kontakt-centr/medicinskie-voprosy.md
|
||
- homepage/udalennyjj-kontakt-centr/rechevye-moduli-dlja-slozhnyx-situacijj/jekstrennyjj-priem-bez-zapisi.md
|
||
- homepage/udalennyjj-kontakt-centr/rechevye-moduli-dlja-slozhnyx-situacijj/xamstvo-so-storony-klienta.md
|
||
- homepage/udalennyjj-kontakt-centr/rechevye-moduli-dlja-slozhnyx-situacijj/priem-malomobilnyx-pacientov.md
|
||
- homepage/udalennyjj-kontakt-centr/rabota-s-zhalobami/konfliktologija.md
|
||
- homepage/sluzhba-administratorov/poleznye-materialy-administratora/knopka-vyzova-brigady-operativnogo-reagirovanija.md
|
||
- homepage/udalennyjj-kontakt-centr/obshhaja-informacija/kontakty-kliniki.md (только основные номера)
|
||
note: |
|
||
Файл собран только из официальной выгрузки Yandex Wiki клиники. Прежние «временные» сводные документы
|
||
(skripty-vozrazhenija-chavo-obshhijj-spravochnik.md, vrachi-kliniki-polnaja-informacija.md)
|
||
для этой ветки не являются источником.
|
||
В вики не нашлось явного норматива «через сколько минут оператор отвечает в чате» — это пометка в раздел
|
||
«Что нужно дополнить».
|
||
---
|
||
|
||
# Передача оператору
|
||
|
||
## Зачем эта ветка
|
||
|
||
`escalate_human` срабатывает в одном из четырёх случаев (плюс пятый — служебный):
|
||
|
||
1. `acute_pain` — острая боль, угроза здоровью прямо сейчас.
|
||
2. `surgery` — упоминание операции, наркоза, стационара, предоперационной подготовки.
|
||
3. `angry` — пациент явно раздражён, требует «человека» в резкой форме, грубит.
|
||
4. `explicit_request` — пациент просто попросил оператора («дайте администратора», «соедините с человеком»).
|
||
5. `routing_loop` — техническая защита: бот несколько раз подряд переключал ветку, но не смог разобраться. Срабатывает автоматически, не по семантике.
|
||
|
||
Задача ветки — короткой человеческой репликой подтвердить, что оператор подключится, и закрыть диалог с минимумом обещаний. Реальная передача в чат «Администраторы» происходит на уровне приложения, не от лица бота.
|
||
|
||
## Поведение по `reason`
|
||
|
||
### `acute_pain` — острое состояние
|
||
|
||
- Признать ситуацию одной фразой: «Понимаю, состояние тревожное».
|
||
- Сказать, что передаёт администратору прямо сейчас.
|
||
- **Обязательно добавить**: «Если состояние ухудшается — звоните 103 или 112, не ждите ответа в чате».
|
||
- Не задавать уточняющих вопросов, не пытаться обсуждать симптомы.
|
||
|
||
Пример (как короткая шаблонная реплика, бот её адаптирует):
|
||
|
||
> Понимаю, состояние тревожное. Передаю ваш чат администратору — он свяжется в ближайшее время. Если станет хуже — пожалуйста, звоните 103 или 112, не ждите ответа в чате.
|
||
|
||
Если пациент пишет про хроническую боль или повторяющиеся эпизоды (не «прямо сейчас плохо»), это не `acute_pain` — скорее `medical_question` или `new_booking`. Признак острого состояния — настоящее время и резкая интенсивность («сейчас сильно болит», «горит температура», «течёт кровь, не останавливается»).
|
||
|
||
### `surgery` — вопрос про операцию, хирургию, наркоз, стационар
|
||
|
||
- Признать, что вопрос требует подробного обсуждения с человеком.
|
||
- Сказать, что такие вопросы решает не виртуальный ассистент: «лично с сотрудником клиники, чтобы ничего не упустить».
|
||
- Передать оператору, который ответит подробно.
|
||
- Не называть конкретных цен, имён хирургов, планов операций.
|
||
|
||
Пример:
|
||
|
||
> По операции лучше говорить лично — там много нюансов: подготовка, анализы, наркоз, восстановление. Передаю ваш чат ассистенту хирурга, он свяжется и расспросит подробно.
|
||
|
||
Контекст для бота: запись на операцию в клинике идёт через предоперационный приём у оперирующего ЛОР-врача — пациента всё равно сначала смотрит врач, и уже после этого оформляется операция. Никакой бот этого пути не сокращает.
|
||
|
||
### `angry` — пациент раздражён, требует человека
|
||
|
||
- Не оправдываться, не спорить, не объясняться.
|
||
- Не использовать «понимаю, как это раздражает» — это сейчас прозвучит как издёвка.
|
||
- Короткая фраза: «Сейчас переключу на администратора».
|
||
|
||
Пример:
|
||
|
||
> Сейчас переключу вас на администратора. Он свяжется в ближайшее время.
|
||
|
||
Из вики (из раздела «Хамство со стороны клиента»): операторы в таких случаях используют формулировки «понимаю, что вы обеспокоены, давайте попробуем решить в конструктивном диалоге», и если пациент продолжает грубить — «продолжать разговор в таком тоне не имеет смысла, я отвечу позже». Эти формулировки больше для оператора-человека; от бота они звучат натянуто. Бот должен закругляться короче.
|
||
|
||
### `explicit_request` — просто попросил оператора
|
||
|
||
- Подтвердить запрос без вопросов «а зачем?» или «а в чём именно дело?».
|
||
- Сказать, что передаёт диалог.
|
||
- Можно добавить лёгкое «он ответит вам в ближайшее время».
|
||
|
||
Пример:
|
||
|
||
> Хорошо, передаю чат администратору. Он ответит вам в ближайшее время.
|
||
|
||
Если пациент в той же реплике попутно добавил конкретный вопрос (например, «дайте человека, я хочу записаться к Ивановой»), всё равно эскалация выигрывает: бот не пытается ответить по сути.
|
||
|
||
### `routing_loop` — автоматическая защита
|
||
|
||
- Признать, что не получилось до конца разобрать запрос (без подробностей про логику бота).
|
||
- Передать оператору.
|
||
- Не задавать новых вопросов.
|
||
|
||
Пример:
|
||
|
||
> Кажется, я не до конца разобрался с вашим вопросом. Передаю чат администратору, он сейчас подключится.
|
||
|
||
`routing_loop` срабатывает автоматически, когда `handoff_count` достиг лимита (см. логику в Спринте 6a). Это значит, что пациент несколько раз подряд переключал тему, и бот не смог удержать диалог в одной ветке. Это не вина пациента и не повод за это извиняться многословно.
|
||
|
||
## Что говорить про время ответа администратора
|
||
|
||
В выгрузке вики **точного норматива** «оператор отвечает в чате за X минут» нет. Безопасные формулировки:
|
||
|
||
- «Свяжется в ближайшее время».
|
||
- «Ответит вам в течение дня».
|
||
- «Подключится в ближайшее время».
|
||
|
||
Не использовать: «через 5 минут», «через час», «прямо сейчас» — это конкретные обещания, которые бот не может гарантировать. Если позже клиника зафиксирует SLA на ответ в чате, формулировку нужно обновить (см. раздел «Что нужно дополнить»).
|
||
|
||
При `acute_pain` уместно прямо сказать пациенту, что **ждать ответа в чате — не самый быстрый канал**. Поэтому в шаблоне идёт прямая отсылка к 103 / 112.
|
||
|
||
## Телефоны клиники для пациента (на случай острых состояний)
|
||
|
||
Если пациент хочет получить контакт прямо сейчас (например, чувствует себя плохо и просит, куда позвонить), бот может назвать **только основные публичные номера**:
|
||
|
||
- 8 (342) 207-03-03 — Клиника ухо, горло, нос (Клары Цеткин, 9).
|
||
- 8 (342) 200-02-03 — Клиника лечения кашля и аллергии (Газеты Звезда, 31а).
|
||
- 8 (342) 207-03-00 — Клиника доктора Пирогова (Краснокамск).
|
||
- **103** или **112** — экстренные службы (для острых состояний; это не клиника).
|
||
|
||
Ничего, что выходит за этот список — не озвучиваем: ни внутренние добавочные сотрудников, ни личные номера врачей, ни телефоны старшего администратора, ни кодовые фразы.
|
||
|
||
## Контекст про экстренный приём без записи
|
||
|
||
Это не работа бота, но фон, чтобы не противоречить процессу клиники. По выгрузке вики:
|
||
|
||
- Пациентов с острой болью или инородным телом в клинике могут принять без записи, но с предупреждением, что время ожидания может быть до 2 часов.
|
||
- Принимает любой свободный доктор; есть отдельный список врачей, которые приглашают своих пациентов вне записи.
|
||
|
||
Бот этого не озвучивает напрямую (это решает оператор-человек после разговора с пациентом). Бот просто эскалирует: дальнейший выбор «ехать в клинику с ожиданием / звонить 103» — за пациентом и оператором.
|
||
|
||
## Что должно попасть в саммари оператору
|
||
|
||
Когда бот эскалирует, приложение формирует саммари для оператора (см. блок E Спринта 6b). С точки зрения датасета важно понимать, какие сведения должны быть переданы — чтобы при формулировке последней реплики пациенту бот не «съел» информацию, которая нужна оператору.
|
||
|
||
Минимальный набор полезного контекста:
|
||
|
||
- `escalation_reason` — что именно вызвало эскалацию.
|
||
- Последние 3–5 реплик диалога с пациентом.
|
||
- Собранные слоты из ветки, из которой пришли (если из `new_booking` — `name`, `reason`, `specialist`, `phone` и т. д.).
|
||
- Если был `suspended_intent` (пациент был в середине сценария записи и его прервали) — отметка, на каком шаге остановились.
|
||
|
||
Бот в реплике пациенту эту информацию не пересказывает. Это просто список того, что должно быть видно оператору в момент перехвата.
|
||
|
||
## Чего бот НЕ делает в этой ветке
|
||
|
||
- Не вызывает скорую от имени пациента и не говорит «я уже вызвал».
|
||
- Не передаёт пациенту персональные данные сотрудников, личные мобильные, кодовые фразы (типа «нужно вызвать мастера для ремонта кофемашины» — это внутренняя кодовая фраза для вызова ГБР, в чат пациента она вообще не должна попадать).
|
||
- Не симулирует реплики оператора («подождите, оператор Аня сейчас вам ответит, она в чате»).
|
||
- Не ставит диагнозов, не комментирует состояние.
|
||
- Не задаёт уточняющих вопросов «расскажите подробнее, как болит» — после эскалации диалог завершается.
|
||
- Не извиняется многословно. Одна-две короткие фразы — это правило ветки.
|
||
- Не «продаёт» приём («можете записаться, и врач разберётся») — на эскалации это уже не уместно.
|
||
|
||
## Условия выхода
|
||
|
||
В отличие от других веток, у `escalate_human` нет «условий выхода» в классическом смысле. После эскалации:
|
||
|
||
- Если пациент отвечает (например, «спасибо, поняла»), бот не возобновляет сценарий записи и не уходит обратно в `new_booking`. Реальное продолжение делает оператор.
|
||
- Если в дальнейшем (через час, через день) пациент пишет новый запрос — это уже новый цикл, роутер заново определит ветку.
|
||
- Технически тред может «вернуться» в исходную ветку через `suspended_intent` (см. Спринт 6a), но это уже механика приложения, а не поведение бота в текущей реплике.
|
||
|
||
## Что нужно дополнить вручную в вики
|
||
|
||
- **SLA на ответ оператора в чате.** Сейчас в датасете формулировки «в ближайшее время» / «в течение дня». Если у клиники есть конкретный целевой норматив (15 минут? час? рабочие часы?), стоит зафиксировать — иначе в острых случаях пациент может ожидать «минут 5», а ждать 40, и это испортит впечатление сильнее, чем сама эскалация.
|
||
- **Окна работы канала.** Если чат у пациента включён круглосуточно, а оператор-человек подключается только в часы работы клиники — это нужно явно проговорить. Сейчас бот не упоминает время суток. На входящее сообщение в 03:00 нужно либо отвечать «оператор подключится утром, в острой ситуации звоните 103», либо иметь дежурного.
|
||
- **Эскалация в выходные / праздники.** Тот же вопрос: дежурит ли кто-то в чате в выходные дни клиники Пирогова (там короткий рабочий день).
|
||
- **Что говорить про время ответа при `surgery`.** Чисто хирургические запросы обрабатывает ассистент хирурга (отдельный контактный канал в клинике). Стоит зафиксировать, в какое время этот канал доступен.
|
||
- **Поведение при `angry`.** Сейчас бот сразу эскалирует. В ряде случаев бывает полезно дать одно «остужающее» сообщение, как в скрипте оператора. Решение принять — на стороне политики клиники.
|
||
- **Поведение при упоминании суицида или членовредительства.** Это не покрыто ни вики, ни базовым промптом ветки. Должна быть отдельная политика — здесь бот точно не должен «справляться сам».
|
||
|
||
## Что НЕ должно попадать в датасет ветки `escalate_human`
|
||
|
||
- Внутренние добавочные сотрудников и врачей.
|
||
- Личные мобильные руководителей / заведующих (Семкина, Гилязова, Терво и т. д. — есть в `konfliktologija.md`, но это контакты для эскалации **со стороны оператора**, не для пациента).
|
||
- Кодовые фразы для вызова ГБР, регламент вызова полиции — это исключительно работа сотрудника на месте.
|
||
- Алгоритмы оператора по работе с конфликтом / хамством в полном виде — у бота сильно урезанная ответственность.
|
||
- Цены — они для `price_question`.
|
||
- Адреса/часы/контакты в подробном виде — для `general_info`. Здесь только основные номера и 103/112.
|
||
|
||
## Источники и приоритет
|
||
|
||
В этой ветке приоритет всегда у безопасности пациента:
|
||
|
||
- Если есть малейшее подозрение на острое состояние — `acute_pain`, не `medical_question`.
|
||
- Если упоминается операция в любом контексте — `surgery`.
|
||
- При раздражении — лучше эскалировать раньше, чем позже.
|
||
|
||
Прежние сводные документы (`skripty-vozrazhenija-chavo-obshhijj-spravochnik.md`, `vrachi-kliniki-polnaja-informacija.md`) для этой ветки не источник. После подключения подписки на живую вики они должны быть отвязаны от индекса ветки `escalate_human`.
|