The Engineering Behind the COVID-19 Chatbot at Telegram

M Gilang Januar
4 min readMar 30, 2020

Motivation

COVID-19 is a pandemic that threatens global health. Now, the impacts are not even only in the health sector; economic, politic, national defense and security, etc are also threatened. And my country, Indonesia, is very slow in dealing with the spread of this virus.

Data source: https://databoks.katadata.co.id/datapublish/2020/03/29/perkembangan-terkini-corona-meninggal-114-sembuh-64-minggu-293

Based on the data, the number of deaths is higher than recovered (up to 2 times of it! 😨). And unfortunately, the data only shows people who have been tested. How about the rest? A lot of people don’t know whether they are infected by this virus or not.

So, I want to give a little help in this case.

Solution

I built a chatbot that can be accessed by the public at Telegram. The idea is: this chatbot can make a diagnosis for the early symptoms of COVID-19. Why Telegram? It provides free access to the API for making bots, easy and without limits. Simplicity at its best 👌

COVID-19 Chatbot: https://t.me/COVID19_ID_bot

Disclaimer: the result may not be 100% accurate. And maybe if you don’t have any symptoms, you might become a carrier for the virus.

Components

  • Bahasa.ai bot engine
    I built a chatbot, so I take advantage of office facilities for that. LOL.
  • Infermedica service
    On March 20th, Infermedica as an AI company in the health sector released the free COVID-19 Risk Assessment API. So, I use their API to make a diagnosis.

How it works

For the first chat, I want to show the number of cases in Indonesia, I get it from covid19.go.id. But, should I scrape out the data from HTML tags? Nope. In the modern web architecture, they usually serve a font-end and back-end separately. So, what I do is inspect the element and go to the network panel.

Data from: https://www.covid19.go.id/situasi-virus-corona/

We’ll see the request URL and get the data with JSON format. So, I just formatted and showed it to a message for the user. Cool! The nice-to-have-feature has done 🤣

Now, Infermedica plays its role. For make a diagnosis, we need some data from user like his age and sex because Infermedica needs that for endpoint /diagnosis. Here is the example of initial data for it:

{
"sex": "male",
"age": 30,
"evidence": []
}

And here is the example of its response:

{
"conditions": [],
"extras": {},
"question": {
"explanation": null,
"extras": {},
"items": [
{
"choices": [
{
"id": "present",
"label": "Yes"
},
{
"id": "absent",
"label": "No"
}
],
"explanation": "Chronic lung diseases are disorders that affect the lung and other parts of the respiratory system. Conditions: Chronic Obstructive Pulmonary Disease, moderate and severe Asthma, and other lung conditions.",
"id": "p_16",
"name": "Diagnosed chronic lung disease"
}
...
],
"text": "Please check all statements that apply to you",
"type": "group_multiple"
},
"should_stop": false
}

That service tells us to ask the user questions on the question.items list. And in question type they have 3 types of it:

  • single, only a simple question that can be answered by the user whether yes or no
  • group_single, like multiple choices that the user should choose one of the items provided
  • group_multiple, some questions that must be asked to the user (for this, I always ask them first item only)

All the user responses are saved to the memory and added to the evidence list in the request body for the next request. Do it continuously until the attribute should_stop is true.

Then, when the attribute should_stop is true, we should hit endpoint /triage with full of evidence list from the previous request. And the response shows whether the user is infected or not by the coronavirus. Here is the example of its response:

{
"description": "Your symptoms are very serious, and you may be infected with COVID-19.",
"label": "Call the emergency number. Avoid all contact.",
"serious": [
{
"common_name": "Cough",
"id": "s_1",
"is_emergency": false,
"name": "Cough"
},
{
"common_name": "Shortness of breath",
"id": "s_2",
"is_emergency": true,
"name": "Shortness of breath"
},
...
],
"triage_level": "isolation_ambulance"
}

Next, I just wrap it all and show the result to the user; and tell him what he should do.

That’s all, I hope what I make and share can be useful for you. Stay safe and healthy everyone!

#PhysicalDistancing

--

--