Я собрал все медицинские данные семьи в одном сервисе и подключил Claude Opus. Рассказываю, что из этого вышло

Я собрал все медицинские данные семьи в одном сервисе и подключил Claude Opus. Рассказываю, что из этого вышло

Привет, Хабр. В прошлых статьях рассказывал про Telegram-бота на Gemini и внедрение AI во все поля ввода Windows. Сегодня — история другая: личная, экспериментальная. Я написал медицинский сервис для своей семьи, подключил к нему Claude Opus и честно не знаю, чем всё закончится. Но пока результат интереснее, чем я ожидал.

У сына задержка речевого развития. За два года мы прошли кучу специалистов: неврологов, психиатров, логопедов, дефектологов. У каждого — своя карта, свои записи, своё мнение. В какой-то момент я понял две вещи. Первая: жена, которая занимается этим 24/7, физически не может удержать всё в голове. Вторая: врачи между собой не общаются, и никто не видит полной картины.

Был случай с неврологом, которую направили из поликлиники. Она настоятельно рекомендовала остеопата. Я загуглил — остеопатия не относится к доказательной медицине. В отзывах видно, что она почти всем направляет одного и того же остеопата. Я задумался: как понять, профессионал передо мной или нет, если я не врач? Ответ: никак. Если нет инструмента, который проверит за тебя.

Медицина — точная наука: анализы, дозировки, референсные значения — всё это цифры. Нейросеть с цифрами работает хорошо. Главное — она видит всю картину целиком: все взаимосвязи между анализами, назначениями и диагнозами, которые ни один врач не охватит за 15 минут приёма. Так я начал писать сервис.

Что получилось на данный момент

Это — семейная медицинская база данных. В неё загружаются все данные о здоровье: документы, анализы, расшифровки приёмов, назначения, прививки, рост и вес. Нейросеть анализирует всё целиком — не фрагмент, а всю историю со всеми связями.

Ключевое отличие от «просто спросить ChatGPT» я понял на жене. Она пользуется бесплатной версией и говорит: «мне хватает». Для простых вопросов — да. Но когда у тебя папка документов за пять лет, а ты спрашиваешь про новый анализ, нейросеть в чате уже забыла, что три приёма назад другой врач назначил препарат. Контекст не резиновый. По мере диалога нюансы теряются.

У меня Claude получает полный контекст: все диагнозы, препараты, анализы, хронологию, связи между ними — за один запрос. Ничего не теряется между сеансами. Это не чат, а персистентная база знаний с нейросетью в роли аналитика.

Важно: AI в сервисе не ставит диагнозы. Он объясняет на языке фактов, что было сделано, что упущено и почему это важно. Никаких «скорее всего», только: «врач N не назначил анализ X, хотя при диагнозе Y это стандарт по международным гайдлайнам». Разница принципиальная.

Главный экран

При открытии — PIN-экран. Если на устройстве настроена биометрия, можно войти через Face ID или Windows Hello. Иначе — 6-значный код.

После входа — сводка: четыре кликабельные карточки: активные диагнозы, текущие препараты, количество визитов, критичные ошибки. Ниже — топ диагнозов, текущие препараты, ближайшие напоминания и AI-резюме по пациенту.

AI-резюме — это структурированная сводка, которую нейросеть генерирует после анализа всей базы: приоритеты, план действий, на что обратить внимание. Обновляется при добавлении нового документа.

Остальные страницы: план обследований (можно менять приоритеты перетаскиванием), список врачебных ошибок и несостыковок, все диагнозы, документы (визиты и анализы в одной ленте с фильтрами), карта здоровья, AI-чат, раздел «ещё» — специалисты, прививки, рост-вес, глобальный поиск.

Есть и десктопная версия — не просто адаптация под ПК. На десктопе: сайдбар, модалки во весь экран, таблицы и графики используют всё пространство. Я сам пользуюсь наполовину с телефона, наполовину с компьютера, и важно, чтобы на обеих платформах интерфейс ощущался нативно.

Карта здоровья и почему связи важнее хранения

