Одна из ключевых частей продукта BloodGPT — способность превратить сырой вход от лаборатории (название теста + единицы + значение + контекст пациента) в структурированный результат: LOINC-код, trending-группа, клинические связи, референсный диапазон, сигналы актуальности. В процессе работы разные части системы накапливают знание о биомаркерах: коды, связи, диапазоны, ручные правки куратора.

Поскольку у этой способности нет единого pipeline’а или ядра, а есть распределённый набор артефактов и процессов, мы условно называем её Biomarker Knowledge Layer (BKL). «Слой» — рабочее слово; страница описывает что туда входит и как оно растёт.

Это не одно хранилище и не один конвейер — это слой, собранный из нескольких модулей под общим продуктовым взглядом. Растёт нарастающим итогом: каждое подтверждённое соответствие «название → LOINC» = постоянный актив; каждая запись в biomarker graph = клиническое знание с обоснованием и цитатами; каждая ручная правка = коррекция поверх автоматического pipeline’а. Это не кэш во время выполнения — соответствие «Глюкоза → 2345-7» это детерминированный факт, не временное состояние (см. dictionary-first-paradigm).

Все модули описывают один и тот же объект — биомаркер (biomarker) с разных сторон.

Состав

МодульЧто хранитГде живётИсточник
trending-groupsLOINC-коды одного analyte → один trending_group_id (синонимия кодификации)CSV в git + генераторРелиз LOINC + наш Union-Find augment
Decision Dictionary (dm:{hash} Redis)Подтверждённые соответствия «сырое название → LOINC»Redis (постоянный, TTL убран)LOINC harmonization pipeline + warmup endpoint
Override-таблицаРучные коррекции поверх автоматических соответствийPostgres + админ-UI прототипКуратор (medical advisor)
biomarker-graphКлинические связи биомаркера (ego-сети) с обоснованиями и цитатамиJSON в git (13K строк, 113 биомаркеров)Артур + Катя, вручную
loinc-lab-codes.json (~60МБ)Производный LOINC-индекс для быстрого lookup’аНе в git (см. large-data-files-storage)Релиз LOINC
compound-keywords.json (~2.7МБ)Ключевые слова для расширения токенов при поиске LOINCTBDРелиз LOINC + наш генератор
normalization-dictionary.json (~9МБ)Старый словарь нормализацииTBDdictionary-creation
Custom reference ranges (BG-925, в плане)Лабораторные ValueSet’ы поверх LOINCTBD (FHIR ObservationDefinition? Postgres?)Лаборатория / админ
Малые таблицы: панели / specimen-families / measurement-type mapsКлинические группировки, нормализация specimen system, классификация единицЗахардкожено в кодеDomain-знание

Сам релиз LOINC — внешний источник, не часть слоя; слой строится поверх него с дополнением и кураторской работой.

Два процесса — linking и enrichment

В слое накапливаются два параллельных типа знания, у каждого свой жизненный цикл.

Entity linking — сырая строка → сущность

Термин из NLP / information extraction: связывание входной строки с известной сущностью. У нас: «Глюкоза, ммоль/л, кровь» → биомаркер «Глюкоза», LOINC 2345-7, trending group LG.... Это вход в слой; до него raw-данные неструктурированы, после него — на ID-уровне их можно сшивать с уже известным.

Пополнение (по RFC-0251):

Новый вход (нет в слое)
    │
    ├─ Pipeline обрабатывает (LLM keywords → search → LLM selection)
    │
    ├─ Grade A → AUTO_ACCEPT → сразу в слой
    ├─ Grade B/C → MANUAL_REVIEW → в очередь куратору
    └─ REJECTED → не в слой (попробуем позже)

Верификация куратором (админ-UI):
    ├─ Подтвердить → в слой (verified)
    ├─ Исправить код → в слой (manual)
    └─ Подтвердить «нет соответствия» → в слой как явный verified-отказ

По мере работы доля запросов, попадающих в pipeline, стремится к нулю. Каждая новая лаборатория онбордится не «с нуля» — она потребляет уже накопленные варианты названий тестов; терминологии разных лабораторий накладываются.

Entity enrichment — сущность → богаче сущность

Когда биомаркер уже идентифицирован, продолжаем накапливать про него клиническое знание, чтобы downstream-задачи (интерпретация, follow-up, координация) работали эффективнее и меньше зависели от LLM в момент запроса. Это второй путь, по которому слой растёт.

Что наполняется:

  • Клинические связи в biomarker-graph — ego-сети (диагнозы, лекарства, преаналитические факторы) с обоснованием и цитатой guideline’а. Добавляются вручную medical advisor’ом.
  • Референсные диапазоны (reference-ranges, custom-reference-ranges в плане) — нормы для интерпретации. Сейчас LLM-generated per-test, целевое — централизованный каталог.
  • Сигналы актуальности (biomarker-actuality-thresholds) — когда значение становится out-of-date, какой панелью якорится.
  • Trending-группы (trending-groups) — синонимия LOINC-кодов: один analyte, несколько представлений (units / specimens / methods) → один тренд.
  • Override’ы и аннотации куратора — поправки, экспертные пометки, decisions «не использовать этот код».
  • Прошлые результаты пациента (не часть BKL — runtime-композиция, см. carry-over про Health Knowledge Layer внизу).

