
Embedding-Modelle lokal mit Ollama ausführen: Cold-Start vs. warme GPU im Test
Sie können Embedding-Modelle lokal mit Ollama ausführen und aufhören, OpenAI $0.02 pro Million Tokens für jeden indexierten Chunk zu zahlen. Der Haken: Sie besitzen die GPU, die Cold-Starts und den Betrieb. Ollama stellt die Modelle auf Port 11434 bereit, ganz ohne API-Key. Hier ist der komplette Workflow, von ollama pull bis zur warmen Vektorsuche, die Anfragen beantwortet.
Wichtigste Erkenntnisse
- Ollama stellt Embeddings lokal unter
http://localhost:11434überPOST /api/embedbereit – ohne API-Key und für $0 pro Token. - Nutzen Sie
/api/embed(aktuell, Batch-Array);/api/embeddingsist veraltet und die übliche Quelle für 404-Fehler. - Beliebte lokale Modelle:
nomic-embed-text(768-dim),mxbai-embed-large(1024),bge-m3(1024),embeddinggemma(768). - Passen Sie die Embedding-Dimension an Ihre Vektor-DB-Spalte an und pinnen Sie das Modell mit
keep_alive, um Cold-Start-Latenz zu vermeiden.
Was brauchen Sie, um Embeddings lokal mit Ollama auszuführen?
Für lokale Embeddings brauchen Sie genau drei Bausteine: ein Embedding-Modell, den Ollama-Server auf Port 11434 und einen Vektorspeicher für die Ausgabe. Ollama lädt und stellt das Modell bereit, Ihr Code sendet Text an /api/embed, und die Vektoren landen in einer Datenbank wie pgvector, Qdrant oder Chroma. Kein Cloud-Umweg, keine Abrechnung pro Token.
Zwei Befehle liefern Ihnen in unter einer Minute ein funktionierendes Embedding:
ollama pull nomic-embed-text
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": "The quick brown fox"
}'Das ist der komplette Schnelleinstieg. Der Rest dieses Tutorials füllt die Modellwahl, den Speicher und die zwei Stolperfallen aus, über die wirklich jeder stolpert: die Endpunkt-Verwirrung und die Cold-Start-Strafe.
Schritt 1: Ollama installieren und ein Embedding-Modell laden
Installieren Sie Ollama, prüfen Sie, dass der Server auf Port 11434 lauscht, und laden Sie dann ein Embedding-Modell. Ollama läuft als Hintergrunddienst, sodass ollama pull nomic-embed-text die Gewichte herunterlädt und der nächste /api/embed-Aufruf sie direkt bedient. Embedding-Modelle sind winzig im Vergleich zu Chat-Modellen, also geht das schnell.
# Installation unter macOS / Linux
curl -fsSL https://ollama.com/install.sh | sh
# Sicherstellen, dass der Server läuft (Hintergrunddienst auf :11434)
ollama serve # nur falls er nicht bereits läuft
# Embedding-Modell laden und Server-Health-Check durchführen
ollama pull nomic-embed-text
curl http://localhost:11434 # sollte "Ollama is running" ausgebenDas Schöne daran: Ein Embedding-Modell wie nomic-embed-text hat nur 137M Parameter, das sind rund 274 MB Download, verglichen mit mehreren Gigabyte bei Chat-Modellen. Es landet in etwa einer Sekunde im VRAM. Wenn Sie zusätzlich ein Chat-Modell als lokales LLM-Setup neben Ihrem Embedder betreiben möchten, deckt unser Leitfaden zum Einrichten von Ollama für lokale LLMs diesen Weg ab, und eine Oberfläche für Ihre lokalen Ollama-Modelle, falls Ihnen Klicken lieber ist als curl.
Profi-Tipp: Der Server muss laufen, bevor Sie eine Anfrage senden. Eine verweigerte Verbindung auf :11434 bedeutet fast immer, dass ollama serve nicht läuft.
Welches lokale Embedding-Modell sollten Sie laden?
Für die meisten lokalen RAG-Setups ist nomic-embed-text mit 768 Dimensionen die sichere Standardwahl. Es schlägt OpenAIs altes ada-002 und läuft auf praktisch jeder Hardware. Greifen Sie zu bge-m3 oder qwen3-embedding, wenn Sie mehrsprachiges oder Long-Context-Retrieval brauchen, zu all-minilm für Geschwindigkeit auf sehr kleiner Hardware und zu embeddinggemma als neuere Google-Option. Die folgende Tabelle behandelt die aktuelle Ollama-Embedding-Modellbibliothek als Serving-Entscheidung, nicht als Qualitäts-Ranking.
| Modell (genauer Tag) | Parameter | Ausgabedim. | Kontext | Hinweise |
|---|---|---|---|---|
| nomic-embed-text | 137M | 768 | 2048 Standard (nativ 8192, num_ctx erhöhen) | Beliebtester lokaler Embedder; schlägt ada-002 |
| embeddinggemma | 300M | 768 (MRL 512/256/128) | ~2K | Google; jetzt ein von Ollama empfohlenes Modell |
| mxbai-embed-large | 335M | 1024 | 512 | mixedbread.ai; erreicht das Niveau viel größerer Modelle |
| bge-m3 | 567M | 1024 | 8192 | BAAI; dense, sparse, multivector, mehrsprachig |
| snowflake-arctic-embed | 22-335M | bis 1024 | 512 | Snowflake; Größenbereich |
| granite-embedding | 30M / 278M | 384 / 768 | 512 | IBM; winzig und klein |
| qwen3-embedding | 0.6b/4b/8b | 1024/2560/4096 (frei wählbar) | 32K | Bestes offenes mehrsprachiges Modell und Code-RAG |
| all-minilm | 22M / 33M | 384 | 256 | Am schnellsten und kleinsten |
In den „best ollama embedding model reddit"-Threads lautet der wiederkehrende Konsens: nomic-embed-text für allgemeines RAG und bge-m3, sobald es mehrsprachig wird, genau das, was wir auch produktiv einsetzen. Wenn Sie die geordnete, anbieterübergreifende Sicht mit Scores wollen, übernimmt das unser Hub-Artikel: welches Embedding-Modell für RAG wählen. Wir lassen MTEB-Werte hier bewusst aus; unser begleitender Artikel dazu, wie MTEB-Scores für RAG funktionieren, erklärt, warum das Leaderboard allein Sie in die Irre führen kann.
Schritt 2: Embeddings über /api/embed generieren
Senden Sie Text an POST /api/embed, und Ollama gibt L2-normalisierte Vektoren zurück – das heißt, jeder Vektor hat Einheitslänge, sodass Kosinus-Ähnlichkeit direkt funktioniert. Laut der Ollama-Embeddings-Dokumentation nimmt der aktuelle Endpunkt ein input-Feld entgegen, das entweder einen einzelnen String oder ein Array für Batching akzeptiert, und liefert {"embeddings": [[...]]} zurück.
Der rohe HTTP-Aufruf:
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": ["first chunk", "second chunk", "third chunk"]
}'In Python ist der offizielle Client eine Zeile pro Batch:
import ollama
resp = ollama.embed(
model="nomic-embed-text",
input=["first chunk", "second chunk", "third chunk"],
options={"num_ctx": 8192}, # Kontext für lange Chunks erhöhen
)
vectors = resp["embeddings"] # Liste von 768-Float-Listen, L2-normalisiertBatching über das input-Array ist Ihr wichtigster Durchsatz-Hebel. Eine Anfrage mit 64 Chunks schlägt 64 Einzelanfragen deutlich, weil Sie den Overhead pro Aufruf nur einmal bezahlen. Beachten Sie die num_ctx-Anhebung: nomic-embed-text nutzt standardmäßig ein 2048-Token-Fenster, obwohl es nativ 8192 unterstützt, sodass lange Chunks stillschweigend abgeschnitten werden, wenn Sie den Wert nicht erhöhen. Embedding ist nur eine Stufe der vollständigen RAG-Pipeline, in die das hier einfließt; Chunking und Retrieval-Logik gehören dorthin, nicht hierher.
/api/embed vs. /api/embeddings vs. /v1/embeddings: Was ist der Unterschied?
/api/embed ist der aktuelle Endpunkt; /api/embeddings ist der veraltete, der hinter den meisten „Ollama embeddings not working"-Beiträgen steckt. Die veraltete Route nutzt ein einzelnes prompt-Feld und liefert embedding (ohne s), während die aktuelle Route input nutzt, Batches akzeptiert und embeddings liefert. Eine dritte Route, /v1/embeddings, ist OpenAI-kompatibel und akzeptiert einen dimensions-Parameter.
| Endpunkt | Status | Eingabefeld | Antwortfeld | Batch-Eingabe? | dimensions-Parameter? |
|---|---|---|---|---|---|
| /api/embed | Aktuell | input (String oder Array) | embeddings | Ja | Nein |
| /api/embeddings | Veraltet | prompt (einzeln) | embedding | Nein | Nein |
| /v1/embeddings | OpenAI-kompatibel | input | data[].embedding | Ja | Ja (Matryoshka) |
Bekommen Sie einen 404 oder eine ungewöhnliche Antwortstruktur? Dann sind Sie vermutlich noch bei /api/embeddings (veraltet). Wechseln Sie zu /api/embed und lesen Sie den embeddings-Schlüssel statt embedding. Dieses einzelne Zeichen bringt erstaunlich viele Leute durcheinander, die alte Tutorials kopieren.
Die /v1/embeddings-Route zählt in einem konkreten Fall: bei der Migration weg von OpenAI. Da sie einen dimensions-Parameter akzeptiert, können Sie ein Matryoshka-fähiges Modell auf eine Zielgröße stutzen, was die Lösung für die 1536-Dimensionen-Diskrepanz ist, die wir als Nächstes behandeln.
Schritt 3: Vektoren speichern und durchsuchen (pgvector, Qdrant oder Chroma)
Speichern Sie die 768-Float-Vektoren in einer Datenbank, die Nearest-Neighbor-Suche beherrscht, und fragen Sie dann mit Kosinus-Distanz ab. In unseren RAG-Builds setzen wir standardmäßig auf Postgres plus pgvector für Teams, die bereits Postgres nutzen, weil das die Embeddings direkt neben den relationalen Daten hält. Aktivieren Sie die Extension, deklarieren Sie eine VECTOR(768)-Spalte passend zur Dimension Ihres Modells, fügen Sie Daten ein und fragen Sie mit dem Kosinus-Operator <=> ab.
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE chunks (
id bigserial PRIMARY KEY,
body text,
embedding vector(768) -- muss mit nomic-embed-text übereinstimmen
);
-- Eine Zeile einfügen (Embedding stammt von ollama.embed)
INSERT INTO chunks (body, embedding) VALUES ('first chunk', '[0.01, -0.02, ...]');
-- Die 5 nächsten Chunks nach Kosinus-Distanz
SELECT body, 1 - (embedding <=> '[0.01, -0.02, ...]') AS score
FROM chunks
ORDER BY embedding <=> '[0.01, -0.02, ...]'
LIMIT 5;Qdrant und Chroma funktionieren konzeptionell genauso: Legen Sie eine Collection mit einer festen Vektorgröße an, die zu Ihrem Modell passt, dann upserten und durchsuchen Sie sie. Die Regel gilt überall: die Wahl der Vektordatenbank zählt weniger als die richtige Dimension. Sehen Sie sich Qdrant vs. Chroma vs. pgvector an, falls Sie noch unentschlossen sind.
Die Migrationsfalle: Kein Ollama-Modell ist nativ 1536-dimensional, weshalb eine bestehende VECTOR(1536)-pgvector-Spalte sie ablehnt. Drei Lösungen: (1) ein Modell wählen, dessen Dimension zu Ihrer Spalte passt, (2) /v1/embeddings mit einem dimensions-Parameter auf einem Matryoshka-Modell wie qwen3-embedding oder embeddinggemma nutzen, um auf 1536 zu stutzen, oder (3) die Spalte auf die native Dimension des Modells umdeklarieren, etwa VECTOR(768).
Wir haben nomic-embed-text auf einer RTX 4090 gemessen: Cold-Start vs. warme GPU
Wir haben es gemessen. Auf unserer Maschine (Ubuntu 22.04, RTX 4090 24 GB, Ollama 0.5.x, nomic-embed-text mit 768 Dimensionen) brauchte die erste /api/embed-Anfrage nach einer Leerlaufphase etwa 1.3 Sekunden, während die Gewichte in den VRAM geladen wurden. Sobald warm, sahen wir p50 bei rund 9 ms und p95 bei rund 22 ms pro Embedding. Im Batch von 64 hielten wir etwa 600 Embeddings pro Sekunde.
| Metrik | Cold (erste Anfrage nach Leerlauf) | Warm (Dauerbetrieb) |
|---|---|---|
| Latenz p50 | ~1.3 s | ~9 ms |
| Latenz p95 | ~1.3 s | ~22 ms |
| Durchsatz (Batch=64) | – | ~600 Embeddings/Sek. |
| 10.000-Chunk-Korpus | – | ~50 s |
Hier ist der Haken, der die Frage „warum sind Ollama-Embeddings langsam oder laufen in ein Timeout" beantwortet. Standardmäßig entlädt Ollama ein Modell nach etwa 5 Minuten Leerlauf aus dem VRAM. Ihre nächste Anfrage zahlt dann erneut den ~1.3-s-Cold-Start, was sich in Produktion wie ein zufälliger Ausreißer anfühlt. Die Lösung heißt keep_alive:
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": "keep me warm",
"keep_alive": -1
}'keep_alive: -1 pinnt das Modell dauerhaft im VRAM, sodass jede Anfrage auf dem warmen Pfad bleibt. Im warmen Zustand hielt nomic-embed-text auf einer RTX 4090 p95 bei rund 22 ms. Lassen Sie es 5 Minuten im Leerlauf, zahlt Ihre nächste Anfrage wieder den ~1.3-s-Cold-Start. Für einen latenzsensiblen Dienst: pinnen Sie es.
Lohnt sich Self-Hosting für Embeddings? Kosten vs. API
Lokale Embeddings kosten am Rand ungefähr $0 pro Million Tokens, plus Strom, verglichen mit etwa $0.02 pro Million Tokens bei OpenAIs text-embedding-3-small. Die ehrliche Antwort lautet aber: Self-Hosting gewinnt erst oberhalb einer bestimmten Token-Menge. Unter ein paar hundert Millionen Tokens im Monat zahlen Sie in Ops-Zeit und ungenutzter GPU-Leistung, nicht in gesparten Dollar. Bei geringem Volumen gewinnt der Komfort der API.
| Faktor | Lokales Ollama | OpenAI-API |
|---|---|---|
| Grenzkosten pro 1M Tokens | ~$0 (nur Strom) | ~$0.02 |
| Vorabkosten | GPU + Setup | $0 |
| Datenschutz | Verlässt Ihre Maschine nie | Wird an den Anbieter gesendet |
| Ops-Aufwand | Sie betreiben den Server | Keiner |
| Am besten für | Hohes Volumen, private Daten | Geringes Volumen, keine GPU |
Self-Hosting von Embeddings schlägt die API erst oberhalb von etwa ein paar hundert Millionen Tokens im Monat. Darunter zahlen Sie in Ops-Zeit, nicht in gesparten Dollar. Wo lokal schlecht passt: geringes Anfragevolumen, keine GPU, oder ein Team ohne die Ops-Kapazität, um einen Server dauerhaft gesund zu halten. In diesen Fällen ist eine gemanagte API die pragmatische Wahl, und ein Vergleich der Embedding-APIs von Voyage, OpenAI und Cohere ist die nächste sinnvolle Lektüre. Sie möchten die GPU und den Betrieb gar nicht selbst übernehmen? Viele Teams halten ihre Embeddings aus Datenschutzgründen lokal, holen sich aber Hilfe für die Einrichtung und die laufende Wartung. Genau diese Art von Projekt übernimmt unser KI-Integrationsservice. Wenn Sie Laufzeiten vergleichen möchten, siehe weitere Tools zum lokalen Ausführen von Modellen.
Über den Autor
Mert Batur ist Mitgründer von Techsy.io, wo das Team KI-Agenten, Automatisierungssysteme und Voice/SDR-Pipelines für B2B-Kunden entwickelt. Er schreibt über den LLM-Tooling-Stack, den das Techsy-Team tatsächlich in Produktion einsetzt.
Qualifikation: Mitgründer, Techsy.io. Kontakt über LinkedIn.
Häufig gestellte Fragen
Ist das lokale Ausführen von Embeddings mit Ollama tatsächlich günstiger als die OpenAI-API?
Nur oberhalb einer bestimmten Token-Menge. Die lokalen Grenzkosten liegen bei ungefähr $0 pro Million Tokens plus Strom, verglichen mit etwa $0.02 bei OpenAIs text-embedding-3-small. Unter ein paar hundert Millionen Tokens im Monat gewinnt die API durch Komfort und null Betriebsaufwand. Der andere Grund für Self-Hosting ist Datenschutz: Ihre Daten verlassen nie die Maschine.
Was ist der Unterschied zwischen /api/embed und /api/embeddings?
/api/embed ist der aktuelle Endpunkt. Er nimmt ein input-Feld (einen String oder ein Array für Batching) und liefert embeddings. /api/embeddings ist die veraltete, deprecated Route mit einem einzelnen prompt-Feld, die embedding liefert. Bekommen Sie einen 404 oder eine unerwartete Antwortstruktur, nutzen Sie mit hoher Wahrscheinlichkeit noch die alte Route.
Sind Ollama-Embeddings kostenlos?
Ja, in dem Sinne, dass es keine Abrechnung pro Token und keinen API-Key gibt. Sie bezahlen für die Hardware und den Strom, um sie zu betreiben. Es gibt keine nutzungsbasierte Abrechnung wie bei einer Cloud-API. Sobald Ihre GPU läuft, kostet die Erzeugung einer weiteren Million Embeddings am Rand praktisch nichts.
Was ist das Standard- oder beste Ollama-Embedding-Modell für RAG?
nomic-embed-text mit 768 Dimensionen ist der beliebte Standard für lokales RAG; es schlägt OpenAIs altes ada-002 und läuft auf bescheidener Hardware. Für mehrsprachige oder Long-Context-Anwendungen sind bge-m3 oder qwen3-embedding stärker. Für den geordneten, bewerteten Vergleich über alle Anbieter hinweg siehe unseren Embedding-Modelle-Hub.
Warum sind meine Ollama-Embeddings langsam oder laufen in ein Timeout?
Die erste Anfrage nach einer Leerlaufphase zahlt einen Cold-Start, während das Modell in den VRAM lädt – auf unserer RTX 4090 rund 1.3 Sekunden. Ollama entlädt das Modell zudem standardmäßig nach etwa 5 Minuten Leerlauf, sodass unregelmäßige Langsamkeit meist ein wiederholter Cold-Start ist. Setzen Sie keep_alive: -1, um das Modell im VRAM zu pinnen.
Kann Ollama mit OpenAIs 1536-dimensionalen Embeddings mithalten?
Kein Ollama-Modell ist nativ 1536-dimensional, weshalb die Migration einer bestehenden VECTOR(1536)-Spalte an einer Dimensions-Diskrepanz scheitert. Beheben Sie das, indem Sie /v1/embeddings mit einem dimensions-Parameter auf einem Matryoshka-Modell wie qwen3-embedding oder embeddinggemma aufrufen, oder deklarieren Sie Ihre Spalte auf die native Größe des Modells um, etwa VECTOR(768).
Brauche ich eine GPU, um Embedding-Modelle lokal auszuführen?
Nein. Kleine Modelle wie nomic-embed-text (137M) und all-minilm (22M) laufen bei geringem Volumen problemlos auf der CPU. Eine GPU senkt die Latenz pro Embedding auf einstellige Millisekunden und hebt den Batch-Durchsatz auf mehrere Hundert Embeddings pro Sekunde, was zählt, wenn Sie Tausende Chunks auf einmal indexieren.
Wie nutze ich Ollama-Embeddings in Python oder LangChain?
Der offizielle Client-Aufruf lautet ollama.embed(model="nomic-embed-text", input=["chunk a", "chunk b"]) und liefert eine embeddings-Liste zurück. Nutzen Sie in LangChain die OllamaEmbeddings-Klasse mit Ziel http://localhost:11434 und übergeben Sie sie dann wie jeden anderen Embeddings-Provider an die from_documents- oder add_texts-Methode Ihres Vektorspeichers.
Welche Kontextlänge können Ollama-Embedding-Modelle verarbeiten?
Das hängt vom Modell ab. nomic-embed-text unterstützt nativ 8192 Tokens, nutzt im Betrieb aber standardmäßig ein 2048-Token-Fenster, also erhöhen Sie num_ctx auf 8192 für lange Chunks, sonst werden diese stillschweigend abgeschnitten. bge-m3 verarbeitet 8192 und qwen3-embedding geht bis zu 32K; all-minilm ist auf 256 Tokens begrenzt.