Нужна база знаний по клиническим документам, из которой агент берёт обоснованные фрагменты с указанием источника и страницы: КР «Посттравматическое стрессовое расстройство» (МЗ РФ, 2023), КР «Депрессивный эпизод, рекуррентное депрессивное расстройство» (МЗ РФ, 2024), спецификация модуля «Лекарства».
PDF уже переведены в txt конвертером (pdfplumber + pdftotext): колонтитулы вырезаны, таблицы в markdown, маркеры --- стр. N ---, текст блок-схем перенесён вручную. Сверка по словам с pdftotext: теряются только колонтитулы.
Ограничения: офлайн по умолчанию, без зарубежных API (ADR-004, guardrail 9), без новых зависимостей (pyproject.toml заморожен, #34). Поэтому поиск лексический (BM25 + русский стеммер), без эмбеддингов.
Желаемый результат
app/llm/rag/ — чанкинг корпуса (страница + раздел в метаданных, таблицы не рвутся без шапки), BM25-индекс, retrieve(query) и answer(question) с цитатами «[КР ПТСР 2023, стр. N]».
answer() — экстрактивный: только предложения из найденных фрагментов; опциональная перефразировка через gateway.phrase с отбраковкой добавленного содержания (как в med_qa); для пациента — без доз и без запрещённого вывода.
Корпус и параметры — в config/rag/ (ADR-008); исходники PDF и конвертер — в docs/source/rag/.
CLI: python -m app.llm.rag "вопрос".
Тесты: набор контрольных вопросов → ожидаемый документ/страница в top-k.
Подзадачи
перенос PDF, конвертера, figures/manual в docs/source/rag/, txt — в config/rag/corpus/
КР написаны для врача: пациенту — только экстрактивно, с источником и припиской «решение за врачом»; дозировки пациенту не показываются.
В LLM — только scrub()-текст через gateway (guardrail 1). Safety-проверка — на стороне вызывающего (движок).
Встраивание в диалог (свободные вопросы пациента, подсказки врачу в дашборде) — отдельные issue.
Архитектурный выбор
Эмбеддинги (GigaChat Embeddings / локальная модель) требуют сети или тяжёлых зависимостей → BM25 со стеммингом и синонимами; интерфейс Retriever позволяет позже добавить гибридный поиск.
Как проверить
make lint && make test; uv run python -m app.llm.rag "через сколько начинают действовать антидепрессанты" → фрагменты с документом и страницей.
Лог выполнения
2026-10-04
Что сделано: PDF → txt (конвертер с таблицами в markdown, маркерами страниц, ручной транскрипцией блок-схем; исправлены ложные шапки и разрывы строк в таблицах HAM-D/MADRS). Пакет app/llm/rag: стеммер Snowball, чанкинг по разделам КР с номерами страниц, BM25 + синонимы + переранжирование по плотному отрывку, экстрактивный answer() с цитатами, порогом покрытия, фильтром доз/назначений для пациента и проверкой перефразировки LLM. CLI python -m app.llm.rag. ADR-011.
Результат: 443 фрагмента; контрольный набор hit@3 = 15/18; 9/9 вопросов не по теме → «ответа нет»; вопросы о дозе → к врачу. Сверка txt с pdftotext: теряются только колонтитулы (и список литературы, исключён намеренно).
Не сделано / дальше: встраивание в диалог (свободные вопросы пациента) и в дашборд врача — отдельными issue; разговорная лексика без общих слов с КР ищется хуже (лечится словарём synonyms).
## Описание
Нужна база знаний по клиническим документам, из которой агент берёт обоснованные фрагменты с указанием источника и страницы: КР «Посттравматическое стрессовое расстройство» (МЗ РФ, 2023), КР «Депрессивный эпизод, рекуррентное депрессивное расстройство» (МЗ РФ, 2024), спецификация модуля «Лекарства».
PDF уже переведены в txt конвертером (pdfplumber + pdftotext): колонтитулы вырезаны, таблицы в markdown, маркеры `--- стр. N ---`, текст блок-схем перенесён вручную. Сверка по словам с `pdftotext`: теряются только колонтитулы.
Ограничения: офлайн по умолчанию, без зарубежных API (ADR-004, guardrail 9), без новых зависимостей (`pyproject.toml` заморожен, #34). Поэтому поиск лексический (BM25 + русский стеммер), без эмбеддингов.
## Желаемый результат
- `app/llm/rag/` — чанкинг корпуса (страница + раздел в метаданных, таблицы не рвутся без шапки), BM25-индекс, `retrieve(query)` и `answer(question)` с цитатами «[КР ПТСР 2023, стр. N]».
- `answer()` — экстрактивный: только предложения из найденных фрагментов; опциональная перефразировка через `gateway.phrase` с отбраковкой добавленного содержания (как в med_qa); для пациента — без доз и без запрещённого вывода.
- Корпус и параметры — в `config/rag/` (ADR-008); исходники PDF и конвертер — в `docs/source/rag/`.
- CLI: `python -m app.llm.rag "вопрос"`.
- Тесты: набор контрольных вопросов → ожидаемый документ/страница в top-k.
## Подзадачи
- [ ] перенос PDF, конвертера, figures/manual в `docs/source/rag/`, txt — в `config/rag/corpus/`
- [ ] `config/rag/sources.yaml` — манифест документов, параметры, синонимы (ПТСР ↔ посттравматическое...)
- [ ] `app/llm/rag/` — chunker, stemmer, BM25, retrieve, answer, CLI
- [ ] шаблон `rag_answer` в `config/texts/`
- [ ] `tests/test_llm_rag.py`
## Анализ
### Затрагиваемые файлы
| Файл | Что меняется |
|---|---|
| `app/llm/rag/*` | новый пакет |
| `config/rag/*` | корпус и манифест |
| `config/texts/phrases.yaml`, `config/texts/rag.yaml` | шаблоны ответа |
| `docs/source/rag/*` | PDF-исходники, конвертер |
| `tests/test_llm_rag.py` | тесты |
### Ограничения и риски
- КР написаны для врача: пациенту — только экстрактивно, с источником и припиской «решение за врачом»; дозировки пациенту не показываются.
- В LLM — только `scrub()`-текст через `gateway` (guardrail 1). Safety-проверка — на стороне вызывающего (движок).
- Встраивание в диалог (свободные вопросы пациента, подсказки врачу в дашборде) — отдельные issue.
### Архитектурный выбор
Эмбеддинги (GigaChat Embeddings / локальная модель) требуют сети или тяжёлых зависимостей → BM25 со стеммингом и синонимами; интерфейс `Retriever` позволяет позже добавить гибридный поиск.
## Как проверить
`make lint && make test`; `uv run python -m app.llm.rag "через сколько начинают действовать антидепрессанты"` → фрагменты с документом и страницей.
---
## Лог выполнения
### 2026-10-04
- **Что сделано:** PDF → txt (конвертер с таблицами в markdown, маркерами страниц, ручной транскрипцией блок-схем; исправлены ложные шапки и разрывы строк в таблицах HAM-D/MADRS). Пакет `app/llm/rag`: стеммер Snowball, чанкинг по разделам КР с номерами страниц, BM25 + синонимы + переранжирование по плотному отрывку, экстрактивный `answer()` с цитатами, порогом покрытия, фильтром доз/назначений для пациента и проверкой перефразировки LLM. CLI `python -m app.llm.rag`. ADR-011.
- **Результат:** 443 фрагмента; контрольный набор hit@3 = 15/18; 9/9 вопросов не по теме → «ответа нет»; вопросы о дозе → к врачу. Сверка txt с pdftotext: теряются только колонтитулы (и список литературы, исключён намеренно).
- **Не сделано / дальше:** встраивание в диалог (свободные вопросы пациента) и в дашборд врача — отдельными issue; разговорная лексика без общих слов с КР ищется хуже (лечится словарём synonyms).
Eleboba
added this to the Этап 1 · Ветераны СВО milestone 2026-10-04 03:50:14 +03:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Описание
Нужна база знаний по клиническим документам, из которой агент берёт обоснованные фрагменты с указанием источника и страницы: КР «Посттравматическое стрессовое расстройство» (МЗ РФ, 2023), КР «Депрессивный эпизод, рекуррентное депрессивное расстройство» (МЗ РФ, 2024), спецификация модуля «Лекарства».
PDF уже переведены в txt конвертером (pdfplumber + pdftotext): колонтитулы вырезаны, таблицы в markdown, маркеры
--- стр. N ---, текст блок-схем перенесён вручную. Сверка по словам сpdftotext: теряются только колонтитулы.Ограничения: офлайн по умолчанию, без зарубежных API (ADR-004, guardrail 9), без новых зависимостей (
pyproject.tomlзаморожен, #34). Поэтому поиск лексический (BM25 + русский стеммер), без эмбеддингов.Желаемый результат
app/llm/rag/— чанкинг корпуса (страница + раздел в метаданных, таблицы не рвутся без шапки), BM25-индекс,retrieve(query)иanswer(question)с цитатами «[КР ПТСР 2023, стр. N]».answer()— экстрактивный: только предложения из найденных фрагментов; опциональная перефразировка черезgateway.phraseс отбраковкой добавленного содержания (как в med_qa); для пациента — без доз и без запрещённого вывода.config/rag/(ADR-008); исходники PDF и конвертер — вdocs/source/rag/.python -m app.llm.rag "вопрос".Подзадачи
docs/source/rag/, txt — вconfig/rag/corpus/config/rag/sources.yaml— манифест документов, параметры, синонимы (ПТСР ↔ посттравматическое...)app/llm/rag/— chunker, stemmer, BM25, retrieve, answer, CLIrag_answerвconfig/texts/tests/test_llm_rag.pyАнализ
Затрагиваемые файлы
app/llm/rag/*config/rag/*config/texts/phrases.yaml,config/texts/rag.yamldocs/source/rag/*tests/test_llm_rag.pyОграничения и риски
scrub()-текст черезgateway(guardrail 1). Safety-проверка — на стороне вызывающего (движок).Архитектурный выбор
Эмбеддинги (GigaChat Embeddings / локальная модель) требуют сети или тяжёлых зависимостей → BM25 со стеммингом и синонимами; интерфейс
Retrieverпозволяет позже добавить гибридный поиск.Как проверить
make lint && make test;uv run python -m app.llm.rag "через сколько начинают действовать антидепрессанты"→ фрагменты с документом и страницей.Лог выполнения
2026-10-04
app/llm/rag: стеммер Snowball, чанкинг по разделам КР с номерами страниц, BM25 + синонимы + переранжирование по плотному отрывку, экстрактивныйanswer()с цитатами, порогом покрытия, фильтром доз/назначений для пациента и проверкой перефразировки LLM. CLIpython -m app.llm.rag. ADR-011.