Skip to main content

End-to-end: vitals watch

Advanced ⏱ 25 min healthcare · end-to-end · local llm

You will build: the deterioration-watch pipeline from the Healthcare use case — vitals windowed per patient, escalation thresholds with no model in the alarm path, and a situation summary drafted by a local Ollama so PHI never leaves the machine.

vitals → streaming:trend → rule-based:escalate → llm:summarize (local) → webhook (unit board)

Prerequisites

  • The quickstart completed.
  • A local Ollama for step 4 — the point of this pipeline is that the model runs inside your perimeter. (Without it, stop after step 3: escalation already works.)

1 · Scaffold

pulse new vitals --source webhook \
--stage streaming:trend --stage rule-based:escalate --stage llm:summarize \
--sink webhook

2 · The trend stage — per-patient windows

stages:
- name: trend
engine: streaming
operators:
- { type: keyBy, field: patient_id }
- type: window
spec: "sliding(10m,1m)"
aggregations:
hr_avg: "avg(heart_rate)"
hr_stddev: "stddev(heart_rate)"
spo2_min: "min(spo2)"

3 · The escalation stage — deterministic, microseconds, auditable

- name: escalate
engine: rule-based
rules:
- { condition: "spo2_min < 92 || hr_stddev > 15", action: flag }

The alarm path contains no model: thresholds your clinical governance signed off, applied identically every time.

4 · The summary stage — a local model drafts the context

- name: summarize
engine: llm
systemPrompt: |
Draft a one-paragraph situation summary for the
responding clinician: what crossed the line, the
trend, and the window it happened in.

Point Pulse's LLM provider at your local Ollama — the event data is summarized without leaving the machine.

5 · Sink to the unit board and deploy

pulse secret set UNIT_BOARD_WEBHOOK https://webhook.site/<your-id>
pulse secret set PULSE_WEBHOOK_SECRET dev-secret # the scaffolded webhook source requires it
pulse deploy .

6 · Simulate a deteriorating patient

for spo2 in 97 96 95 93 91 90; do
pulse events publish --topic vitals.in --value '{"patient_id":"p-12","heart_rate":'"$((RANDOM % 40 + 80))"',"spo2":'"$spo2"'}'
done
pulse events tail --topic vitals.escalate.out

The moment spo2_min drops under 92 inside the window, the escalation fires; vitals.summarize.out carries the drafted paragraph; the unit board webhook receives both.

What just happened

The clinical constraints shaped the architecture: rules decide, the model only describes, the human acts — and every step landed on an auditable topic. Because the LLM is local, the privacy property is architectural, not contractual. The system surfaced attention; it never acted on a patient.

Troubleshooting

No escalation fires

The window needs readings below 92 within the sliding window — send the burst within a couple of minutes. Check vitals.trend.out to see the computed spo2_min per window.

summarize is unhealthy

Ollama isn't reachable. That stage stays visibly unhealthy — escalation (the safety-critical part) keeps working without it.

Next