Saturday, April 26, 2025

Part 2 of series on Amazing power of HL7 FHIR and GenAI

For the past one week I have been working on part 2 of the series (refer to the overview of the series here - https://healthinterconnect.blogspot.com/2025/04/amazing-power-of-hl7-fhir-supercharged.html ). This time my purpose is to create CRUD page for Encounter resource based on its FHIR resource structure definition. It took longer than I expected, probably took about more than 8 hour. 

There are few challenges

1) Even though the FHIRResourceUIDevGuide.md  is able to generate the dynamic CRUD page based on Encounter resource structure definition, however these fields do not work properly - CodeableConcept or Coding such as Encounter.class, or fields which refer to other resources eg Encounter.serviceProvider. I think it took me more than 20 iterations so that the dropdown for these fields are showing correctly

2) After these dropdown fields are showing correctly, still spent few iterations to make sure the UI shows the selected field

3) Another issue is that the AI does not work consistently. For example when I asked Copilot to generate PatientCrudPage, some of the previous prompts working in EncounterCrudPage are not rendering the same outcome in PatientCrudPage.

My key takeaway for part 1 is that AI can help me start very fast, however during part 2, the key take away is that it starts to get slower, and I am starting to get prompt fatigue.

Thus for part 2, I will continue to use the EncounterCrudPage created to refine the original prompt instructions in FHIRResourceUIDevGuide.md , hopefully it will be getting smarter and smarter, and reduce the iterations of prompt

However in general, the GenAI is still very impressive, below is few example

1) I asked Copilot to organize the UI layout of the data elements based on FHIR resource structure. Take the use case of Encounter resource, I asked Copilot to arrange the data elements directly under Encounter resource root level as "Overview" section, and the elements under Encounter backbone level in the respective groups - Diagnosis, Participant, Reason, Location and Admission

2) Initially the dropdown input is not working, it encountered error upon saving, as the field is immutable, it is able to identify the root cause and fixed the issue


GitHub Copilot

I see the issue now. The errors in the console indicate that we're trying to modify objects that are immutable. This typically happens when React's strict mode is enabled or when the state objects are frozen. Let's make deep copies of the objects before modifying them.

Let me fix the error by updating the handleInputChange function to ensure we're creating new objects rather than trying to modify existing ones:


Below is the screnshot of the generated Encounter Crud Page, you can check out the source code at https://github.com/sg-victorchai/gep-poc  and run locally.






Amazing power of HL7 FHIR supercharged by Gen AI

I will be sharing 5-part series to demonstrate the amazing power of HL7 FHIR and GenAI assisted development.


  1. Use FHIR StructureDefinition meta resource to identify the key data elements of domain resource eg Observation and CarePlan, and automatically create the record summary list page on UI
  2. Use data elements defined in FHIR StructureDefinition meta resource to auto render the CRUD form for the domain resource eg CarePlan
  3. Use FHIR SearchParameter meta resource to identify the search parameters for the domain resource eg CarePlan,  automatically render filtering fields in record summary list UI
  4. Use data validation rules defined in FHIR StructureDefinition to perform UI level data validation
  5. Use FHIR OperationDefinition to inspect the APIs and its input/output parameters of each API, and generate UI to allow users to perform specific actions, eg show "Reschedule appointment" button on UI if the backend API supports rescheduling appointment, and then bring users to the appointment reschedule UI with the input parameters specified in the OperationDefinition.


If you are developer, and still not sure how to leverage Gen AI, then you'd better quickly get yourself dive into this once-in-a-lifetime revolution.

I think the best way to get started is to hop on to the repo I just published on GitHub, you can check out and try to create new Summary list view and CRUD page using the prompt instruction md I have already created, all can be done without coding (Vibe coding)





Sunday, January 5, 2025

HL7 FHIR APIs can fundamentally transform the rapid development of frontend web application

 Just imagine if all your backend APIs is based on HL7 FHIR API, how it will fundamentally transform your frontend web application development

