MediBot / docs /OFFLINE_LITE.md
github-actions[bot]
Deploy MedOS Global from 956ae78f
e3e3e14
|
Raw
History Blame Contribute Delete
5.86 kB
# MedOS Offline-Lite
**Status:** design only. Implementation lands when a contributor picks it up.
This document describes a deliberately small, deliberately limited offline mode for MedOS. It is **not** a promise of a full offline medical AI. The deterministic safety floor is what works offline; an LLM is only added on top of it as a small-model best-effort.
Read this together with `SAFETY.md` at the repo root.
## Why "Lite"
Two honest constraints set the scope:
1. **Llama 3.3 70B does not run on a phone or a budget laptop.** Promising "offline medical AI" with a 70B model is misleading. We do not.
2. **Safety must hold offline.** The deterministic red-flag rules in `9-HuggingFace-Global/lib/safety/red-flags.ts` and the regional emergency numbers in `config/locales/*.medical.json` are pure code + pure data. Both already work offline. That is the foundation.
Offline-Lite therefore ships:
```text
Always available offline:
- Deterministic red-flag triage (R0..R5)
- Regional emergency numbers, crisis lines, poison-control numbers
- Locale disclaimers + clinician-referral phrasing
- (Historically lib/providers/cached-faq.ts held canned FAQ entries
here; it was removed in b83db95 because its keyword matcher
surfaced unrelated answers — e.g. "my child has fever" returned
malaria info. Offline guidance in this tier is now limited to
the deterministic triage + emergency-number cards above, which
are always safe to show without an LLM.)
Best-effort offline (optional, behind a flag):
- Phi-3 mini / Gemma 2B / TinyLlama for non-clinical guidance only
- Strictly capped at R0/R1 outputs
- Strict post-filter
```
## What the user sees
A clearly-marked **Offline Lite** banner appears whenever the app detects no connectivity (or the user explicitly enables it):
> **You are using Offline Lite.** I can show emergency numbers, run a basic safety check on your symptoms, and answer common questions from a small, on-device model. I cannot do full medical chat without a connection. **For anything urgent, call your local emergency number.**
The banner is sticky, dismissible per session but never per app, and the local emergency number from the active locale pack is shown next to it.
## Architecture
```text
User input
Pre-LLM safety engine (always; pure code, works offline)
- R5 → emergency template, end. (NO LLM CALL.)
- R4 → urgent template + local emergency number
- R3 → urgent care suggestion + clinician phrasing
- R0/R1 → small on-device model OR cached FAQ, then post-filter
- R2 → cached FAQ + clinician referral
Post-LLM safety filter (always; pure code, works offline)
Final answer + disclaimer + emergency number when required
```
## Small-model selection
| Model | Approx. size | Plausible host | License |
|---|---|---|---|
| Phi-3 mini (3.8B) | ~2.4 GB quantised | Browser via WebGPU / phone via ONNX | Permissive |
| Gemma 2B-IT | ~1.5 GB quantised | Same | Open weights, terms apply |
| TinyLlama 1.1B | ~700 MB quantised | Lightest option | Permissive |
The model **must** be:
- Routed through the existing `chatWithFallback` path (so the safety sandwich still applies).
- Pinned to **R0/R1 only**. Anything routed to R2+ uses cached responses or a clinician-referral template, **not** the small model.
- Wrapped in the **same** post-filter as the cloud path. There are no shortcuts for "the small model is on-device, so it's fine." It isn't.
- Distributed via the standard PWA caching / app-bundle path. No third-party CDN that can later silently change weights.
## Implementation outline
A contributor implementing this would touch:
1. `9-HuggingFace-Global/lib/providers/offline-lite.ts` — new provider that wraps a WebGPU / ONNX / GGUF runtime. Returns the same `ProviderResponse` shape so `chatWithFallback` can plug it in.
2. `9-HuggingFace-Global/lib/providers/index.ts` — add Offline-Lite as the **last** fallback step, after cached FAQ.
3. `9-HuggingFace-Global/lib/safety/safety-engine.ts` — when the input resolves to R2 or higher under Offline-Lite, route to a template / cached response, not the small model. Add an explicit `offline: true` audit field.
4. `web/components/OfflineBanner.tsx` (or equivalent in the live app) — the always-visible banner described above.
5. PWA / service-worker config — pre-cache `config/locales/*.medical.json` at install time. They are tiny and safety-critical.
## What Offline-Lite explicitly does NOT do
- Full medical chat.
- Diagnosis (it never does, online or offline).
- Dose recommendations.
- "You're fine, no need to see a doctor." The post-filter blocks this on every path.
- Pretending to be the same product as online MedOS. The banner is loud about the limits.
## Testing
The same `tests/safety/run_golden.ts` set runs in offline mode by mocking the provider chain to return only Offline-Lite results. The R5 / R4 floor must hold; the post-filter rules apply identically.
A few extra cases tagged `offline_lite` may be added if specific failure modes are discovered (e.g., a small model hallucinating a dose).
## Roadmap
- **Step 1.** Pre-cache the medical packs in the service worker. (Self-contained, no model.)
- **Step 2.** Add a clear Offline banner that surfaces emergency numbers regardless of model availability.
- **Step 3.** Add Offline-Lite small-model provider behind a feature flag (`MEDOS_OFFLINE_LITE_ENABLED=true`). Keep the flag off by default while validation runs.
- **Step 4.** Run the full golden set in offline mode; require the same R5/R4 sensitivity targets as the online path before flipping the flag on.
Until Step 4 passes, Offline-Lite is documented but not enabled. The deterministic safety floor + emergency numbers + cached FAQ already give users a useful, honest offline experience.