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.
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
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.
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
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.
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.