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

11 KiB
Raw Blame History

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 «Критерии оценки качества медицинской помощи» По строке таблицы

Пример единицы:

{
  "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;
    • строгие цитаты.

    Эмбеддинги и реранкер — по остаточному принципу: глубину даёт качество разметки, а не векторная база.