Как использовать ChatGPT для кодинга по медицинским стандартам
Рассказываем о проекте по приемке и первичной обработке медицинских данных
Задача:
PMT online — сервис дистанционного медицинского обслуживания. Он предлагает своим клиентам медицинские приборы, которые отслеживают важные показатели здоровья и передают данные о них в общую систему. На их основании формируется отчет и отправляется врачу, который решает, нужно ли корректировать план лечения или принимать экстренные меры.
Причина:
Компания обратилась в Evrone, когда назрела необходимость обновлений и накопился критический объем технического долга. Основа системы приемки и обработки первичных данных — это сервисы на Ruby, собранные в единую систему на EventMachine. Так же есть еще несколько Rails приложений.
Обмен данными по стандарту
Медицина — специфическая отрасль, поэтому обмен данными в e-Health регулируется стандартом FHIR (Fast Healthcare Interoperability Resources). Он описывает форматы медицинских данных и обмен ими через API. Это нужно для того, чтобы даже устаревшие системы могли взаимодействовать между собой и доступ к данным был возможен с различных устройств.
Перед нами стояла задача создать API для обмена данными между своим сервисом и внешними медицинскими информационными системами (МИС), при этом реализуя стандарт HL7 FHIR. Обычно это МИС клиник, в которых врачи могут создавать программы дистанционного мониторинга и отслеживать состояние пациентов на основе отчетов и данных из сервиса PMT online.
Проблема в том, что стандарт предполагает довольно общие рекомендации, более детально реализация описана в профилях для разных регионов. Для России профиля нет, поэтому с одной стороны, мы были вольны выбирать решения, с другой же была цель обеспечить максимальную совместимость. Наша задача состояла в том, чтобы найти правильные объекты или атрибуты, которые бы позволили детально описать действие стандарта для нашей системы.
В этом нам очень помог Chat GPT-4. Эта версия openAI, как оказалось, отлично разбирается в реализации стандарта FHIR. Помимо «переваренной» документации в данных нейросети, по-видимому, есть и множество примеров реализаций, то есть опыта разработчиков. На основе всей этой информации получалось довольно эффективно генерировать примеры ресурсов с объяснением, почему стоит делать именно так. Это и помогло хорошо разобраться в стандарте и сэкономить много времени на его изучении.
Генерация отчетов
Главное, для чего нужны данные — это отчеты. Они генерируются автоматически на основании информации, полученной с медицинских приборов. Документ формируется за какой-то период, и должен отражать, какие показатели были в течении цикла, а также обращать внимание на потенциальные проблемы.
Изначально логика отчетов была довольно простой, но со временем становилась все сложнее. Приборы контролируют разные показатели и изменение значения каждого может сигнализировать о потенциальной проблеме. Разные типы отчетов опираются на разные показатели, а нам хотелось бы универсального решения, которое не перегружало бы и без того большую кодовую базу. В итоге мы смогли учесть множество условий для каждого значения и предложили максимально гибкое решение.
API для мобильных приложений
Чтобы пациентам было удобно следить за своим состоянием, существует множество мобильных приложений, из которых собирает данные наша система. Мы сделали универсальный API, через который разные приложения могут обмениваться данными.
Для этого мы активно использовали Grape. Это REST-подобная API-инфраструктура для Ruby. Он предназначен для работы на Rack или дополняет фреймворки типа Rails и Sinatra. Grape имеет кучу полезных встроенных возможностей, заточенных под создание API. Поэтому для решения задач по обмену данными мы предпочли его классическому Rails.
Личный кабинет врача
В системе есть личные кабинеты врача и пациента с различным функционалом, которые выполнены как отдельные приложения. В них был устаревший интерфейс и в целом не всегда они работали корректно. Перед нами стояла задача не только разработать новый функционал (например, отчеты), но и поддержать команду в создании API для нового фронтенда медицинского сервиса.
Старые кабинеты рендерились частично на бэкенде, частично на React, из-за чего в коде царил хаос и все работало с ошибками. Сейчас собственная команда работает над переносом фронтенда полностью на React, и мы немного помогаем им в этом.
Стек
Одной из основных задач на начальных этапах нашей работы был рефакторинг сервиса на Ruby. Из-за старых версий ПО мы не могли использовать новые инструменты, поэтому в первую очередь мы обновили Ruby с версии с 2.3.8 до 2.7.7, и Rails c четвертой до пятой. После обновления мы смогли начать использовать некоторые библиотеки, которые не работали на старой версии, например dry-rb. Это система библиотек для реализации востребованных ежедневных приемов программирования на Ruby, а также продвинутых паттернов функционального программирования. Например, dry-monads элегантно реализует паттерн монады — инструмента контроля над выполнением последовательности операций с побочными эффектами. Монада — это функциональный паттерн программирования, определяющий правила поочередного выполнения операций с учетом контекста (т.н. эффектов) этих операций. Например, сложная бизнес-транзакция, запуск каждого последующего шага которой зависит от того, успешно ли выполнился предыдущий шаг. В ФП-терминологии транзакция становится монадой, возможность сбоя в цепочке выполнения — контекстом, информация о возможном сбое — эффектом.
В качестве брокера сообщений используется RabbitMQ. Это инструмент с открытым исходным кодом, который помогает организовать очередь сообщений между двумя приложениями и предлагает временное хранилище. Через него обмениваются данными модули внутри системы, также он помогает обрабатывать данные полученные через интерфейсы личных кабинетов и формировать задачи.
Мы продолжаем работать с PMT online и поддерживаем систему дистанционного наблюдения пациентов. Со временем наше присутствие на проекте выросло, мы помогаем в работе собственной команде клиента, в том числе участвуем в отборе новых разработчиков на этапе технических интервью.