Inspiration

Meet Nasreen, a 31 year old woman who lives in Lahore. She has to take her children for a routine checkup but she isn't sure which hospital to go to. She doesn't have a lot of doctors in her family, but a friend of a friend suggests going to one that's a 30 minute drive away. Nasreen has a terrible experience at the hospital and feels like she wasted hours of her day. The next time she has to go for a checkup, she's sure she has to go someplace else - but she has no idea where.

Going to a hospital is part of most people's routines and personal lives. But due to a lack of centralized platform that contains publicly available data about hospitals, Pakistanis primarily rely on word-of-mouth to find the right hospital to go to, or may avoid seeking healthcare entirely. This compounds the stress and adds to the confusion that patients experience, as well as delay timely healthcare delivery. This problem can be felt by individuals across Pakistan; patients experience this routinely when seeking healthcare - for monthly checkups or in personal emergencies. Existing public healthcare platforms are built primarily for internal administration or strictly medical related purposes; most patient-facing platforms focus on specialist books (such as Marham), not on hospital level facilities and with little to no focus on disclosing hospital quality or any comparison based tool. These platforms are also difficult to use and do not make information digestible for the average person -- a hindrance in both people's personal lives, productivity and their routine.

This project aims to solve this problem by leveraging artificial intelligence deliver easy to understand information about 45 hospitals in Lahore, as a small proof of concept project to show the benefits of a patient-facing centralized healthcare platform. Instead of digging through a confusing UI, having to comb across multiple different websites and calling hospitals themselves, users can simply talk to my chatbot!

What it does

  • Uses a novel dataset I created myself; Lahore currently has no publicly available dataset collecting statistics for both private and public hospitals. I made a list of 45 general hospitals in Lahore with over a hundred Google Reviews. For each, I collected various data points by synthesizing information from multiple sources, including public databases and official hospital websites. This dataset also includes negative Google Reviews (1-3 stars) of each hospital, grouped into themes of complaints across six major categories (Environment, Behavior, Management, Money, Wait Time and Department Specific complaints) using BERTopic AI.

  • Can understand your query even if it's misspelled, abbreviated, or referred to casually. I wanted to ensure that the chatbot could recognize hospital names as they are referred to in common speech (for example: IMC instead of Integrated Medical Complex). In order to make the chatbot accessible to a wide variety of users and recognizing that the vast majority of Pakistanis feel more comfortable communicating in Urdu, it can also respond to users in Roman Urdu and Nastaliq Urdu.

  • Makes asking questions easier. If the user doesn't want to type in a query, I provide a sidebar where the user can customize their own commonly asked questions. Users can select a hospital from a dropdown to learn more about it, compare two hospitals, or select the features they are looking for a hospital. This automatically generates a personalized query quickly that the bot can answer.

  • Every answer is grounded in review data. I didn't want the bot to just list statistics at the user; instead, it calculates the ratio of negative reviews as a percentage of the whole, the frequency of certain themes, and uses information from each theme to help give an overview of patient experience at the hospital. It also creates benchmarks against a city-level to ensure that the user gets a look at how the hospital compares to others. It explains each in a conversational, easy to understand manner.

  • Factors in your location when answering your questions. When the user enters their location into the sidebar, the bot automatically calculates drive times and approximate distance to the hospital, for better and more personalized recommendations on which hospital is best suited for the user's needs. If you enter a nickname, you can even store locations within the website, for home or work.

  • Can handle follow up questions. The bot automatically remembers the context from the user's messages, so conversational flow remains natural and just like talking to a friend.

Throughout, I make sure that it is very explicit that the bot only gives hospital choice guidance, not medical advice. The goal of my project is simply to provide centralized, accessible information about hospitals in Lahore. I want to convert an overwhelming decision rife that is sometimes suspect to misinformation into a quick conversation!

How we built it

Review Analysis & Database Creation

To conduct my analysis of negative reviews of each hospital, I leveraged Google Review data across 45 hospitals in Lahore. I created a dataset of these reviews, filtered them by the number of stars and processed the dataset to get rid of spam and overly short reviews. I then used BERTopic to group each of the reviews into themes. I was left with a large number of themes, which were then grouped into larger, meta-themes. I used BERTopic to get two representative reviews from each theme. To collect statistics about each hospital, I collected information from the follow websites, listed below. This was by far the most time-consuming part of the project.

