Решение касается per-параметрного rich-output biomarker-analysis-pipeline (~8 полей: clinicalInterpretation, whatAdditionalDataWouldClarify, foundContext[], missingContext[], referenceContext[], additionalWorkup[], triage, citations[]). Compounding на decision: см. также foundcontext-fhir-mapping (sub-вопрос про конкретный slot для foundContext[]).

Контекст

Per-параметрный AI clinical assessment pipeline (см. biomarker-analysis-pipeline) на каждый параметр производит rich-output: prose-резюме (Writer), prose-«что доисследовать» (Personalizer), три массива evidence items с цитатами из guidelines (foundContext / missingContext / referenceContext), массив рекомендованных тестов (additionalWorkup), enum приоритета (triage), URLs guideline-источников (citations).

Конструкция должна:

  • Лечь в FHIR R4 (Google Healthcare API не принимает custom resourceTypes — см. zero-extensions-fhir).
  • Поддерживать update-on-rerun без накопления дубликатов и без ненужных перезаписей (если содержимое не поменялось — не платить write-resources). Стратегия conditional PUT через identifier — один из подходов, но не единственный; нюанс «когда обновлять» open.
  • Сохранять структуру evidence items (rationale, quotes, source, personalizedRationale — нельзя сливать в один блок prose, см. правило в принципы-fhir-моделирования-ai-контента).
  • Поддаваться audit trail в смысле regulatory traceability (включая «glass box» подход FDA для AI-medical-devices — отдельная концептуализация TBD, см. open).

Внутри принятой [[zero-extensions-fhir]] стратегии (минимум custom extensions, максимум native FHIR) есть несколько open осей. Вопрос «всё в одном слоте vs spread» в основе своей про денормализацию vs нормализацию данных — общая тема обсуждается в fhir-modeling-ai-content.

Оси выбора

Три ортогональные оси:

  1. Host resource — какой FHIR ресурс owner’ит rich-output.
  2. Гранулярность CI — если выбрали ClinicalImpression: один CI на тест, или CI per параметр.
  3. Distribution — если выбрали CI: всё в одну custom extension / в один native slot / spread по semantic-correct native slots.

Ось 1 — host resource

КандидатПрименимостьПочему
fhir-clinical-impressionосновной кандидатspec-семантика «AI/clinician’s view of patient situation» совпадает с rich-output
fhir-compositionsecondaryсейчас контейнер для overview; section-based, расширяется под per-param но смешивает overview и per-param assessment
Pure Observation.note[]regressionгде parameterDetails живёт в V2; теряет structure (foundContext / additionalWorkup arrays)
Другой ресурсopenвозможно есть подходящий FHIR-ресурс, не рассмотренный — не settled

ClinicalImpression — leading кандидат.

Ось 2 — гранулярность CI

При выборе CI:

ВариантОписание
Per-testодин ClinicalImpression на весь тест, N параметров внутри одного CI как repeating extensions / sub-sections
Per-parameterодин ClinicalImpression на каждый Observation (биомаркер), focus → Observation/{biomarker}. Один тест → N CIs.

Ось 3 — distribution V2.5 fields в CI

При выборе CI, для всех 8 V2.5 полей надо решить куда они ложатся внутри ресурса:

ВариантОписание
One custom extensionвсё (~8 полей) внутри одной repeating bloodgpt-parameter-analysis extension. Native FHIR slots (summary, investigation, supportingInfo, note, finding, problem) пусты.
One native slot piled-inвсё ложится в один permissive native slot (например supportingInfo[] который принимает Reference(Any) и не имеет жёсткой семантики). Custom extensions — только для триажа/citations enum’ов.
Spread across nativesкаждое поле в semantic-correct native slot: clinicalInterpretation → summary, foundContext → investigation.item[], referenceContext → supportingInfo[], whatAdditionalDataWouldClarify / reasoning → note[], additionalWorkup → отдельный ServiceRequest(intent: proposal), custom extensions минимальны.

Конкретные комбинации, которые реально рассматриваются

Комбинация A — per-test + one custom extension

ClinicalImpression × 1
├── identifier = "{system}|{testId}"               (для conditional PUT)
├── meta.versionId
├── meta.security = [{ code: "AIAST" }]
├── status = "completed"
├── (native slots — пустые)
└── extension[] × N parameters
    └── url: "bloodgpt-parameter-analysis"
        ├── parameterName, loincCode, value, unit, refRange, interpretation, testDate, isHealthy
        ├── clinicalInterpretation        (valueString, Writer prose)
        ├── whatAdditionalDataWouldClarify (valueString, Personalizer prose)
        ├── foundContext                   (complex extension — items с {name, type, rationale, quotes, source, personalizedRationale, unmatched})
        ├── missingContext                 (complex)
        ├── referenceContext               (complex)
        ├── additionalWorkup               (complex)
        └── citations                      (complex — repeating valueUrl)

Свойства: один conditional PUT per тест; read pattern «1 CI → N extensions через свой parser»; внешний FHIR-клиент не видит structured данных; foundContext items — inline данные, не References на real Observation/Condition; partner-unfriendly; audit per-test через _history.

Комбинация B — per-parameter + spread across natives

