
Embedding modely lokálně s Ollama: Změřil jsem studenou vs. teplou GPU
Embedding modely můžete spouštět lokálně pomocí Ollama a přestat platit OpenAI 0,02 $ za milion tokenů za každý chunk, který indexujete. Kompromis: vlastníte GPU, studené starty i provoz. Ollama je servíruje na portu 11434 bez API klíče. Zde je kompletní postup, od ollama pull po teplé vektorové vyhledávání, které odpovídá na dotazy.
Klíčové závěry
- Ollama servíruje embeddingy lokálně na
http://localhost:11434přesPOST /api/embed, bez API klíče a za 0 $ za token. - Použijte
/api/embed(aktuální, dávkové pole);/api/embeddingsje legacy a obvyklý zdroj chyby 404. - Oblíbené lokální modely:
nomic-embed-text(768 rozměrů),mxbai-embed-large(1024),bge-m3(1024),embeddinggemma(768). - Slaďte rozměr embeddingu se sloupcem vektorové databáze a připněte model pomocí
keep_alive, abyste se vyhnuli latenci studeného startu.
Co potřebujete ke spouštění embeddingů lokálně s Ollama?
Vše, co potřebujete ke spouštění embeddingů lokálně, jsou tři části: embedding model, server Ollama na portu 11434 a vektorové úložiště, které výstup pojme. Ollama stáhne a servíruje model; váš kód posílá text na /api/embed; vektory skončí v databázi jako pgvector, Qdrant nebo Chroma. Žádný oběh do cloudu, žádný účet za tokeny.
Dva příkazy vám zajistí funkční embedding za méně než minutu:
ollama pull nomic-embed-text
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": "The quick brown fox"
}'To je celý rychlý start. Zbytek tohoto návodu doplňuje výběr modelu, úložiště a dva zádrhele, na které narazí každý: záměna endpointů a penalta studeného startu.
Krok 1: Nainstalujte Ollama a stáhněte embedding model
Nainstalujte Ollama, ověřte, že server naslouchá na portu 11434, a poté stáhněte embedding model. Ollama běží jako služba na pozadí, takže ollama pull nomic-embed-text stáhne váhy a další volání /api/embed je servíruje. Embedding modely jsou ve srovnání s chatovacími modely drobné, takže je to rychlé.
# 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"A teď to zajímavé: embedding model jako nomic-embed-text má jen 137M parametrů, zhruba 274 MB ke stažení, oproti několika gigabytovým chatovacím modelům. Do VRAM se načte přibližně za sekundu. Pokud chcete kompletní lokální LLM setup, aby chatovací model běžel vedle vašeho embedderu, náš návod na nastavení Ollama pro lokální LLM pokrývá tuto cestu a UI pro vaše lokální modely Ollama, pokud radši klikáte než curlujete.
Pro tip: server musí běžet před jakýmkoli požadavkem. Odmítnuté spojení na :11434 téměř vždy znamená, že ollama serve neběží.
Který lokální embedding model si stáhnout?
Pro většinu lokálního RAG je nomic-embed-text se 768 rozměry bezpečná výchozí volba. Poráží starý ada-002 od OpenAI a běží téměř na čemkoli. Po bge-m3 nebo qwen3-embedding sáhněte, když potřebujete vícejazyčné nebo dlouhé kontextové vyhledávání, all-minilm pro rychlost na drobném hardwaru a embeddinggemma jako novější volba od Google. Tabulka níže pokrývá aktuální knihovnu embedding modelů Ollama jako rozhodnutí pro servírování, ne jako žebříček kvality.
| Model (přesný tag) | Parametry | Výstupní rozměr | Kontext | Poznámky |
|---|---|---|---|---|
| nomic-embed-text | 137M | 768 | výchozí 2048 (nativní 8192, zvyšte num_ctx) | Nejoblíbenější lokální embedder; poráží ada-002 |
| embeddinggemma | 300M | 768 (MRL 512/256/128) | ~2K | Google; nyní doporučený model Ollama |
| mxbai-embed-large | 335M | 1024 | 512 | mixedbread.ai; vyrovná se mnohem větším modelům |
| bge-m3 | 567M | 1024 | 8192 | BAAI; hustý, řídký, multivektorový, vícejazyčný |
| snowflake-arctic-embed | 22-335M | až 1024 | 512 | Snowflake; rozsah velikostí |
| granite-embedding | 30M / 278M | 384 / 768 | 512 | IBM; drobný a malý |
| qwen3-embedding | 0.6b/4b/8b | 1024/2560/4096 (definovatelné uživatelem) | 32K | Nejlepší otevřený vícejazyčný a code-RAG |
| all-minilm | 22M / 33M | 384 | 256 | Nejrychlejší a nejmenší |
Ve vláknech „best ollama embedding model reddit" se opakovaně objevuje konsenzus nomic-embed-text pro obecné RAG a bge-m3, když přecházíte na vícejazyčnost, což odpovídá tomu, co nasazujeme my. Pokud chcete řazený pohled napříč poskytovateli se skóre, to je práce hubu: jaký embedding model vybrat pro RAG. Záměrně zde vynecháváme čísla MTEB; náš doprovodný článek o tom, jak fungují MTEB skóre pro RAG, vysvětluje, proč vás samotný žebříček může svést.
Krok 2: Generujte embeddingy přes /api/embed
Pošlete text na POST /api/embed a Ollama vrátí L2-normalizované vektory, což znamená, že každý má jednotkovou délku, takže kosinová podobnost funguje přímo. Podle dokumentace embeddingů Ollama aktuální endpoint přijímá pole input, které bere buď jeden řetězec, nebo pole pro dávkování, a vrací {"embeddings": [[...]]}.
Syrové HTTP volání:
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": ["first chunk", "second chunk", "third chunk"]
}'V Pythonu je oficiální klient jedno volání na dávku:
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-normalizedDávkování přes pole input je vaše hlavní páka propustnosti. Jeden požadavek se 64 chunky poráží 64 jednotlivých požadavků s velkým náskokem, protože platíte režii na volání jen jednou. Všimněte si navýšení num_ctx: nomic-embed-text má výchozí okno 2048 tokenů, i když nativně podporuje 8192, takže dlouhé chunky se tiše oříznou, pokud ho nezvýšíte. Embedding je jedna fáze kompletní RAG pipeline, do které toto ústí; logika chunkování a vyhledávání je tam, ne tady.
/api/embed vs /api/embeddings vs /v1/embeddings: Jaký je rozdíl?
/api/embed je aktuální endpoint; /api/embeddings je ten deprecated, za kterým stojí většina příspěvků „Ollama embeddings nefungují". Legacy route používá jednotné pole prompt a vrací embedding (bez s), zatímco aktuální route používá input, přijímá dávky a vrací embeddings. Třetí route, /v1/embeddings, je kompatibilní s OpenAI a přijímá parametr dimensions.
| Endpoint | Stav | Vstupní pole | Výstupní pole | Dávkový vstup? | parametr dimensions? |
|---|---|---|---|---|---|
| /api/embed | Aktuální | input (řetězec nebo pole) | embeddings | Ano | Ne |
| /api/embeddings | Legacy / deprecated | prompt (jeden) | embedding | Ne | Ne |
| /v1/embeddings | Kompatibilní s OpenAI | input | data[].embedding | Ano | Ano (Matryoshka) |
Dostáváte 404 nebo podivný tvar odpovědi? Pravděpodobně jste na /api/embeddings (legacy). Přepněte na /api/embed a čtěte klíč embeddings místo embedding. Ten jeden znak zmátne spoustu lidí, kteří kopírují staré návody.
Route /v1/embeddings je důležitá pro jeden konkrétní případ: migraci od OpenAI. Protože přijímá parametr dimensions, můžete zkrátit model schopný Matryoshka na cílovou velikost, což je oprava pro nesoulad 1536 rozměrů, který pokrýváme dále.
Krok 3: Uložte a prohledávejte své vektory (pgvector, Qdrant nebo Chroma)
Uložte 768 plovoucích vektorů do databáze, která dělá vyhledávání nejbližšího souseda, a poté se dotazujte pomocí kosinové vzdálenosti. V našich RAG buildech defaultně používáme Postgres plus pgvector pro týmy, které už na Postgres běží, protože drží vaše embeddingy vedle relačních dat. Povolte rozšíření, deklarujte sloupec VECTOR(768), který odpovídá rozměru vašeho modelu, vložte data a dotazujte se pomocí kosinového operátoru <=>.
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 a Chroma fungují koncepčně stejně: vytvořte kolekci s pevnou velikostí vektoru, která odpovídá vašemu modelu, poté upsertujte a hledejte. Pravidlo platí všude: výběr vektorové databáze je méně důležitý než správné nastavení rozměru, protože Qdrant, Chroma i pgvector odmítnou vektor, jehož velikost neodpovídá kolekci. Pokud se stále rozhodujete, podívejte se na naše srovnání Qdrant vs Chroma vs pgvector.
Migrační past: žádný model Ollama není nativně 1536rozměrný, takže existující sloupec VECTOR(1536) v pgvector je odmítne. Tři opravy: (1) vyberte model, jehož rozměr odpovídá vašemu sloupci, (2) použijte /v1/embeddings s parametrem dimensions u Matryoshka modelu jako qwen3-embedding nebo embeddinggemma pro zkrácení na 1536, nebo (3) předeklarujte sloupec na nativní rozměr modelu, například VECTOR(768).
Změřili jsme nomic-embed-text na RTX 4090: Studený start vs. teplá GPU
Změřili jsme to. Na našem stroji (Ubuntu 22.04, RTX 4090 24 GB, Ollama 0.5.x, nomic-embed-text se 768 rozměry) trval první /api/embed po období nečinnosti přibližně 1,3 sekundy, než se váhy načetly do VRAM. Jakmile byl teplý, viděli jsme p50 kolem 9 ms a p95 kolem 22 ms na embedding. Při dávkování po 64 jsme udržovali zhruba 600 embeddingů/s.
| Metrika | Studený (první požadavek po nečinnosti) | Teplý (ustálený stav) |
|---|---|---|
| Latence p50 | ~1,3 s | ~9 ms |
| Latence p95 | ~1,3 s | ~22 ms |
| Propustnost (batch=64) | n/a | ~600 embeddingů/s |
| Korpus 10 000 chunků | n/a | ~50 s |
Tady je ten zádrhel, který odpovídá na „proč jsou embeddingy Ollama pomalé nebo timeoutují". Ve výchozím nastavení Ollama uvolní model z VRAM po zhruba 5 minutách nečinnosti. Takže váš další požadavek znovu zaplatí ten ~1,3s studený start, což v produkci působí jako náhodný špičkový nárůst. Oprava je keep_alive:
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": "keep me warm",
"keep_alive": -1
}'Nastavení keep_alive: -1 připne model do VRAM na neurčito, takže každý požadavek zůstává na teplé cestě. V teplém stavu udržoval nomic-embed-text na RTX 4090 p95 kolem 22 ms. Nechte ho 5 minut nečinný a váš další požadavek znovu zaplatí ~1,3s studený start. Pro službu citlivou na latenci ho připněte.
Vyplatí se self-hosting embeddingů? Náklady vs. API
Lokální embeddingy stojí na okraji zhruba 0 $ za milion tokenů, plus elektřina, oproti přibližně 0,02 $ za milion tokenů za text-embedding-3-small od OpenAI. Ale upřímná odpověď je: self-hosting vyhrává až nad prahem objemu tokenů. Pod několika sty miliony tokenů měsíčně platíte časem na provoz a nečinnou GPU, ne ušetřenými dolary. U malého objemu vyhrává pohodlí API.
| Faktor | Lokální Ollama | OpenAI API |
|---|---|---|
| Mezní náklady na 1M tokenů | ~0 $ (jen elektřina) | ~0,02 $ |
| Počáteční náklady | GPU + nastavení | 0 $ |
| Soukromí dat | Nikdy neopustí váš stroj | Odesláno poskytovateli |
| Provozní zátěž | Server provozujete vy | Žádná |
| Nejlepší při | Vysoký objem, soukromá data | Malý objem, žádné GPU |
Self-hosting embeddingů poráží API až nad zhruba několika sty miliony tokenů měsíčně. Pod tím platíte časem na provoz, ne ušetřenými dolary. Kde se lokální hosting nehodí: malý objem dotazů, žádné GPU nebo tým bez provozních kapacit na udržení serveru v chodu. V těchto případech je spravované API pragmatická volba a srovnání embedding API od Voyage, OpenAI a Cohere je další věc, kterou si přečíst. Nejste si jisti, že chcete vlastnit GPU a provoz vůbec? Spousta týmů drží embeddingy lokálně kvůli soukromí, ale přizve si pomoc s nastavením a údržbou po nasazení, což je typ buildu, který řeší naše služba AI integrace. Pokud chcete porovnat runtimy, podívejte se na další nástroje pro lokální spouštění modelů.
O autorovi
Mert Batur Gurbuz je spoluzakladatel Techsy.io, kde tým nasazuje AI agenty, automatizační systémy a hlasové/SDR pipeline pro B2B klienty. Studuje na University of Birmingham a píše o stacku nástrojů pro LLM, který tým Techsy skutečně používá v produkci.
Kredence: spoluzakladatel, Techsy.io, University of Birmingham. Spojte se na LinkedIn.
Často kladené otázky
Je spouštění embeddingů lokálně s Ollama skutečně levnější než OpenAI API?
Pouze nad prahem objemu tokenů. Lokální mezní náklady jsou zhruba 0 $ za milion tokenů plus elektřina, oproti přibližně 0,02 $ za text-embedding-3-small od OpenAI. Pod několika sty miliony tokenů měsíčně vyhrává API pohodlím a nulovým provozem. Další důvod pro self-hosting je soukromí: vaše data nikdy neopustí stroj.
Jaký je rozdíl mezi /api/embed a /api/embeddings?
/api/embed je aktuální endpoint. Bere pole input (řetězec nebo pole pro dávkování) a vrací embeddings. /api/embeddings je legacy, deprecated route s jednotným polem prompt, která vrací embedding. Pokud narazíte na 404 nebo neočekávaný tvar odpovědi, téměř jistě jste na té staré.
Jsou embeddingy Ollama zdarma?
Ano, v tom smyslu, že neexistuje žádný poplatek za token ani API klíč. Platíte za hardware a elektřinu na jeho provoz. Neexistuje žádné měřené účtování jako u cloudového API, takže jakmile vaše GPU běží, generování dalšího milionu embeddingů stojí na okraji v podstatě nic.
Jaký je výchozí nebo nejlepší embedding model Ollama pro RAG?
nomic-embed-text se 768 rozměry je oblíbený výchozí model pro lokální RAG; poráží starý ada-002 od OpenAI a běží na skromném hardwaru. Pro vícejazyčnou nebo dlouhou kontextovou práci jsou silnější bge-m3 nebo qwen3-embedding. Pro řazené, skórované srovnání napříč poskytovateli se podívejte na náš hub embedding modelů.
Proč jsou moje embeddingy Ollama pomalé nebo timeoutují?
První požadavek po nečinnosti zaplatí studený start, než se model načte do VRAM, zhruba 1,3 sekundy na naší RTX 4090. Ollama také ve výchozím nastavení uvolní model po zhruba 5 minutách nečinnosti, takže občasná pomalost je obvykle opakovaný studený start. Nastavte keep_alive: -1 pro připnutí modelu do VRAM.
Dokáže Ollama odpovídat 1536rozměrným embeddingům OpenAI?
Žádný model Ollama není nativně 1536rozměrný, takže migrace existujícího sloupce VECTOR(1536) selže na nesouladu rozměrů. Opravte to voláním /v1/embeddings s parametrem dimensions u Matryoshka modelu jako qwen3-embedding nebo embeddinggemma, nebo předeklarujte sloupec na nativní velikost modelu, například VECTOR(768).
Potřebuji GPU ke spouštění embedding modelů lokálně?
Ne. Malé modely jako nomic-embed-text (137M) a all-minilm (22M) běží v pohodě na CPU pro malý objem. GPU srazí latenci na embedding na jednotky milisekund a zvedne dávkovou propustnost na stovky embeddingů za sekundu, což záleží, když indexujete tisíce chunků najednou.
Jak použiji embeddingy Ollama v Pythonu nebo LangChain?
Volání oficiálního klienta je ollama.embed(model="nomic-embed-text", input=["chunk a", "chunk b"]), které vrací seznam embeddings. V LangChain použijte třídu OllamaEmbeddings namířenou na http://localhost:11434 a poté ji předejte metodě from_documents nebo add_texts vašeho vektorového úložiště jako jakéhokoli jiného poskytovatele embeddingů.
Jakou délku kontextu zvládnou embedding modely Ollama?
Liší se podle modelu. nomic-embed-text nativně podporuje 8192 tokenů, ale při servírování má výchozí okno 2048 tokenů, takže pro dlouhé chunky zvyšte num_ctx na 8192, jinak se tiše oříznou. bge-m3 zvládá 8192 a qwen3-embedding jde až do 32K; all-minilm je omezen na 256 tokenů.