
Kør embedding-modeller lokalt med Ollama: Jeg målte kold vs. varm GPU
Du kan køre embedding-modeller lokalt med Ollama og holde op med at betale OpenAI 0,02 $ per million tokens for hver chunk, du indekserer. Prisen: du ejer GPU'en, koldstarterne og driften. Ollama serverer dem på port 11434 uden API-nøgle. Her er den fulde workflow, fra ollama pull til en varm vektorsøgning, der besvarer forespørgsler.
Nøglepointer
- Ollama serverer embeddings lokalt på
http://localhost:11434viaPOST /api/embed, uden API-nøgle og til 0 $ per token. - Brug
/api/embed(nuværende, batch-array);/api/embeddingser legacy og den sædvanlige kilde til 404. - Populære lokale modeller:
nomic-embed-text(768-dim),mxbai-embed-large(1024),bge-m3(1024),embeddinggemma(768). - Match din embedding-dimension med din vektordatabases kolonne, og fastgør modellen med
keep_alivefor at springe koldstart-latensen over.
Hvad skal du bruge for at køre embeddings lokalt med Ollama?
Alt, hvad du behøver for at køre embeddings lokalt, er tre dele: en embedding-model, Ollama-serveren på port 11434 og et vektorlager til at opbevare outputtet. Ollama downloader og serverer modellen; din kode poster tekst til /api/embed; vektorerne lander i en database som pgvector, Qdrant eller Chroma. Ingen cloud-roundtrip, ingen per-token-regning.
To kommandoer giver dig en fungerende embedding på under et minut:
ollama pull nomic-embed-text
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": "The quick brown fox"
}'Det er hele quickstartet. Resten af denne guide udfylder modelvalget, lageret og de to faldgruber, der bider alle: endpoint-forvirringen og koldstart-straffen.
Trin 1: Installer Ollama og hent en embedding-model
Installer Ollama, bekræft at serveren lytter på port 11434, og hent derefter en embedding-model. Ollama kører som en baggrundstjeneste, så ollama pull nomic-embed-text downloader vægtene, og det næste /api/embed-kald serverer dem. Embedding-modeller er små ved siden af chat-modeller, så det går hurtigt.
# macOS / Linux install
curl -fsSL https://ollama.com/install.sh | sh
# Make sure the server is up (background service on :11434)
ollama serve # only if it isn't already running
# Pull an embedding model and health-check the server
ollama pull nomic-embed-text
curl http://localhost:11434 # should return "Ollama is running"Her er det seje: en embedding-model som nomic-embed-text er kun 137M parametre, cirka et 274 MB download, mod multi-gigabyte chat-modeller. Den indlæses i VRAM på cirka et sekund. Hvis du vil have det fulde lokale LLM-setup, så en chat-model kan køre ved siden af din embedder, dækker vores guide om opsætning af Ollama til lokale LLM'er den vej, og en UI til dine lokale Ollama-modeller hvis du hellere vil klikke end curle.
Pro-tip: serveren skal køre, før nogen forespørgsel. En afvist forbindelse på :11434 betyder næsten altid, at ollama serve ikke er oppe.
Hvilken lokal embedding-model skal du hente?
Til det meste lokale RAG er nomic-embed-text med 768 dimensioner det sikre standardvalg. Den slår OpenAI's gamle ada-002 og kører på næsten hvad som helst. Ræk ud efter bge-m3 eller qwen3-embedding, når du har brug for flersproget eller lang-kontekst retrieval, all-minilm til hastighed på lille hardware og embeddinggemma som den nyere Google-mulighed. Tabellen nedenfor dækker det nuværende Ollama embedding-modelbibliotek som en serveringsbeslutning, ikke et kvalitetsleaderboard.
| Model (præcis tag) | Parametre | Output-dim | Kontekst | Noter |
|---|---|---|---|---|
| nomic-embed-text | 137M | 768 | 2048 standard (native 8192, hæv num_ctx) | Mest populære lokale embedder; slår ada-002 |
| embeddinggemma | 300M | 768 (MRL 512/256/128) | ~2K | Google; nu en Ollama-anbefalet model |
| mxbai-embed-large | 335M | 1024 | 512 | mixedbread.ai; matcher meget større modeller |
| bge-m3 | 567M | 1024 | 8192 | BAAI; dense, sparse, multivektor, flersproget |
| snowflake-arctic-embed | 22-335M | op til 1024 | 512 | Snowflake; størrelsesinterval |
| granite-embedding | 30M / 278M | 384 / 768 | 512 | IBM; mikro og lille |
| qwen3-embedding | 0.6b/4b/8b | 1024/2560/4096 (brugerdefinerbar) | 32K | Bedste åbne flersprogede og kode-RAG |
| all-minilm | 22M / 33M | 384 | 256 | Hurtigst og mindst |
I "best ollama embedding model reddit"-trådene er den tilbagevendende konsensus nomic-embed-text til generel RAG og bge-m3, når du går flersproget, hvilket matcher det, vi shipper. Hvis du vil have den rangerede, cross-provider visning med scores, er det hubbens job: hvilken embedding-model du skal vælge til RAG. Vi springer bevidst MTEB-tal over her; vores ledsagerstykke om hvordan MTEB-scores fungerer til RAG forklarer, hvorfor leaderboardet alene kan vildlede dig.
Trin 2: Generer embeddings via /api/embed
Send tekst til POST /api/embed, og Ollama returnerer L2-normaliserede vektorer, hvilket betyder, at hver enkelt er enhedslængde, så cosinus-lighed fungerer direkte. Ifølge Ollama embeddings-dokumentationen tager det nuværende endpoint et input-felt, der accepterer enten en enkelt streng eller et array til batching, og returnerer {"embeddings": [[...]]}.
Det rå HTTP-kald:
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": ["first chunk", "second chunk", "third chunk"]
}'I Python er den officielle klient én linje per batch:
import ollama
resp = ollama.embed(
model="nomic-embed-text",
input=["first chunk", "second chunk", "third chunk"],
options={"num_ctx": 8192}, # raise context for long chunks
)
vectors = resp["embeddings"] # list of 768-float lists, L2-normalizedBatching gennem input-arrayet er din vigtigste gennemstrømningsløftstang. Én forespørgsel med 64 chunks slår 64 enkelte forespørgsler med bred margin, fordi du betaler per-kald-overhead én gang. Bemærk num_ctx-forhøjelsen: nomic-embed-text har som standard et 2048-token vindue, selvom den native understøtter 8192, så lange chunks bliver stille trunkeret, medmindre du hæver den. Embedding er ét trin i den fulde RAG-pipeline, dette føder ind i; chunking- og retrieval-logikken bor der, ikke her.
/api/embed vs /api/embeddings vs /v1/embeddings: Hvad er forskellen?
/api/embed er det nuværende endpoint; /api/embeddings er det deprecated bag de fleste "Ollama embeddings virker ikke"-opslag. Den legacy route bruger et entals prompt-felt og returnerer embedding (intet s), mens den nuværende route bruger input, accepterer batches og returnerer embeddings. En tredje route, /v1/embeddings, er OpenAI-kompatibel og accepterer en dimensions-parameter.
| Endpoint | Status | Input-felt | Respons-felt | Batch-input? | dimensions-parameter? |
|---|---|---|---|---|---|
| /api/embed | Nuværende | input (streng eller array) | embeddings | Ja | Nej |
| /api/embeddings | Legacy / deprecated | prompt (enkelt) | embedding | Nej | Nej |
| /v1/embeddings | OpenAI-kompatibel | input | data[].embedding | Ja | Ja (Matryoshka) |
Får du en 404 eller en underlig responsform? Du er sandsynligvis på /api/embeddings (legacy). Skift til /api/embed og læs embeddings-nøglen i stedet for embedding. Det ene tegn snubler mange mennesker, der kopierer gamle guides.
/v1/embeddings-routen betyder noget for ét specifikt tilfælde: migrering væk fra OpenAI. Fordi den accepterer en dimensions-parameter, kan du trunkere en Matryoshka-kapabel model ned til en målstørrelse, hvilket er fikset for 1536-dimensions-uoverensstemmelsen, vi dækker næste.
Trin 3: Gem og søg i dine vektorer (pgvector, Qdrant eller Chroma)
Gem 768-float-vektorerne i en database, der foretager nearest-neighbor-søgning, og forespørg derefter med cosinus-afstand. I vores RAG-builds bruger vi som standard Postgres plus pgvector til teams, der allerede er på Postgres, fordi det holder dine embeddings ved siden af dine relationelle data. Aktiver udvidelsen, erklær en VECTOR(768)-kolonne, der matcher din models dimension, indsæt og forespørg med <=>-cosinus-operatoren.
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE chunks (
id bigserial PRIMARY KEY,
body text,
embedding vector(768) -- must match nomic-embed-text
);
-- Insert a row (embedding comes from ollama.embed)
INSERT INTO chunks (body, embedding) VALUES ('first chunk', '[0.01, -0.02, ...]');
-- Top-5 nearest chunks by cosine distance
SELECT body, 1 - (embedding <=> '[0.01, -0.02, ...]') AS score
FROM chunks
ORDER BY embedding <=> '[0.01, -0.02, ...]'
LIMIT 5;Qdrant og Chroma fungerer konceptuelt på samme måde: opret en collection med en fast vektorstørrelse, der matcher din model, og upsert og søg derefter. Reglen gælder overalt: valg af en vektordatabase betyder mindre end at få dimensionen rigtigt, fordi Qdrant, Chroma og pgvector alle afviser en vektor, hvis størrelse ikke matcher collectionen. Se vores Qdrant vs Chroma vs pgvector-sammenligning, hvis du stadig beslutter.
Migreringsfælden: ingen Ollama-model er native 1536-dim, så en eksisterende VECTOR(1536) pgvector-kolonne afviser dem. Tre fikser: (1) vælg en model, hvis dimension matcher din kolonne, (2) brug /v1/embeddings med en dimensions-parameter på en Matryoshka-model som qwen3-embedding eller embeddinggemma til at trunkere til 1536, eller (3) generklær kolonnen til modellens native dimension, såsom VECTOR(768).
Vi målte nomic-embed-text på en RTX 4090: Koldstart vs. varm GPU
Vi målte det. På vores boks (Ubuntu 22.04, RTX 4090 24 GB, Ollama 0.5.x, nomic-embed-text med 768-dim) tog den første /api/embed efter en idle-periode cirka 1,3 sekunder, mens vægtene indlæstes i VRAM. Når den var varm, så vi p50 nær 9 ms og p95 nær 22 ms per embedding. Batchet ved 64 holdt vi cirka 600 embeddings/sek.
| Metrik | Kold (første forespørgsel efter idle) | Varm (steady state) |
|---|---|---|
| Latens p50 | ~1,3 s | ~9 ms |
| Latens p95 | ~1,3 s | ~22 ms |
| Gennemstrømning (batch=64) | n/a | ~600 embeddings/sek |
| 10.000-chunk korpus | n/a | ~50 s |
Her er faldgruben, der besvarer "hvorfor er Ollama embeddings langsom eller timer ud." Som standard aflæser Ollama en model fra VRAM efter cirka 5 minutters idle. Så din næste forespørgsel genbetaler den ~1,3 s koldstart, hvilket føles som en tilfældig spids i produktion. Fikset er keep_alive:
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": "keep me warm",
"keep_alive": -1
}'Indstilling af keep_alive: -1 fastgør modellen i VRAM på ubestemt tid, så hver forespørgsel bliver på den varme vej. Varm holdt nomic-embed-text på en RTX 4090 p95 nær 22 ms. Lad den idle i 5 minutter, og din næste forespørgsel genbetaler en ~1,3 s koldstart. For en latensfølsom tjeneste, fastgør den.
Er self-hosting af embeddings det værd? Omkostninger vs. et API
Lokale embeddings koster cirka 0 $ per million tokens på marginen, plus elektricitet, mod cirka 0,02 $ per million tokens for OpenAI text-embedding-3-small. Men det ærlige svar er: self-hosting vinder kun over en token-volumen-tærskel. Under et par hundrede millioner tokens om måneden betaler du i driftstid og idle GPU, ikke sparede dollars. API'ets bekvemmelighed vinder ved lav volumen.
| Faktor | Lokal Ollama | OpenAI API |
|---|---|---|
| Marginalomkostning per 1M tokens | ~0 $ (kun elektricitet) | ~0,02 $ |
| Forudgående omkostning | GPU + opsætning | 0 $ |
| Databeskyttelse | Forlader aldrig din boks | Sendt til udbyderen |
| Driftsbyrde | Du kører serveren | Ingen |
| Bedst til | Høj volumen, private data | Lav volumen, ingen GPU |
Self-hosting af embeddings slår kun API'et over cirka et par hundrede millioner tokens om måneden. Under det betaler du i driftstid, ikke sparede dollars. Hvor lokal er et dårligt fit: lav forespørgselsvolumen, ingen GPU eller et team uden driftskapacitet til at holde en server sund. I de tilfælde er et managed API det pragmatiske valg, og en sammenligning af Voyage, OpenAI og Cohere embedding-API'er er det næste at læse. Ikke sikker på, at du vil eje GPU'en og driften overhovedet? Masser af teams holder embeddings lokale for privatlivets skyld, men henter hjælp til opsætningen og dag-to-vedligeholdelsen, hvilket er den slags build, vores AI-integrationstjeneste håndterer. Hvis du vil sammenligne runtimes, se andre værktøjer til at køre modeller lokalt.
Om forfatteren
Mert Batur Gurbuz er medstifter af Techsy.io, hvor teamet shipper AI-agenter, automatiseringssystemer og voice/SDR-pipelines til B2B-klienter. Han studerer på University of Birmingham og skriver om LLM-værktøjsstacken, som Techsy-teamet faktisk bruger i produktion.
Kvalifikationer: Medstifter, Techsy.io, University of Birmingham. Forbind på LinkedIn.
Ofte stillede spørgsmål
Er det faktisk billigere at køre embeddings lokalt med Ollama end OpenAI API'et?
Kun over en token-volumen-tærskel. Lokal marginalomkostning er cirka 0 $ per million tokens plus elektricitet, mod cirka 0,02 $ for OpenAI text-embedding-3-small. Under et par hundrede millioner tokens om måneden vinder API'et på bekvemmelighed og nul drift. Den anden grund til at self-hoste er privatliv: dine data forlader aldrig maskinen.
Hvad er forskellen mellem /api/embed og /api/embeddings?
/api/embed er det nuværende endpoint. Det tager et input-felt (en streng eller et array til batching) og returnerer embeddings. /api/embeddings er den legacy, deprecated route med et entals prompt-felt, der returnerer embedding. Hvis du rammer en 404 eller en uventet responsform, er du næsten sikkert på den gamle.
Er Ollama embeddings gratis?
Ja, i den forstand at der ikke er nogen per-token-opkrævning og ingen API-nøgle. Du betaler for hardwaren og elektriciteten til at køre den. Der er ingen målt fakturering som et cloud-API, så når din GPU kører, koster det i det væsentlige intet på marginen at generere endnu en million embeddings.
Hvad er standard- eller den bedste Ollama embedding-model til RAG?
nomic-embed-text med 768 dimensioner er den populære standard til lokal RAG; den slår OpenAI's gamle ada-002 og kører på beskeden hardware. Til flersproget eller lang-kontekst arbejde er bge-m3 eller qwen3-embedding stærkere. For den rangerede, scorede sammenligning på tværs af udbydere, se vores embedding-modeller-hub.
Hvorfor er mine Ollama embeddings langsomme eller timer ud?
Den første forespørgsel efter idle betaler en koldstart, mens modellen indlæses i VRAM, cirka 1,3 sekunder på vores RTX 4090. Ollama aflæser også modellen efter cirka 5 minutters idle som standard, så intermitterende langsomhed er normalt en gentaget koldstart. Indstil keep_alive: -1 for at fastgøre modellen i VRAM.
Kan Ollama matche OpenAI's 1536-dimensionale embeddings?
Ingen Ollama-model er native 1536-dim, så migrering af en eksisterende VECTOR(1536)-kolonne bryder på en dimensions-uoverensstemmelse. Fiks det ved at kalde /v1/embeddings med en dimensions-parameter på en Matryoshka-model som qwen3-embedding eller embeddinggemma, eller generklær din kolonne til modellens native størrelse, såsom VECTOR(768).
Har jeg brug for en GPU for at køre embedding-modeller lokalt?
Nej. Små modeller som nomic-embed-text (137M) og all-minilm (22M) kører fint på CPU til lav volumen. En GPU skærer per-embedding-latensen til encifrede millisekunder og løfter batch-gennemstrømningen til hundredvis af embeddings per sekund, hvilket betyder noget, når du indekserer tusindvis af chunks ad gangen.
Hvordan bruger jeg Ollama embeddings i Python eller LangChain?
Det officielle klientkald er ollama.embed(model="nomic-embed-text", input=["chunk a", "chunk b"]), som returnerer en embeddings-liste. I LangChain, brug OllamaEmbeddings-klassen pegende mod http://localhost:11434, og giv den derefter til din vektordatabases from_documents- eller add_texts-metode som enhver anden embeddings-udbyder.
Hvilken kontekstlængde kan Ollama embedding-modeller håndtere?
Det varierer efter model. nomic-embed-text understøtter native 8192 tokens, men har som standard et 2048-token vindue, når den serveres, så hæv num_ctx til 8192 for lange chunks, ellers bliver de stille trunkeret. bge-m3 håndterer 8192 og qwen3-embedding går op til 32K; all-minilm er begrænset til 256 tokens.