README переписан под текущее состояние — был TBD со времён init:
- Статус: Спринты 1–2 и доработки (2.5) закрыты, что именно уже
работает (RAG, многошаговый диалог, переиндексация, две страницы).
- Запуск: команды для установки, старта, ручного наката миграций и
создания новых. Автомиграции на старте отмечены.
- Использование: табличка API-эндпоинтов (/documents, /query, /chat,
/threads, /reindex), описание двух веб-страниц и правки системного
промпта через prompts/system_prompt.md.
- Структура: актуальное дерево директорий с назначением каждого
модуля (db/, prompts/, routers/, services/, static/).
SPRINTS.md: Спринт 2.5 помечен закрытым — все пять задач пройдены
(логи, системный промпт в файле, markdown-рендер, чистка чанков +
reindex, README).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Три подряд доработки по плану Спринта 2.5.
1) Логи. Проблема: uvicorn ставит handlers на root-logger до того, как
отработает наш lifespan, поэтому logging.basicConfig там был no-op, и
logger.exception ничего не писал. Переносим basicConfig на уровень
импорта main.py с force=True — наш StreamHandler перебивает
uvicorn-овский root, остальные логгеры (uvicorn.access, uvicorn.error,
alembic, chromadb) остаются со своими форматами. В lifespan
basicConfig больше не зовётся.
2) Системный промпт вынесен из services/llm_client.py в
prompts/system_prompt.md. LLMClient читает файл при импорте модуля
через _load_system_prompt(); если файла нет — пустая строка + warning.
Это задел под Спринт 3, где промпт будет редактируемым и
версионируемым — физически положить его как файл дешевле, чем
держать в исходниках.
3) Markdown в ответах ассистента. Подключены marked и DOMPurify с
CDN в sandbox.html. Рендер через renderMd(text): marked.parse +
DOMPurify.sanitize — защищает от <script> на случай, если LLM вернёт
сырой HTML. Реплики пациента остаются plain text (esc). Добавлены
стили для p/ul/ol/code/pre/a/h1-h3/blockquote внутри .msg.assistant,
чтобы всё выглядело уместно в пузыре. Обёртка msg-body введена,
чтобы разделить контент и msg-meta.
План в SPRINTS.md уточнён по переиндексации — будет отдельный
endpoint.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
По итогам Спринтов 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>
Завершающий кусок Спринта 2 — UI для ведения диалогов.
static/sandbox.html:
- Трёхколоночная раскладка во всю высоту экрана.
- Слева: список сохранённых диалогов (имя, дата последнего обновления,
счётчик сообщений, превью первой реплики), кнопка «+ новый»;
на каждой карточке — «переименовать» (prompt) и «удалить» (confirm).
- Центр: чат в привычной стилистике (пузыри, user справа, assistant
слева), Enter — отправить, Shift+Enter — перенос строки. Заголовок
сверху показывает имя активного треда.
- Справа: отладка ответа — найденные фрагменты со score в процентах
+ собранный промпт в моноширинном блоке на светлом фоне.
- При отправке первой реплики тред создаётся автоматически, API
возвращает thread_id и thread_name — дальше реплики уходят в тот
же тред.
static/index.html: в шапке добавлены ссылки «Отладка» / «Песочница»,
подсветка активной страницы; тот же стиль nav-ссылок продублирован
в sandbox.html.
routers/chat: detail сообщения ошибки теперь включает тип исключения
(удобнее при диагностике), trace пишется через logger.exception.
SPRINTS.md: Спринт 2 помечен как закрытый.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Уточнения к плану Спринта 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>
Скоуп MVP: RAG-ядро + веб-инструмент настройки (загрузка wiki, песочница,
промпт/правила с версиями, сценарии, экспорт конфига). Интеграцию с каналами
(приложение, МАКС) делает другой разработчик.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>