An AI service that reads a clinical note and fills in the fields the clinic already uses. Every value must come from the note itself, so no invented doses are ever stored.
Overview
What this is and why it matters, in plain English.
An AI service that reads a clinical note and fills in the fields the clinic already uses. Every value must come from the note itself, so no invented doses are ever stored.
AI that turns a doctor’s free-text note into structured problems, medications and follow-ups.
The situation
What was going on before, and why it needed fixing.
Clinicians wrote a note, then typed the same history again into the discrete fields that billing and follow-up screens required.
Clinicians typed the same history twice: once in the note, again into discrete fields the billing and follow-up screens required.
What it needed to do
The outcomes the project had to deliver.
- Turn free-text notes into structured problems, medications and follow-ups.
- Store only fields the clinic already uses, and nothing the note does not support.
- Keep patient text out of logs.
What I did
My part of the work and who I worked with.
I designed and built the Python extraction service, the closed schema and validator, the LLM prompts for Claude and Gemini, and the logging policy.
How it works
The main building blocks, from the screen people use to the data underneath.
A Python service sends the note to Claude or Gemini with a closed schema, then rejects any key that is not problems, medications, or follow-up.
- 01
REST endpoint
Accepts a note and returns structured JSON in a fixed schema.
- 02
LLM call
Claude or Gemini with a system prompt that asks for the schema only and forbids invented fields.
- 03
Python validator
Parses the response, drops unknown keys, and rejects any value without a source span in the note.
- 04
Chart write
Only validated problems, medications and follow-ups reach the chart.
Key choices and trade-offs
Every build involves trade-offs. These are the important ones and what each one cost.
| Decision | Trade-off |
|---|---|
| Closed schema over open extraction. | Less information captured, but every stored field is one the clinic actually uses. |
| Require a source span for each value. | Some true facts are dropped if the model cannot point to them, but nothing invented is stored. |
| Two model providers. | Two prompts to maintain, but no single-vendor dependency. |
Under the hood
Implementation details for technical readers, with a code sample.
- Closed-schema extraction with zero invented doses stored.
- One API path for every note.
- Patient text excluded from application traces.
async function extractClinicalNote(note: string) {
const completion = await llm.complete({
model: 'claude',
system: 'Return only the clinical JSON schema. Do not invent fields.',
input: note,
});
return ClinicalNoteSchema.parse(JSON.parse(completion.text));
}Problems solved
What got in the way, and how each problem was fixed.
- 01
The model would invent a dose that was not in the note. The parser drops any value without a source span.
The parser drops any value that has no source span in the note, so an invented dose never reaches the chart.
- 02
Notes mixed English shorthand and abbreviations. The schema had to accept both without guessing a diagnosis.
The schema accepts shorthand and abbreviations as text, without inferring a diagnosis the note does not state.
- 03
Patient text could not be logged in application traces.
Logging records request metadata and validation outcomes only, never the note content.
Security, speed and growth
How data is protected, and how the system stays fast as usage grows.
Security
Notes are processed in memory and never logged. The schema is closed, so the model cannot add fields that would carry extra patient data into storage.
Speed & growth
One synchronous extraction call per note, with validation in Python adding negligible overhead to the model call.
Quality and releases
How changes were tested and shipped safely.
A fixture set of notes with expected outputs, including notes designed to tempt the model into inventing doses or diagnoses, runs against the validator.
Tech stack
The tools and technologies used, for recruiters and technical reviewers.
Results
Measured outcomes recorded for this project.
| Metric | Result |
|---|---|
| Schema reject | closed keys |
| Invented dose | 0 stored |
| Extract path | 1 API |
Questions
Plain answers first, then the detail a technical reviewer would ask about.
Common questions
- Does the AI ever make things up?
- It is not allowed to store anything that is not in the original note. If the AI suggests a value with no source in the text, it is dropped.
- What does this save a clinic?
- The second typing pass: problems, medications and follow-ups land in structured fields instead of being copied by hand.
For your tech lead
- What happens if the model invents something?
- Values without a source span in the note are dropped before anything is stored.
- Which models are used?
- Claude or Gemini, behind the same schema and validator.
Key takeaways
- •AI that turns a doctor’s free-text note into structured problems, medications and follow-ups.
- •Built with Python, Claude, Gemini, REST, HIPAA.