Type Source
Name HDX Pakistan Health Facilities List
Individual hospital websites
Coordinates Google Maps
HDX Pakistan Health Facilities List
Whether it is public or private Individual hospital websites
Official government notice, 2024
Whether it is a teaching hospital Teaching & Specialized Hospital List
Teaching Hospitals & Affiliated School List
Average price of consultancy Marham Consultants for each hospital
Number of beds Individual hospital websites
Official government notice, 2024
OPD availability Individual hospital websites
Blood bank availability Individual hospital websites
Licensed blood bank list
Emergency availability Individual hospital websites
Departments Individual hospital websites
MSDS compliance zone Punjab Healthcare Commission Zones
Sehat-Sahulat Card empanelment status NPQSC Official Website
Calling front desk
Departments which accept the Sehat-Sahulat Card NPQSC Official Website

Bot Creation

I load the hospital data from a .csv file into an in-memory SQLite database. Every query that the LLM generates to the SQL is passed through a safety function to ensure that only SELECT/WITH statements are allowed. I also make sure that the SELECT clause is rewritten to SELECT * so the model can't omit columns that later logic depends on. The database connection itself is also opened in SQLite's read-only URI mode.

The hardest part to get right was the name resolution. Hospital names can be written in different ways: ful, formal names as they are stored in the database, in Roman Urdu, Urdu script, or partially. Firstly, I create an alias index that pre-computes known abbreviations, parenthetical acronyms and unique first-word/two-word shortcuts for each hospital. Secondly, I use a fuzzy-matching fallback using rapidfuzz that strips filler words like "hospital" and "complex" so that a one-letter typo in the most memorable part of the hospital name isn't drowned out by generic words. For example, the bot could still recognize "Evecar" as referring to "Evercare Hospital". I use this everywhere, including when detecting hospitals mentioned in a query or when correcting names the LLM extracts.

I also use intent routing for two types of answer-types either "comparison" related queries or "general queries". This mostly runs in Python due to the constraints of operating on the free tier of our LLM. Regez checks for comparison language, such as "compare" or "better than" combined with how many known hospitals were locally detected to decide whether the question needs the comparison or general search path. The LLM's JSON-based router is largely superseded by this deterministic logic, with an LLM call only reserved for rewriting follow-up queries like "compare them" into standalone questions using chat history.

I use two different Gemini 3.5 Flash prompts (again, I chose the most cost-efficient model with the highest free token limit on the free tier). One generates SQL, and one turns the results from the query into a short, conversational answer, with instructions to match the user's language, avoid jargon and tables, translation percentages and numbers into plain language and to clarify that the bot only provides hospital guidance, not medical advice.

For location, I integrate the Google Maps Distance Matrix API for real drive times and use geopy's geodesic calculations as a fallback if the API key is missing.

The app's UI is made using Streamlit. It has a chat interface for free-form questions and a sidebar where the user can enter their location and generate their own queries. It has point-and-click filters for departments, sector, review sentiment capacity and a slider for the price range that creates a natural-language prompt for the chatbot. This is to ensure ease of usage for people who don't want to type a full sentence, and for all users to get a sense of the capabilities of the bot.

Challenges we ran into

The first challenge I faced was the name recognition code for each user's query in the hospital. In the beginning, I had the LLM simply generate a query for whatever hospital the user inputted, regardless of how it was written. This obviously triggered various errors since the LLM was looking for an exact match that wasn't present in the database. Early on, I relied on straightforward substring and token comparisons. This was fine in cases like: "Integrated Medical Complex" vs. "Integrated Medical Care Hospital", which have the same core tokens in different arrangements, but it broke down when the user misspelled a word, like: "Shiekh Zayed" vs. "Sheikh Zayed". I soon realized that I was scoring entire the user's sentence against each hospital name. A short but distinctive misspell like "Evrcar" is obviously diluted when it's compared against a whole sentence of filler words; hence, the similarity score was never high enough for the LLM to recognize it. To fix this, I started comparing shorter candidate windows: I stripped filler words from the hospital name and query and fuzzy-match the remaining tokens against each other. This was very effective and made sure even the worst misspells could be understood by the LLM.

The second was the incorporation of geolocation data. I started out using geopy's Nominatim (OpenStreetMap) geocoder because it was free and didn't need an API key. However, Nominatim's default timeout is only one second and it was much weaker than Google Maps at being able to recognize place names in Lahore. For example, writing "Phase J2 Johar Town" would resolve as "Block L Johar Town". I was not happy with it's performance and decided to move to the Google Maps Geocoding API and Distance Matrid API for drive times.