ClinicalImpression × N (по одному на параметр)
├── focus → Observation/{biomarker}
├── identifier = "{system}|{testId}|{biomarker}"
├── effectiveDateTime, status
├── summary                                          ← clinicalInterpretation (prose)
├── investigation[].item[]                           ← foundContext[] type=observation (References to Observation)
├── problem[]                                        ← foundContext[] type=condition (References to Condition)
├── supportingInfo[]                                 ← referenceContext[] + foundContext[] type=medication (Reference(Any))
├── note[]
│   ├── { authorString: "writer", text }            ← clinicalInterpretation (если уже не в summary)
│   ├── { authorString: "personalizer", text }      ← whatAdditionalDataWouldClarify
│   └── { authorString: "missing-context", text }   ← missingContext[]
└── extension
    ├── bloodgpt-triage                              ← triage
    └── bloodgpt-citation*                           ← citations[]

<{recommended-tests resource} × M (reasonReference → CI)  ← additionalWorkup[]>

Provenance × 1 (target → все CI + SRs)

Куда конкретно идут «рекомендованные нами анализы» — отдельный sub-вопрос: ServiceRequest(intent: proposal) (типичный кандидат), или Task (если описывается как pending action, не lab order), или другой ресурс. Не settled — open ниже.

Свойства: granular linkage (focus → Observation, Provenance per CI); native FHIR-search работает (?_include=focus, GET /ServiceRequest?intent=proposal&...); partner-friendly; bundle multi-resource per rerun; conditional updates по identifier per CI; sub-вопрос куда foundContext[].type=condition/medication идёт пересекается closed list investigation.item — см. foundcontext-fhir-mapping.

Комбинация C — per-test + one native slot piled-in

Один CI на весь тест (per-test гранулярность как в A — не per-param), всё V2.5 ложится в native supportingInfo[] slot:

ClinicalImpression × 1
├── identifier = "{system}|{testId}"
├── meta.security = [{ code: "AIAST" }]
├── summary = <общий prose-резюме на тест>          (опционально)
├── supportingInfo[]                                 ← всё V2.5 ложится сюда как Reference(Any) или inline-by-extension
│   ├── { extension: bloodgpt-parameter-analysis (per param) }
│   └── ...
└── extension
    └── bloodgpt-citation*                           (если хочется триажа/citations отдельно)

Свойства: один resource как в A, но V2.5 кладётся в native supportingInfo[] slot (permissive Reference(Any)) — внешний FHIR-клиент видит «ресурс полный»; structured данные доступны через extension’ы внутри supportingInfo entries; нет distribution semantics (всё в одном слоте), но slot существует в spec; partner-неполноценный (нет References на реальные Observation/Condition), но «не пустой».

Связи между осями

Не все 6 комбинаций равно осмыслены. Per-test composability с distributed-natives (investigation.item[] как aggregate всех param Observations) теряет per-param структуру. Per-parameter с one-custom-extension тратит N writes без выигрыша интероп. Реальные кандидаты — A, B, C.

Open

  • Какой подход выбираем для prod cutover. Текущая implementation пишет вариант A; не commit’нуто как architectural decision.
  • Если B — как разрешается closed-list constraint на investigation.item[] (не принимает Condition/Medication). См. foundcontext-fhir-mapping.
  • В A и C: как партнёр-EHR (InterSystems и др.) парсит наши custom extensions — нужен published Profile, или договорённость в integration spec.
  • Как мигрировать между вариантами без потери versionId истории (если выбираем разные identifier patterns).
  • Composition + section-based маршрут: open параллельно — Composition.section[] уже используется для overview, можно расширить под per-param assessment вместо CI вообще.
  • Какой FHIR-ресурс owner’ит «рекомендованные доисследования» (additionalWorkup): ServiceRequest(intent: proposal) vs Task vs другой. ServiceRequest — типичный кандидат для lab order proposal, но если нюанс в “это AI-задача врачу для рассмотрения”, Task или другой может подойти лучше.
  • Когда переписывать CI на rerun: всегда conditional PUT vs только при изменении содержимого (диффом). Связано с cost’ом FHIR-write resources.
  • Audit trail / regulatory traceability — концептуализация на отдельной странице (TBD): включая FDA glass-box подход для AI-medical-devices, требования к тому что должно быть прослеживаемо.
  • DiagnosticReport rollup: conclusion + conclusionCode[] (max-severity triage) — слой над CI/CIs, общий для всех вариантов выше.

Сопутствующая документация требуется

Несколько концептуальных вопросов всплывают при принятии этого решения; каждый достоин отдельной страницы (TBD):

  • Карта связей всех FHIR-ресурсов в нашей системе — как Patient/Observation/DiagnosticReport/CI/Composition/CarePlan/ServiceRequest/Provenance связаны через References. Раньше это была наша relational schema; сейчас это spec-driven FHIR model — но вопрос «как у нас данные связаны между собой» тот же. Не задокументировано.
  • Regulatory audit trail / glass-box AI — концепт-страница про требования к tracability AI-выводов и FDA glass-box подход.

Связано

Источники

Источники: 1.

Сноски

  1. FHIR R4 ClinicalImpression, accessed 2026-05-17, https://hl7.org/fhir/R4/clinicalimpression.html.