One immediate benefit is that your frontend developer will not be pressing you to come up the running APIs, because he/she can just pick any publicly available HL7 FHIR Server to test and integrate. 

Another greater benefit is that we can fundamentally re-design the web application to take full advantage of the consistent APIs that are based on HL7 FHIR. 

Let me walk through the 2nd benefits here

I am going to walk through a simple ReactJS Single Page Application (SPA) I have created in the past, the actual source code is hosted on code sandbox - https://muqhwj.csb.app/patients. This demo SPA is integrated with the live APIs hosted in HealthX Sandbox - https://api.healthx.sg/.../2807f247634c4f3c941568d460835a71. (Note the last part of the URL is the tenant ID)

For the demo ReactJS SPA, pls take note that the intent of the demo app is NOT to demonstrate the coding best practice for ReactJS SPA, eg I did not use TypeScript in the demo yet, the configuration is not maintained in external configuration settings etc. I only spent 1 or 2 days to put up the demoReactJS SPA.

The demo application shows whatever health records available in the backend system with a simple UI design - summary view and detail view. There is only one API component and oneUI component regardless of how many resources you like to show on the UI
  1. All the backend API integration is coded in this API slice - https://codesandbox.io/p/sandbox/muqhwj...
    1. I use the method - getResourcesEntries for getting ALL kinds of resources (other than Patient record) and also do transformation from backend process API to experience API for the Summary View (I moved the included patient resources into respective patient data resource eg Condition under the element "_includedPatient", so that it is easier for UI to render the data). 
    2. The second method is getResourceDetail which is to get the detail payload of the specific record for any given type of resource for the Detail View
  2. The UI layout is implemented in these two files
If you want to try out yourself, you can fork to a new project, and then try to modify these two files to add additional record type to be shown in UI, or update the data elements to be shown for each record type

  1. Add new record type and corresponding menu item name in this file - https://codesandbox.io/p/sandbox/muqhwj...
  2. Add/update data elements to be shown for the corresponding record type - update function resourceSummaryElements in this file - https://codesandbox.io/p/sandbox/muqhwj...

Thursday, October 10, 2024

Public Sector Day Singapore 2024


I was delighted to be invited by AWS to share how we designed and implemented robust tech foundation for Singapore Healthier SG and Age Well SG at recent Public Sector Day Singapore 2024 on 03 Oct 202

It is hard to design robust future ready tech foundation for such large scale solution with extremely high throughout and fast performance, in generally all the APIs are performing at around 0.2 to 0.3 second even at peak volume. It is also relatively easy if the team has been consciously investing in the following four areas

  1. Deeper understanding of business domains, ability to shape the requirements, and ability to predict what will come next
  2. Deeper understanding of technologies - products/solutions and industry trend, set future ready technology direction, be ready to transform your team, the organisation and the industry
  3. Once you are equipped with deep understanding of business and technology, you will be naturally have the courage and determination to hold the vision and direction
  4. Build strong team whom you can count on so that you are confident that things will work out well even though some parts are not clear or fully sorted out yet at beginning
The two pillars of our strong tech foundation are AWS cloud platform and HL7 FHIR
  1. AWS has the broadest and richest cloud services for us to build modern cloud native and highly resilient applications
    • Use API GW, AWS EKS, RDS,SQS, Lambda and ActiveMQ for transactional part of the application
    • Use AWS Glue, AWS Data Lake for Operational Data Store 
    • Use AWS BedRock for RAG implementation
  2. HL7 FHIR provides suite of framework for us to build future proof applications
    • Use HL7 Extended Operation to define fined grained APIs to be accessed by external systems
    • Use HL7 FHIR data model as basis for our internal data model, so that it can support any future business needs without change to the data model
    • HL7 FHIR Profile as data validation control for API, any ongoing changes are handled with simple update to the profile without single line of code at all. For example, if we need to support different set of goals and activities for Health Plan, we can just update the profile for Health Plan API
    • Use "SQL On FHIR" to have universal transformation to transform any data subject to any data format required by data analysis and visualisation tool


