Files
RAG_helper/SPRINTS.md
T
AR 15 M4 835c0b3cc3 docs: план Спринта 2.5 — доработки после пилота
По итогам Спринтов 1–2 накопился технический долг и несколько косяков,
которые видно при живой работе в «Песочнице». Выделяем промежуточный
спринт-доработок перед заходом на Спринт 3:

- Качество RAG: чанкер тащит в базу markdown-ссылки, блоки навигации
  вроде «Вернуться на:», дубликаты меню — из-за этого в LLM уходит
  мусор вместо полезного контекста.
- UI: ответ ассистента рендерится plain text с сырыми ** и дефисами
  списков — в чате это читать тяжело.
- Системный промпт зашит в services/llm_client.py — перед Спринтом 3
  (редактор промпта) его логично вынести в отдельный файл.
- Логи: logger.exception сейчас съедается конфигом uvicorn, traceback
  при 500-х не виден — диагностика вслепую.
- README не обновлялся с init-коммита, не отражает ни Спринта 1, ни 2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:43:41 +05:00

17 KiB
Raw Blame History

Спринты — 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 на последнем шаге
  • Старая страница отладки (/) работает как раньше, ничего не сломано

Спринт 2.5. Доработки после пилота Спринтов 1–2

Цель

Закрыть технический долг, накопленный за первые два спринта: почистить чанки от markdown-мусора, сделать ответ агента читаемым в UI, подготовить системный промпт к вынесению в редактор (Спринт 3) и навести порядок в логах и README.

Статус: Запланирован

Задачи

Качество RAG:

  • Почистить чанки: убрать markdown-ссылки [текст](url), блоки навигации **Вернуться на:**, дубликаты меню; добавить нормализацию/переиндексацию текущей базы (или documented reindex procedure)

UI:

  • Markdown-рендер ответов ассистента в «Песочнице» (жирный, курсив, списки, код); реплики пациента оставить plain text

Системность:

  • Вынести системный промпт из services/llm_client.py в отдельный файл (например, prompts/system_prompt.md), загружать при старте — задел под Спринт 3
  • Привести логи в порядок: настроить root-logger так, чтобы logger.exception писался в stderr/файл; не ломать uvicorn access/error
  • Обновить README.md под текущее состояние: две страницы, /chat + /threads, SQLite + Alembic, как запустить и как мигрировать

Критерий готовности

  • Загружаем свежую wiki-статью → в её чанках нет markdown-ссылок и блоков «Вернуться на:»
  • На «Песочнице» ответ агента рендерится с жирным/курсивом/списками
  • Системный промпт хранится в отдельном файле, правится без трогания кода
  • При ошибке в /chat в логах виден читаемый traceback
  • README описывает актуальное состояние (две страницы, эндпоинты, запуск, миграции)

Спринт 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) — чтобы переиндексировать без повторной загрузки и показывать оператору оригинал документа