Изначально данные лежали рядом, но не связаны. Препарат, диагноз, приём у врача — всё записано, но нигде не зафиксировано: кто назначил, от какого диагноза, на каком приёме. Нейросети приходилось каждый раз угадывать по тексту и датам. Работало, пока данных было мало. Потом начались сбои.

Я смотрел графовые БД: SurrealDB, Kuzu, Neo4j. Но понял: у меня 100 сущностей и 300 связей — это не тот масштаб. Проблема не в движке, а в схеме данных.

Решение оказалось простым: связующие таблицы в SQLite.

Теперь у каждой связи есть явный ID. Это позволяет использовать SQL с JOIN’ами. Нейросеть больше не парсит текст, а работает с чёткими связями. Точность анализа выросла на порядок.

Поверх базы — визуализация на Cytoscape.js. Узлы: диагнозы, врачи, препараты, приёмы, ошибки. Рёбра: кто что назначил, от какого диагноза, на каком приёме. При клике на узел подсвечиваются только его связи, остальное затемняется.

AI-координатор: как это работает без вызовов API

В сервисе нет прямых вызовов API нейросети. Ни одной строки fetch('https://api.anthropic.com/...'). Ни одного @anthropic-ai/sdk в зависимостях. Ни одного API-ключа в .env.

Как тогда работает AI?

На сервере лежит файл service_instructions.md — документ на 50+ КБ с полным протоколом: как оценивать визиты, строить планы, искать противоречия, в каком формате записывать результаты. Это — промпт для Claude, но структурированный и детализированный.

Работает по двум механизмам:

  1. Очередь запросов: в базе есть таблица ai_requests. Когда я нажимаю «Запросить AI-анализ» на любой сущности, туда добавляется запись со статусом pending.
  2. Единая точка контекста: эндпоинт GET /api/patient-context. Он возвращает ВСЁ, что знает база: диагнозы, препараты, анализы, визиты, ошибки, план, историю изменений. Один JSON на 200–500 КБ.

Цикл обработки:

  1. Загружаю новый документ
  2. Открываю Claude Code и говорю: «Посмотри инструкцию, есть новый документ»
  3. Claude читает service_instructions.md, делает GET /api/patient-context, видит новый документ и очередь ai_requests
  4. Анализирует, сверяет с данными, ищет противоречия и пропущенные обследования
  5. Пишет результаты напрямую в базу: ai_assessment, новые ошибки, обновления плана
  6. Помечает запросы как completed

Визуально это выглядит как полный цикл: от загрузки документа до записи результатов в базу.

Это работает лучше, чем прямые API-вызовы. У Claude в Claude Code есть инструменты: чтение файлов, запуск SQL, HTTP-запросы. Он сам перерендерит PDF в высоком разрешении, если не прочитал показатель, сам сверит с оригиналом.

Есть кнопка «Запросить AI-анализ» под любой сущностью. Нажимаешь — запрос в очереди. Нейросеть при следующем обновлении видит, что нужно проанализировать, без лишних объяснений. Та же логика с комментариями: можно задать вопрос под документом и получить ответ с учётом контекста.

Минус: это не автоматика. Мне нужно вручную открыть Claude Code и запустить анализ. Примерно раз в неделю. Можно было автоматизировать через хук на загрузку, но пока мне спокойнее контролировать процесс. Новые данные появляются не каждый день.

Сколько это стоит

На примере карты сына:

  • service_instructions.md — 51 КБ → ~17 000 токенов
  • patient-context — 188 КБ → ~63 000 токенов
  • Итого на вход: ~80 000 токенов

На выходе Claude генерирует 5–10 тыс. токенов: оценки, новые записи, правки.

По ценам OpenRouter (Claude Opus 4.6):

  • Вход: 80K токенов × $0.005 = $0.40
  • Выход: 8K токенов × $0.025 = $0.20
  • Итого: ~$0.60 за полный анализ всей медкарты

Новые документы — 2–4 раза в месяц. Через API это обошлось бы в $1.5–2.5 в месяц.

Я использую подписку Claude Max за $100/мес, но не ради сервиса — он просто едет в том же потоке. Claude — мой основной инструмент для кода, текстов, анализа.

