Skip to content
Blog

Local-First AI: Ollama, llama.cpp, and On-Prem Inference

Keep your data in-house and your bills predictable. A practical guide to running open models locally with Ollama and llama.cpp, plus when on-prem inference beats the cloud APIs.

Published on August 9, 2026

AI Assistant

Every call to a hosted model ships your data to someone else’s data center and shows up on a monthly invoice. For code on a laptop, internal tools, or anything handling sensitive data, “local-first AI” is increasingly the default — and it’s never been easier, because Ollama and llama.cpp turned a fiddly ML deployment problem into a two-command install.

In this post, you will learn how to run open models locally with Ollama, drop down to llama.cpp when you need maximum control, and pick a sensible deployment strategy (laptop, server, or Docker).

The stack in one picture

LayerToolWhat it does
Runtimellama.cppC/C++ inference engine — the same backend Ollama uses
OrchestrationOllamaModel registry, CLI, and REST API on top of llama.cpp
Accessollama-python / OpenAI-compatible APITalk to models from your code

Ollama’s supported backends are built on llama.cpp, so understanding the lower layer explains what Ollama is doing for you — quantization, KV-cache management, and hardware acceleration (Metal, CUDA, ROCm).

Get started with Ollama

Install and run a model in three commands:

# macOS / Linux
curl -fsSL https://ollama.com/install.sh | sh
# Windows
irm https://ollama.com/install.ps1 | iex

ollama run gemma4

ollama run starts an interactive chat. But the real value for developers is the daemon: Ollama serves a REST API on http://localhost:11434 the moment it’s installed.

curl http://localhost:11434/api/chat -d '{
  "model": "gemma4",
  "messages": [{"role": "user", "content": "Why is the sky blue?"}],
  "stream": false
}'

Using it from Python

pip install ollama gives you a first-party SDK:

from ollama import chat

response = chat(model="gemma4", messages=[
    {"role": "user", "content": "Why is the sky blue?"},
])
print(response.message.content)

Because Ollama also exposes an OpenAI-compatible endpoint at /v1, you can point any tool that speaks OpenAI — LangChain, LlamaIndex, LiteLLM — at your local models without code changes:

from openai import OpenAI

client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
r = client.chat.completions.create(
    model="gemma4",
    messages=[{"role": "user", "content": "Why is the sky blue?"}],
)
print(r.choices[0].message.content)

Running in Docker for on-prem

For a shared team box or a containerized service, the official image is ollama/ollama. Warm a model on startup so the first request isn’t slow:

# docker-compose.yml
services:
  ollama:
    image: ollama/ollama
    ports:
      - "11434:11434"
    volumes:
      - ollama_data:/root/.ollama
    environment:
      - OLLAMA_HOST=0.0.0.0
volumes:
  ollama_data:
docker compose up -d
docker exec ollama ollama pull gemma4

Dropping down to llama.cpp directly

Ollama handles most cases, but when you need a specific quantization, a GGUF you built yourself, or bare-metal control, use llama.cpp directly:

git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp && cmake -B build && cmake --build build --config Release

# server mode with an OpenAI-compatible API
./build/bin/llama-server \
  -m models/gemma-4b-it-q4_k_m.gguf \
  -c 8192 \
  --port 8080

The model file is a GGUF — llama.cpp’s quantized format. q4_k_m is a good default: ~4-bit quantization that keeps most of the quality at a fraction of the memory. Ollama handles GGUF for you; with llama.cpp you manage it yourself.

Putting It All Together

A realistic local-first setup for a dev team: Docker Compose runs Ollama with a couple of pinned models, your FastAPI app talks to localhost:11434/v1 through the OpenAI SDK, and CI uses the same image so tests run identically on a laptop or a server. The complete compose file and app wiring are in this gist.

Conclusion & Next Steps

You can now run open models locally via Ollama, reach them with an OpenAI-compatible client, and drop to llama.cpp for fine-grained control. Next steps: pin model versions for reproducibility, add a Modelfile to tune system prompts and parameters per model, and measure throughput (tok/s) with OLLAMA_NUM_PARALLEL before scaling to a GPU server.

References / Sources