The shape of this final lesson
Tie the quest together by shipping one real thing: a small backend service that answers user prompts using your cloud provider of choice, with Ollama as a transparent fallback when the cloud is unreachable. This is the smallest production-shape proof of the patterns from every prior track.
Production check-list
- Adapter pattern. Cloud and Ollama both implement
stream(). - Health checks. Both have
health_check()with a fast timeout. - Orchestrator. Tries cloud first; falls back to Ollama on failure or degraded health. Priority is an argument, not a default — the adapters track builds the same class local-first, so a service that means cloud-first has to say so.
- Streaming. Frontend sees one continuous SSE stream regardless of which vessel answered.
- Pinned model tags. Both Ollama and cloud model versions are explicit.
- Observability. Log what answered each request — the skeleton below records the model tag, which is what the chunks carry; if you need the vessel key, have the orchestrator yield it — and read that log once before you trust it — a name field that is empty rather than absent will happily record nothing forever. You'll want this when you wonder later why some answers feel different.
- Mini mode. If your local model is small, the system prompt is stripped down.
- Warm-up. A startup task pre-loads the local model with
keep_alive: -1so first-fallback latency is acceptable — reading the tag off the adapter, so the warmed model and the called model cannot drift apart.
What you've built when this works
A service that's privacy-aware, cost-aware, and outage-aware. Cloud goes down → users keep getting answers. Cloud rate-limits you → users keep getting answers. Cloud gets expensive → bulk batch jobs route local. The orchestrator is dumb and the adapters are narrow; that's why it's robust.