Нейросеть ошибается

Однажды при обработке лабораторного отчёта Claude неправильно прочитал значение в PDF: число из соседней строки «перескочило». В базу попало критическое отклонение, которого не было. Нейросеть построила на этом аналитику, завела ошибку, добавила пункт в план. Я заметил при проверке, попросил перепроверить — Claude сам нашёл расхождение и исправил всё.

После этого я добавил в инструкцию обязательную двухэтапную проверку для документов с числами: первый проход в стандартном разрешении, второй — с перерендером PDF в 400–500 DPI и построчной сверкой. Только при полном совпадении данные идут в базу.

Вывод: всегда проверяйте данные за нейросетью, особенно когда речь о здоровье. Но прогресс идёт быстро — с каждым обновлением таких ошибок будет меньше.

Автоматическая история: 40 триггеров и ноль кода для логирования

Логирование изменений работает без единой строки кода в роутах. Никаких await log('medication_added', ...). История строится через триггеры SQLite.

40 триггеров на 13 таблицах (insert/update/delete). Любая правка — из фронтенда, админки или консоли — автоматически записывается в audit_log как старый и новый JSON. Обойти нельзя — триггер на уровне базы.

Модуль changelog.js превращает сырые логи в читаемые записи:

  • Если статус ошибки изменился с open на resolved — пишет «Решена ошибка: СОЭ 24, не учли»
  • Правки за 60 секунд группируются в одну запись
  • Группировка по дням: Сегодня / Вчера / 3 дня назад / 2026-04-05

На фронте — страница «История». Создана, чтобы видеть, что изменилось после обработки документа: какие напоминания добавились, какие выводы переписаны, какие ошибки закрыты. Изменения от AI отмечаются отдельно, можно откатить, если что-то пошло не так.

Стек и деплой

Сервис на VPS: nginx + TLS снаружи, Node.js + better-sqlite3 внутри, systemd для автозапуска.

Фронт: React 19 + TypeScript strict + Vite, роутинг — React Router 7, данные — TanStack Query, формы — react-hook-form + zod, граф — Cytoscape, анимации — Motion, иконки — @tabler/icons-react, PWA — vite-plugin-pwa + Workbox.

Бэкенд: Express + better-sqlite3, биометрия — @simplewebauthn/server.

Все SQL-запросы написаны в стиле PostgreSQL: pool.query('SELECT * FROM patients WHERE id = $1', [id]). В db.js — обёртка, которая транслирует $1 в ?, эмулирует RETURNING, заменяет NOW() на datetime('now'). Формально SQLite, но переключиться на PostgreSQL можно за полчаса.

Безопасность. Это стоит обсудить отдельно

Медицинские данные ребёнка — самое чувствительное. Я не хочу, чтобы их кто-то увидел, и не хочу потерять базу. Безопасность — приоритет с первого дня. Защита многослойная: нужно пробить несколько независимых барьеров.

Сеть и TLS

На VPS — UFW с default-deny: открыты только SSH (22), ACME (80), HTTPS (443). Fail2ban банит IP при попытках взлома: 3 неудачные попытки за 10 минут → час бана, срок растёт при повторах. SSH принимает только ключи, паролей нет — брутфорс невозможен.

TLS 1.2 и 1.3, старые протоколы отключены. Сертификат Let’s Encrypt с автопродлением. Заголовки безопасности: HSTS на 2 года, CSP (запрет сторонних скриптов), X-Frame-Options: DENY, nosniff, Referrer-Policy, Permissions-Policy (отключены камера, микрофон, GPS и др.).

Три способа войти

Биометрия (Face ID / Touch ID / Windows Hello). Через WebAuthn — тот же стандарт, что у банков. Ключ хранится в Secure Enclave, сервер видит только публичный ключ. Подпись возможна только при физической разблокировке устройства.

PIN + контрольное слово. PIN — 4–10 цифр. Хранится как scrypt-хеш. Сравнение — constant-time, чтобы исключить угадывание по времени. Контрольное слово запрашивается только при входе с нового устройства. Устройство определяется по UUID в localStorage. После входа — уведомление в Telegram с IP, браузером и временем. Если зашёл не я — узнаю мгновенно.