However, even when the user's coordinates were set up properly, the hospitals did not show up with distance or properly sorted in order due to a number of tiny bugs. I saw that the function in my code (ask_chatbot_general) which generated SQL queries and decide which 5 rows to LIMIT to would do so before distance was calculated. Since the model has no way to select or order rows by proximity, it simply listed whatever rows showed up in default order and distance was only added to that batch afterwards. So, if the actual nearest hospitals were not already in that list of five, they did not show up at all. Even after I calculated distance, I was not sorting results by them. I moved the distance calculation to run on the full result set (not the limited one) and sorted them by nearest-first in the the function add_distance_to_dataframe, then explicitly using the location name into the comparison and general search prompts rather than on the table so the LLM would be sure to use it in its response.

Accomplishments that we're proud of

I am particularly proud of the work I did to make sure that this bot was accessible to as many people in Lahore as possible. Even when users use Urdu script, Roman Urdu, misspell or abbreviate hospital names, and vague prompts like "compare them" the bot is able to understand which hospital(s) the user is talking about and what their intent is. I do this with minimal LLM usage, instead using Python logic, which made the entire system much more predictable and reliable. Since the entire project hinged on the LLM being able to actually recognize which hospitals the user was talking about, nailing this feature made me very happy.

I was also very proud of the feature for making your own prompts in the sidebar. I initially planned to limit the bot to a chat interface, but I soon realized that this made the actual capabilities of the bot unclear; people would not really know the extent of what the bot could do and hence might not ask the right questions in the first place. Also, a lot of users might prefer to just input their specifications as if they were filling out a form instead of writing their own questions. The sidebar just creates a prompt using the specifications by appending clauses to a pre-made question. Particularly, I was proud of the incorporation of a price range into the prompt; I created custom clauses depending on the ranges used. For example, if they were equal, the clause would say: where the price is exactly PKR {min_price:,} or where the consultation/fee is free (PKR 0).

What we learned

I think the most valuable lesson I learnt, particularly for a project revolving around a chatbot, was that LLMs are good at language, not at logic. Throughout my code, I would ask the LLM to decide intent or remember coordinates -- this would almost always introduce a place where it would default to hallucination, dropping information to save tokens or give a wrong answer due to a lack of context. I would end up having to use the data I already had locally and hardcode Python logic wherever I could. An LLM should only be given information it needs to reason about, like synthesizing findings from human reviews or writing in a conversational manner.

I also think the scope of the project -- working in Pakistan, with a Pakistani user in mind -- provided insight into the limitations of large APIs and libraries. Nominatim, for example, did not function well for Pakistani locations. The LLM would often not answer in Roman Urdu or Nastaliq Urdu unless I hardcoded it into the prompt. Making something for a Pakistani user who would be using the chatbot in their everyday life meant that I had to be thinking about the messiest case scenarios and write code to make sure my bot could understand it.

What's next for Lahore Hospital Finder

My idea is to increase the number of hospitals that the bot knows about, extending to other healthcare facilities in Lahore. It ensures that I have a broader range of hospitals on my website, so it is more reflective of the healthcare landscape in my city. This is relatively easy to carry out; however, I'd have to come up with new categories of data especially if I choose to incorporate healthcare facilities that are not general hospitals (like maternity hospitals, instead).

I was also limited to free tools when making this bot. For future expansion, I'd like to use the paid tier of Gemini instead of a free model; right now, I have guardrails in place to make sure I stay within my token limits but I think the quality of output could be increased if those didn't exist. I'd also like to add an Roman Urdu/Nastaliq Urdu translation for the entire website, which simply wasn't feasible to do for a one-week hackathon on top of the rest of the work I did. This isn't too difficult to carry out, only a bit time consuming. I think another quality of life feature for improvement could be to have the chat history be saved to the cache, alongside the user's locations.

Finally, I'd love to seek out recognition for this project and increase the number of users to get more feedback. For this project to achieve it's purpose on a larger scale and help people gain access to reliable healthcare information, I'd need to make sure people are comfortable using it in the first place. Although I currently have anti-jailbreak prompts in place, I'd also like to explore more guardrails for full implementation. For this purpose, I'd like to contact key stakeholders or advertise the website more and incorporate suggestions into the website.

Built With

Share this project:

Updates

Submission history