Public Health LLM

DDS Chatbot

A guardrailed, Thai-language conversational assistant that gives disease-surveillance staff direct, self-service answers over an aggregate, PII-free data mart — no dashboards, no dropdowns, no raw case-level records exposed.

Live Demo LLM Tool Calling Public Health PDPA-Aligned
Open Live Demo ↗
DDS Chatbot Thai disease surveillance conversational interface
Problem

Disease-surveillance staff at Thailand's Department of Disease Control (DDC) previously had to open one of more than a dozen separate dashboards for every question, then work through cascading dropdown filters just to get a single number — a slow, dashboard-hopping workflow that turned simple questions (a case count, a ranking, a rate) into a multi-step chore. DDS Chatbot replaces that with one conversational interface: ask a question in Thai, get an answer immediately.

Approach & Architecture

The system is built so the language model can never touch raw data directly. It runs on Qwen through an OpenAI-compatible tool-calling interface, restricted to a fixed whitelist of 31 tool schemas — it can only select a tool and supply validated (Pydantic) arguments, never write or execute its own queries. Those tools are the sole path to data, and they read exclusively from three read-only, aggregate, PII-free DuckDB marts (province-level surveillance, amphoe/tambon geography, and facility-level reporting timeliness), all built by anonymizing a real government line-list before aggregation — so case-level or personally identifiable records never exist downstream of that step, and never reach the model.

Responses are rendered through deterministic Thai templates for exact figures and canonical disease names, with model narration used only as a fallback layer — keeping the numbers the model reports exactly as trustworthy as the underlying query.

Guardrails

Safety is layered cheapest-and-strongest-first: fast deterministic rules catch prompt injection, PII requests, and medical-advice requests; an optional lightweight guard-model classifier adds a second layer and fails open safely if unavailable; a hardened system prompt constrains behavior further; and — the layer that actually matters most — a structural safeguard where the tools themselves are physically incapable of reaching PII, since that data simply doesn't exist in the marts they read. A final output scrub redacts any 13-digit, Thai national-ID-shaped string as a last resort. For example, asking for a patient's national ID number is refused outright.

31 / 35
Red-team attacks caught by rule-layer alone, zero false positives
Outcome & Evaluation

DDS Chatbot currently runs as a public demo on synthetic, non-patient data — no real case records are exposed at any point. A structured benchmark of 123 single-turn and 8 multi-turn questions, spanning difficulty from simple counts to computed epidemiological metrics and guardrail probes, is used to evaluate model performance.

Separately, the underlying data pipeline itself was validated against DDC's official public dashboard, confirming the aggregate mart faithfully reflects the source data it's built from.

42 / 49
Diseases matched vs. DDC's official dashboard at week 21
0.996
Spearman rank correlation vs. official figures
~91%
Completeness (residual gap traced to reporting lag)
Tech Stack
Python FastAPI Qwen (tool-calling LLM) DuckDB PostgreSQL / Supabase Docker Hugging Face Spaces