Чем богаче сущность, тем больше задач можно решать без LLM-вызова: lookup вместо генерации, deterministic join вместо fuzzy-матча, точная интерпретация вместо приблизительной.

Linking и enrichment независимы, но усиливают друг друга: enrichment без надёжного linking приклеивается «не к той» сущности; linking без enrichment даёт только сырой ID без полезных свойств.

Хранение и доставка — четыре фрагментарных страницы-решения

Грани вопроса «как хранить и распространять BKL» исторически разнесены по отдельным открытым страницам-решениям. На самом деле они про один и тот же продуктовый вопрос с разных сторон:

  • dictionary-first-paradigm (proposed) — постановка: кэш → постоянный управляемый словарь. Основная идея Ильдара; TTL убран.
  • biomarker-graph-storage (draft) — редактируемость: где хранить граф (admin-UI / Postgres / гибрид). Сейчас правки требуют PR + redeploy.
  • large-data-files-storage (draft, висит с f09d1111) — доставка: как привозить 60+9+2.7МБ JSON-словари в runtime (git-lfs / GCS download / Docker bake / regenerate on build).
  • override-storage-design (contested) — кураторский слой: отдельная override-таблица или единая с историей.

Объединять в одно мета-решение или решать каждое отдельно — см. «Открытые вопросы» ниже.

Прецеденты

  • RFC-025 «LOINC Mapping Dictionary»1 (февраль 2026) — первая формулировка идеи, но с узким охватом «только LOINC-маппинг». Здесь охват расширен на весь слой.
  • Бизнес-спецификация «Medical Knowledge Base»2 — снимок легаси-состояния .NET-стека. Сам же отмечает: «Medical KB — не единая база, а набор разрозненных источников». Полезен как инвентаризация накопленного.
  • FHIR Terminology Service — индустриальный стандарт со смежной функциональностью. Реализации (CSIRO Ontoserver, Apelon, Snowstorm, Termhub) продают именно накопленный curated content + сервис вокруг — параллель: наш BKL потенциально может стать продаваемым артефактом сам по себе.

Открытые вопросы

  • Мета-решение о консолидации. Четыре фрагментарных страницы-решения (dictionary-first-paradigm, biomarker-graph-storage, large-data-files-storage, override-storage-design) — оставить как есть и решать каждое отдельно, или объединить в одно архитектурное решение «как организуем BKL». За объединение: все они про одно и то же с разных сторон. Против: каждая содержит важную специфику и может разрешиться раньше остальных.
  • Охват vs Health Knowledge Layer. Текущее имя — Biomarker Knowledge Layer — точное по сегодняшнему охвату (биомаркер-центричный). Если в будущем добавятся независимые модули для диагнозов / лекарств / lifestyle-факторов (сейчас они в графе как соседи биомаркера, не самостоятельные сущности) — может понадобиться broader umbrella Health Knowledge Layer поверх. Вложенная модель вероятна: BKL = curated reference, HKL = сборка для пациента во время выполнения.
  • FHIR-совместимость API. Делать ли API FHIR-совместимым ($translate, $lookup, $expand endpoints). Не блокер сегодня, но когда появятся внешние потребители (b2b-партнёры через FHIR) — переезд дорогой.
  • Версионирование, происхождение, распространение. Индустриальные практики (семантические версии терминологии, delta-обновления, журнал изменений per запись) сейчас ad-hoc. Если BKL становится продуктом — нужны.
  • Дорожная карта к публичному продукту. Гипотеза или серьёзный план. Если серьёзный — лицензирование (ограничения LOINC; SNOMED licensing заблочено), модель монетизации, внешний API-контракт.
  • Обратная заливка. Как импортировать существующее (input_mapping в Postgres, ключи dm: в Redis, trending_groups.csv, biomarker_graph.json, override-таблица) в единую форму. Миграция — TBD.

Связано

Carry-over: имя «Biomarker Knowledge Layer» выбрано 2026-05-19 из перебора альтернатив (Health Knowledge Layer, Biomarker Catalog / Dictionary / Registry, Medical Knowledge Catalog, Healthcare Master Data, Medical Vocabulary Service, Medical Ontology). Промежуточная попытка technical/terminology-service.md (2026-05-18) удалена как преждевременная формулировка — «terminology service» уже́, BKL шире и включает клинический граф + диапазоны + сигналы актуальности. История обсуждения — в цепочке 08b544c5 (snapshot + digest).

Сноски

  1. RFC-025 «LOINC Mapping Dictionary», Ильдар, 2026-02-27 — первая формулировка dictionary-first подхода для LOINC-маппинга. https://github.com/Realai-plus/bloodgpt-specs/blob/main/RFC/025-loinc-terminology-service.md 2

  2. Бизнес-спецификация «6. Medical Knowledge Base» — снимок легаси-состояния .NET-стека: каталог биомаркеров (JSON + Postgres ParametersV2), панели (PanelConstants.cs), референсные диапазоны (LLM-generated per-test), keywords (CSV), LOINC (mapping в schema, не в production БД), управление через Internal API (ParameterMergeService, ParameterMappingService). https://github.com/Realai-plus/bloodgpt-specs/blob/main/business/06-medical-knowledge-base.md