Below are some photos taken during the public sector day  and the slides (in MP4 format at the bottom of this post)

Enjoy!
















Wednesday, September 25, 2024

HL7 FHIR difficult to implement - Misperception or truth?

Recently I am approached by one project team, who stated that it is very difficult to implement HL7 FHIR API with the following two reasons

1) Their system only supports RESTful with JSON

2) They are not familiar with HL7 FHIR

For technical people who has some basic understanding of HL7 FHIR, you must be laughing,  since HL7 FHIR API is using RESTful with JSON, and only difference between HL7 FHIR and other proprietary API is that the format and syntax in HL7 FHIR is standardised

Instead of brushing it aside, and knowing that the system is using Java. So I spent 5 minutes to ask Chatgrp, how to implement client side programme in Java to call HL7 FHIR API

Afterward I spent next few mins to try out and validate in Java IDE (Integrated Development Environment) Eclipse.

Below I briefly described the steps provided by chatgrp
1) Create a Maven project in Eclipse
2) Configure the dependent libraries(HAPI FHIR libraries) in Maven POM
3) Copy and paste the sample code provided by chatgpt into my Java application, and updated the remote FHIR server to FHIR server hosted by Firely (its FHIR server is written in .NET)
Below is the source code of the java application, you can run the application to create patient resource, once it is created, you can check the created resources at Firely Server using this URL - https://server.fire.ly/

package synapxe.fhir.demo;

import java.util.Calendar;

import java.util.Random;

import org.apache.commons.lang3.RandomStringUtils;

import org.hl7.fhir.r4b.model.Bundle;

import org.hl7.fhir.r4b.model.Enumerations;

import org.hl7.fhir.r4b.model.Identifier;

import org.hl7.fhir.r4b.model.Patient;

import ca.uhn.fhir.context.FhirContext;

import ca.uhn.fhir.rest.api.MethodOutcome;

import ca.uhn.fhir.rest.client.api.IGenericClient;

/**

* Sample FHIR Client using HAPI open source library https://github.com/hapifhir/hapi-fhir

*

* @author victorchai

*

*/

