
Εκτελέστε Μοντέλα Embedding Τοπικά με το Ollama: Μέτρησα την Καθυστέρηση Cold vs Warm GPU
Μπορείτε να εκτελέσετε μοντέλα embedding τοπικά με το Ollama και να σταματήσετε να πληρώνετε στην OpenAI $0,02 ανά εκατομμύριο tokens για κάθε κομμάτι (chunk) που ευρετηριάζετε. Το αντάλλαγμα: εσείς αναλαμβάνετε το GPU, τις ψυχρές εκκινήσεις (cold starts) και τη λειτουργική συντήρηση. Το Ollama τα εξυπηρετεί στη θύρα 11434 χωρίς κλειδί API. Ακολουθεί η πλήρης ροή εργασίας, από το ollama pull έως μια θερμή αναζήτηση vectors που απαντά σε ερωτήματα.
Βασικά Συμπεράσματα
- Το Ollama εξυπηρετεί embeddings τοπικά στο
http://localhost:11434μέσωPOST /api/embed, χωρίς κλειδί API και με κόστος $0 ανά token. - Χρησιμοποιήστε το
/api/embed(τρέχον, batch array)· το/api/embeddingsείναι παλαιό και η συνηθισμένη αιτία σφάλματος 404. - Δημοφιλή τοπικά μοντέλα:
nomic-embed-text(768 διαστάσεων),mxbai-embed-large(1024),bge-m3(1024),embeddinggemma(768). - Ταιριάξτε τις διαστάσεις του embedding σας με τη στήλη της βάσης δεδομένων vectors και «καρφώστε» το μοντέλο με
keep_aliveγια να αποφύγετε την καθυστέρηση ψυχρής εκκίνησης.
Τι Χρειάζεστε για να Εκτελέσετε Embeddings Τοπικά με το Ollama;
Ό,τι χρειάζεστε για να εκτελέσετε embeddings τοπικά αποτελείται από τρία μέρη: ένα μοντέλο embedding, τον διακομιστή Ollama στη θύρα 11434 και μια αποθήκη vectors για να κρατήσει την έξοδο. Το Ollama κατεβάζει και εξυπηρετεί το μοντέλο· ο κώδικάς σας στέλνει κείμενο στο /api/embed· τα vectors καταλήγουν σε μια βάση δεδομένων όπως η pgvector, η Qdrant ή η Chroma. Χωρίς往返 στο cloud, χωρίς χρέωση ανά token.
Δύο εντολές σας δίνουν ένα λειτουργικό embedding σε λιγότερο από ένα λεπτό:
ollama pull nomic-embed-text
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": "The quick brown fox"
}'Αυτός είναι όλος ο γρήγορος οδηγός ξεκινήματος. Το υπόλοιπο αυτού του άρθρου συμπληρώνει την επιλογή μοντέλου, την αποθήκη και τα δύο σημεία προσοχής που ταλαιπωρούν όλους: τη σύγχυση endpoint και το κόστος ψυχρής εκκίνησης.
Βήμα 1: Εγκαταστήστε το Ollama και Κατεβάστε ένα Μοντέλο Embedding
Εγκαταστήστε το Ollama, επιβεβαιώστε ότι ο διακομιστής ακούει στη θύρα 11434 και στη συνέχεια κατεβάστε ένα μοντέλο embedding. Το Ollama τρέχει ως υπηρεσία στο παρασκήνιο, οπότε το ollama pull nomic-embed-text κατεβάζει τα weights και η επόμενη κλήση /api/embed τα εξυπηρετεί. Τα μοντέλα embedding είναι μικρά σε σχέση με τα μοντέλα chat, οπότε αυτή η διαδικασία είναι γρήγορη.
# 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"Εδώ είναι το ενδιαφέρον μέρος: ένα μοντέλο embedding όπως το nomic-embed-text έχει μόνο 137 εκατομμύρια παραμέτρους, περίπου 274 MB download, σε αντίθεση με τα μοντέλα chat πολλαπλών gigabyte. Φορτώνεται στη VRAM σε περίπου ένα δευτερόλεπτο. Αν θέλετε την πλήρη τοπική ρύθμιση LLM ώστε ένα μοντέλο chat να βρίσκεται δίπλα στον embedder σας, ο οδηγός μας για ρύθμιση του Ollama για τοπικά LLM καλύπτει αυτή τη διαδρομή, καθώς και ένα UI για τα τοπικά μοντέλα Ollama σας αν προτιμάτε τα κλικ από το curl.
Συμβουλή ειδικού: ο διακομιστής πρέπει να τρέχει πριν από οποιοδήποτε αίτημα. Μια απορριφθείσα σύνδεση στο :11434 σχεδόν πάντα σημαίνει ότι το ollama serve δεν είναι ενεργό.
Ποιο Τοπικό Μοντέλο Embedding Πρέπει να Κατεβάσετε;
Για τις περισσότερες τοπικές εφαρμογές RAG, το nomic-embed-text στις 768 διαστάσεις είναι η ασφαλής προεπιλογή. Ξεπερνά το παλιό ada-002 της OpenAI και τρέχει σε σχεδόν οποιοδήποτε hardware. Επιλέξτε bge-m3 ή qwen3-embedding όταν χρειάζεστε πολυγλωσσική ανάκτηση ή ανάκτηση μεγάλου context, all-minilm για ταχύτητα σε πολύ μικρό hardware και embeddinggemma ως τη νεότερη επιλογή της Google. Ο παρακάτω πίνακας καλύπτει την τρέχουσα βιβλιοθήκη μοντέλων embedding του Ollama ως απόφαση εξυπηρέτησης, όχι ως πίνακα κατάταξης ποιότητας.
| Μοντέλο (ακριβής ετικέτα) | Παράμετροι | Διαστάσεις εξόδου | Context | Σημειώσεις |
|---|---|---|---|---|
| nomic-embed-text | 137M | 768 | 2048 προεπιλογή (native 8192, αυξήστε num_ctx) | Πιο δημοφιλής τοπικός embedder· ξεπερνά το ada-002 |
| embeddinggemma | 300M | 768 (MRL 512/256/128) | ~2K | Google· πλέον μοντέλο προτεινόμενο από το Ollama |
| mxbai-embed-large | 335M | 1024 | 512 | mixedbread.ai· ταιριάζει με πολύ μεγαλύτερα μοντέλα |
| bge-m3 | 567M | 1024 | 8192 | BAAI· dense, sparse, multivector, πολυγλωσσικό |
| snowflake-arctic-embed | 22-335M | έως 1024 | 512 | Snowflake· εύρος μεγεθών |
| granite-embedding | 30M / 278M | 384 / 768 | 512 | IBM· tiny και small |
| qwen3-embedding | 0.6b/4b/8b | 1024/2560/4096 (ορίζεται από τον χρήστη) | 32K | Καλύτερο ανοιχτό πολυγλωσσικό και code-RAG |
| all-minilm | 22M / 33M | 384 | 256 | Ταχύτερο και μικρότερο |
Στα threads του Reddit με θέμα «best ollama embedding model», η επαναλαμβανόμενη συναίνεση είναι το nomic-embed-text για γενικό RAG και το bge-m3 όταν πάτε σε πολυγλωσσικό περιβάλλον, κάτι που συμφωνεί με όσα υλοποιούμε. Αν θέλετε την καταταγμένη, δια-παροχική άποψη με βαθμολογίες, αυτό είναι δουλειά του hub: ποιο μοντέλο embedding να επιλέξετε για RAG. Παραλείπουμε σκόπιμα τους αριθμούς MTEB εδώ· το συνοδευτικό άρθρο μας για πώς λειτουργούν οι βαθμολογίες MTEB για RAG εξηγεί γιατί ο πίνακας κατάταξης alone μπορεί να σας παραπλανήσει.
Βήμα 2: Δημιουργήστε Embeddings μέσω /api/embed
Στείλτε κείμενο στο POST /api/embed και το Ollama επιστρέφει vectors κανονικοποιημένα L2, meaning each one is unit-length so cosine similarity works directly. Σύμφωνα με τα έγγραφα embeddings του Ollama, το τρέχον endpoint δέχεται ένα πεδίο input που αποδέχεται είτε ένα single string είτε έναν array για batching, και επιστρέφει {"embeddings": [[...]]}.
Η raw HTTP κλήση:
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": ["first chunk", "second chunk", "third chunk"]
}'Σε Python, ο επίσημος client είναι μία γραμμή ανά 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-normalizedΤο batching μέσω του array input είναι ο κύριος μοχλός απόδοσης (throughput). Ένα αίτημα με 64 chunks ξεπερνά κατά πολύ τα 64 single requests, επειδή πληρώνετε το overhead ανά κλήση μόνο μία φορά. Προσέξτε την αύξηση του num_ctx: το nomic-embed-text έχει προεπιλογή παραθύρου 2048 tokens παρόλο που υποστηρίζει native 8192, οπότε τα μεγάλα chunks περικόπτονται σιωπηρά αν δεν το αυξήσετε. Το embedding είναι ένα στάδιο της πλήρους ροής RAG στην οποία τροφοδοτεί· η λογική chunking και retrieval βρίσκεται εκεί, όχι εδώ.
/api/embed vs /api/embeddings vs /v1/embeddings: Ποια Είναι η Διαφορά;
Το /api/embed είναι το τρέχον endpoint· το /api/embeddings είναι το deprecated πίσω από τις περισσότερες αναρτήσεις «Ollama embeddings not working». Η legacy διαδρομή χρησιμοποιεί ένα singular πεδίο prompt και επιστρέφει embedding (χωρίς s), ενώ η τρέχουσα διαδρομή χρησιμοποιεί input, δέχεται batches και επιστρέφει embeddings. Μια τρίτη διαδρομή, /v1/embeddings, είναι συμβατή με OpenAI και δέχεται μια παράμετρο dimensions.
| Endpoint | Κατάσταση | Πεδίο Input | Πεδίο Response | Batch input; | Παράμετρος dimensions; |
|---|---|---|---|---|---|
| /api/embed | Τρέχον | input (string ή array) | embeddings | Ναι | Όχι |
| /api/embeddings | Legacy / deprecated | prompt (single) | embedding | Όχι | Όχι |
| /v1/embeddings | Συμβατό με OpenAI | input | data[].embedding | Ναι | Ναι (Matryoshka) |
Λαμβάνετε 404 ή ένα παράξενο σχήμα response; Πιθανότατα βρίσκεστε στο /api/embeddings (legacy). Μεταβείτε στο /api/embed και διαβάστε το κλειδί embeddings αντί για embedding. Αυτός ο ένας χαρακτήρας μπερδεύει πολλούς ανθρώπους που αντιγράφουν παλιά tutorials.
Η διαδρομή /v1/embeddings έχει σημασία για μία συγκεκριμένη περίπτωση: μετάβαση από το OpenAI. Επειδή δέχεται μια παράμετρο dimensions, μπορείτε να περικόψετε ένα μοντέλο ικανό για Matryoshka σε ένα target size, which is the fix for the 1536-dimension mismatch we cover next.
Βήμα 3: Αποθηκεύστε και Αναζητήστε τα Vectors Σας (pgvector, Qdrant ή Chroma)
Αποθηκεύστε τα vectors των 768 floats σε μια βάση δεδομένων που κάνει αναζήτηση nearest-neighbor και στη συνέχεια κάντε query με απόσταση cosine. Στα RAG builds μας προεπιλέγουμε το Postgres plus pgvector για ομάδες που ήδη χρησιμοποιούν Postgres, επειδή κρατά τα embeddings σας δίπλα στα relational data σας. Ενεργοποιήστε την επέκταση, δηλώστε μια στήλη VECTOR(768) που ταιριάζει με τις διαστάσεις του μοντέλου σας, εισάγετε και κάντε query με τον τελεστή cosine <=>.
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 και Chroma λειτουργούν με τον ίδιο τρόπο εννοιολογικά: δημιουργήστε μια collection με σταθερό μέγεθος vector που ταιριάζει με το μοντέλο σας, στη συνέχεια upsert και search. Ο κανόνας ισχύει παντού: η επιλογή μιας βάσης δεδομένων vectors έχει μικρότερη σημασία από το να πετύχετε σωστά τις διαστάσεις, επειδή οι Qdrant, Chroma και pgvector απορρίπτουν όλα ένα vector cuyo μέγεθος δεν ταιριάζει με την collection. Δείτε τη σύγκρισή μας Qdrant vs Chroma vs pgvector αν ακόμα αποφασίζετε.
Η παγίδα της μετάβασης: κανένα μοντέλο Ollama δεν είναι native 1536 διαστάσεων, οπότε μια υπάρχουσα στήλη pgvector VECTOR(1536) θα τα απορρίψει. Τρεις λύσεις: (1) επιλέξτε ένα μοντέλο cuyas διαστάσεις ταιριάζουν με τη στήλη σας, (2) χρησιμοποιήστε /v1/embeddings με παράμετρο dimensions σε ένα μοντέλο Matryoshka όπως qwen3-embedding ή embeddinggemma για περικοπή σε 1536, ή (3) επαναδηλώστε τη στήλη στις native διαστάσεις του μοντέλου, όπως VECTOR(768).
Μετρήσαμε το nomic-embed-text σε RTX 4090: Cold Start vs Warm GPU
Το μετρήσαμε. Στο μηχάνημά μας (Ubuntu 22.04, RTX 4090 24 GB, Ollama 0.5.x, nomic-embed-text στις 768 διαστάσεις), το πρώτο /api/embed μετά από αδράνεια πήρε περίπου 1,3 δευτερόλεπτα ενώ τα weights φορτώνονταν στη VRAM. Μόλις ζεσταθεί, είδαμε p50 κοντά στα 9 ms και p95 κοντά στα 22 ms ανά embedding. Σε batch των 64, διατηρήσαμε περίπου 600 embeddings/sec.
| Μετρική | Cold (πρώτο αίτημα μετά αδράνειας) | Warm (steady state) |
|---|---|---|
| Καθυστέρηση p50 | ~1,3 s | ~9 ms |
| Καθυστέρηση p95 | ~1,3 s | ~22 ms |
| Απόδοση (batch=64) | n/a | ~600 embeddings/sec |
| Σώμα 10.000 chunks | n/a | ~50 s |
Εδώ είναι το σημείο προσοχής που απαντά στο «γιατί τα embeddings του Ollama είναι αργά ή κάνουν timeout». Προεπιλεγμένα, το Ollama unloadάρει ένα μοντέλο από τη VRAM μετά από περίπου 5 λεπτά αδράνειας. Έτσι, το επόμενο αίτημά σας ξαναπληρώνει εκείνο το ~1,3 s cold start, which feels like a random spike in production. Η λύση είναι το keep_alive:
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": "keep me warm",
"keep_alive": -1
}'Ρυθμίζοντας keep_alive: -1 καρφώνει το μοντέλο στη VRAM επ' αόριστον, οπότε κάθε αίτημα παραμένει στο warm path. Ζεστό, το nomic-embed-text σε RTX 4090 διατήρησε p95 κοντά στα 22 ms. Αφήστε το αδρανές για 5 λεπτά και το επόμενο αίτημά σας ξαναπληρώνει ένα ~1,3 s cold start. Για μια υπηρεσία ευαίσθητη στην καθυστέρηση, καρφώστε το.
Αξίζει το Self-Hosting των Embeddings; Κόστος vs API
Τα τοπικά embeddings κοστίζουν περίπου $0 ανά εκατομμύριο tokens στο οριακό κόστος, plus electricity, versus about $0.02 per million tokens for OpenAI text-embedding-3-small. But the honest answer is: self-hosting only wins above a token-volume threshold. Below a few hundred million tokens a month, you're paying in ops time and idle GPU, not dollars saved. The API's convenience wins for low volume.
| Παράγοντας | Τοπικό Ollama | OpenAI API |
|---|---|---|
| Οριακό κόστος ανά 1M tokens | ~$0 (μόνο ηλεκτρικό) | ~$0,02 |
| Αρχικό κόστος | GPU + setup | $0 |
| Ιδιωτικότητα δεδομένων | Δεν φεύγει ποτέ από το μηχάνημά σας | Στέλνεται στον πάροχο |
| Φόρτος Ops | Εσείς τρέχετε τον διακομιστή | Κανένας |
| Καλύτερο για | Υψηλό όγκο, ιδιωτικά δεδομένα | Χαμηλός όγκος, χωρίς GPU |
Το self-hosting embeddings ξεπερνά το API μόνο πάνω από περίπου μερικά εκατοντάδες εκατομμύρια tokens το μήνα. Κάτω από αυτό, πληρώνετε σε χρόνο ops, όχι σε δολάρια που γλιτώνετε. Πού το τοπικό δεν ταιριάζει καλά: χαμηλός όγκος ερωτημάτων, έλλειψη GPU ή ομάδα χωρίς την ικανότητα ops να διατηρεί έναν διακομιστή υγιή. Σε αυτές τις περιπτώσεις, ένα managed API είναι η πρακτική επιλογή, και μια σύγκριση των Voyage, OpenAI και Cohere embedding APIs είναι το επόμενο πράγμα που πρέπει να διαβάσετε. Δεν είστε σίγουροι αν θέλετε να αναλάβετε το GPU και τα ops καθόλου; Πολλές ομάδες κρατούν τα embeddings τοπικά για ιδιωτικότητα αλλά φέρνουν βοήθεια για το setup και τη συντήρηση day-two, which is the kind of build our AI integration service handles. If you want to compare runtimes, see other tools for running models locally.
Σχετικά με τον Συγγραφέα
Ο Mert Batur Gurbuz είναι Συνιδρυτής της Techsy.io, όπου η ομάδα παραδίδει AI agents, συστήματα αυτοματοποίησης και pipelines voice/SDR για B2B πελάτες. Σπουδάζει στο Πανεπιστήμιο του Birmingham και γράφει για το stack εργαλείων LLM που η ομάδα της Techsy χρησιμοποιεί πραγματικά σε production.
Πιστοποιήσεις: Συνιδρυτής, Techsy.io, Πανεπιστήμιο του Birmingham. Συνδεθείτε στο LinkedIn.
Συχνές Ερωτήσεις
Είναι η εκτέλεση embeddings τοπικά με το Ollama πραγματικά φθηνότερη από το API της OpenAI;
Μόνο πάνω από ένα όριο όγκου tokens. Το οριακό κόστος τοπικά είναι περίπου $0 ανά εκατομμύριο tokens plus electricity, versus about $0.02 for OpenAI text-embedding-3-small. Κάτω από μερικά εκατοντάδες εκατομμύρια tokens το μήνα, το API κερδίζει σε ευκολία και μηδενικά ops. Ο άλλος λόγος για self-hosting είναι η ιδιωτικότητα: τα δεδομένα σας δεν φεύγουν ποτέ από το μηχάνημα.
Ποια είναι η διαφορά μεταξύ /api/embed και /api/embeddings;
Το /api/embed είναι το τρέχον endpoint. Δέχεται ένα πεδίο input (ένα string ή έναν array για batching) και επιστρέφει embeddings. Το /api/embeddings είναι η legacy, deprecated διαδρομή με ένα singular πεδίο prompt που επιστρέφει embedding. Αν λαμβάνετε 404 ή ένα απροσδόκητο σχήμα response, σχεδόν σίγουρα βρίσκεστε στο παλιό.
Είναι τα embeddings του Ollama δωρεάν;
Ναι, με την έννοια ότι δεν υπάρχει χρέωση ανά token και δεν απαιτείται κλειδί API. Πληρώνετε για το hardware και την ηλεκτρική ενέργεια για να το τρέξετε. Δεν υπάρχει metered billing όπως σε ένα cloud API, οπότε μόλις τρέξει το GPU σας, η δημιουργία άλλου ενός εκατομμυρίου embeddings κοστίζει ουσιαστικά τίποτα στο οριακό κόστος.
Ποιο είναι το προεπιλεγμένο ή καλύτερο μοντέλο embedding του Ollama για RAG;
Το nomic-embed-text στις 768 διαστάσεις είναι η δημοφιλής προεπιλογή για τοπικό RAG· ξεπερνά το παλιό ada-002 της OpenAI και τρέχει σε modest hardware. Για πολυγλωσσική εργασία ή μεγάλο context, τα bge-m3 ή qwen3-embedding είναι ισχυρότερα. Για την καταταγμένη, βαθμολογημένη σύγκριση across providers, δείτε το hub μοντέλων embedding μας.
Γιατί τα embeddings του Ollama μου είναι αργά ή κάνουν timeout;
Το πρώτο αίτημα μετά από αδράνεια πληρώνει ένα cold start ενώ το μοντέλο φορτώνεται στη VRAM, περίπου 1,3 δευτερόλεπτα στο RTX 4090 μας. Το Ollama επίσης unloadάρει το μοντέλο μετά από περίπου 5 λεπτά αδράνειας προεπιλεγμένα, οπότε η διαλείπουσα βραδύτητα είναι συνήθως επαναλαμβανόμενο cold start. Ρυθμίστε keep_alive: -1 για να καρφώσετε το μοντέλο στη VRAM.
Μπορεί το Ollama να ταιριάξει τα embeddings 1536 διαστάσεων της OpenAI;
Κανένα μοντέλο Ollama δεν είναι native 1536 διαστάσεων, οπότε η μετάβαση μιας υπάρχουσας στήλης VECTOR(1536) σπάει λόγω mismatch διαστάσεων. Διορθώστε το καλώντας /v1/embeddings με παράμετρο dimensions σε ένα μοντέλο Matryoshka όπως qwen3-embedding ή embeddinggemma, ή επαναδηλώστε τη στήλη σας στο native μέγεθος του μοντέλου, όπως VECTOR(768).
Χρειάζομαι GPU για να εκτελέσω μοντέλα embedding τοπικά;
Όχι. Μικρά μοντέλα όπως το nomic-embed-text (137M) και το all-minilm (22M) τρέχουν καλά σε CPU για χαμηλό όγκο. Ένα GPU μειώνει την καθυστέρηση ανά embedding σε single-digit milliseconds και αυξάνει το batch throughput σε εκατοντάδες embeddings ανά δευτερόλεπτο, which matters when you're indexing thousands of chunks at once.
Πώς χρησιμοποιώ τα embeddings του Ollama σε Python ή LangChain;
Η κλήση του επίσημου client είναι ollama.embed(model="nomic-embed-text", input=["chunk a", "chunk b"]), which returns an embeddings list. Σε LangChain, χρησιμοποιήστε την κλάση OllamaEmbeddings pointing στο http://localhost:11434, then pass it to your vector store's from_documents or add_texts method like any other embeddings provider.
Τι μήκος context μπορούν να διαχειριστούν τα μοντέλα embedding του Ollama;
Ποικίλλει ανά μοντέλο. Το nomic-embed-text υποστηρίζει native 8192 tokens αλλά έχει προεπιλογή παραθύρου 2048 tokens όταν εξυπηρετείται, οπότε αυξήστε το num_ctx σε 8192 για μεγάλα chunks ή θα περικοπούν σιωπηρά. Το bge-m3 διαχειρίζεται 8192 και το qwen3-embedding φτάνει έως 32K· το all-minilm περιορίζεται στα 256 tokens.