Просто PIN. Если устройство уже доверенное, а биометрия не настроена.

Защита от брутфорса

Реализован экспоненциальный таймаут после трёх неудачных попыток: 3-я — 1 минута, 4-я — 2, 5-я — 4, дальше удваивается до 24 часов. С 14-й попытки — блокировка на сутки. Перебрать миллион комбинаций невозможно.

Счётчик в базе — очисткой кеша не обойти. Лимит: 20 попыток входа за 15 минут на IP, 1000 запросов на всё остальное. Fail2ban на уровне файрвола. Сессии живут 14 дней, при смене PIN — мгновенно инвалидируются.

Серверный бэкенд и данные

Сервис работает не от root. Есть отдельный системный пользователь с минимальными правами. Даже при уязвимости в коде — атакующий получит только доступ к медкарте, но не сможет лезть в другие сервисы.

systemd-unit настроен с изоляцией: NoNewPrivileges, ProtectSystem=strict, ProtectHome, PrivateTmp и др. Файлы базы и конфигов — права 600, видны только владельцу.

Поиск — через FTS5 (встроенный полнотекстовый индекс SQLite). Это исключает SQL-инъекции: пользовательский ввод не склеивается вручную.

Загрузка документов проверяется дважды: MIME-тип и расширение. Разрешены: PDF, DOC/DOCX, XLS/XLSX, JPG, PNG, WebP, HEIC. SVG запрещён — может содержать JavaScript. Каждому файлу — UUID-имя. При скачивании — проверка пути, защита от path traversal.

Бэкапы по правилу 3-2-1

Три копии, две среды, одна оффсайт.

Копия 1: горячие снимки каждые 6 часов через нативный .backup API SQLite. Хранятся последние 14. Защита от логических ошибок: случайное удаление, ошибка AI.

Копия 2: полный ежедневный архив в 02:00. База + все медиа. Упаковывается в tar, шифруется AES-256-CBC с PBKDF2 (100 000 итераций, стандарт OWASP). Без ключа — бессмысленный набор байтов. Хранятся 14 последних.

Копия 3: сразу после создания архив отправляется в Telegram через бота. Физически лежит в облаке Telegram — отдельно от VPS, GitHub, ноутбука. История в Telegram — вечная, скачать можно с любого устройства. Файл зашифрован, ключ — в менеджере паролей.

Код — на GitHub (private repo), данные — на VPS с двумя уровнями бэкапов, зашифрованная копия — в Telegram. Даже если VPS сгорит — код клонируется, данные скачиваются, расшифровываются, сервис поднимается за час.

Аудит и уведомления

Все изменения — в audit_log. auth_log — все события входа, выхода, смены PIN, биометрии, отвязки устройства: с IP, user-agent, временем.

В Telegram — мгновенные уведомления:

  • Новое устройство вошло
  • Настроена биометрия
  • Сменён PIN
  • Сервис перезапущен
  • Ежедневный бэкап создан или упал

Так я узнаю о подозрительной активности в ту же секунду.

Честно о слабых местах

Идеальной безопасности нет:

  • VPS не выделенный хост: виртуалка на общем железе. Теоретически возможна утечка через соседний контейнер. Минимизирую изоляцией, но физическая изоляция — другой бюджет. Для семьи — риск приемлем, для тысячи пациентов — нет.
  • База на диске не зашифрована: файл в открытом виде. При root-доступе — можно прочитать. Защита — через права 600 и непривилегированного пользователя. SQLCipher ломает FTS5, критичный для AI. Смягчение: ежедневный бэкап в Telegram — зашифрован.
  • Сессионные токены в localStorage: теоретически уязвимы к XSS. Снижаю риск через CSP, запрет SVG, валидацию. Смягчение: короткий срок жизни, уведомления, возможность разлогинить все устройства.

Для семейного инструмента — разумный уровень защиты с чёткими компромиссами.

Что AI реально нашёл

