한국어
CASE 08Pilltip / AI Agent, Sensitive data boundaries

Medication chatbot: keeping health profiles out of external AI inputs

Pilltip has to guide medication by health condition, but I thought that health information is the most sensitive personal data. So I built a chatbot that guides medication through RAG-based AI orchestration while separating symptom-based drug search from profile-based decisions. It uses the model's language understanding, while code controls how far the sensitive profile is used.

2025.09

Spring AIWeaviateRAGAI Orchestration

01 Background

Users describe symptoms in different words from drug indications, so keyword search could not match symptoms to drugs. Personalization also needed pregnancy status, current medications and underlying conditions, but sending that health profile to an external LLM as-is would make it hard to control where sensitive data goes.

What solving it enables

I judged that sending health information to external AI brings leak risk and regulatory burden, while not sending it loses personalisation, the core feature. Handling the decision internally, I thought, could protect both.

02 Design and implementation

  1. Semantic search connecting symptoms to drug indications

    Problem Everyday symptom descriptions and drug indications use different words for the same meaning. Related information needed to be found without exact keyword matches.

    Decision I first started building a symptom synonym dictionary and wrote code for it. But there were too many symptoms, and when users described several at once the dictionary entries overlapped. I still had to pick the drugs that fit that person, yet vague drug descriptions matched almost every symptom. So I used semantic search to link natural-language symptoms to drug indications, and split processing paths by what each question needed.

    Implementation Among free vector databases with hybrid search I tried Milvus first, but it was too heavy, so I stored drug indications in the lighter Weaviate. Because the backend was Spring, I ran orchestration with Spring AI on the same server instead of adding a separate Python container. Stored drug indications in Weaviate for semantic symptom search. Built paths for drug discovery, medication risks and dosage information according to the question.

    Verification In user-scenario E2E tests in August 2025, natural-language symptoms were routed to the right path (drug search, medication risk, dosage). I did not keep a numeric accuracy evaluation per symptom.

  2. Internal health-profile processing, separate from external AI inputs

    Problem Personalization required pregnancy status, medications and underlying conditions, but sending those profiles to an external LLM risked exposing sensitive information.

    Decision At first I considered sending the health profile to the external AI with sensitive content filtered out. But there were too many expressions and cases to filter, and I judged that code could not cover them all. So I separated understanding symptom language from deciding profile conditions, and kept profile decisions in internal code where inputs and rules can be controlled directly.

    Implementation Excluded pregnancy, medication and underlying-condition fields from external LLM inputs. Connected internal profile decisions to symptom search results to provide personalized information.

    Verification Pregnancy status, current medications and underlying conditions are never put into external LLM inputs; an internal tool uses them to judge contraindications, duplicates and interactions and filter out unsuitable drugs. The AI guidance on the drug detail screen did not send these three fields either.

03 Improved processing flow

ARCHITECTUREMermaid diagram
flowchart TD
 S[Natural-language symptoms] --> V[Weaviate: semantic search of indications]
 P[Pregnancy, medications and underlying conditions] --> T[Internal tool: profile decisions]
 V --> R[Personalized information]
 T --> R
 B[External LLM input boundary] -.-> X[Exclude these profile fields]
 classDef accent fill:#e5edff,stroke:#4164c8,color:#142b60;
 class T,B,X accent;

A conceptual view of responsibilities and data boundaries, not the exact call sequence or a guarantee against every form of data leakage.

View Mermaid source
flowchart TD
 S[Natural-language symptoms] --> V[Weaviate: semantic search of indications]
 P[Pregnancy, medications and underlying conditions] --> T[Internal tool: profile decisions]
 V --> R[Personalized information]
 T --> R
 B[External LLM input boundary] -.-> X[Exclude these profile fields]
 classDef accent fill:#e5edff,stroke:#4164c8,color:#142b60;
 class T,B,X accent;

04 Results and lessons

Separating symptom search from internal health-profile decisions

Enabled natural-language drug discovery while excluding pregnancy status, current medications and underlying conditions from external LLM inputs. Explicitly separated information sent to AI from information evaluated by internal code. In a domain that handles sensitive data, I settled the boundary between what the model may judge and what code stays responsible for before writing the implementation.

Scope and tradeoffs

Internal code has to change when profile conditions change, but keeping sensitive health information from reaching external models came first, so I handled this decision in code instead of AI. This removes specific profile fields from external input; it is not a measurement of leak prevention on every path. As users grow, I think AI processing should move to a separate service.