- SPRINTS.md → docs/SPRINTS.md - GRAPH_ARCHITECTURE.md → docs/architecture/GRAPH_ARCHITECTURE_v1.md - GRAPH_ARCHITECTURE_v2.md → docs/architecture/GRAPH_ARCHITECTURE_v2.md - Новый docs/architecture/GRAPH_ARCHITECTURE_v3.md (билингв. термины + ссылки на примеры) - Новые docs/examples/: 01 базовая запись, 02 цена во время записи (soft vs hard), 03 запись ребёнка (guard), 04 простой general_info - README обновлён: ссылки на новые пути + раздел «Документация» Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
38 KiB
Пример 04 · Простые информационные запросы (general_info)
Связано с
GRAPH_ARCHITECTURE_v3.md, разделы 1, 2, 6. Демонстрирует простейший случай: веткаgeneral_infoбез машины состояний — одна реплика пациента, ретривер, ответ,done. Никаких слотов, никаких tool calls, никаких guard'ов. Это та точка, с которой реально удобно запускать систему: классификатор + RAG + одна шаблонная ветка.
О чём этот пример
Это сборник коротких самостоятельных диалогов по одному типу запросов — общая информация (часы, адрес, проезд, телефоны, что брать с собой, чего клиника не делает). У всех у них одна и та же траектория:
- Роутер классифицирует реплику как
general_info. - Запускается ветка
general_info, шагanswer(он же единственный). - Ретривер достаёт чанки из соответствующего раздела вики (
/wiki/contacts/**,/wiki/branches/**,/wiki/hours/**,/wiki/preparation/**,/wiki/services/_general/**). - Модель формирует ответ строго по найденным чанкам.
state_after = done.
Цель — на каждой реплике показать:
- решение роутера (router) — какое намерение распознано;
- работу ретривера (retriever) — какие чанки достаются и из каких разделов вики;
- структурированный ответ модели —
reply,state_after,slots_updated; - итоговое состояние треда (thread_state).
Слоты у general_info практически не используются — одно поле info_topic модель проставляет, чтобы ретривер при последующих репликах в том же треде не лез в посторонние разделы. Если в ходе ответа возникает запрос на запись («а можно тогда записаться?»), это уже жёсткий переход в new_booking (см. примеры 05+).
Конфигурация ветки general_info
intent: general_info
steps:
answer:
wiki_sources:
- /wiki/contacts/**
- /wiki/branches/**
- /wiki/hours/**
- /wiki/preparation/**
- /wiki/services/_general/**
tools: []
next: done
done:
wiki_sources: []
tools: []
Начальное состояние (общее для всех примеров ниже)
Перед каждым диалогом в thread_state пусто — это первый ход свежего треда:
{
"thread_id": "T-9XXX",
"current_intent": null,
"current_step": null,
"slots": {},
"handoff_count": 0,
"suspended_intent": null,
"resumable_step": null,
"resumable_slots": null
}
После ответа current_intent = "general_info", current_step = "done", и тред физически не закрывается — пациент может задать следующий вопрос. Если он задаст ещё один информационный вопрос, тот пройдёт по той же траектории заново (роутер его классифицирует, ветка отработает и снова уйдёт в done).
A · Часы работы
A.1 · «Во сколько вы открываетесь?»
Решение роутера: general_info. Чёткий вопрос про режим работы, никаких других намерений.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/hours/**'). - top-k: 2.
- Достались чанки:
hours/clinic-czetkina-9.md(score 0.93) — режим работы филиала на Клары Цеткин 9.hours/clinic-pirogova.md(score 0.71) — режим работы филиала «Пирогова».
Модели достаточно первого чанка. Второй пригодится, если пациент уточнит про другой адрес.
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "Здравствуйте! Клиника на Клары Цеткин 9 открывается в 8:00 в будни и в 9:00 в выходные. Закрываемся в 21:00 в будни и в 18:00 в выходные. Если интересует другой филиал — подскажу отдельно.",
"state_after": "done",
"slots_updated": {
"info_topic": "hours"
}
}
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "hours"
}
}
A.2 · «До скольки работает клиника на Цеткина?»
Решение роутера: general_info. Конкретика про филиал — это всё ещё информационный вопрос, не запись.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/hours/**', '/wiki/branches/**'). - top-k: 2.
- Достались чанки:
hours/clinic-czetkina-9.md(score 0.94) — режим работы.branches/czetkina-9.md(score 0.78) — карточка филиала с адресом.
Реплика содержит «Цеткина» — в индексе совпадает по названию филиала, поэтому ретривер уверенно вытаскивает нужную карточку.
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "Клиника на Клары Цеткин 9 работает до 21:00 в будни и до 18:00 в выходные.",
"state_after": "done",
"slots_updated": {
"info_topic": "hours",
"branch_mention": "Клары Цеткин 9"
}
}
Заметим: branch_mention модель кладёт в слоты, чтобы при возможном следующем вопросе («а проезд как?») ретривер мог сразу дать чанк именно про этот филиал, а не про другой.
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "hours",
"branch_mention": "Клары Цеткин 9"
}
}
A.3 · «У вас по выходным открыто?»
Решение роутера: general_info.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/hours/**'). - top-k: 2.
- Достались чанки:
hours/clinic-czetkina-9.md(score 0.86).hours/clinic-pirogova.md(score 0.81).
Здесь пациент не уточнил филиал, поэтому в ответе разумно перечислить оба.
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "Да, мы работаем и в субботу, и в воскресенье. На Клары Цеткин 9 — с 9:00 до 18:00, в Клинике Пирогова — с 9:00 до 17:00. Расписание конкретного врача может отличаться, при записи подскажу.",
"state_after": "done",
"slots_updated": {
"info_topic": "hours"
}
}
Замечание: фраза «расписание конкретного врача может отличаться» — это зашитая в промпт ветки оговорка (canned disclaimer), не результат RAG. Часы работы клиники и слоты конкретного врача — разные вещи, и модель должна на этом не зависать.
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "hours"
}
}
A.4 · «Завтра праздник, вы работаете?»
Решение роутера: general_info.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/hours/**'). - top-k: 3.
- Достались чанки:
hours/clinic-czetkina-9.md(score 0.74) — обычный режим.hours/holidays-2026.md(score 0.42) — праздничный календарь, низкий score (документ короткий, неточное совпадение по датам).hours/clinic-pirogova.md(score 0.71).
Score праздничного чанка — ниже порога уверенности (0.50). По правилу шага: если ни один чанк не покрывает запрос полностью — отвечаем шаблоном «уточним и перезвоним», а не выдумываем расписание праздников.
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "В обычные дни мы работаем с 8:00 до 21:00. В праздничные дни режим может меняться. Подскажите, пожалуйста, на какую дату вы планируете визит — я уточню у регистратуры и сообщу вам в течение дня.",
"state_after": "done",
"slots_updated": {
"info_topic": "hours",
"needs_followup": true
}
}
Слот needs_followup: true — сигнал для оператора в инбоксе, что тред нужно дозакрыть человеком. На дашборде такие треды попадают в очередь «требуется уточнение».
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "hours",
"needs_followup": true
}
}
B · Адрес и филиалы
B.1 · «Где вы находитесь?»
Решение роутера: general_info.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/branches/**'). - top-k: 3.
- Достались чанки:
branches/_index.md(score 0.88) — общий перечень филиалов.branches/czetkina-9.md(score 0.71).branches/pirogova.md(score 0.69).
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "У нас два адреса в Перми: ул. Клары Цеткин, 9 (основная клиника, ЛОР, сурдология, отоневрология) и Клиника Пирогова, ул. Героев Хасана 24 (терапия, аллергология, телемед). Подсказать, какой ближе к вам или какая специальность нужна?",
"state_after": "done",
"slots_updated": {
"info_topic": "branches"
}
}
Финальный встречный вопрос — лёгкий, без обязательного ответа. Если пациент проигнорирует, тред просто останется в done. Если ответит — пойдёт ещё один проход через роутера.
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "branches"
}
}
B.2 · «Какой у вас точный адрес на Цеткина?»
Решение роутера: general_info.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/branches/**'). - top-k: 1.
- Достались чанки:
branches/czetkina-9.md(score 0.96) — карточка филиала: адрес, ориентиры, вход.
Высокий score, точный матч — достаточно одного чанка.
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "Адрес: г. Пермь, ул. Клары Цеткин, 9. Вход со стороны двора, ориентир — голубая вывеска «Клиника Ухо, Горло, Нос». Регистратура на первом этаже.",
"state_after": "done",
"slots_updated": {
"info_topic": "branches",
"branch_mention": "Клары Цеткин 9"
}
}
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "branches",
"branch_mention": "Клары Цеткин 9"
}
}
B.3 · «Сколько у вас филиалов в городе?»
Решение роутера: general_info.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/branches/**'). - top-k: 1.
- Достались чанки:
branches/_index.md(score 0.90) — общий перечень.
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "В Перми у нас два филиала: основная клиника на ул. Клары Цеткин, 9, и Клиника Пирогова на ул. Героев Хасана, 24. Других филиалов и онлайн-клиник в других городах у нас нет — приём только в этих двух.",
"state_after": "done",
"slots_updated": {
"info_topic": "branches"
}
}
Замечание: пациенты иногда спрашивают «вы же есть в Москве?», путая клинику с одноимёнными. Ответ намеренно явно говорит «других филиалов нет» — чтобы не оставить надежду на не-существующее.
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "branches"
}
}
B.4 · «Как вас на Яндекс Картах искать?»
Решение роутера: general_info.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/branches/**', '/wiki/contacts/**'). - top-k: 2.
- Достались чанки:
contacts/online-presence.md(score 0.84) — карточка организации, ссылки на 2ГИС / Я.Карты.branches/_index.md(score 0.66).
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "На Яндекс Картах ищите по запросу «Клиника Ухо Горло Нос Пермь» — найдутся обе наших точки: на Клары Цеткин 9 и на Героев Хасана 24. Можно сразу проложить маршрут оттуда.",
"state_after": "done",
"slots_updated": {
"info_topic": "branches"
}
}
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "branches"
}
}
C · Как добраться и парковка
C.1 · «На метро как до вас доехать?»
Решение роутера: general_info.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/branches/**'). - top-k: 2.
- Достались чанки:
branches/czetkina-9.md(score 0.62) — раздел «как добраться».branches/pirogova.md(score 0.59).
Ни один чанк не упоминает метро — потому что в Перми метро нет. Ретривер вытащил то, что про транспорт ближе всего по теме.
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "В Перми метро нет, поэтому удобнее всего добираться на автобусе, троллейбусе или такси. До Клары Цеткин 9 — остановка «Площадь Восстания» (5 минут пешком), маршруты 14, 32, 36, 67. До Клиники Пирогова — остановка «Героев Хасана», маршруты 19, 27. Подсказать что-то конкретнее, если знаете, откуда поедете?",
"state_after": "done",
"slots_updated": {
"info_topic": "transit"
}
}
Это полезный пограничный кейс: вопрос содержит ложное допущение (метро). Промпт ветки требует мягко поправить пациента, не оставляя его в недоумении, и сразу предложить рабочую альтернативу.
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "transit"
}
}
C.2 · «Парковка у вас есть?»
Решение роутера: general_info.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/branches/**'). - top-k: 2.
- Достались чанки:
branches/czetkina-9.md(score 0.81) — раздел «парковка».branches/pirogova.md(score 0.78) — раздел «парковка».
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "Да, парковка есть на обоих филиалах. На Клары Цеткин 9 — небольшая бесплатная парковка во дворе клиники, обычно есть свободные места. У Клиники Пирогова — общая платная парковка торгового центра рядом, въезд с ул. Героев Хасана. Подсказать, какой филиал вам удобнее?",
"state_after": "done",
"slots_updated": {
"info_topic": "parking"
}
}
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "parking"
}
}
C.3 · «Как пешком от центра дойти до Цеткина?»
Решение роутера: general_info.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/branches/**'). - top-k: 1.
- Достались чанки:
branches/czetkina-9.md(score 0.79) — раздел «как добраться» → подраздел «пешком».
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "От Комсомольского проспекта дойти можно за 12–15 минут: вниз по Сибирской до Клары Цеткин, направо до дома 9. Удобнее всего ориентироваться на Яндекс Карты — там же увидите маршрут.",
"state_after": "done",
"slots_updated": {
"info_topic": "transit",
"branch_mention": "Клары Цеткин 9"
}
}
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "transit",
"branch_mention": "Клары Цеткин 9"
}
}
D · Контакты
D.1 · «Дайте телефон регистратуры»
Решение роутера: general_info.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/contacts/**'). - top-k: 1.
- Достались чанки:
contacts/registratura.md(score 0.95) — телефоны регистратуры по филиалам.
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "Регистратура на Клары Цеткин 9 — +7 (342) 204-00-00. Регистратура Клиники Пирогова — +7 (342) 204-67-16. Звонят с 8:00 до 21:00 в будни. Если удобнее, можно записаться прямо здесь — я помогу.",
"state_after": "done",
"slots_updated": {
"info_topic": "contacts"
}
}
Хвостовая фраза «можно записаться прямо здесь» — это soft-cross-sell, разрешённая в ветке general_info. Пациент свободен её проигнорировать; если откликнется — следующая реплика уйдёт в new_booking через роутера.
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "contacts"
}
}
D.2 · «У вас WhatsApp есть?»
Решение роутера: general_info.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/contacts/**'). - top-k: 1.
- Достались чанки:
contacts/messengers.md(score 0.93) — мессенджеры, в которых отвечает клиника.
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "Да, мы отвечаем в WhatsApp по номеру +7 (342) 204-00-00 — это тот же телефон регистратуры. Также есть Telegram: @ugn_clinic. Уведомления о приёме приходят на тот номер, который вы оставите при записи.",
"state_after": "done",
"slots_updated": {
"info_topic": "contacts"
}
}
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "contacts"
}
}
D.3 · «А сайт у вас какой?»
Решение роутера: general_info.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/contacts/**'). - top-k: 1.
- Достались чанки:
contacts/online-presence.md(score 0.91).
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "Сайт клиники: ugn-clinic.ru. Там можно посмотреть прайс, расписание врачей и записаться. Если хотите — могу записать вас прямо сейчас, без перехода на сайт.",
"state_after": "done",
"slots_updated": {
"info_topic": "contacts"
}
}
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "contacts"
}
}
E · Документы и подготовка к приёму
E.1 · «Что нужно с собой принести?»
Решение роутера: general_info.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/preparation/**'). - top-k: 2.
- Достались чанки:
preparation/what-to-bring.md(score 0.92) — общий список.preparation/лор-первичный.md(score 0.65) — для ЛОРа отдельно.
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "На приём возьмите паспорт (для пациентов с 14 лет) и, если есть, выписки или результаты предыдущих обследований по теме визита. Полис ОМС не нужен — клиника частная. Если есть конкретная специальность, к которой записываетесь, могу подсказать, что взять именно для неё.",
"state_after": "done",
"slots_updated": {
"info_topic": "preparation"
}
}
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "preparation"
}
}
E.2 · «Полис ОМС у вас принимают?»
Решение роутера: general_info. Это ещё не вопрос про цену в чистом виде — пациент уточняет принцип, не считает деньги. Но граница тонкая, см. замечание ниже.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/preparation/**', '/wiki/services/_general/**'). - top-k: 2.
- Достались чанки:
preparation/what-to-bring.md(score 0.74) — там есть строка про ОМС.services/_general/payment-options.md(score 0.81) — формы оплаты, ДМС.
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "Нет, мы частная клиника и по полису ОМС не работаем. Принимаем оплату наличными, картой и переводом. По ДМС — работаем не со всеми страховыми, нужно уточнять по конкретной компании.",
"state_after": "done",
"slots_updated": {
"info_topic": "preparation"
}
}
Замечание: следующая реплика «а с какими страховыми работаете?» — это уже жёсткий переход в price_question (там есть отдельная ветвь про ДМС-покрытие). На текущей реплике мы аккуратно касаемся темы, но не углубляемся.
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "preparation"
}
}
E.3 · «Сыну 16, можно без меня прийти?»
Решение роутера: general_info. Вопрос про порядок приёма несовершеннолетних — это организационный, не медицинский и не запись.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/preparation/**', '/wiki/_faq/**'). - top-k: 2.
- Достались чанки:
_faq/teenagers-without-parents.md(score 0.94) — соответствует в точности.preparation/what-to-bring.md(score 0.61).
Чанк teenagers-without-parents.md — это статья из раздела ЧаВо (см. источник vrachi-kliniki-...md, пункт «Если пациенту 16-17 лет»), индексированная в общий пул general_info.
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "С 15 лет подросток может прийти на приём один и сам подписать договор — нужен паспорт. Если родители смогут позже подъехать или прислать документы — это тоже подойдёт. Записать сына на удобное время?",
"state_after": "done",
"slots_updated": {
"info_topic": "preparation"
}
}
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "preparation"
}
}
F · Что клиника не делает
F.1 · «У вас можно сделать бронхоскопию?»
Решение роутера: general_info. По формальному признаку — пациент спрашивает про услугу. Но это не запись и не цена, это уточнение «делаете ли вы такое в принципе». Промпт роутера явно относит подобные формулировки к general_info, чтобы не запускать механизм записи на услугу, которой нет.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/services/_general/**'). - top-k: 2.
- Достались чанки:
services/_general/not-performed.md(score 0.97) — список процедур, которые НЕ проводятся.services/_general/scope.md(score 0.62) — общий профиль клиники.
Чанк not-performed.md собран из соответствующего раздела вики (см. источник «Процедуры, которые в клинике НЕ проводятся» в skripty-...md). Бронхоскопия там есть в явном виде.
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "Бронхоскопию у нас не делают — это исследование с эндоскопом по слизистым трахеи и бронхов, его нужно искать в специализированных пульмонологических центрах. Если вас беспокоит кашель или дыхание — мы можем записать к пульмонологу на консультацию, он уже подскажет, куда дальше.",
"state_after": "done",
"slots_updated": {
"info_topic": "scope_of_services"
}
}
Это важный сценарий для honesty-eval'а: модель не должна выдумывать «да, конечно, запишем» в надежде, что пациент придёт и разберётся на месте. Прямой отказ + полезная альтернатива.
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "scope_of_services"
}
}
F.2 · «Криодеструкцию миндалин делаете?»
Решение роутера: general_info.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/services/_general/**'). - top-k: 1.
- Достались чанки:
services/_general/not-performed.md(score 0.94).
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "Нет, криодеструкцию миндалин в нашей клинике не проводят. Если вас беспокоит хронический тонзиллит — можем записать на приём к ЛОР-врачу: он осмотрит, предложит варианты лечения из тех, что у нас доступны, и подскажет, куда обратиться, если понадобится именно эта процедура.",
"state_after": "done",
"slots_updated": {
"info_topic": "scope_of_services"
}
}
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "scope_of_services"
}
}
F.3 · «Электрофорез носа можно у вас?»
Решение роутера: general_info.
Активная ветка / шаг: general_info / answer.
Ретривер:
- Фильтр:
doc_path STARTS WITH any('/wiki/services/_general/**'). - top-k: 1.
- Достались чанки:
services/_general/not-performed.md(score 0.91) — электрофорез в списке «не проводится».
Вызовы инструментов: нет.
Структурированный ответ модели:
{
"reply": "Нет, электрофорез у нас не делают. Из физиопроцедур по ЛОР-профилю мы предлагаем промывания, орошения, лечебные ингаляции — если интересно, могу подробнее рассказать или сразу записать на приём.",
"state_after": "done",
"slots_updated": {
"info_topic": "scope_of_services"
}
}
thread_state после хода:
{
"current_intent": "general_info",
"current_step": "done",
"slots": {
"info_topic": "scope_of_services"
}
}
Что показал этот пример
- Одна реплика — один проход. Ветка
general_infoне имеет машины состояний: единственный «осмысленный» шагanswerсразу уводит вdone. Это самый дешёвый путь в системе и логичная точка запуска первой версии бота. - Слоты почти не используются. Поле
info_topicнужно ровно для того, чтобы при следующем вопросе в том же треде ретривер знал, в какую сторону смотреть в первую очередь. Опционально —branch_mention, чтобы помнить, про какой филиал шла речь. - Ретривер делает основную работу. Все факты в ответе должны быть из чанков, не из памяти модели. Если score лучшего чанка ниже порога — модель уходит в шаблон «уточним и перезвоним» с
needs_followup=true(см. A.4). - Пограничные кейсы важнее, чем happy path. Метро в Перми (которого нет — C.1), услуги, которых клиника не предоставляет (F), праздничные дни без чанка (A.4) — именно на них модель ломается чаще всего и именно их полезно держать в eval-наборе с самого начала.
- Soft cross-sell разрешён, но мягкий. Хвост «могу записать прямо сейчас» — нормальная практика для информационных ответов. Жёстко продавать запись — нет.
Что важно проверять в eval-наборе на этом примере
- Роутер не уводит информационные вопросы в
new_bookingилиprice_question(классическая ошибка — на «сколько у вас стоит» в чистом виде это ужеprice_question, а на «какие у вас услуги» —general_info; границы должны быть чёткими). - Все факты в
replyнаходимы в одном из чанков, попавших в контекст. Хорошая метрика —groundedness(доля утверждений, для которых есть прямое подтверждение в источниках). - При отсутствии релевантных чанков модель отвечает шаблоном «уточним», а не выдумывает (см. A.4 и логика
needs_followup). - Ответы не превышают 3–4 предложений.
general_info— не место для лекций. - Слот
info_topicпроставлен корректно (hours,branches,transit,parking,contacts,preparation,scope_of_services) — эта же таксономия используется в дашборде «о чём чаще всего спрашивают». - На пограничных кейсах (метро в Перми, услуги, которых нет, праздничные дни) ответ не выдаёт ложных утверждений — это критичный безопасный минимум для запуска.