Без примеров — это теория. Вот три реальных кейса.

Пропущенные базовые обследования

Claude проанализировал историю сына за пять лет и выявил, что ряд базовых анализов не назначались:

  • ТТГ — не проверялся больше трёх лет, хотя при диагнозе это стандарт
  • МРТ головного мозга — ни разу за пять лет, хотя может показать структурные изменения
  • Ферритин — ни разу, хотя скрытый дефицит железа у таких детей — частое явление и коррекция помогает

Каждый специалист не обязан назначать всё. Но когда видишь всю историю — пробелы очевидны.

Три невролога, три схемы

За полтора года — три невролога, три разные схемы лечения:

  • Первый: Когитум, Кортексин, Глицин
  • Второй: Винпоцетин, Аминолон
  • Третий: Ницерголин, Глиатилин, Нейробион

Только один уточнил, что ребёнок уже принимает.

Claude построил хронологию и задал вопрос, который я не задавал: «Какая схема работала? Почему меняли? Где записан ответ?» А нигде. Система не говорит «кто прав». Она показывает факты и предлагает задать эти вопросы врачу.

И та самая история: при загрузке расшифровки приёма Claude отметил: остеопатия — альтернативная медицина, рекомендация строить лечение на ней — не соответствует доказательному подходу. Без оценки врача — просто факт.

Мне именно это и нужно: не «хороший или плохой», а «соответствует ли подход доказательной медицине». Решение — моё.

Я добавил себя

Сын был первым пациентом. Потом я добавил себя. Мне 38, и я никогда толком не разбирался со здоровьем. Ходил на диспансеризацию, получал лист — «всё норм» — и забывал.

Попросил Claude составить базовый чекап для мужчины 38 лет с сидячим образом жизни. Он подобрал 35 пунктов:

  • Анализы: ОАК, биохимия, ТТГ, глюкоза, гомоцистеин, онкомаркеры, тестостерон, витамин D
  • Инструментальные: флюорография, ЭКГ, УЗИ брюшной полости, щитовидной, почек
  • Врачи: терапевт, офтальмолог, стоматолог, уролог, дерматолог (с дерматоскопией), ревматолог

Сумма — больше 35 тысяч рублей. Но выяснилось, что всё покрывается корпоративным ДМС. Полный чекап — бесплатно. Начну на следующей неделе.

Это главное. Не «AI найдёт ошибки врачей», а «AI поможет не пройти мимо того, что ты мог бы сделать для себя».

Честный взгляд на то, что я сделал

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

Garbage in, garbage out. Если данные кривые — анализ будет кривым. Двухэтапная проверка помогает, но не устраняет проблему.

Это не production-сервис. Это эксперимент. Я не знаю, чем он закончится. Может, через год напишу: «сервис изменил моё отношение к здоровью». А может — «забил через три месяца». Пока ощущение первое. Подождём.

Про расшифровки приёмов

Жена давно записывает все визиты на диктофон. Эти записи — золото: нейросеть получает не только выписку, но и полную расшифровку разговора — с нюансами, вопросами, рекомендациями.

Транскрибирую через NotebookLM от Google: загружаю аудио, получаю текст, вставляю в сервис. Whisper пока не использую — боюсь ошибок в терминологии и названиях препаратов на неидеальных записях. NotebookLM справляется лучше.

Открытый код и что дальше

Код планирую выложить на GitHub в ближайшие недели. Идея «своя база + AI-координатор через инструкцию и patient-context» может быть полезна как шаблон — не только для медицины. Допилю и выложу, ссылку — в Telegram.

Я скорее выберу врача, который использует нейросеть вместе со своим опытом, чем того, кто игнорирует прогресс.

Если у вас был похожий опыт — собрали медданные, пробовали AI — пишите в комментарии. Интересно увидеть другие примеры.

Жена после знакомства с сервисом написала три сообщения:

— Как интересно всё, конечно
— Не то слово как полезно
— Да конечно п* она умная

Для меня это — лучшая приёмка продукта. Если она сказала «полезно» — значит, сервис делает то, ради чего я его писал.

Читать оригинал