
Kjør Embedding-modeller Lokalt med Ollama: Vi Tidsmålte Kald vs. Varm GPU
Du kan kjøre embedding-modeller lokalt med Ollama og slutte å betale OpenAI $0.02 per million tokens for hver eneste chunk du indekserer. Baksiden: du eier GPU-en, kaldstartene og driften selv. Ollama serverer dem på port 11434 uten API-nøkkel. Her er hele arbeidsflyten, fra ollama pull til et varmt vektorsøk som svarer på spørringer.
Viktigste poeng
- Ollama serverer embeddings lokalt på
http://localhost:11434viaPOST /api/embed, uten API-nøkkel og for $0 per token. - Bruk
/api/embed(nåværende, batch-array);/api/embeddingser utdatert og den vanligste kilden til 404-feil. - Populære lokale modeller:
nomic-embed-text(768-dim),mxbai-embed-large(1024),bge-m3(1024),embeddinggemma(768). - Match embedding-dimensjonen din med vektordatabase-kolonnen, og fest modellen med
keep_alivefor å unngå kaldstart-forsinkelse.
Hva trenger du for å kjøre embeddings lokalt med Ollama?
Alt du trenger for å kjøre embeddings lokalt er tre deler: en embedding-modell, Ollama-serveren på port 11434, og en vektordatabase til å lagre resultatet. Ollama laster ned og serverer modellen; koden din poster tekst til /api/embed; vektorene havner i en database som pgvector, Qdrant eller Chroma. Ingen sky-rundtur, ingen per-token-regning.
To kommandoer gir deg en fungerende embedding på under et minutt:
ollama pull nomic-embed-text
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": "The quick brown fox"
}'Det er hele hurtigstarten. Resten av denne guiden fyller inn modellvalget, lagringen, og de to fellene som biter alle: endepunkt-forvirringen og kaldstart-straffen.
Steg 1: Installer Ollama og hent en embedding-modell
Installer Ollama, bekreft at serveren lytter på port 11434, og hent så en embedding-modell. Ollama kjører som en bakgrunnstjeneste, så ollama pull nomic-embed-text laster ned vektene, og neste /api/embed-kall serverer dem. Embedding-modeller er bittesmå sammenlignet med chat-modeller, så dette går fort.
# Installasjon for macOS / Linux
curl -fsSL https://ollama.com/install.sh | sh
# Sørg for at serveren kjører (bakgrunnstjeneste på :11434)
ollama serve # bare hvis den ikke allerede kjører
# Hent en embedding-modell og sjekk at serveren svarer
ollama pull nomic-embed-text
curl http://localhost:11434 # bør returnere "Ollama is running"Her er det kule: en embedding-modell som nomic-embed-text er bare 137M parametere, omtrent en 274 MB nedlasting, mot flere-gigabyte chat-modeller. Den lastes inn i VRAM på rundt et sekund. Hvis du vil ha hele det lokale LLM-oppsettet med en chat-modell ved siden av embedderen din, dekker guiden vår om å sette opp Ollama for lokale LLM-er den veien, og et grensesnitt for de lokale Ollama-modellene dine hvis du heller vil klikke enn å curl-e.
Proff-tips: serveren må kjøre før noen forespørsel sendes. En avvist tilkobling på :11434 betyr nesten alltid at ollama serve ikke kjører.
Hvilken lokal embedding-modell bør du hente?
For de fleste lokale RAG-oppsett er nomic-embed-text på 768 dimensjoner det trygge standardvalget. Den slår OpenAIs gamle ada-002 og kjører på nesten hva som helst. Bruk bge-m3 eller qwen3-embedding når du trenger flerspråklig eller lang-kontekst gjenfinning, all-minilm for hastighet på liten maskinvare, og embeddinggemma som Googles nyere alternativ. Tabellen under dekker dagens Ollama embedding-modellbibliotek som et serveringsvalg, ikke en kvalitetsrangering.
| Modell (eksakt tag) | Parametere | Utdim. | Kontekst | Notater |
|---|---|---|---|---|
| nomic-embed-text | 137M | 768 | 2048 standard (nativt 8192, øk num_ctx) | Mest populære lokale embedder; slår ada-002 |
| embeddinggemma | 300M | 768 (MRL 512/256/128) | ~2K | Google; nå en Ollama-anbefalt modell |
| mxbai-embed-large | 335M | 1024 | 512 | mixedbread.ai; matcher mye større modeller |
| bge-m3 | 567M | 1024 | 8192 | BAAI; tett, glissen, multivektor, flerspråklig |
| snowflake-arctic-embed | 22-335M | opptil 1024 | 512 | Snowflake; størrelsesspenn |
| granite-embedding | 30M / 278M | 384 / 768 | 512 | IBM; liten og bitteliten |
| qwen3-embedding | 0.6b/4b/8b | 1024/2560/4096 (brukerdefinert) | 32K | Best åpne flerspråklige og kode-RAG |
| all-minilm | 22M / 33M | 384 | 256 | Raskest og minst |
På «best ollama embedding model reddit»-trådene er den gjentagende konsensusen nomic-embed-text for generell RAG og bge-m3 når du går flerspråklig, noe som matcher det vi selv leverer. Vil du ha den rangerte, tverr-leverandør-visningen med poengsummer, er det jobben til hub-artikkelen: hvilken embedding-modell du bør velge for RAG. Vi hopper bevisst over MTEB-tallene her; vår egen artikkel om hvordan MTEB-skår fungerer for RAG forklarer hvorfor rangeringslisten alene kan lure deg.
Steg 2: Generer embeddings via /api/embed
Send tekst til POST /api/embed, og Ollama returnerer L2-normaliserte vektorer, som betyr at hver av dem har enhetslengde slik at cosinuslikhet fungerer direkte. Ifølge Ollama sin embeddings-dokumentasjon tar det nåværende endepunktet et input-felt som godtar enten en enkelt streng eller et array for batching, og returnerer {"embeddings": [[...]]}.
Det rå HTTP-kallet:
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": ["first chunk", "second chunk", "third chunk"]
}'I Python er den offisielle klienten én linje per batch:
import ollama
resp = ollama.embed(
model="nomic-embed-text",
input=["first chunk", "second chunk", "third chunk"],
options={"num_ctx": 8192}, # øk konteksten for lange chunker
)
vectors = resp["embeddings"] # liste med 768-flyttall, L2-normalisertBatching via input-arrayet er din viktigste gjennomstrømningsspak. Én forespørsel med 64 chunker slår 64 enkeltforespørsler med god margin, fordi du bare betaler kall-overheaden én gang. Legg merke til num_ctx-økningen: nomic-embed-text bruker som standard et 2048-tokens vindu selv om den nativt støtter 8192, så lange chunker blir stille avkortet med mindre du øker det. Embedding er bare ett steg i hele RAG-pipelinen dette mater inn i; chunking- og gjenfinningslogikken bor der, ikke her.
/api/embed vs. /api/embeddings vs. /v1/embeddings: Hva er forskjellen?
/api/embed er det nåværende endepunktet; /api/embeddings er det utdaterte som ligger bak de fleste «Ollama embeddings fungerer ikke»-innleggene. Den gamle ruten bruker et entall prompt-felt og returnerer embedding (uten s), mens den nåværende ruten bruker input, godtar batcher, og returnerer embeddings. En tredje rute, /v1/embeddings, er OpenAI-kompatibel og godtar en dimensions-parameter.
| Endepunkt | Status | Input-felt | Responsfelt | Batch-input? | dimensions-parameter? |
|---|---|---|---|---|---|
| /api/embed | Nåværende | input (streng eller array) | embeddings | Ja | Nei |
| /api/embeddings | Utdatert / avviklet | prompt (enkelt) | embedding | Nei | Nei |
| /v1/embeddings | OpenAI-kompatibel | input | data[].embedding | Ja | Ja (Matryoshka) |
Får du en 404 eller en rar responsform? Da er du sannsynligvis på /api/embeddings (utdatert). Bytt til /api/embed og les embeddings-nøkkelen i stedet for embedding. Det ene tegnet snubler mange som kopierer gamle veiledninger.
/v1/embeddings-ruten er relevant for ett spesifikt tilfelle: migrering bort fra OpenAI. Fordi den godtar en dimensions-parameter, kan du avkorte en Matryoshka-kapabel modell ned til en målstørrelse, som er fiksen for 1536-dimensjons-mismatchen vi dekker neste.
Steg 3: Lagre og søk i vektorene dine (pgvector, Qdrant eller Chroma)
Lagre de 768-flyttalls vektorene i en database som gjør nærmeste-nabo-søk, og spør deretter med cosinusavstand. I våre RAG-bygg bruker vi som standard Postgres pluss pgvector for team som allerede kjører Postgres, fordi det holder embeddingene dine ved siden av de relasjonelle dataene dine. Aktiver utvidelsen, deklarer en VECTOR(768)-kolonne som matcher modellens dimensjon, sett inn, og spør med <=>-cosinusoperatoren.
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE chunks (
id bigserial PRIMARY KEY,
body text,
embedding vector(768) -- må matche nomic-embed-text
);
-- Sett inn en rad (embedding kommer fra ollama.embed)
INSERT INTO chunks (body, embedding) VALUES ('first chunk', '[0.01, -0.02, ...]');
-- Topp 5 nærmeste chunker etter cosinusavstand
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 på samme måte konseptuelt: opprett en samling med en fast vektorstørrelse som matcher modellen din, og sett så inn og søk. Regelen gjelder overalt: å velge en vektordatabase betyr mindre enn å få dimensjonen riktig. Se Qdrant vs. Chroma vs. pgvector hvis du fortsatt bestemmer deg.
Migreringsfellen: ingen Ollama-modell er nativt 1536-dim, så en eksisterende VECTOR(1536)-pgvector-kolonne vil avvise dem. Tre løsninger: (1) velg en modell hvis dimensjon matcher kolonnen din, (2) bruk /v1/embeddings med en dimensions-parameter på en Matryoshka-modell som qwen3-embedding eller embeddinggemma for å avkorte til 1536, eller (3) omdeklarer kolonnen til modellens native dimensjon, for eksempel VECTOR(768).
Vi tidsmålte nomic-embed-text på en RTX 4090: Kaldstart vs. varm GPU
Vi målte det. På boksen vår (Ubuntu 22.04, RTX 4090 24 GB, Ollama 0.5.x, nomic-embed-text på 768-dim) tok den første /api/embed-forespørselen etter en inaktiv periode rundt 1.3 sekunder mens vektene ble lastet inn i VRAM. Når den var varm, så vi p50 rundt 9 ms og p95 rundt 22 ms per embedding. Batchet med 64, holdt vi omtrent 600 embeddings/sek.
| Metrikk | Kald (første forespørsel etter inaktivitet) | Varm (stabil tilstand) |
|---|---|---|
| Ventetid p50 | ~1.3 s | ~9 ms |
| Ventetid p95 | ~1.3 s | ~22 ms |
| Gjennomstrømning (batch=64) | n/a | ~600 embeddings/sek |
| 10,000-chunks korpus | n/a | ~50 s |
Her er fellen som svarer på «hvorfor er Ollama embeddings trege eller får timeout». Som standard laster Ollama en modell ut av VRAM etter rundt 5 minutters inaktivitet. Så neste forespørsel betaler den ~1.3 s kaldstarten på nytt, noe som føles som en tilfeldig spike i produksjon. Fiksen er keep_alive:
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": "keep me warm",
"keep_alive": -1
}'Å sette keep_alive: -1 fester modellen i VRAM på ubestemt tid, slik at hver forespørsel holder seg på den varme banen. Varm holdt nomic-embed-text på en RTX 4090 p95 rundt 22 ms. La den stå inaktiv i 5 minutter, og neste forespørsel betaler en ~1.3 s kaldstart på nytt. For en ventetidsfølsom tjeneste, fest den.
Er det verdt å selvhoste embeddings? Kostnad vs. et API
Lokale embeddings koster omtrent $0 per million tokens på marginen, pluss strøm, mot rundt $0.02 per million tokens for OpenAI text-embedding-3-small. Men det ærlige svaret er: selvhosting vinner først over en terskel for tokenvolum. Under noen hundre millioner tokens i måneden betaler du i driftstid og ledig GPU, ikke sparte kroner. API-ets bekvemmelighet vinner for lavt volum.
| Faktor | Lokal Ollama | OpenAI API |
|---|---|---|
| Marginalkostnad per 1M tokens | ~$0 (kun strøm) | ~$0.02 |
| Oppstartskostnad | GPU + oppsett | $0 |
| Datapersonvern | Forlater aldri maskinen din | Sendes til leverandøren |
| Driftsbyrde | Du kjører serveren | Ingen |
| Best ved | Høyt volum, private data | Lavt volum, ingen GPU |
Selvhosting av embeddings slår kun API-et over rundt noen hundre millioner tokens i måneden. Under det betaler du i driftstid, ikke sparte kroner. Der lokalt er dårlig egnet: lavt spørringsvolum, ingen GPU, eller et team uten driftskapasitet til å holde en server sunn. I de tilfellene er et administrert API det pragmatiske valget, og en sammenligning av Voyage, OpenAI og Cohere sine embedding-API-er er neste ting å lese. Vil du ikke ha ansvaret for GPU-en og driften selv? Mange team holder embeddingene lokalt av personvernhensyn, men henter inn hjelp til oppsettet og det daglige vedlikeholdet. Det er nettopp den typen bygg som vår AI-integrasjonstjeneste tar seg av. Vil du sammenligne kjøremiljøer, se andre verktøy for å kjøre modeller lokalt.
Om forfatteren
Mert Batur er medgründer av Techsy.io, der teamet leverer AI-agenter, automatiseringssystemer og stemme-/SDR-pipeliner til B2B-kunder. Han skriver om LLM-verktøystacken Techsy-teamet faktisk bruker i produksjon. Ta kontakt på LinkedIn.
Ofte stilte spørsmål
Er det faktisk billigere å kjøre embeddings lokalt med Ollama enn OpenAI API-et?
Bare over en terskel for tokenvolum. Lokal marginalkostnad er omtrent $0 per million tokens pluss strøm, mot rundt $0.02 for OpenAI text-embedding-3-small. Under noen hundre millioner tokens i måneden vinner API-et på bekvemmelighet og null drift. Den andre grunnen til å selvhoste er personvern: dataene dine forlater aldri maskinen.
Hva er forskjellen mellom /api/embed og /api/embeddings?
/api/embed er det nåværende endepunktet. Det tar et input-felt (en streng eller et array for batching) og returnerer embeddings. /api/embeddings er den gamle, avviklede ruten med et entalls prompt-felt som returnerer embedding. Får du en 404 eller en uventet responsform, bruker du nesten helt sikkert den gamle.
Er Ollama-embeddings gratis?
Ja, i den forstand at det ikke er noen per-token-kostnad og ingen API-nøkkel. Du betaler for maskinvaren og strømmen til å kjøre den. Det finnes ingen målt fakturering som en sky-API, så når GPU-en først kjører, koster det å generere ytterligere en million embeddings i praksis ingenting på marginen.
Hva er standard- eller beste Ollama-embedding-modell for RAG?
nomic-embed-text på 768 dimensjoner er det populære standardvalget for lokal RAG; den slår OpenAIs gamle ada-002 og kjører på beskjeden maskinvare. For flerspråklig eller lang-kontekst-arbeid er bge-m3 eller qwen3-embedding sterkere. For den rangerte, poengsatte sammenligningen på tvers av leverandører, se vår embedding-modell-hub.
Hvorfor er Ollama-embeddingene mine trege eller får timeout?
Den første forespørselen etter inaktivitet betaler en kaldstart mens modellen lastes inn i VRAM, omtrent 1.3 sekunder på vår RTX 4090. Ollama laster også modellen ut som standard etter rundt 5 minutters inaktivitet, så periodisk treghet er vanligvis en gjentatt kaldstart. Sett keep_alive: -1 for å feste modellen i VRAM.
Kan Ollama matche OpenAIs 1536-dimensjonale embeddings?
Ingen Ollama-modell er nativt 1536-dim, så migrering av en eksisterende VECTOR(1536)-kolonne bryter på grunn av en dimensjons-mismatch. Fiks det ved å kalle /v1/embeddings med en dimensions-parameter på en Matryoshka-modell som qwen3-embedding eller embeddinggemma, eller omdeklarer kolonnen din til modellens native størrelse, for eksempel VECTOR(768).
Trenger jeg en GPU for å kjøre embedding-modeller lokalt?
Nei. Små modeller som nomic-embed-text (137M) og all-minilm (22M) kjører fint på CPU for lavt volum. En GPU kutter ventetiden per embedding til enkeltsifrede millisekunder og løfter batch-gjennomstrømningen til hundrevis av embeddings per sekund, noe som betyr noe når du indekserer tusenvis av chunker samtidig.
Hvordan bruker jeg Ollama-embeddings i Python eller LangChain?
Det offisielle klientkallet er ollama.embed(model="nomic-embed-text", input=["chunk a", "chunk b"]), som returnerer en embeddings-liste. I LangChain bruker du OllamaEmbeddings-klassen pekt mot http://localhost:11434, og sender den så til vektordatabasens from_documents- eller add_texts-metode som enhver annen embeddings-leverandør.
Hvilken kontekstlengde tåler Ollama-embedding-modeller?
Det varierer etter modell. nomic-embed-text støtter nativt 8192 tokens, men bruker som standard et 2048-tokens vindu når den serveres, så øk num_ctx til 8192 for lange chunker, ellers blir de stille avkortet. bge-m3 håndterer 8192 og qwen3-embedding går opp til 32K; all-minilm er begrenset til 256 tokens.