Как из FHIR-хранилища (анализы, выписки, PHR за годы) получить “текущее состояние здоровья” для LLM.
Pending refactor: страница пока в digest-стиле ([Н]/[Р] секции, длинные inline rationales). Concept-page в нашей wiki — thin layer-овый narrative со ссылками на entity/decision pages, не all-inclusive. Аналогичная ситуация с custom-domains-saas. Refactor — отдельный pass.
Сессия 18d2aef8 (Jan 30 → Feb 3) установила каркас: что уже есть в индустрии (IPS-стандарт), какими подходами решают retrieval, как фильтровать данные без feedback (cold start). Детали архитектуры под BloodGPT-специфику (Composition + CarePlan + Google Healthcare) — отдельные wiki-страницы (это нормально, wiki состоит из cross-linked страниц).
Факты [Н]
[Н1] IPS = формальный международный стандарт для “essential healthcare information extract”
International Patient Summary — ISO 27269 / HL7 FHIR IPS IG v2.0.0. Не “полная медкарта”, а минимальный набор клинически значимой инфы о пациенте (для emergency, cross-border, specialist handoff).
Три обязательные секции с LOINC-кодами:
- Allergies —
48765-2 - Medications —
10160-0 - Problems (active conditions) —
11450-4
Опциональные (~20): Procedures, Immunizations, Devices, Results (labs), Vital Signs, Past Illness History, Functional Status, Plan of Care и т.д.
Структурно — FHIR Bundle с Composition как корневым ресурсом, который группирует секции через section[].entry[] → FHIR references на Condition, MedicationStatement, AllergyIntolerance и пр.
Происхождение факта — RFC-019 §3.1 (пересказ Claude по HL7 IPS IG v2.0.0 + ISO 27269):
«IPS (International Patient Summary) — ISO 27269 / HL7 FHIR IPS IG v2.0.0 — “essential healthcare information extract”» (session digest 18d2aef8 [Н1])
[Н2] HAPI FHIR имеет нативную генерацию IPS через Patient/$summary
С версии HAPI 7.2 — built-in operation. Сервер сам собирает IPS Bundle по стандарту из ресурсов пациента, без самописной логики формирования Composition.
Для BloodGPT значит: если используем HAPI как FHIR backend, не надо писать свою agregation-логику для базового IPS. Можно строить кастом-фильтрацию поверх или вместо $summary.
Ильдар: «в хапи есть генерация ипс?» (session 18d2aef8, 2026-01-30)
[Н3] emptyReason — FHIR-способ различать “нет данных” и “не спросили”
Для обязательных IPS-секций, когда данных нет, FHIR требует явной причины пустоты:
nilknown— известно, что у пациента этого нет (“no known allergies”)unavailable— не спросили / не выяснили
Клинически критично: “no known allergies” ≠ “we didn’t ask”. Для medical-LLM это значит нельзя просто опустить пустую секцию в промпте — надо передавать reason.
Источник — FHIR R4 spec (AllergyIntolerance.code nil flavor). RFC-019 это не canonical источник — это LLM-эксперимент Ильдара (см. memory project_bgloodgpt_specs_decisions_llm_summaries), используется как secondary reference, не source-of-truth. Также — у нас в проекте этот pattern (emptyReason) пока не реализован в коде.
[Н4] Temporal relevance имеет research-обоснованные half-life значения
Stanford research (PMC5459355) — медицинские данные имеют “период полураспада” релевантности ~4 месяца в среднем (с большим разбросом по типам).
Carry-over (отдельная page): эта тема — temporal decay в медицинских данных — заслуживает выделения. Аналогично carry-over в llm-safety-in-medicine про medical-knowledge benchmarks. Возможная page:
domain/medical-temporal-decay.mdили частьdomain/medical-research-references.md— что показывает Stanford research, как это влияет на наш scoring, какие альтернативные источники half-life. TBD.
Формула затухания:
decay = 0.5 ^ (age_months / half_life)
Разбивка по типам (из RFC-019 §3.3):
| Тип | Half-life | Lookback |
|---|---|---|
| AllergyIntolerance | ∞ (не затухают) | ∞ |
| Chronic Condition | 48 мес | ∞ |
| Acute Condition | 12 мес | 365 дней |
| Lab (Observation) | 4 мес | 30 дней |
| Vitals | 0.5 мес | 72 часа |
Итоговая scoring-формула в RFC-019: score = base × decay × context × severity.
[Н5] Prompt engineering формат влияет на точность FHIR-операций
Vanderbilt Dec 2025 study (найдено на замену устаревшей GPT-3.5 работе):
- Claude 85% accuracy на JSON/YAML представлении FHIR-ресурсов
- TOON format (табличный) экономит 30-60% токенов против JSON
- Gemini и GPT-4o включены в compare, результаты сопоставимы
Предыстория — Ильдар сам принёс arXiv:2411.10541 (GPT-3.5 вариативность до 40% от формата), пометил как устаревшую (GPT-3.5 эра уже не релевантна для нашего текущего LLM-stack):
Ильдар: «Важное открытие: https://arxiv.org/html/2411.10541v1 показало, что GPT-3.5 производительность варьируется до 40% в зависимости от формата промпта. устаревшее укажи. найти бы что-то за конец 2025» (session 18d2aef8, 2026-01-31)
[Н6] Industry-паттерн: pre-visit summary готовится ДО приёма, не в момент запроса
Abridge, Nabla, Ambience — все используют один и тот же pattern:
- Summary генерируется заранее (batch / overnight), когда врач ещё не у пациента
- Агрессивная компрессия (target: one-pager)
- Linked evidence — каждое утверждение в summary кликабельно, ведёт на конкретный FHIR ресурс / документ-источник. Особенно у Abridge — explicit доверительный механизм для врачей.
Детальные разборы в RFC-019 §2 (Abridge Contextual Reasoning Engine, Nabla pre-visit, Ambience Patient Recap nightly batch, Recursive Summarization research pattern).
[Н7] IPS — это база, а не потолок
(Важная идея — confirmed Ильдаром.)
Концепт, сформулированный Ильдаром в середине сессии: IPS даёт минимальный общий знаменатель для всех врачей. Поверх него каждая специализация дозапрашивает своё (endocrinologist → HbA1c trends; cardiologist → ECG history). Это легитимизирует two-layer модель: static IPS baseline + dynamic per-specialty retrieval.
Ильдар: «а мы же в итоге вроде ушли от ИПС. сделали шаг вперёд какой-то, да что ИПС. это такая база. но мы ещё можем учесть более сложную логику» (session 18d2aef8, 2026-02-01)
Ильдар: «если мы хотим представить что-то больше, чем ипс — то, что не только минимальное, но какие-то ещё дополнительные вещи… для каждого врача как свои. в этом идея, что ипс — это одинаково для всех врачей. потом дополнительно каждый врач может запрос[ить]» (session 18d2aef8, 2026-02-03)
Решения [Р]
Note: этот раздел структурно похож на digest (списки [Р1-Р4] с alternatives). В отрефактoренной concept-page будет thin layer со ссылками на atomic decision-pages в
decisions/. Сейчас alternative pattern — оставлено как-есть до refactor.
[Р1] Tool Calling (+ опционально MCP) над RAG для retrieval структурированных FHIR данных
Рассмотренные варианты:
- RAG (embeddings FHIR-ресурсов) — семантический поиск по тексту ресурса. Проблема: разрушает structural связи (
clinicalStatus=active,code.system=LOINC), embeddings не чувствительны к типу ресурса и ref-графу. - Tool Calling — LLM вызывает чёткие функции:
get_active_conditions(patient_id),get_lab_results(patient_id, loinc_codes, date_range). За кулисами — FHIR search API, то есть нативный способ доступа. - MCP (Model Context Protocol) — обёртка над tool-endpoints, Anthropic-стандарт для стандартизации LLM↔systems интерфейсов.
Выбор: Tool Calling основной, MCP опционально как transport-layer.
Причина: FHIR данные структурированы (ресурс-тип + поля + references). Семантический поиск embeddings-ом режет именно то, что FHIR уникально предоставляет — structured queryability. RAG остаётся уместен для нестандартных документов (свободный текст выписок, OCR PDF), но не для structured FHIR.
Ильдар: «раг как будто уместно, а вот интеграция не очень» (session 18d2aef8, 2026-01-30)
Ильдар: «а если погуглить подходы, которые сейчас реализуются вместо рага? я имею в виду, что агенты и агенты для кода стали больше работать с помощью вызовов» (session 18d2aef8, 2026-01-31)
Детали: RFC-019 §4.1.
[Р2] Cold Start фильтрация — standards-based, не feedback-driven
Open question (выделено): “cold start” — сложная тема сама по себе. Сейчас написан standards-based подход (использовать external research half-life / mapping LOINC). Альтернатива — feedback-driven pipeline который обучается на реальных данных у нас (доходит до validation, sees что врачи кликают / approve, постепенно adapts). Не обязательно идти по standards-based — может в будущем свой pipeline сделать. Это не финализированный выбор, направление worth выносить в отдельную concept-page или decision (TBD:
decisions/cold-start-strategy.md).
Задача: как построить Patient Summary до того, как у нас есть feedback / ML-training data.
Рассмотренные источники весов:
- Expert-driven (опрос врачей) — долго, дорого на cold start
- Data-driven (обучение на больших EHR) — нет датасета
- Standards-based — IPS required sections + Stanford half-life + AHRQ chief-complaint mapping + FHIR
clinicalStatus - LLM-based (LLM сам оценивает важность) — дорого, недетерминированно
- Hybrid — standards сейчас, feedback позже когда накопится
Выбор: Standards-based на холодном старте. Feedback-driven calibration — будущая итерация.
Причина: research-based defaults (Stanford, AHRQ, IPS) дают воспроизводимый baseline, не зависят от продакшн-данных, которых у нас нет. Их формальность упрощает позже regulatory / validation story (см. страницу domain/llm-safety-in-medicine.md — process validation pre-deployment).
Детали: RFC-019 §3.3, §3.4, §3.5.
Static vs Dynamic — один спектр правил, не два режима
Static cold-start rules и dynamic LLM retrieval — это один спектр, не два изолированных режима. Оба слоя — правила выбора релевантного из FHIR Bundle; различие только в trigger-е: precomputed batch (static) vs on-demand interactive (dynamic). Архитектурно — IPS-like baseline поверх которого LLM может задавать дополнительные queries, не отдельный retrieval-pipeline сбоку.
[Р4] RFC-019 структурирован: Industry → Concept → Implementation
RFC после reorganisation: (1) Problem → (2) Industry examples (Abridge, Nabla, Ambience, Recursive Summarization) → (3) Our Approach (scoring model) → (4) Implementation → (5) FHIR examples → (6) Questions → (7) Next Steps → (8) References. Industry наверх — для контекста “как вообще решают”.
Ильдар: «может быть примеры из индустрии поместить вверх?» (session 18d2aef8, 2026-02-01)
Следствия для BloodGPT
(Черновик — не согласовано с Ильдаром.)
-
Composition как root-ресурс для BloodGPT summary — напрямую mapping в IPS Bundle. Не надо изобретать свой контейнер; использование IPS-compatible формата даёт: (a) cross-vendor interoperability, (b) понятную для клиницистов семантику, (c) путь к HAPI
$summaryесли backend поменяем. Это пересекается с более поздним решением “Composition + CarePlan” (Feb 13+), но ingest той сессии — отдельная страница. -
Tool Calling как primary retrieval — архитектурный якорь. Интерфейс между pipeline-и (recognize, interpretation, enrichments) и FHIR store должен быть в терминах “типизированных функций”, не “общего SQL-подобного запроса к бандлу”. Это упрощает auditability (какая функция что вернула → цитируется в LLM-ответе).
-
Cold start scoring должен быть zero-PII reproducible. Если параметры декайа и базовых скоров вынесены в config / registry (a не закодированы), это позволяет: independent review клиницистами, versioning scoring policy, trace-back почему ресурс попал / не попал в summary. Для regulatory (Purolea-precedent) это формальная опора accountability.
-
Linked evidence как возможный roadmap-этап. Abridge делает click → source. Для BloodGPT — если каждый утверждение в summary несёт FHIR-reference (DiagnosticReport/…, Observation/…), это одновременно: (a) trust mechanism для врачей, (b) compliance evidence (как AI пришёл к выводу), (c) debugging — видно когда AI fabricates. Не приоритет на сейчас, но архитектурно стоит закладывать.
-
“IPS как база” = ready-made контракт с partners. Medical-grade partnerships (labs, клиники) часто уже говорят на IPS. Если наш summary IPS-compatible, мы упрощаем onboarding. Если кастом — каждый integration заново.
-
Prompt engineering format — testable, not implicit. Vanderbilt research даёт reproducible выбор (Claude + JSON/YAML). Но это research; под нашу задачу (интерпретация лабораторных) нужен собственный replication: prod cases, наши prompts, наши metrics. Иначе полагаемся на paper, которого не проверяли под себя.
Actuality биомаркеров
Биомаркеры в summary разделяются на два списка по актуальности — актуальные (последнее значение на дату недавнего среза) и out-of-date (не сдавались давно). Счётчики типа «130 нормальных» в summary не показываются: они не отражают текущее состояние здоровья и создают ложное ощущение благополучия.
Трендовые показатели по определению не подпадают под actuality split — их scope исторический ряд, не точка.
Actuality — это UX-слой поверх temporal-decay scoring (см. half-life выше): continuous decay раскладывается в два бинарных bucket’а для отображения.
TTL-механизм:
- TTL per panel — клетки крови, иммунология, гормоны имеют разный refresh-rate, общее правило не подходит.
- Anchor — дата самого нового биомаркера пациента, не current date. Корректно работает с историческими загрузками: если пациент backfill’ит старые результаты, «сейчас» для actuality = его последняя сдача.
- Out-of-date биомаркер не передаётся в retrieval-контекст, но подсвечивается в UI с пометкой. Параметр не исчезает с экрана.
Подробности и open вопросы — в biomarker-actuality-thresholds.
Остальное:
- Что показывать врачу vs пациенту в summary различается (врачу нужна новизна / длительность / клинические акценты). Конкретный набор полей врачебной версии не определён.
Реализация: PatientSummaryAgent на Mastra (BG-1049)
В session 3d5c475c (Mar 23-25 2026) RFC-019 retrieval logic портирована в Mastra-агента (patientSummaryAgent). Это первая working реализация концепта на этой странице.
4-фазный agent-loop:
Phase 1 — basic collection (always):
├─ patient demographics
├─ active conditions
├─ allergies
├─ medications
└─ immunizations
Phase 2 — condition-driven retrieval:
├─ diabetes detected → HbA1c history, glucose, eGFR
├─ hypertension → blood pressure series
├─ CKD → eGFR, creatinine
├─ anemia → hemoglobin
├─ hyperlipidemia → cholesterol panel
├─ female 15-49 → getPregnancyStatus
├─ age >=65 → getFunctionalStatus
└─ age <18 → growth observations
Phase 3 — full sweep:
├─ resolved conditions, procedures
├─ family history, vitals
├─ diagnostic reports, devices
├─ care plans, encounters
Phase 4 — finishSummary tool exit
6/6 test scenarios passed на SmartHealthIT public sandbox с разными patient profiles (chronic, allergies, female-fertile, elderly, pediatric, minimal). Test runner — direct mode через agent.generate() + tsx --env-file=.env. Подробности pattern и debugging — mastra.
finishSummary tool сохранён как structured contract (не для exit-control — Mastra сама останавливается). Гарантирует что summary в toolCall.args.summary (не parse-via-result.text). Поверх — finishSummaryStructured со Zod-схемой повторяющий Python JSON output (для DB persist / UI sections / evals comparison).
См. agent-vs-workflow про agent-for-retrieval pattern (третий тип после decomposed-for-structured-task и agent-for-conversation).
Production deployment не зафиксирован — вызывается через Studio / direct mode test runner. Подключение как Inngest function или API-endpoint — open.
Открытые вопросы [О]
[О1] Валидация внешних клинических спецификаций против RFC-019
В конце сессии Ильдар загрузил 3 документа из Downloads (part1_intro_sections1-7_FORMATTED.md, part2_sections8-12_FORMATTED.md, part3_special_cases_rules_FORMATTED.md, ~1.5K строк). Claude начал анализ: это клиническая спецификация содержания (rules по organ system), RFC-019 — техническая модель фильтрации. Полный cross-check не завершён. Происхождение документов (чьи, какая версия, какой оригинал) — неясно; файлы в Downloads и могут быть потеряны.
Ильдар: «можешь провалидировать то что написано в эти документах в сравнении с тем, что мы записали в наш РФЦ» (session 18d2aef8, 2026-02-02)
Ильдар: «то есть у нас есть типы правил для фильтрации/отбора. а в документах конкретные правила?» (session 18d2aef8, 2026-02-02)
[О2] Linked Evidence — нужна ли функция “кликни на утверждение → покажи источник”
Помечено в RFC-019 как discussion question (добавлено по просьбе Ильдара). Abridge это делает, но удорожает pipeline. Трейд-офф не разрешён.
[О3] Evaluation metrics для medical summarization
Упомянуто как possible next step, не раскрыто в сессии. Конкретный вопрос: какой метрикой меряем качество summary (coverage, factuality, clinical-utility)? Пересекается со страницей domain/llm-safety-in-medicine.md — NOHARM-стиль evaluation (Safety, Completeness, Restraint) применим, но требует адаптации под summary, а не под clinical-decision.
[О4] Privacy / consent considerations
Упомянуто, не раскрыто. Отдельная тема, вероятно требует самостоятельной concept-страницы.
[О5] Production deployment PatientSummaryAgent
В session 3d5c475c агент реализован и протестирован, но не deployed как production endpoint. Варианты: Inngest function (вписывается в существующий orchestrator pipeline), API endpoint (через b2b-api), или часть snapshot-generation pipeline (см. health-report-vision — PatientSummaryAgent как retrieval-stage перед AI-generation).
[О6] Langfuse tracing project не создан
Mastra поддерживает Langfuse out-of-box. Сейчас logging через manual parse result.steps[].toolCalls/toolResults. См. mastra.
[С1] Откуда конкретные значения severity/weights в scoring formula
Standards-based — ответ на “где их искать” (Stanford half-life, AHRQ mapping, IPS config). Но конкретное “почему severity=2.0 для аллергии, а не 1.5” — не обоснованно в сессии. Это калибровочный параметр, который остаётся “expert judgement, to be validated”.
Ильдар: «ты ответила на вопрос: как получить коды? я хотел понять, как получить под то, на сколько каждый из параметров влияет?» (session 18d2aef8, 2026-02-01)
Источники
Пересечения
domain/llm-safety-in-medicine.md— NOHARM 76.6% omissions + Purolea accountability. Summary-pipeline должен иметь coverage check и documented human review.- recognition-enrichment-hourglass — patient summary это финальный этап нижнего конуса (FHIR → enrichment → human-readable output)
- TBD: страница про Composition + CarePlan архитектуру под Google Healthcare API (source — session 871a7608 / aae4c1fd / c9560637, Feb 13-20). Конкретные design-решения (Device → Organization pivot, multi-tenant dataset-per-tenant) — туда, не сюда.
Источники (incremental)
- 2026-04-27 Daily + Sprint Planning (actuality split): https://github.com/Realai-plus/meeting-digests/blob/main/data/digest/2026/04/2026-04-27T08%3A00%3A00.000Z_Daily_%2B_Sprint_Review%26Planning_01KPX39F5EMF092HA0PGKSX1FV.md
- 2026-04-27 Health status-centric юзер флоу (TTL per panel + anchor + retrieval exclusion + UI highlight, [Р3+Р4]): https://github.com/Realai-plus/meeting-digests/blob/main/data/digest/2026/04/2026-04-27T17%3A00%3A00.000Z_Health_status-centric_%D1%8E%D0%B7%D0%B5%D1%80_%D1%84%D0%BB%D0%BE%D1%83_01KQ7WPNNMNBT3K8NDZQXM2321.md
Сноски
-
Сессия
ildar/18d2aef8, 2026-01-30 — ad63-4563-b3a1-9994c30a08ae. ↩ -
HL7 FHIR IPS IG v2.0.0:, accessed 2026-05-17, http://hl7.org/fhir/uv/ips/ — Composition structure, required sections, LOINC codes). ↩
-
ISO 27269 (IPS):, accessed 2026-05-17, https://www.iso.org/standard/79491.html. ↩
-
HAPI FHIR
$summaryoperation:, accessed 2026-05-17, https://hapifhir.io/hapi-fhir/docs/server_plain/ips.html — since v7.2). ↩ -
arXiv:2411.10541, accessed 2026-05-17, https://arxiv.org/html/2411.10541v1 — помечен Ильдаром как устаревший GPT-3.5 исследование). ↩
-
Abridge Contextual Reasoning Engine:, accessed 2026-05-17, https://www.abridge.com/blog/contextual-reasoning-engine-video. ↩