
Ollama ile Embedding Modellerini Yerel Çalıştırma: Soğuk ve Sıcak GPU Testi
Ollama ile embedding modellerini yerel çalıştırabilir ve indekslediğiniz her parça için OpenAI'ye milyon token başına $0.02 ödemeyi bırakabilirsiniz. Karşılığında: GPU'yu, soğuk başlangıçları ve ops işini siz üstlenirsiniz. Ollama bunları 11434 portunda, API anahtarı gerektirmeden sunar. İşte ollama pull'dan sorguları yanıtlayan sıcak bir vektör aramasına kadar tüm iş akışı.
Temel Çıkarımlar
- Ollama, embeddingleri yerel olarak
http://localhost:11434adresindePOST /api/embedüzerinden sunar; API anahtarı gerekmez ve token başına $0 maliyet. /api/embedkullanın (güncel, batch dizisi destekler);/api/embeddingsise eski (legacy) uç noktadır ve genelde 404 hatasının kaynağıdır.- Popüler yerel modeller:
nomic-embed-text(768 boyut),mxbai-embed-large(1024),bge-m3(1024),embeddinggemma(768). - Embedding boyutunuzu vektör veritabanı sütununuzla eşleştirin ve soğuk başlangıç gecikmesini atlamak için modeli
keep_aliveile sabitleyin.
Ollama ile Embeddingleri Yerel Çalıştırmak İçin Neye İhtiyacınız Var?
Embeddingleri yerel çalıştırmak için gereken her şey üç parçadan ibaret: bir embedding modeli, 11434 portundaki Ollama sunucusu ve çıktıyı tutacak bir vektör deposu. Ollama modeli indirip sunar; kodunuz metni /api/embed'e gönderir; vektörler pgvector, Qdrant veya Chroma gibi bir veritabanına düşer. Buluta gidiş-dönüş yok, token başına fatura yok.
İki komutla bir dakikadan kısa sürede çalışan bir embedding elde edersiniz:
ollama pull nomic-embed-text
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": "The quick brown fox"
}'Hızlı başlangıç bu kadar. Bu rehberin geri kalanında model seçimini, depolamayı ve herkesi ısıran iki tuzağı ele alacağız: uç nokta karışıklığı ve soğuk başlangıç cezası.
Adım 1: Ollama'yı Kurun ve Bir Embedding Modeli İndirin
Ollama'yı kurun, sunucunun 11434 portunu dinlediğini doğrulayın, ardından bir embedding modeli indirin. Ollama arka planda bir servis olarak çalışır; bu yüzden ollama pull nomic-embed-text ağırlıkları indirir ve bir sonraki /api/embed çağrısı bunları sunar. Embedding modelleri, sohbet modellerinin yanında oldukça küçüktür, bu yüzden bu işlem hızlıdır.
# macOS / Linux kurulumu
curl -fsSL https://ollama.com/install.sh | sh
# Sunucunun ayakta olduğundan emin olun (arka plan servisi :11434'te)
ollama serve # zaten çalışmıyorsa
# Bir embedding modeli indirin ve sunucuyu sağlık kontrolünden geçirin
ollama pull nomic-embed-text
curl http://localhost:11434 # "Ollama is running" dönmeliİşte ilginç kısım: nomic-embed-text gibi bir embedding modeli sadece 137M parametre, yaklaşık 274 MB'lık bir indirme; çok gigabaytlık sohbet modellerinin yanında devede kulak kalır. VRAM'e yaklaşık bir saniyede yüklenir. Embedder'ınızın yanına bir sohbet modeli için tam bir yerel LLM kurulumu istiyorsanız, yerel LLM'ler için Ollama kurulumu rehberimiz bu yolu anlatıyor; curl yerine tıklamayı tercih ediyorsanız yerel Ollama modelleriniz için bir arayüz de var.
İpucu: sunucu her istekten önce çalışıyor olmalı. :11434 üzerinde bağlantı reddi hatası, neredeyse her zaman ollama serve'in çalışmadığı anlamına gelir.
Hangi Yerel Embedding Modelini İndirmelisiniz?
Çoğu yerel RAG kurulumu için, 768 boyutlu nomic-embed-text güvenli varsayılan seçimdir. OpenAI'nin eski ada-002 modelini geride bırakır ve neredeyse her donanımda çalışır. Çok dilli veya uzun bağlamlı retrieval gerektiğinde bge-m3 veya qwen3-embedding'e, küçük donanımlarda hız için all-minilm'e, daha yeni bir Google seçeneği olarak da embeddinggemma'ya yönelin. Aşağıdaki tablo güncel Ollama embedding model kütüphanesini bir sunum kararı olarak ele alıyor, kalite lig tablosu olarak değil.
| Model (tam etiket) | Parametre | Çıktı boyutu | Bağlam | Notlar |
|---|---|---|---|---|
| nomic-embed-text | 137M | 768 | Varsayılan 2048 (doğal 8192, num_ctx'i artırın) | En popüler yerel embedder; ada-002'yi geride bırakır |
| embeddinggemma | 300M | 768 (MRL 512/256/128) | ~2K | Google; artık Ollama'nın önerdiği bir model |
| mxbai-embed-large | 335M | 1024 | 512 | mixedbread.ai; çok daha büyük modellere denk performans |
| bge-m3 | 567M | 1024 | 8192 | BAAI; dense, sparse, multi-vektör, çok dilli |
| snowflake-arctic-embed | 22-335M | 1024'e kadar | 512 | Snowflake; boyut aralığı geniş |
| granite-embedding | 30M / 278M | 384 / 768 | 512 | IBM; minik ve küçük |
| qwen3-embedding | 0.6b/4b/8b | 1024/2560/4096 (kullanıcı tanımlı) | 32K | Açık kaynakta en iyi çok dilli ve kod-RAG seçeneği |
| all-minilm | 22M / 33M | 384 | 256 | En hızlı ve en küçük |
"Best ollama embedding model reddit" başlıklı gönderilerde tekrar eden görüş birliği, genel RAG için nomic-embed-text, çok dilli kullanımda ise bge-m3 yönünde; bu da bizim sunduğumuzla örtüşüyor. Sağlayıcılar arası puanlı, sıralı bir karşılaştırma istiyorsanız, bu iş RAG için hangi embedding modelini seçmeli rehberimizin görevi. MTEB sayılarını burada bilerek atlıyoruz; RAG için MTEB puanlarının nasıl işlediğini anlatan yazımız, lig tablosunun tek başına neden yanıltıcı olabileceğini açıklıyor.
Adım 2: /api/embed ile Embedding Oluşturun
Metni POST /api/embed'e gönderin; Ollama, L2-normalize edilmiş vektörler döndürür, yani her biri birim uzunluktadır ve kosinüs benzerliği doğrudan çalışır. Ollama embeddings dokümantasyonuna göre, güncel uç nokta tekil bir string ya da toplu işlem için bir dizi kabul eden bir input alanı alır ve {"embeddings": [[...]]} döndürür.
Ham HTTP çağrısı:
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": ["first chunk", "second chunk", "third chunk"]
}'Python'da resmi istemci ile her batch tek satırdır:
import ollama
resp = ollama.embed(
model="nomic-embed-text",
input=["first chunk", "second chunk", "third chunk"],
options={"num_ctx": 8192}, # uzun parçalar için bağlamı artır
)
vectors = resp["embeddings"] # 768 elemanlı float listeleri, L2-normalizeinput dizisi üzerinden toplu işleme, en büyük verimlilik kaldıracınızdır. 64 parçayı tek bir istekte göndermek, 64 ayrı istekten çok daha hızlıdır, çünkü çağrı başına gelen ek yükü sadece bir kez ödersiniz. num_ctx artırımına dikkat edin: nomic-embed-text, doğal olarak 8192'yi desteklese de varsayılan olarak 2048 tokenlik bir pencereyle çalışır, bu yüzden artırmazsanız uzun parçalar sessizce kesilir. Embedding, bunun beslediği tam RAG pipeline'ının tek bir aşamasıdır; parçalama (chunking) ve retrieval mantığı burada değil, orada yaşar.
/api/embed, /api/embeddings ve /v1/embeddings: Fark Nedir?
/api/embed güncel uç noktadır; /api/embeddings ise çoğu "Ollama embeddings not working" gönderisinin arkasındaki, kullanımdan kaldırılmış eski rotadır. Eski rota tekil bir prompt alanı kullanır ve embedding (s'siz) döndürür, güncel rota ise input kullanır, toplu işlemi kabul eder ve embeddings döndürür. Üçüncü bir rota olan /v1/embeddings, OpenAI uyumludur ve bir dimensions parametresi kabul eder.
| Uç Nokta | Durum | Girdi Alanı | Yanıt Alanı | Toplu Girdi? | dimensions Parametresi? |
|---|---|---|---|---|---|
| /api/embed | Güncel | input (string veya dizi) | embeddings | Evet | Hayır |
| /api/embeddings | Eski / kullanımdan kaldırıldı | prompt (tekil) | embedding | Hayır | Hayır |
| /v1/embeddings | OpenAI uyumlu | input | data[].embedding | Evet | Evet (Matryoshka) |
404 hatası mı alıyorsunuz ya da yanıt şekli garip mi geliyor? Muhtemelen /api/embeddings (eski) uç noktasındasınız. /api/embed'e geçin ve embedding yerine embeddings anahtarını okuyun. Eski eğitimleri kopyalayan pek çok kişiyi tökezleten şey, tam olarak bu tek harf.
/v1/embeddings rotası özellikle tek bir durumda önem kazanır: OpenAI'den geçiş yaparken. Bir dimensions parametresi kabul ettiği için, Matryoshka destekli bir modeli hedef boyuta kısaltabilirsiniz; bu da bir sonraki bölümde ele alacağımız 1536 boyut uyuşmazlığının çözümüdür.
Adım 3: Vektörlerinizi Saklayın ve Arayın (pgvector, Qdrant veya Chroma)
768 elemanlı float vektörleri, en yakın komşu araması yapabilen bir veritabanında saklayın, ardından kosinüs uzaklığıyla sorgulayın. RAG kurulumlarımızda, halihazırda Postgres kullanan takımlar için varsayılan olarak Postgres artı pgvector tercih ediyoruz, çünkü embeddinglerinizi ilişkisel verinizin hemen yanında tutar. Uzantıyı etkinleştirin, modelinizin boyutuna uyan bir VECTOR(768) sütunu tanımlayın, veriyi ekleyin ve <=> kosinüs operatörüyle sorgulayın.
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE chunks (
id bigserial PRIMARY KEY,
body text,
embedding vector(768) -- nomic-embed-text ile eşleşmeli
);
-- Bir satır ekle (embedding ollama.embed'den gelir)
INSERT INTO chunks (body, embedding) VALUES ('first chunk', '[0.01, -0.02, ...]');
-- Kosinüs uzaklığına göre en yakın 5 parça
SELECT body, 1 - (embedding <=> '[0.01, -0.02, ...]') AS score
FROM chunks
ORDER BY embedding <=> '[0.01, -0.02, ...]'
LIMIT 5;Qdrant ve Chroma kavramsal olarak aynı şekilde çalışır: modelinizle eşleşen sabit bir vektör boyutuyla bir koleksiyon oluşturun, ardından upsert edip arayın. Kural her yerde geçerli: vektör veritabanı seçmek, boyutu doğru almaktan daha az önemlidir. Hâlâ karar veremediyseniz Qdrant vs Chroma vs pgvector yazımıza bakın.
Geçiş tuzağı: hiçbir Ollama modeli doğal olarak 1536 boyutlu değildir, bu yüzden mevcut bir VECTOR(1536) pgvector sütunu bunları reddeder. Üç çözüm var: (1) sütununuzla eşleşen boyuta sahip bir model seçin, (2) qwen3-embedding veya embeddinggemma gibi Matryoshka destekli bir modelde dimensions parametreli /v1/embeddings'i kullanarak 1536'ya kısaltın, ya da (3) sütunu modelin doğal boyutuna, örneğin VECTOR(768)'e yeniden tanımlayın.
nomic-embed-text'i RTX 4090'da Test Ettik: Soğuk Başlangıç vs Sıcak GPU
Ölçtük. Kendi makinemizde (Ubuntu 22.04, RTX 4090 24 GB, Ollama 0.5.x, 768 boyutlu nomic-embed-text), boşta kaldıktan sonraki ilk /api/embed çağrısı, ağırlıklar VRAM'e yüklenirken yaklaşık 1.3 saniye sürdü. Isındıktan sonra, embedding başına p50 yaklaşık 9 ms ve p95 yaklaşık 22 ms gördük. 64'lük gruplarla yaklaşık 600 embedding/saniye tuttuk.
| Metrik | Soğuk (boşta sonrası ilk istek) | Sıcak (kararlı durum) |
|---|---|---|
| Gecikme p50 | ~1.3 sn | ~9 ms |
| Gecikme p95 | ~1.3 sn | ~22 ms |
| Verim (batch=64) | yok | ~600 embedding/sn |
| 10.000 parçalık veri kümesi | yok | ~50 sn |
"Ollama embeddings neden yavaş veya zaman aşımına uğruyor" sorusunu yanıtlayan tuzak da bu. Ollama, varsayılan olarak bir modeli yaklaşık 5 dakika boşta kaldıktan sonra VRAM'den kaldırır. Bu yüzden bir sonraki isteğiniz o ~1.3 sn'lik soğuk başlangıcı tekrar öder ki bu da production'da rastgele bir sıçrama gibi hissettirir. Çözüm keep_alive:
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": "keep me warm",
"keep_alive": -1
}'keep_alive: -1 ayarı, modeli VRAM'de süresiz olarak sabitler, böylece her istek sıcak yolda kalır. Sıcakken, RTX 4090'da nomic-embed-text p95'te yaklaşık 22 ms tuttu. 5 dakika boşta bırakırsanız, bir sonraki isteğiniz ~1.3 sn'lik soğuk başlangıcı tekrar öder. Gecikmeye duyarlı bir servis için, modeli sabitleyin.
Embeddingleri Kendiniz Barındırmaya Değer mi? Maliyet vs API
Yerel embeddingler, marjinal olarak milyon token başına kabaca $0 artı elektrik masrafına mal olur; OpenAI text-embedding-3-small içinse bu rakam milyon token başına yaklaşık $0.02'dir. Ama dürüst cevap şu: self-hosting yalnızca belirli bir token hacmi eşiğinin üzerinde kazanır. Ayda birkaç yüz milyon tokenin altında, kazandığınız dolar değil; harcadığınız ops zamanı ve boşta bekleyen GPU'dur. Düşük hacimde API'nin kolaylığı kazanır.
| Faktör | Yerel Ollama | OpenAI API |
|---|---|---|
| 1M token başına marjinal maliyet | ~$0 (sadece elektrik) | ~$0.02 |
| Başlangıç maliyeti | GPU + kurulum | $0 |
| Veri gizliliği | Makinenizden hiç çıkmaz | Sağlayıcıya gönderilir |
| Operasyon yükü | Sunucuyu siz çalıştırırsınız | Yok |
| En iyi olduğu durum | Yüksek hacim, özel veri | Düşük hacim, GPU yok |
Embeddingleri kendiniz barındırmak, API'yi ancak ayda kabaca birkaç yüz milyon tokenin üzerinde geçer. Bunun altında, kazandığınız dolar değil, harcadığınız ops zamanıdır. Yerelin uymadığı durumlar: düşük sorgu hacmi, GPU yokluğu veya bir sunucuyu sağlıklı tutacak ops kapasitesi olmayan bir ekip. Bu durumlarda yönetilen bir API pragmatik tercihtir ve Voyage, OpenAI ve Cohere embedding API'lerinin karşılaştırması bir sonraki okumanız olmalı. GPU'yu ve operasyonu hiç kendiniz üstlenmek istemiyor musunuz? Birçok ekip gizlilik için embeddinglerini yerelde tutar ama kurulum ve günlük bakım için destek alır. Tam da bu tür projeler bizim yapay zeka entegrasyonu hizmetimizin işidir. Çalışma zamanlarını karşılaştırmak isterseniz modelleri yerel çalıştırmak için diğer araçlara göz atın.
Yazar Hakkında
Mert Batur, B2B müşteriler için AI ajanları, otomasyon sistemleri ve sesli/SDR pipeline'ları geliştiren Techsy.io'nun Kurucu Ortağı'dır. Techsy ekibinin production'da gerçekten kullandığı LLM araç yığını hakkında yazıyor.
Unvanlar: Kurucu Ortak, Techsy.io. LinkedIn üzerinden bağlantı kurun.
Sıkça Sorulan Sorular
Ollama ile embeddingleri yerel çalıştırmak OpenAI API'sinden gerçekten daha ucuz mu?
Yalnızca belirli bir token hacmi eşiğinin üzerinde. Yerel marjinal maliyet, milyon token başına kabaca $0 artı elektrik iken, OpenAI text-embedding-3-small için bu yaklaşık $0.02'dir. Ayda birkaç yüz milyon tokenin altında, API kolaylık ve sıfır ops avantajıyla kazanır. Kendiniz barındırmanın diğer nedeni gizliliktir: veriniz asla makineden çıkmaz.
/api/embed ile /api/embeddings arasındaki fark nedir?
/api/embed, güncel uç noktadır. Bir input alanı alır (tekil string veya toplu işlem için bir dizi) ve embeddings döndürür. /api/embeddings ise, embedding döndüren tekil bir prompt alanına sahip, kullanımdan kaldırılmış eski rotadır. 404 hatası alıyorsanız veya beklenmedik bir yanıt şekliyle karşılaşıyorsanız, neredeyse kesin olarak eski rotadasınızdır.
Ollama embeddingleri ücretsiz mi?
Token başına ücret ve API anahtarı gerekmemesi anlamında, evet. Donanım ve onu çalıştırmak için harcanan elektrik için ödeme yaparsınız. Bulut API'lerindeki gibi ölçümlü faturalandırma yoktur, bu yüzden GPU'nuz çalışır durumdayken bir milyon embedding daha üretmek, marjinal olarak neredeyse hiçbir şeye mal olmaz.
RAG için varsayılan veya en iyi Ollama embedding modeli hangisi?
768 boyutlu nomic-embed-text, yerel RAG için popüler varsayılan seçimdir; OpenAI'nin eski ada-002 modelini geride bırakır ve mütevazı donanımda çalışır. Çok dilli veya uzun bağlamlı işler için bge-m3 veya qwen3-embedding daha güçlüdür. Sağlayıcılar arası puanlı ve sıralı karşılaştırma için embedding modelleri rehberimize bakın.
Ollama embeddinglerim neden yavaş veya zaman aşımına uğruyor?
Boşta kaldıktan sonraki ilk istek, model VRAM'e yüklenirken bir soğuk başlangıç bedeli öder; bizim RTX 4090'ımızda bu yaklaşık 1.3 saniyedir. Ollama ayrıca varsayılan olarak yaklaşık 5 dakika boşta kaldıktan sonra modeli kaldırır, bu yüzden aralıklı yavaşlık genellikle tekrarlanan bir soğuk başlangıçtır. Modeli VRAM'de sabitlemek için keep_alive: -1 ayarlayın.
Ollama, OpenAI'nin 1536 boyutlu embeddinglerine denk gelebilir mi?
Hiçbir Ollama modeli doğal olarak 1536 boyutlu değildir, bu yüzden mevcut bir VECTOR(1536) sütununa geçiş, boyut uyuşmazlığı nedeniyle bozulur. Bunu düzeltmek için qwen3-embedding veya embeddinggemma gibi bir Matryoshka modelinde dimensions parametreli /v1/embeddings'i çağırın, ya da sütununuzu modelin doğal boyutuna, örneğin VECTOR(768)'e yeniden tanımlayın.
Embedding modellerini yerel çalıştırmak için GPU'ya ihtiyacım var mı?
Hayır. nomic-embed-text (137M) ve all-minilm (22M) gibi küçük modeller, düşük hacimde CPU'da gayet iyi çalışır. Bir GPU, embedding başına gecikmeyi tek haneli milisaniyelere indirir ve batch verimini saniyede yüzlerce embeddinge yükseltir; bu da binlerce parçayı aynı anda indekslerken önem kazanır.
Ollama embeddinglerini Python veya LangChain'de nasıl kullanırım?
Resmi istemci çağrısı ollama.embed(model="nomic-embed-text", input=["chunk a", "chunk b"]) şeklindedir ve bir embeddings listesi döndürür. LangChain'de, http://localhost:11434'e yönlendirilmiş OllamaEmbeddings sınıfını kullanın, ardından bunu diğer herhangi bir embeddings sağlayıcısı gibi vektör deponuzun from_documents veya add_texts metoduna aktarın.
Ollama embedding modelleri hangi bağlam uzunluğunu destekler?
Modele göre değişir. nomic-embed-text, doğal olarak 8192 tokeni destekler ancak sunulduğunda varsayılan olarak 2048 tokenlik bir pencereyle çalışır, bu yüzden uzun parçalar için num_ctx'i 8192'ye çıkarın, yoksa sessizce kesilirler. bge-m3, 8192'yi destekler ve qwen3-embedding 32K'ya kadar çıkar; all-minilm ise 256 tokenle sınırlıdır.