[bot][A] LLM-саммари динамики для врача по структурированным данным #19

Closed
opened 2026-10-03 14:38:56 +03:00 by Eleboba · 0 comments
Owner

Описание

SPEC §7 п.4. Функция в app/llm/summary.py: build_summary(structured: dict) -> str поверх gateway.summarize_for_doctor — 3–5 строк: динамика шкал, приверженность, побочки, флаги, «что обсудить на визите». Структуру входа задаёт app/api/schemas.py (PatientCard). Lane B вызывает её из API карточки.

Зона и владение файлами

Lane A (бот, Егор) — владеет: app/dialog/**, app/channels/**, app/llm/**, config/texts/**, tests/test_dialog_*.py, tests/test_telegram*.py.

Замороженные контракты (менять только отдельным мелким PR с пингом всех): app/core/types.py, app/dialog/contracts.py, app/api/schemas.py, app/integrations/base.py, app/services/contracts.py, app/main.py, app/config.py, config/modules.yaml, config/rules.yaml, config/scales/*, pyproject.toml/uv.lock, docker-compose.yml, Makefile.


Лог выполнения

2026-10-03

2026-10-03

  • Что сделано: app/llm/summary.py — build_structured(card, *, period_days=14, today=None) -> dict (детерминированная агрегация PatientCard: траектории шкал с опорной точкой до окна, delta / delta_prev, внеплановые; настроение среднее / последние 3 дня / минимум; ночи со сном < 4 ч и самая длинная серия; дни с алкоголем; приверженность taken/planned и дни пропусков; события из кодов алертов (кризис, намерение бросить, побочки); открытые алерты по уровням; риск отказа; темы «Что обсудить на визите») и async build_summary(card, *, period_days=14, today=None) -> str поверх gateway.summarize_for_doctor. Шаблон и пороги — config/texts/summary.yaml. Кэш в памяти по ключу (token, провайдер, sha256 структуры), LRU на 256 записей.
  • Результат: на andrey_card(): PHQ-9 14 → 13 → 18 (+4, последний внеплановый), сон < 4 ч — 4 ночи (серия 3), алкоголь 4 дня, приём 12/13, острый алерт PHQ-9 п.9 — первой строкой. 12 тестов в tests/test_llm_summary.py, make lint test зелёный.
  • Заметки/решения: в структуру не попадают имя, токен, reason алертов и план безопасности — только числа и коды. Mock и отказ провайдера отдают generic-дамп шлюза; build_summary распознаёт его и подставляет собственный шаблон. Если в ответе LLM при открытом остром алерте нет слова «безопасность», строка безопасности из шаблона добавляется первой. «Сегодня» карточки = последняя дата в её данных (без datetime.now()), можно передать today. Для карточек без ряда (фикстуры остальных пациентов) берутся phq9_last / pcl5_last / adherence_7d / open_alerts из PatientListItem. Lane B (#12): card.summary = await build_summary(card).
## Описание SPEC §7 п.4. Функция в `app/llm/summary.py`: `build_summary(structured: dict) -> str` поверх `gateway.summarize_for_doctor` — 3–5 строк: динамика шкал, приверженность, побочки, флаги, «что обсудить на визите». Структуру входа задаёт `app/api/schemas.py` (`PatientCard`). Lane B вызывает её из API карточки. ## Зона и владение файлами **Lane A (бот, Егор)** — владеет: `app/dialog/**`, `app/channels/**`, `app/llm/**`, `config/texts/**`, `tests/test_dialog_*.py`, `tests/test_telegram*.py`. **Замороженные контракты** (менять только отдельным мелким PR с пингом всех): `app/core/types.py`, `app/dialog/contracts.py`, `app/api/schemas.py`, `app/integrations/base.py`, `app/services/contracts.py`, `app/main.py`, `app/config.py`, `config/modules.yaml`, `config/rules.yaml`, `config/scales/*`, `pyproject.toml`/`uv.lock`, `docker-compose.yml`, `Makefile`. --- ## Лог выполнения ### 2026-10-03 ### 2026-10-03 - **Что сделано**: `app/llm/summary.py` — `build_structured(card, *, period_days=14, today=None) -> dict` (детерминированная агрегация `PatientCard`: траектории шкал с опорной точкой до окна, delta / delta_prev, внеплановые; настроение среднее / последние 3 дня / минимум; ночи со сном < 4 ч и самая длинная серия; дни с алкоголем; приверженность taken/planned и дни пропусков; события из кодов алертов (кризис, намерение бросить, побочки); открытые алерты по уровням; риск отказа; темы «Что обсудить на визите») и `async build_summary(card, *, period_days=14, today=None) -> str` поверх `gateway.summarize_for_doctor`. Шаблон и пороги — `config/texts/summary.yaml`. Кэш в памяти по ключу (token, провайдер, sha256 структуры), LRU на 256 записей. - **Результат**: на `andrey_card()`: PHQ-9 14 → 13 → 18 (+4, последний внеплановый), сон < 4 ч — 4 ночи (серия 3), алкоголь 4 дня, приём 12/13, острый алерт PHQ-9 п.9 — первой строкой. 12 тестов в `tests/test_llm_summary.py`, `make lint test` зелёный. - **Заметки/решения**: в структуру не попадают имя, токен, `reason` алертов и план безопасности — только числа и коды. Mock и отказ провайдера отдают generic-дамп шлюза; `build_summary` распознаёт его и подставляет собственный шаблон. Если в ответе LLM при открытом остром алерте нет слова «безопасность», строка безопасности из шаблона добавляется первой. «Сегодня» карточки = последняя дата в её данных (без `datetime.now()`), можно передать `today`. Для карточек без ряда (фикстуры остальных пациентов) берутся `phq9_last` / `pcl5_last` / `adherence_7d` / `open_alerts` из `PatientListItem`. Lane B (#12): `card.summary = await build_summary(card)`.
Eleboba added this to the Этап 1 · Ветераны СВО milestone 2026-10-03 14:38:56 +03:00
Eleboba added the featureP1botsize/0.5 labels 2026-10-03 14:38:56 +03:00
Eleboba self-assigned this 2026-10-03 14:38:56 +03:00
Eleboba changed title from [bot] LLM-саммари динамики для врача по структурированным данным to [bot][A] LLM-саммари динамики для врача по структурированным данным 2026-10-03 15:16:31 +03:00
Eleboba added the lane/Astage/veterans labels 2026-10-03 15:16:32 +03:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: MedITron/PTSRaiAgent#19