Files
PTSRaiAgent/docs/info/RAG_GUIDELINES.md
T
Arxip222andClaude Opus 5.5 4d331e4c05 docs(rag): describe RAG approach for Minzdrav clinical guidelines
Structure-aware units with audience/evidence metadata, manual review,
hybrid BM25 search, citation-checked answers and an eval set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 07:57:00 +03:00

143 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RAG по клиническим рекомендациям Минздрава
> Статус: черновик подхода, 2026-10-04. Реализация — отдельной задачей (lane B, `app/llm/rag.py` по SPEC §структура).
> Пример исходника: КР «Посттравматическое стрессовое расстройство», ID 753, 2023 (Российское общество психиатров).
## Принцип
Файлов мало, глубина нужна максимальная, поэтому мы **не** делаем классический RAG «нарезка по N токенов → эмбеддинги → top-k».
Каждая КР один раз превращается в **размеченную и вычитанную базу знаний** из смысловых единиц. Поиск по ней почти тривиален, а
каждый ответ проверяется по цитате.
## 1. Кому отвечает RAG
КР написаны для врачей: дозы, препараты off-label (`#`), показания к госпитализации. Пересказывать это пациенту нельзя —
это противоречит нашим guardrails (`app/llm/med_qa.py`: о препаратах — только по инструкции ГРЛС и без доз).
| Потребитель | Что можно отдавать из КР |
|---|---|
| Пациент (бот) | Только `Приложение В. Информация для пациента` и психообразование. Без доз и названий препаратов |
| Врач (дашборд) | Всё, с цитатой, уровнем убедительности (УУР) и достоверности доказательств (УДД) |
| Команда (design-time) | Обоснование порогов в `config/` (TSQ ≥ 6 — Прил. Г1, градации шкалы Бека — Г10): ссылки на источник, а не runtime-RAG |
У каждой единицы есть поле `audience`. Фильтр по нему применяется **до** поиска, а не через промпт LLM.
## 2. Разбивка на смысловые единицы
Структура КР Минздрава стабильна, используем её как схему.
| `type` | Пример из КР ПТСР | Как хранить |
|---|---|---|
| `recommendation` | «Пациентам с ПТСР … рекомендуется начинать терапию с СИОЗС…» | Тезис + УУР/УДД + комментарий + номера источников |
| `definition` / `criteria` | Критерии МКБ-10 А–Д, кластеры МКБ-11 | По одному критерию на единицу |
| `dose_row` | Таблица «Рекомендуемые дозы» (Прил. А3) | Строка: препарат, диапазон, `off_label`, `zhnvlp` (**) |
| `scale` | TSQ, CAPS, IES-R, BHS, TOP-8 (Прил. Г1–Г11) | Пункты + ключ интерпретации как данные |
| `algorithm` | Прил. Б и Б1 (в PDF это картинки) | Переписать вручную в шаги и ветвления |
| `patient_info` | Прил. В | Абзацы с `audience: patient` |
| `quality_criterion` | «Критерии оценки качества медицинской помощи» | По строке таблицы |
Пример единицы:
```json
{
"id": "kr753.3.2.rec01",
"doc": {"kr_id": 753, "title": "ПТСР", "approved": "2023", "revise_by": "2025"},
"path": ["3. Лечение", "3.2. Психофармакотерапия", "Терапия первой линии"],
"type": "recommendation",
"text": "Пациентам с ПТСР в качестве препаратов первой линии ... рекомендуется начинать терапию с СИОЗС ...",
"comment": "После установления диагноза ... эффективность оценивается через 4–6 недель ...",
"uur": "A",
"udd": 1,
"refs": [51, 53, 302],
"drugs": ["пароксетин", "сертралин", "флуоксетин", "венлафаксин"],
"contains_dose": true,
"off_label": ["флуоксетин", "венлафаксин"],
"audience": ["doctor"],
"pages": [17, 18]
}
```
Комментарий хранится вместе с тезисом: по отдельности они теряют смысл, а основная глубина КР — именно в комментариях.
## 3. Пайплайн подготовки: автоматика, затем вычитка
Файлов мало, поэтому ручная вычитка реальна и даёт больше всего качества. Повторяем практику `docs/clinical/`: хеши
исходников, `review-status.json`.
1. **Источник.** Первоисточник — cr.minzdrav.gov.ru, а не перевёрстки (пример выше — перевёрстка с disuria.ru). Храним sha256.
2. **Очистка.** Убрать колонтитулы («Страница N из 117», рекламу сайта), склеить переносы и разрывы страниц
(слипания вида «клиникопсихопатологических»), собрать таблицы, разорванные между страницами.
3. **Парсер по шаблону.** Абзац «- Пациентам…» до строки «Уровень убедительности рекомендаций X (уровень достоверности
доказательств N)» — одна единица `recommendation`. Следующий за ней блок «Комментарии:» — её поле `comment`.
4. **Список литературы не индексируем.** Это шум для поиска; номера источников остаются в `refs`.
5. **Ручная вычитка.** В первую очередь — единицы для пациента и всё, где есть числа. В КР ПТСР уже видны ошибки самого
источника, которые автоматика пропустит:
- в таблице критериев качества перепутаны колонки УДД и УУР;
- раздел 6.1 встречается дважды;
- опечатка «ценить суицидальный риск» вместо «оценивать».
6. **Словарь аббревиатур и синонимов** — из списка сокращений в начале каждой КР. Нужен для расширения запросов:
СИОЗС ↔ сертралин/пароксетин, ДПДГ ↔ EMDR, ТФ-КПТ и т.д.
Раскладка по ADR-008:
```
data/kb/sources/ исходные PDF + sha256
data/kb/units/*.jsonl вычитанные единицы (в git)
data/kb/review-status.json статус вычитки по единицам
data/eval/kb_questions.yaml эталонные вопросы
```
## 4. Поиск
Корпус маленький, тяжёлая инфраструктура не нужна.
- **Фильтр по метаданным до поиска:** `audience`, `doc`, `type`. Вопрос пациента о дозе — отказ без поиска.
- **Гибридный поиск:**
- BM25 с русской лемматизацией (pymorphy3) и расширением запроса по словарю аббревиатур;
- эмбеддинги — только GigaChat Embeddings или локальная модель (guardrails 4 и 9; для офлайн-демо — только локальная).
- **Small-to-big.** Найден тезис — в контекст LLM уходит тезис с комментарием и заголовками родительского раздела. При
нашем объёме допустимо отдавать раздел целиком.
- **Порог уверенности.** Лучшая единица ниже порога — ответ «В клинических рекомендациях ответа на этот вопрос нет»
(по аналогии с `fallback` в `config/texts/med_qa.yaml`).
## 5. Генерация строго по источнику
Переиспользуем механизмы `app/llm/med_qa.py`:
- LLM получает пронумерованные единицы и обязана ссылаться на `id` в каждом утверждении.
- **Детерминированная проверка после генерации:**
- каждое число в ответе встречается в процитированных единицах;
- доля «новых» слов ограничена (`MAX_NOVEL_STEM_SHARE`).
Не прошло — вместо пересказа отдаём саму цитату.
- Ссылка на источник («КР ПТСР 2023, разд. 3.2, УУР A») и фраза «решение принимает врач» добавляются кодом, не через LLM.
- До поиска действуют общие guardrails: проверка безопасности (`acute` → фиксированный кризисный скрипт), затем `scrub()`,
затем вызов модели только через `app/llm/gateway.py`.
## 6. Оценка качества
Эталонный набор в `data/eval/` на 50–100 вопросов с ожидаемыми `id` единиц. Вопросы трёх видов:
- прямые;
- перефразированные;
- ловушки, на которые в КР ответа нет.
Метрики:
- recall@k по `id` (есть ли нужные единицы среди первых k найденных);
- доля ответов, прошедших проверку по цитате;
- доля правильных отказов на ловушках.
Оценка запускается обычным pytest-тестом, чтобы правки разметки не ломали поиск незаметно.
## Риски и ограничения
- **Актуальность.** КР ПТСР указывает «пересмотр не позднее 2025». Перед использованием проверить в рубрикаторе Минздрава
наличие новой редакции. `approved` / `revise_by` храним в метаданных и показываем в ответе.
- **Объём к дедлайну (05.10.2026, 13:00).** Реалистичный MVP:
- 2–3 КР (ПТСР, депрессия), размеченные полуавтоматически и вычитанные;
- BM25 + фильтр по `audience`;
- строгие цитаты.
Эмбеддинги и реранкер — по остаточному принципу: глубину даёт качество разметки, а не векторная база.