public class FHIRClient {

public static void main(String[] args) {

try {

createPatient ();

//searchPatientByName ("HapiVictor");

//deletePatient("cfc18bb8-e1dc-4bab-b4e2-83e1d797034f");

}

catch (Exception ex) {

ex.printStackTrace();

}

}

private static void createPatient() {

// Create a FHIR context for the FHIR version you are using (e.g., R4)

FhirContext ctx = FhirContext.forR4B();

// Create a client to connect to the FHIR server

String serverBaseUrl = "https://server.fire.ly"; // Firely FHIR Server which is implemented in .NET

IGenericClient client = ctx.newRestfulGenericClient(serverBaseUrl);

// Create a Patient resource

Patient patient = new Patient();

Identifier nric = new Identifier();

nric.setSystem("http://fhir.synapxe.sg/Namespace/nric");

String nricDigits = RandomStringUtils.randomNumeric(7).toUpperCase();

nric.setValue("S" +nricDigits + "H");

patient.getIdentifier().add(nric);

patient.addName()

.setFamily("HapiVictor")

.addGiven("John");

patient.setGender(Enumerations.AdministrativeGender.MALE);

Calendar dob= Calendar.getInstance();

Random ran = new Random();

int x = ran.nextInt(10);

dob.set(1970 +x ,Calendar.getInstance().get(Calendar.MONTH), Calendar.getInstance().get(Calendar.DAY_OF_MONTH));

patient.setBirthDate(dob.getTime());

// Send the created patient resource to the server

MethodOutcome outcome = client.create().resource(patient).execute();

// Print the outcome

String patientID = outcome.getId().getIdPart();

System.out.println("Created Patient with ID: " + patientID);

System.out.println("You can access the patient resource at this url - "

+ serverBaseUrl +"/Patient/"+ patientID +"?_format=application/fhir+json");

}

private static void searchPatientByName (String familyName ) {

// Create a FHIR context for the FHIR version you are using (e.g., R4)

FhirContext ctx = FhirContext.forR4B();

// Create a client to connect to the FHIR server

String serverBaseUrl = "https://server.fire.ly"; // Example HAPI FHIR server

IGenericClient client = ctx.newRestfulGenericClient(serverBaseUrl);

Bundle results = client.search()

.forResource(Patient.class)

.where(Patient.FAMILY.matches().value(familyName))

.returnBundle(Bundle.class)

.execute();

System.out.println("Found " + results.getTotal()+ " patients:");

for (Bundle.BundleEntryComponent entry : results.getEntry()) {

Patient patient = (Patient) entry.getResource();

System.out.println("Patient ID:" + patient.getIdElement().getIdPart());

System.out.println("Patient Name:" + patient.getNameFirstRep().getNameAsSingleString());

}

}

private static void deletePatient(String patientID) {

// Create a FHIR context for the FHIR version you are using (e.g., R4)

FhirContext ctx = FhirContext.forR4B();

// Create a client to connect to the FHIR server

String serverBaseUrl = "https://server.fire.ly"; // Example HAPI FHIR server

IGenericClient client = ctx.newRestfulGenericClient(serverBaseUrl);

// Send the patient resource ID to the server

MethodOutcome outcome = client.delete().resourceById("Patient", patientID).execute();

// Print the outcome

System.out.println("Deleted Patient with ID: " + patientID + " with status:" + outcome.getResponseStatusCode()) ;

}

}

Below you can also find the libraries included in  Maven POM.xml which specifies the dependent libraries (again this is also provided by Chatgpt)

<dependencies>

<!-- This dependency includes the core HAPI-FHIR classes -->

<dependency>

<groupId>ca.uhn.hapi.fhir</groupId>

<artifactId>hapi-fhir-base</artifactId>

<version>${hapifhir_version}</version>

</dependency>

<!-- Include the client -->

<dependency>

<groupId>ca.uhn.hapi.fhir</groupId>

<artifactId>hapi-fhir-client</artifactId>

<version>${hapifhir_version}</version>

</dependency>

<!-- At least one "structures" JAR must also be included -->

<dependency>

<groupId>ca.uhn.hapi.fhir</groupId>

<artifactId>hapi-fhir-structures-r4b</artifactId>

<version>${hapifhir_version}</version>

</dependency>

<!--

HAPI-FHIR uses Logback for logging support. The logback library is included

automatically by Maven as a part of the hapi-fhir-base dependency, but you

also need to include a logging library. Logback is used here, but log4j

would also be fine.

-->

<dependency>

<groupId>ch.qos.logback</groupId>

<artifactId>logback-classic</artifactId>

<version>1.2.3</version>

</dependency>

</dependencies>


Btw, there are many many HL7 FHIR open sources libraries available - Java, Net, Python and Javascript, etc, you can find the full list at this URL - https://confluence.hl7.org/.../Open+Source+Implementations
Go explore HL7 FHIR and have fun. Pls msg me if you need have deeper discussion on HL7 FHIR


Tuesday, July 2, 2024

HL7 FHIR DevDays 2024 - Sharing of Singapore's Healthier SG implementation

 Below is the some of the slides from the recent sharing at FHIR DevDays 2024 (https://www.devdays.com/) on Singapore's National Healthier SG implementation.









I am also glad that the implementation got the inaugural FHIR implementers award, below is the finalist pitch I shared during DevDays







For more details, please go to the following Firely site on the highlights of FHIR DevDays 2024



Part 2 of series on Amazing power of HL7 FHIR and GenAI

For the past one week I have been working on part 2 of the series (refer to the overview of the series here - https://healthinterconnect.blo...