feat(web): questionnaires, diary and medication module in the patient app
- Focus screen renders versioned questionnaire items (iq: buttons): section chip, position (adaptive forms without "of N"), recall date, pause / help-now actions, optional skip, sleep-hours input, 0-10 scale anchors, RUS-AUDIT item 2 standard-drink table. - Paused / held-for-review questionnaires get their own screen. - Today: intake and diary tasks, review notice, therapy-day card on days 1/7/14. - Drug card /meds/:ref from data/meds/meds_reference.json (draft built from the Minzdrav guidelines: depression 2024, PTSD 2023) — expected effect, course, side effects, red flags; no doses shown. "Report a side effect" always available (med:side_effects:<ref>). - API: /instruments/catalog, /meds/reference; today gains questionnaire state, reference id, indication and therapy day; demo persona seeds the dashboard dose history. - INTAKE_DEMO=1 (demo clock only) opens the questionnaires on synthetic data without touching the clinical release gate in config/intake_runtime.yaml. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,542 @@
|
||||
"""Builds data/meds/meds_reference.json — the drug reference of the medication module.
|
||||
|
||||
Source of every value: the two Minzdrav clinical guidelines in config/rag/corpus/ —
|
||||
* «Депрессивный эпизод, рекуррентное депрессивное расстройство» (2024): прил. А3 табл. 2 (дозы),
|
||||
табл. 3 (профили побочных эффектов), разд. 3.1–3.6, прил. Б5, В;
|
||||
* «Посттравматическое стрессовое расстройство» (2023, ID 753): разд. 3.2, прил. А3 (дозы).
|
||||
Patient side-effect items: effects rated «++»/«+++» in табл. 3 (antidepressants) or named in the КР text
|
||||
(other drugs), worded for a patient. Nothing here is a recommendation: the app only follows the doctor's
|
||||
prescription (module spec, «Границы»). Texts and draft parameters must be reviewed by a psychiatrist.
|
||||
|
||||
Run: uv run python -m scripts.build_meds_reference
|
||||
"""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
OUT = Path(__file__).resolve().parents[1] / "data" / "meds" / "meds_reference.json"
|
||||
|
||||
DEP = "КР депрессия 2024"
|
||||
PTSD = "КР ПТСР 2023 (ID 753)"
|
||||
|
||||
# Patient wording of the КР табл. 3 columns (and of effects named in the КР text).
|
||||
SE = {
|
||||
"anticholinergic": "Сухость во рту или запоры",
|
||||
"nausea": "Тошнота",
|
||||
"sedation": "Сонливость днём",
|
||||
"insomnia": "Бессонница или беспокойство",
|
||||
"sexual": "Сексуальные проблемы",
|
||||
"orthostatic": "Головокружение при вставании",
|
||||
"weight": "Прибавка веса",
|
||||
"headache": "Головная боль",
|
||||
"dizziness": "Головокружение",
|
||||
"coordination": "Нарушение координации",
|
||||
"memory": "Снижение внимания и памяти",
|
||||
"akathisia": "Беспокойство, невозможность усидеть на месте",
|
||||
"eps": "Скованность или дрожь в теле",
|
||||
"skin": "Кожная сыпь или зуд",
|
||||
}
|
||||
|
||||
RF_BLEEDING = "Необычные кровотечения или синяки"
|
||||
RF_EARLY = "Мысли о самоубийстве или резкое усиление тревоги в первые недели приёма"
|
||||
RF_JAUNDICE = "Желтушность кожи или глаз"
|
||||
RF_RASH = "Кожная сыпь"
|
||||
RF_PRIAPISM = "Длительная болезненная эрекция"
|
||||
RF_UTERINE = "Маточное кровотечение"
|
||||
|
||||
TCA_MON = "Артериальное давление и ЭКГ"
|
||||
AP_MON = "Вес и признаки метаболического синдрома"
|
||||
|
||||
|
||||
def ad(id_, name, cls, start, lo, hi, items, *, ptsd=None, red=(), mon=(), withdrawal=None, overdose=False, note=None):
|
||||
"""Antidepressant: doses from КР депрессия табл. 2, side effects from табл. 3."""
|
||||
d = {
|
||||
"id": id_,
|
||||
"name_ru": name,
|
||||
"group": "Антидепрессант",
|
||||
"class": cls,
|
||||
"indications": {
|
||||
"depression": {
|
||||
"start_mg": start,
|
||||
"min_mg": lo,
|
||||
"max_mg": hi,
|
||||
"off_label": False,
|
||||
"expected_response": "3–4 недели",
|
||||
"course": "После улучшения лечение продолжают в той же дозе ещё 4–6 месяцев",
|
||||
"source": f"{DEP}, прил. А3 табл. 2; разд. 3.1",
|
||||
}
|
||||
},
|
||||
"diary_items": [SE[i] for i in items],
|
||||
"diary_items_source": f"{DEP}, прил. А3 табл. 3 (++/+++)",
|
||||
"red_flags": [RF_EARLY, *red],
|
||||
"monitoring": list(mon),
|
||||
"withdrawal_risk": withdrawal,
|
||||
"overdose_danger": overdose,
|
||||
"max_course_days": None,
|
||||
}
|
||||
if ptsd:
|
||||
d["indications"]["ptsd"] = ptsd
|
||||
if note:
|
||||
d["note"] = note
|
||||
return d
|
||||
|
||||
|
||||
def ptsd_ind(lo, hi, off_label, start=None):
|
||||
return {
|
||||
"start_mg": start,
|
||||
"min_mg": lo,
|
||||
"max_mg": hi,
|
||||
"off_label": off_label,
|
||||
"expected_response": "4–6 недель",
|
||||
"course": "Обычно 6–12 месяцев после стабилизации",
|
||||
"source": f"{PTSD}, разд. 3.2; прил. А3",
|
||||
}
|
||||
|
||||
|
||||
def other(
|
||||
id_, name, cls, lo, hi, off_label, items, *, red=(), mon=(), withdrawal=None, course_days=None, src, note=None
|
||||
):
|
||||
"""Non-antidepressant used for PTSD: doses from КР ПТСР прил. А3 / разд. 3.2, effects named in the text."""
|
||||
ind = ptsd_ind(lo, hi, off_label)
|
||||
ind["expected_response"] = None
|
||||
ind["course"] = None
|
||||
d = {
|
||||
"id": id_,
|
||||
"name_ru": name,
|
||||
"group": next(g for key, g in GROUPS.items() if key in cls),
|
||||
"class": cls,
|
||||
"indications": {"ptsd": ind},
|
||||
"diary_items": [SE[i] for i in items],
|
||||
"diary_items_source": src,
|
||||
"red_flags": list(red),
|
||||
"monitoring": list(mon),
|
||||
"withdrawal_risk": withdrawal,
|
||||
"overdose_danger": False,
|
||||
"max_course_days": course_days,
|
||||
}
|
||||
if note:
|
||||
d["note"] = note
|
||||
return d
|
||||
|
||||
|
||||
# Patient-facing drug group by the КР class wording.
|
||||
GROUPS = {
|
||||
"бензодиазепин": "Анксиолитик (транквилизатор)",
|
||||
"Анксиолитик": "Анксиолитик",
|
||||
"Антипсихотическое": "Антипсихотик",
|
||||
"Противоэпилептический": "Противоэпилептический препарат",
|
||||
}
|
||||
|
||||
SSRI = ["nausea", "insomnia", "sexual", "headache"] # табл. 3 + головная боль из разд. 3.1 (СИОЗС)
|
||||
BENZO = ["sedation", "dizziness", "coordination", "memory"] # КР ПТСР 3.2: седация, головокружение, координация…
|
||||
BENZO_SRC = f"{PTSD}, разд. 3.2 (комментарии о производных бензодиазепина)"
|
||||
AP_SRC = f"{PTSD}, разд. 3.2: акатизия, экстрапирамидные расстройства, метаболический синдром"
|
||||
|
||||
DRUGS = [
|
||||
ad(
|
||||
"paroxetine",
|
||||
"Пароксетин",
|
||||
"СИОЗС",
|
||||
20,
|
||||
20,
|
||||
50,
|
||||
SSRI,
|
||||
ptsd=ptsd_ind(20, 50, False),
|
||||
red=[RF_BLEEDING],
|
||||
withdrawal="high",
|
||||
),
|
||||
ad("sertraline", "Сертралин", "СИОЗС", 50, 50, 200, SSRI, ptsd=ptsd_ind(25, 200, False), red=[RF_BLEEDING]),
|
||||
ad(
|
||||
"fluvoxamine",
|
||||
"Флувоксамин",
|
||||
"СИОЗС",
|
||||
50,
|
||||
100,
|
||||
300,
|
||||
SSRI,
|
||||
red=[RF_BLEEDING],
|
||||
note="Стартовая доза по табл. 2: 50–100 мг",
|
||||
),
|
||||
ad(
|
||||
"fluoxetine",
|
||||
"Флуоксетин",
|
||||
"СИОЗС",
|
||||
20,
|
||||
20,
|
||||
80,
|
||||
SSRI,
|
||||
ptsd=ptsd_ind(20, 40, True),
|
||||
red=[RF_BLEEDING],
|
||||
withdrawal="low",
|
||||
),
|
||||
ad("citalopram", "Циталопрам", "СИОЗС", 20, 20, 40, SSRI, red=[RF_BLEEDING]),
|
||||
ad("escitalopram", "Эсциталопрам", "СИОЗС", 10, 10, 20, SSRI, red=[RF_BLEEDING]),
|
||||
ad(
|
||||
"venlafaxine",
|
||||
"Венлафаксин",
|
||||
"СИОЗСН",
|
||||
75,
|
||||
75,
|
||||
375,
|
||||
["nausea", "insomnia", "sexual"],
|
||||
ptsd=ptsd_ind(75, 225, True),
|
||||
mon=["Артериальное давление"],
|
||||
withdrawal="high",
|
||||
note="Депрессия: >225 мг/сут — в стационарных условиях",
|
||||
),
|
||||
ad("duloxetine", "Дулоксетин", "СИОЗСН", 60, 60, 120, ["nausea", "insomnia"]),
|
||||
ad(
|
||||
"amitriptyline",
|
||||
"Амитриптилин",
|
||||
"ТЦА",
|
||||
50,
|
||||
150,
|
||||
300,
|
||||
["anticholinergic", "sedation", "orthostatic", "weight"],
|
||||
ptsd=ptsd_ind(75, 150, True),
|
||||
mon=[TCA_MON],
|
||||
withdrawal="high",
|
||||
overdose=True,
|
||||
note="Депрессия: старт 50–75 мг; >150 мг/сут — в стационарных условиях",
|
||||
),
|
||||
ad(
|
||||
"imipramine",
|
||||
"Имипрамин",
|
||||
"ТЦА",
|
||||
25,
|
||||
150,
|
||||
300,
|
||||
["anticholinergic", "insomnia", "orthostatic", "weight"],
|
||||
ptsd=ptsd_ind(75, 250, True),
|
||||
mon=[TCA_MON],
|
||||
withdrawal="high",
|
||||
overdose=True,
|
||||
note="Депрессия: старт 25–75 мг; >200 мг/сут — в стационарных условиях",
|
||||
),
|
||||
ad(
|
||||
"clomipramine",
|
||||
"Кломипрамин",
|
||||
"ТЦА",
|
||||
50,
|
||||
100,
|
||||
250,
|
||||
["anticholinergic", "sexual", "orthostatic", "weight"],
|
||||
mon=[TCA_MON],
|
||||
withdrawal="high",
|
||||
overdose=True,
|
||||
note="Старт 50–75 мг; летальность при передозировке средняя",
|
||||
),
|
||||
ad(
|
||||
"pipofezine",
|
||||
"Пипофезин",
|
||||
"ТЦА (АТХ — другие антидепрессанты)",
|
||||
25,
|
||||
150,
|
||||
500,
|
||||
[],
|
||||
note="В табл. 3 КР не описан — побочные эффекты уточнять у врача; старт 25–50 мг",
|
||||
),
|
||||
ad("mianserin", "Миансерин", "НаССА", 30, 60, 90, ["sedation"], mon=["Формула крови (по КР — изменения редко)"]),
|
||||
ad(
|
||||
"mirtazapine",
|
||||
"Миртазапин",
|
||||
"НаССА",
|
||||
15,
|
||||
15,
|
||||
45,
|
||||
["sedation", "weight"],
|
||||
ptsd=ptsd_ind(30, 60, True),
|
||||
note="Старт 15–30 мг",
|
||||
),
|
||||
ad(
|
||||
"trazodone",
|
||||
"Тразодон",
|
||||
"Специфический серотонинергический АД",
|
||||
100,
|
||||
150,
|
||||
600,
|
||||
["sedation", "sexual"],
|
||||
red=[RF_PRIAPISM],
|
||||
note=">450 мг/сут — в стационарных условиях",
|
||||
),
|
||||
ad(
|
||||
"pirlindole",
|
||||
"Пирлиндол",
|
||||
"Ингибитор МАО-А",
|
||||
50,
|
||||
150,
|
||||
400,
|
||||
[],
|
||||
note="В табл. 3 КР не описан — побочные эффекты уточнять у врача; старт 50–75 мг",
|
||||
),
|
||||
ad(
|
||||
"agomelatine",
|
||||
"Агомелатин",
|
||||
"Мелатонинергический АД",
|
||||
25,
|
||||
25,
|
||||
50,
|
||||
[],
|
||||
red=[RF_JAUNDICE],
|
||||
mon=["Билирубин, АСТ, АЛТ, щелочная фосфатаза — в начале лечения и при повышении дозы"],
|
||||
),
|
||||
ad("vortioxetine", "Вортиоксетин", "Серотонинергический модулятор", 10, 10, 20, ["nausea", "insomnia"]),
|
||||
# КР ПТСР: анксиолитики, антипсихотические средства, противоэпилептические препараты
|
||||
other(
|
||||
"diazepam",
|
||||
"Диазепам",
|
||||
"Производное бензодиазепина",
|
||||
5,
|
||||
15,
|
||||
False,
|
||||
BENZO,
|
||||
withdrawal="high",
|
||||
course_days=28,
|
||||
src=BENZO_SRC,
|
||||
note="Курс не более 4 недель, в тяжёлых случаях до 8–12 недель",
|
||||
),
|
||||
other(
|
||||
"lorazepam",
|
||||
"Лоразепам",
|
||||
"Производное бензодиазепина",
|
||||
2,
|
||||
10,
|
||||
False,
|
||||
BENZO,
|
||||
withdrawal="high",
|
||||
course_days=21,
|
||||
src=BENZO_SRC,
|
||||
note="Дозы — из текста разд. 3.2 (в табл. А3 не приведён)",
|
||||
),
|
||||
other(
|
||||
"clonazepam",
|
||||
"Клоназепам",
|
||||
"Производное бензодиазепина",
|
||||
1,
|
||||
4,
|
||||
False,
|
||||
BENZO,
|
||||
withdrawal="high",
|
||||
course_days=21,
|
||||
src=BENZO_SRC,
|
||||
note="Дозы — из текста разд. 3.2 (в табл. А3 не приведён)",
|
||||
),
|
||||
other(
|
||||
"alprazolam",
|
||||
"Алпразолам",
|
||||
"Производное бензодиазепина",
|
||||
0.25,
|
||||
4.5,
|
||||
False,
|
||||
BENZO,
|
||||
withdrawal="high",
|
||||
course_days=90,
|
||||
src=BENZO_SRC,
|
||||
note="Курс до 3 месяцев; отмена в течение 2–6 недель",
|
||||
),
|
||||
other(
|
||||
"tofisopam",
|
||||
"Тофизопам",
|
||||
"Производное бензодиазепина (дневной транквилизатор)",
|
||||
50,
|
||||
300,
|
||||
False,
|
||||
[],
|
||||
course_days=84,
|
||||
src=f"{PTSD}, разд. 3.2",
|
||||
note="По КР не вызывает физической зависимости и седации; курс 4–12 недель",
|
||||
),
|
||||
other(
|
||||
"etifoxine",
|
||||
"Этифоксин",
|
||||
"Анксиолитик",
|
||||
150,
|
||||
200,
|
||||
False,
|
||||
["sedation", "skin"],
|
||||
red=[RF_JAUNDICE, RF_UTERINE],
|
||||
course_days=42,
|
||||
src=f"{PTSD}, разд. 3.2",
|
||||
note="Курс от нескольких дней до 4–6 недель",
|
||||
),
|
||||
other(
|
||||
"hydroxyzine",
|
||||
"Гидроксизин",
|
||||
"Анксиолитик",
|
||||
25,
|
||||
100,
|
||||
True,
|
||||
["sedation"],
|
||||
course_days=56,
|
||||
src=f"{PTSD}, разд. 3.2",
|
||||
note="Курс обычно 4–8 недель",
|
||||
),
|
||||
other(
|
||||
"buspirone",
|
||||
"Буспирон",
|
||||
"Анксиолитик",
|
||||
20,
|
||||
30,
|
||||
False,
|
||||
[],
|
||||
src=f"{PTSD}, разд. 3.2",
|
||||
note="Эффект с 7–14 дня, максимум к 4-й неделе",
|
||||
),
|
||||
other(
|
||||
"alimemazine",
|
||||
"Алимемазин",
|
||||
"Антипсихотическое средство",
|
||||
15,
|
||||
80,
|
||||
False,
|
||||
[],
|
||||
mon=[AP_MON],
|
||||
src=f"{PTSD}, разд. 3.2",
|
||||
note="По КР побочные эффекты редки и слабо выражены",
|
||||
),
|
||||
other(
|
||||
"risperidone",
|
||||
"Рисперидон",
|
||||
"Антипсихотическое средство",
|
||||
0.5,
|
||||
8,
|
||||
True,
|
||||
["akathisia", "eps", "weight"],
|
||||
mon=[AP_MON],
|
||||
src=AP_SRC,
|
||||
),
|
||||
other(
|
||||
"quetiapine",
|
||||
"Кветиапин",
|
||||
"Антипсихотическое средство",
|
||||
50,
|
||||
300,
|
||||
True,
|
||||
["akathisia", "eps", "weight"],
|
||||
mon=[AP_MON],
|
||||
src=AP_SRC,
|
||||
),
|
||||
other(
|
||||
"olanzapine",
|
||||
"Оланзапин",
|
||||
"Антипсихотическое средство",
|
||||
5,
|
||||
20,
|
||||
True,
|
||||
["weight", "sedation"],
|
||||
mon=[AP_MON],
|
||||
src=f"{DEP}, разд. 3.3 (увеличение веса, седация); {PTSD}, разд. 3.2",
|
||||
),
|
||||
other(
|
||||
"tiapride", "Тиаприд", "Антипсихотическое средство", 200, 300, False, [], mon=[AP_MON], src=f"{PTSD}, разд. 3.2"
|
||||
),
|
||||
other(
|
||||
"chlorprothixene",
|
||||
"Хлорпротиксен",
|
||||
"Антипсихотическое средство",
|
||||
25,
|
||||
150,
|
||||
True,
|
||||
[],
|
||||
mon=[AP_MON],
|
||||
src=f"{PTSD}, разд. 3.2",
|
||||
note="Расхождение в КР ПТСР: в тексте 15–100 мг, в табл. А3 — 25–150 мг",
|
||||
),
|
||||
other(
|
||||
"lamotrigine",
|
||||
"Ламотриджин",
|
||||
"Противоэпилептический препарат",
|
||||
25,
|
||||
500,
|
||||
True,
|
||||
[],
|
||||
red=[RF_RASH],
|
||||
src=f"{PTSD}, разд. 3.2",
|
||||
note="Частые кожные высыпания вплоть до токсического эпидермального некролиза",
|
||||
),
|
||||
other("topiramate", "Топирамат", "Противоэпилептический препарат", 200, 400, True, [], src=f"{PTSD}, разд. 3.2"),
|
||||
]
|
||||
|
||||
TEXTS = {
|
||||
"expect_effect_depression": (
|
||||
"Лекарства от депрессии действуют не сразу. Первые изменения иногда заметны уже через 1–2 недели, "
|
||||
"а эффект врач оценивает через 3–4 недели. Принимайте препарат по схеме, даже если пока не чувствуете разницы."
|
||||
),
|
||||
"expect_effect_ptsd": (
|
||||
"Эффект препарата при ПТСР развивается постепенно — его оценивают через 4–6 недель. В первую неделю тревога "
|
||||
"может временно усилиться: это известная реакция, сообщите о ней врачу. Не прекращайте приём самостоятельно."
|
||||
),
|
||||
"dont_stop_alone": (
|
||||
"Не прекращайте приём самостоятельно: резкая отмена может ухудшить самочувствие, а лечение — потерять эффект. "
|
||||
"Если препарат мешает жить или вы в нём сомневаетесь, обсудите это с врачом — он может изменить дозу "
|
||||
"или подобрать другой."
|
||||
),
|
||||
"why_continue_depression": (
|
||||
"Даже когда становится лучше, лечение продолжают ещё несколько месяцев в той же дозе: так ниже риск, "
|
||||
"что депрессия вернётся."
|
||||
),
|
||||
"withdrawal_missed": (
|
||||
"Вы пропустили приём два дня подряд. При резком прекращении этого препарата бывают неприятные ощущения: "
|
||||
"головокружение, раздражительность, нарушения сна, состояние как при гриппе. Вернитесь к обычной схеме "
|
||||
"и сообщите врачу, если стало хуже."
|
||||
),
|
||||
"ran_out": (
|
||||
"Лекарство закончилось? Не откладывайте — попросите у врача новый рецепт: "
|
||||
"перерыв в приёме может ухудшить самочувствие."
|
||||
),
|
||||
"red_flag": "Этот симптом нужно обсудить с врачом сегодня. Если состояние тяжёлое — вызывайте скорую: 103 или 112.",
|
||||
"side_effects_general": (
|
||||
"Спасибо, что сообщили. Побочные эффекты часто ослабевают в первые недели. Если они мешают жить — это повод "
|
||||
"обсудить с врачом дозу или замену препарата. Не меняйте схему сами."
|
||||
),
|
||||
"instruction_fallback": "Уточните у врача или в инструкции к препарату.",
|
||||
}
|
||||
|
||||
RULES = [
|
||||
{"id": "M1", "params": {"missed_days_in_row": 2}, "status": "черновик"},
|
||||
{"id": "M2", "params": {}, "status": "черновик"},
|
||||
{"id": "M3", "params": {"ran_out_days_in_row": 2}, "status": "черновик"},
|
||||
{"id": "M4", "params": {"default_max_course_days": 21}, "status": "КР ПТСР 3.2"},
|
||||
{
|
||||
"id": "M5",
|
||||
"params": {"check_day": 28, "baseline_lookback_days": 14, "phq9_min_drop_pct": 50, "pcl5_min_drop": 10},
|
||||
"status": "черновик",
|
||||
},
|
||||
{"id": "M6", "params": {}, "status": "КР депрессия 3.1.3"},
|
||||
{"id": "M7", "params": {}, "status": "черновик"},
|
||||
{"id": "M8", "params": {"fibser_burden_min": 5, "side_effect_misses_in_7_days": 2}, "status": "черновик"},
|
||||
{"id": "M9", "params": {}, "status": "в сводке врачу"},
|
||||
{"id": "M10", "params": {}, "status": "приложения А3 обеих КР"},
|
||||
]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
OUT.parent.mkdir(parents=True, exist_ok=True)
|
||||
doc = {
|
||||
"version": "draft-2026-10-04",
|
||||
"status": "черновик: собран по КР Минздрава, тексты и параметры вычитывает психиатр",
|
||||
"sources": [
|
||||
{
|
||||
"id": "kr_depression_2024",
|
||||
"title": "Депрессивный эпизод, рекуррентное депрессивное расстройство",
|
||||
"year": 2024,
|
||||
"file": "docs/source/rag/kr_depression.pdf",
|
||||
},
|
||||
{
|
||||
"id": "kr_ptsd_2023",
|
||||
"title": "Посттравматическое стрессовое расстройство",
|
||||
"year": 2023,
|
||||
"kr_id": 753,
|
||||
"file": "docs/source/rag/kr_ptsd.pdf",
|
||||
},
|
||||
],
|
||||
"drugs": DRUGS,
|
||||
"texts": TEXTS,
|
||||
"rules": RULES,
|
||||
}
|
||||
OUT.write_text(json.dumps(doc, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
||||
print(f"{OUT}: {len(DRUGS)} drugs")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user