ccc3dde978
Уточнения к плану Спринта 2 по итогам обсуждения:
- Вторая отладочная страница /sandbox вместо расширения текущей (старый
Debug UI остаётся нетронутым).
- Все диалоги сохраняются навсегда, видны в левой колонке; можно открыть
старый тред, переименовать, удалить. Имя треда — автоматом по первой
реплике, с возможностью поменять.
- Стек хранилища: SQLite + SQLAlchemy 2.0 async + Alembic. Выбор под
будущий рост (мульти-пользователи, мульти-промпты, несколько спец-RAG).
- В таблицу threads сразу заводим nullable-колонки user_id и
agent_config_id — чтобы Спринты 3+ не тащили миграции задним числом.
- Набор эндпоинтов расширен: GET/PATCH/DELETE /threads, GET /threads/{id}.
В бэклог: хранение исходных файлов для переиндексации без повторной
загрузки.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
171 lines
14 KiB
Markdown
171 lines
14 KiB
Markdown
# Спринты — Chat Agent for Patients (инструмент настройки)
|
||
|
||
Поэтапный план MVP: RAG-ядро + веб-инструмент для настройки агента операторами. Подключение реальных каналов (приложение, МАКС) — вне скоупа, это задача другого разработчика.
|
||
|
||
---
|
||
|
||
## Спринт 1. RAG-ядро, загрузка документов и тестовая страница
|
||
|
||
### Цель
|
||
Поднять FastAPI-сервис с ChromaDB и сразу получить воспроизводимый «пайплайн в действии»: на одной тестовой странице видно, какие файлы загружены, можно задать одиночный вопрос от лица пациента и увидеть одновременно три вещи — какие чанки нашёл RAG, какой промпт собрался, какой ответ вернул DeepSeek. Аналог Debug UI из `work-pcs-dr-cdss`.
|
||
|
||
### Статус: ⏳ Запланирован
|
||
|
||
### Задачи
|
||
|
||
**RAG-ядро:**
|
||
- [ ] Инициализация проекта (main.py, config.py, requirements.txt, Dockerfile, docker-compose, .env.example)
|
||
- [ ] Переиспользовать паттерны из `work-pcs-dr-cdss`: `services/embeddings.py`, `vectorstore.py`, `document_processor.py`, `llm_client.py`
|
||
- [ ] Адаптировать чанкер под wiki-статьи (не клинреки)
|
||
|
||
**Эндпоинты:**
|
||
- [ ] `GET /health` — статус, кол-во документов и чанков
|
||
- [ ] `POST /documents/upload` — загрузка + превью первых 3 чанков в ответе
|
||
- [ ] `GET /documents` — список загруженных
|
||
- [ ] `DELETE /documents/{id}` — удаление
|
||
- [ ] `POST /query` — одиночный вопрос от лица пациента → ответ + источники со `score` + `assembled_prompt` (как RAG for Doctors, но без полей карты — только текст вопроса)
|
||
|
||
**Тестовая страница (одна HTML-страница, vanilla JS):**
|
||
- [ ] Шапка со статусом сервиса (auto-refresh `/health`, счётчики документов и чанков)
|
||
- [ ] Блок «База знаний»: drag & drop загрузка, таблица документов с превью первых чанков, кнопка удаления
|
||
- [ ] Блок «Тест-вопрос от пациента»: поле ввода вопроса, поле `top_k`, кнопка «Отправить»
|
||
- [ ] 3-колоночный результат ответа: релевантные фрагменты (текст + document, section, page, score) | собранный промпт | ответ LLM
|
||
|
||
### Критерий готовности
|
||
- [ ] Оператор открывает `http://localhost:PORT/` → видит Debug UI со статусом сервиса
|
||
- [ ] Загружает wiki-статью → она появляется в таблице, превью чанков отображается
|
||
- [ ] Пишет вопрос «как записать ребёнка к лору?» → получает ответ DeepSeek с указанием источников
|
||
- [ ] В средней колонке виден собранный промпт, в левой — какие чанки подтянулись со score
|
||
- [ ] Может удалить статью, счётчики в шапке обновляются
|
||
|
||
---
|
||
|
||
## Спринт 2. Многошаговый диалог с памятью треда
|
||
|
||
### Цель
|
||
Перейти от одиночного `/query` к полноценному диалогу: агент помнит историю, оператор ведёт разговор из 5+ реплик. Текущую страницу отладки (одиночный вопрос) оставляем без изменений, добавляем **вторую отладочную страницу** — «Песочница» со списком всех сохранённых диалогов.
|
||
|
||
### Статус: ⏳ Запланирован
|
||
|
||
### Задачи
|
||
|
||
**Хранилище:**
|
||
- [ ] Стек: SQLite + SQLAlchemy 2.0 (async, ORM-стиль) + Alembic для миграций
|
||
- [ ] Таблицы:
|
||
- `threads` (id, name, user_id nullable, agent_config_id nullable, created_at, updated_at)
|
||
- `messages` (id, thread_id FK, role, text, sources_json, assembled_prompt, created_at)
|
||
- Колонки `user_id` и `agent_config_id` заводим сразу nullable — под будущие Спринты 3+ (мульти-пользователи, мульти-промпты), чтобы не тащить миграции задним числом
|
||
- [ ] Первая миграция Alembic с этими двумя таблицами
|
||
- [ ] Все диалоги сохраняются навсегда (никакого авто-удаления)
|
||
- [ ] Имя треда генерируется автоматически по первой реплике пациента + дата; оператор может переименовать вручную
|
||
|
||
**Эндпоинты:**
|
||
- [ ] `POST /chat` — принимает `thread_id` (или создаёт новый если не передан) + `text` → возвращает ответ агента + источники со score + `assembled_prompt`
|
||
- [ ] `GET /threads` — список всех диалогов (id, name, created_at, messages_count, превью первой реплики)
|
||
- [ ] `GET /threads/{id}` — тред целиком с историей сообщений
|
||
- [ ] `PATCH /threads/{id}` — переименовать тред
|
||
- [ ] `DELETE /threads/{id}` — удалить тред со всеми сообщениями
|
||
|
||
**Сборка ответа:**
|
||
- [ ] Базовый системный промпт (хардкод для старта): роль агента, тон клиники, что можно и нельзя
|
||
- [ ] Сборка контекста для LLM: системный промпт + история треда + RAG-чанки по последней реплике
|
||
|
||
**Веб-интерфейс:**
|
||
- [ ] В шапке обеих страниц — ссылки «Отладка» (текущая `/`) / «Песочница» (новая `/sandbox`)
|
||
- [ ] Текущий `static/index.html` остаётся без изменений
|
||
- [ ] Новая страница `static/sandbox.html` на отдельном маршруте `/sandbox`:
|
||
- [ ] левая колонка — список сохранённых диалогов: превью, дата, кнопка «переименовать», кнопка «удалить», кнопка «новый тред»
|
||
- [ ] центральная колонка — сам чат (оператор пишет как пациент, видит ответы агента, история подгружается при клике на тред из списка)
|
||
- [ ] правая колонка — retrieved-чанки со score + собранный промпт по последней реплике
|
||
|
||
### Критерий готовности
|
||
- [ ] Оператор может провести диалог из 5+ реплик, агент помнит контекст
|
||
- [ ] Все диалоги сохраняются и видны в левой колонке после перезагрузки страницы
|
||
- [ ] Оператор может открыть старый диалог, переименовать его, удалить
|
||
- [ ] В правой колонке видно, что нашёл RAG и что улетело в LLM на последнем шаге
|
||
- [ ] Старая страница отладки (`/`) работает как раньше, ничего не сломано
|
||
|
||
---
|
||
|
||
## Спринт 3. Настройки агента: системный промпт и правила
|
||
|
||
### Цель
|
||
Дать операторам веб-редактор системного промпта и списка правил («если спрашивают про X — отвечай так-то», «если пациент злится — делай то-то»). Версионирование: можно сохранить конфигурацию и откатиться.
|
||
|
||
### Статус: ⏳ Запланирован
|
||
|
||
### Задачи
|
||
- [ ] Хранилище (SQLite): `agent_configs` (version, created_at, system_prompt, rules_text, is_active)
|
||
- [ ] Эндпоинты: `GET /configs`, `POST /configs` (создать новую версию), `POST /configs/{id}/activate`
|
||
- [ ] Песочница использует активную версию при каждом `/chat`
|
||
- [ ] Веб-страница «Настройки агента»:
|
||
- [ ] редактор системного промпта (textarea)
|
||
- [ ] редактор правил (отдельным блоком; на старте — просто textarea, позже — список записей)
|
||
- [ ] кнопка «Сохранить как новую версию»
|
||
- [ ] список версий с кнопкой «Сделать активной» и пометкой активной
|
||
- [ ] Показ активной версии в шапке песочницы
|
||
|
||
### Критерий готовности
|
||
- [ ] Оператор меняет промпт → сохраняет как v2 → активирует → тестирует в песочнице → при желании откатывается к v1
|
||
- [ ] Правила реально влияют на ответы агента (проверяется вручную через песочницу)
|
||
|
||
---
|
||
|
||
## Спринт 4. Сценарии: сохранение и прогон
|
||
|
||
### Цель
|
||
Позволить операторам сохранять отработанные диалоги из песочницы как «сценарии» (с пометкой «эталон / ок / не ок» и заметкой), а потом прогонять их на текущей конфигурации, чтобы сразу увидеть, не сломалось ли что-то после правок.
|
||
|
||
### Статус: ⏳ Запланирован
|
||
|
||
### Задачи
|
||
- [ ] Хранилище (SQLite): `scenarios` (id, name, note, label, messages_json, reference_answers_json, config_version_id)
|
||
- [ ] Эндпоинты:
|
||
- [ ] `POST /scenarios` — сохранить текущий тред песочницы как сценарий
|
||
- [ ] `GET /scenarios`, `GET /scenarios/{id}`
|
||
- [ ] `POST /scenarios/{id}/run` — прогнать реплики пациента на текущей активной конфигурации, вернуть новые ответы агента
|
||
- [ ] Возможность пометить «правильный ответ оператора» для каждой реплики пациента (эталон)
|
||
- [ ] Веб-страница «Сценарии»:
|
||
- [ ] список сценариев с метками и датой
|
||
- [ ] открытая карточка: реплики пациента, ответы агента при сохранении, опциональные «эталонные ответы»
|
||
- [ ] кнопка «Прогнать на текущей конфигурации» → показывает side-by-side: старый ответ / новый ответ
|
||
- [ ] счётчик «сколько сценариев остались в статусе ок» после последнего прогона
|
||
|
||
### Критерий готовности
|
||
- [ ] Оператор может сохранить диалог как сценарий, добавить эталонные ответы, пометить «ок»
|
||
- [ ] После изменения промпта прогон сценариев показывает, где ответы расходятся
|
||
- [ ] Виден общий счётчик «ок / изменилось» по всей базе сценариев
|
||
|
||
---
|
||
|
||
## Спринт 5. Экспорт конфигурации для внешней интеграции
|
||
|
||
### Цель
|
||
Зафиксировать API-контракт и упаковать активную конфигурацию так, чтобы другой разработчик мог подключить чат-канал (приложение / МАКС-бот) без обращений к нам.
|
||
|
||
### Статус: ⏳ Запланирован
|
||
|
||
### Задачи
|
||
- [ ] Документация API: `POST /chat` (с `channel_id`, `user_id`, `thread_id`, `text`), `GET /health`
|
||
- [ ] Эндпоинт `GET /configs/active/export` — JSON со снапшотом: активный промпт + правила + список документов RAG
|
||
- [ ] Инструкция «как подключиться» в README (пример curl-запроса + минимальный webhook-адаптер)
|
||
- [ ] Проверка: внешний разработчик может поднять сервис по docker-compose и получить валидный ответ от `/chat`
|
||
|
||
### Критерий готовности
|
||
- [ ] README раздел «Как подключить канал» готов
|
||
- [ ] Docker-compose поднимается одной командой
|
||
- [ ] На заданном тестовом запросе `/chat` возвращает ответ, который мы видим и в веб-песочнице
|
||
|
||
---
|
||
|
||
## Бэклог
|
||
|
||
- Раздельные правила по доменам (детский приём / ДМС / взрослый приём)
|
||
- A/B сравнение двух версий промпта на одном тест-наборе
|
||
- Метрики качества ответов (MRR, CSAT по сценариям)
|
||
- Подсветка цитат источников в ответе агента
|
||
- Автосинхронизация wiki
|
||
- Перевод правил из свободного текста в структурированный список (pattern → instruction)
|
||
- Мультипользовательский режим (несколько операторов одновременно настраивают)
|
||
- Хранение исходных файлов (`./data/uploads/{document_id}.{ext}` + `source_path` в метаданных Chroma) — чтобы переиндексировать без повторной загрузки и показывать оператору оригинал документа
|