Commit Graph

8 Commits

Author SHA1 Message Date
AR 15 M4 2e2f2321c3 docs: перекройка плана спринтов под графовую архитектуру
После Спринта 3 и обсуждения с пользователем зафиксирован разворот
на графовую архитектуру (GRAPH_ARCHITECTURE.md, коммит 907fdbe).
Обновляем SPRINTS.md под новое направление.

Статусы закрытых спринтов уже стояли ; здесь главное — план 4–7:

- Вставлена секция «Архитектурный разворот после Спринта 3» сразу
  после Спринта 3. В ней зафиксированы принятые решения по 5
  открытым вопросам из GRAPH_ARCHITECTURE.md: фреймворк (вручную,
  без LangGraph/n8n), модель роутера (DeepSeek + отдельный
  RouterClient), exit conditions (свободный текст + роутер на каждой
  реплике как подстраховка), эскалация (одна ветка escalate_human с
  полем reason), confidence score (не в первый спринт).

- Старые Спринт 4 (сценарии) и Спринт 5 (экспорт) заменены новыми
  четырьмя спринтами:
  - Спринт 4. Фундамент графа — intents + роутер + переключение веток.
    Задачи: таблица intents, миграция agent_configs с intent_id, seed
    6 стартовых веток, router_client, оркестрация в chat_service,
    UI настроек по веткам, отображение intent в отладке Песочницы.
  - Спринт 5. State machine + exit conditions (bouncing). Первая
    реальная state machine — в ветке new_booking (6 шагов). Парсер
    [INTENT_CHANGE: ...] + роутер на каждой реплике как подстраховка.
    UI показывает состояние треда и timeline переходов.
  - Спринт 6. Мульти-RAG. Фабрика коллекций в vectorstore, привязка
    коллекции к intent, селектор ветки при загрузке документа.
  - Спринт 7. Сценарии + экспорт графа. Старый план, но адаптирован:
    сценарии фиксируют ожидаемый intent на реплику; экспорт —
    снапшот всего графа (intents + активные промпты + коллекции).

- Бэклог дополнен: confidence score, визуализация графа, вынесение
  роутера на более дешёвую модель, структурированные exit conditions.
  Пункт про «раздельные правила по доменам» помечен как перекрытый
  архитектурой.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 20:28:04 +05:00
AR 15 M4 7ec2ba3c8f feat(sprint3): редактор системного промпта и правил с версионированием
Операторы получают веб-редактор: правят системный промпт и правила,
сохраняют как новую версию, активируют, откатываются. Активная версия
используется в «Песочнице» на каждый /chat.

Принципы, согласованные заранее:
- Сохранённые версии не редактируются — только создание новой. Честный
  откат: v1 всегда та же, что была при создании.
- Правила на этом этапе — свободный markdown (textarea). Переход на
  структурированные правила (pattern → instruction) — в бэклог.
- Файл prompts/system_prompt.md становится сид-источником: при первом
  старте, если таблица agent_configs пустая, из него создаётся v1 и
  активируется. Дальше правда идёт из БД, файл не трогаем.
- rules_text конкатенируется с system_prompt в один system-message
  через compose_full_system_prompt: "{prompt}\n\nДополнительные
  правила:\n{rules}".
- Активную версию удалить нельзя — сначала активируют другую.

Модель и миграция:
- db/models/AgentConfig: id, version (unique/indexed), name (nullable),
  system_prompt, rules_text, is_active (indexed), created_at.
  Без updated_at — версии неизменяемы.
- Миграция b4450e33664d_add_agent_configs_table.

Сервисы и роутеры:
- services/config_service: ensure_seed (seed v1 из файла),
  list/get/get_active/create (version=max+1, при activate атомарно
  сбрасывает is_active у остальных и ставит новой),
  activate_config (та же схема), delete_config (возвращает причину
  отказа: not_found / active), compose_full_system_prompt.
- services/chat_service.send_message: берёт active_cfg, собирает
  system_prompt через compose_full_system_prompt, пишет
  thread.agent_config_id при создании треда (колонка была nullable
  ещё со Спринта 2 — пригодилась именно здесь).
- routers/configs: GET /configs, GET /configs/active, GET /configs/{id},
  POST /configs (activate-флаг), POST /configs/{id}/activate,
  DELETE /configs/{id} (404 / 400 если активная).
- Pydantic: AgentConfigCreateRequest, AgentConfigInfo, ListResponse,
  DeleteResponse.
- main.py: ensure_seed в lifespan после инициализации БД/Chroma/LLM.

UI:
- static/settings.html — трёхблочная страница: имя версии, textarea
  промпта, textarea правил, «Сохранить как новую» + галка
  «Сразу активировать», «Загрузить активную в редактор». Справа —
  список версий с бейджем «активная», действиями «Активировать» /
  «Удалить» (disabled у активной) / «Загрузить в редактор». При
  первом заходе активная версия автоматом подгружается в редактор.
- В nav на index.html и sandbox.html добавлена ссылка «Настройки».
- В шапке «Песочницы» — зелёный кликабельный бейдж «активная: vN · имя»
  (ведёт на /settings.html), обновляется раз в 15 с.

E2E проверено: создана v2 с правилом «ВСЕГДА начинай со слов СПАСИБО
ЗА ВОПРОС», активирована; следующий /chat вернул ответ, начинающийся
ровно с этой фразы; assembled_prompt содержит блок «Дополнительные
правила». После отката на v1 тест-v2 удалена.

SPRINTS.md: Спринт 3 помечен закрытым.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 19:59:06 +05:00
AR 15 M4 6348d9a206 docs: актуализация README, закрытие Спринта 2.5
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>
2026-04-23 11:21:10 +05:00
AR 15 M4 4e45b8b181 feat(sprint2.5): логи, вынесение системного промпта, markdown-рендер
Три подряд доработки по плану Спринта 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>
2026-04-23 10:53:01 +05:00
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
AR 15 M4 22ac40450f feat(sprint2): страница «Песочница» + навигация между страницами
Завершающий кусок Спринта 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>
2026-04-23 10:37:57 +05:00
AR 15 M4 ccc3dde978 docs: план Спринта 2 — диалог с памятью + отдельная страница «Песочница»
Уточнения к плану Спринта 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>
2026-04-23 09:50:42 +05:00
AR 15 M4 d1e7749605 docs: init — README и SPRINTS для инструмента настройки пациентского чат-агента
Скоуп MVP: RAG-ядро + веб-инструмент настройки (загрузка wiki, песочница,
промпт/правила с версиями, сценарии, экспорт конфига). Интеграцию с каналами
(приложение, МАКС) делает другой разработчик.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 13:58:53 +05:00