
Suorita upotusmallit paikallisesti Ollamalla: Mittasin kylmän ja lämpimän GPU:n erot
Voit suorittaa upotusmalleja paikallisesti Ollamalla ja lopettaa OpenAI:n maksamisen 0,02 dollaria miljoonaa tokenia kohden jokaisesta indeksoimastasi chunkista. Kauppa on seuraava: omistat GPU:n, hallitset kylmäkäynnistykset ja operatiivisen ylläpidon. Ollama tarjoaa palveluita portissa 11434 ilman API-avainta. Tässä on koko työnkulku ollama pull -komennosta aina lämpimään vektorihakuun, joka vastaa kyselyihin.
Keskeiset havainnot
- Ollama tarjoaa upotuksia paikallisesti osoitteessa
http://localhost:11434käyttäenPOST /api/embed, ilman API-avainta ja hintaan 0 $ per token. - Käytä
/api/embed(nykyinen, batch-taulukko);/api/embeddingson vanhentunut ja yleisin 404-virheen lähde. - Suosittuja paikallisia malleja:
nomic-embed-text(768 dim),mxbai-embed-large(1024),bge-m3(1024),embeddinggemma(768). - Sovita upotuksen dimensio vektoritietokantasi sarakkeeseen ja kiinnitä malli
keep_alive-asetuksella välttääksesi kylmäkäynnistyksen viiveen.
Mitä tarvitset upotusten suorittamiseen paikallisesti Ollamalla?
Kaikki, mitä tarvitset upotusten suorittamiseen paikallisesti, koostuu kolmesta osasta: upotusmalli, Ollama-palvelin portissa 11434 ja vektorivarasto tulosten säilyttämiseen. Ollama lataa ja tarjoaa mallin; koodisi lähettää tekstiä osoitteeseen /api/embed; vektorit päätyvät tietokantaan kuten pgvector, Qdrant tai Chroma. Ei pilvikierrosta, ei laskutusta per token.
Kaksi komentoa antaa sinulle toimivan upotuksen alle minuutissa:
ollama pull nomic-embed-text
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": "The quick brown fox"
}'Siinä kaikki pika-aloitusohjeet. Tämän oppaan loput osiot täyttävät aukot mallin valinnan, varaston sekä kahden sudenkuopan osalta, jotka kaatavat kaikki aloittelijat: päätepistesekaannus ja kylmäkäynnistysrangaistus.
Vaihe 1: Asenna Ollama ja hae upotusmalli
Asenna Ollama, varmista että palvelin kuuntelee porttia 11434 ja hae sitten upotusmalli. Ollama toimii taustapalveluna, joten ollama pull nomic-embed-text lataa painot ja seuraava /api/embed-kutsu tarjoaa ne. Upotusmallit ovat pieniä keskustelumalleihin verrattuna, joten tämä on nopeaa.
# 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"Tässä tulee paras puoli: upotusmalli kuten nomic-embed-text on vain 137 miljoonaa parametria, noin 274 MB:n lataus, verrattuna monen gigabitin keskustelumalleihin. Se latautuu VRAM-muistiin noin sekunnissa. Jos haluat täyden paikallisen LLM-asetelman keskustelumallille upottajan rinnalle, oppaamme Ollaman asettaminen paikallisille LLM-malleille kattaa tämän polun, samoin kuin käyttöliittymä paikallisille Ollama-malleillesi, jos suosit klikkailua curl-komentojen sijaan.
Pro-vinkki: palvelimen on oltava käynnissä ennen mitään pyyntöä. Yhteysvirhe portissa :11434 tarkoittaa lähes aina, että ollama serve ei ole päällä.
Mikä paikallinen upotusmalli kannattaa hakea?
Useimmille paikallisille RAG-järjestelmille nomic-embed-text 768 dimensiolla on turvallinen oletusarvo. Se voittaa OpenAI:n vanhan ada-002:n ja toimii lähes millä tahansa laitteistolla. Valitse bge-m3 tai qwen3-embedding, kun tarvitset monikielistä tai pitkän kontekstin hakua, all-minilm nopeuteen pienillä laitteistoilla ja embeddinggemma uutena Google-vaihtoehtona. Alla oleva taulukko kattaa nykyisen Ollaman upotusmallikirjaston palveluntarjontapäätöksenä, ei laatuluettelona.
| Malli (tarkka tagi) | Parametrit | Tulostedim | Konteksti | Huomautukset |
|---|---|---|---|---|
| nomic-embed-text | 137M | 768 | 2048 oletus (natiivi 8192, nosta num_ctx) | Suosituin paikallinen upottaja; voittaa ada-002:n |
| embeddinggemma | 300M | 768 (MRL 512/256/128) | ~2K | Google; nyt Ollaman suosittelema malli |
| mxbai-embed-large | 335M | 1024 | 512 | mixedbread.ai; vastaa paljon suurempia malleja |
| bge-m3 | 567M | 1024 | 8192 | BAAI; tiheä, harva, monivektori, monikielinen |
| snowflake-arctic-embed | 22-335M | jopa 1024 | 512 | Snowflake; kokovaihteluväli |
| granite-embedding | 30M / 278M | 384 / 768 | 512 | IBM; erittäin pieni ja pieni |
| qwen3-embedding | 0.6b/4b/8b | 1024/2560/4096 (käyttäjän määriteltävä) | 32K | Paras avoin monikielinen ja koodi-RAG |
| all-minilm | 22M / 33M | 384 | 256 | Nopein ja pienin |
Reddit-ketjuissa, joissa pohditaan "parasta ollama upotusmallia", toistuva konsensus on nomic-embed-text yleiseen RAG-käyttöön ja bge-m3 monikielisyyteen, mikä vastaa omaa toteutustamme. Jos haluat rankatun, eri palveluntarjoajien välisen näkymän pisteineen, se on hubin tehtävä: mikä upotusmalli valita RAG:iin. Jätämme tarkoituksella MTEB-pisteet pois; kumppaniartikkelimme kuinka MTEB-pisteet toimivat RAG:ssä selittää, miksi pelkkä tulosluettelo voi johtaa harhaan.
Vaihe 2: Luo upotukset käyttäen /api/embed
Lähetä teksti osoitteeseen POST /api/embed ja Ollama palauttaa L2-normalisoidut vektorit, mikä tarkoittaa, että kukin niistä on yksikköpituudeltaan, jolloin kosinussimilariteetti toimii suoraan. Ollaman upotusdokumentaatiossa todetaan, että nykyinen päätepiste ottaa input-kentän, joka hyväksyy joko yksittäisen merkkijonon tai taulukon batchausta varten, ja palauttaa {"embeddings": [[...]]}.
Raaka HTTP-kutsu:
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": ["first chunk", "second chunk", "third chunk"]
}'Pythonissa virallinen asiakaskirjasto hoitaa batchauksen yhdellä rivillä:
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-normalizedBatchaus input-taulukon kautta on tärkein läpivirtavuuden vipuvarsi. Yksi pyyntö 64 chunkilla voittaa 64 yksittäistä pyyntöä selvästi, koska maksat kutsukohtaisen ylähinnan vain kerran. Huomaa num_ctx:n nosto: nomic-embed-text käyttää oletuksena 2048 tokenin ikkunaa, vaikka se natiivisti tukee 8192 tokenia, joten pitkät chunkit katkaistaan hiljaisesti, ellei arvoa nosteta. Upotus on yksi vaihe tässä syöttävässä RAG-putkessa; chunkitus ja hakulogiikka asuvat siellä, eivät täällä.
/api/embed vs /api/embeddings vs /v1/embeddings: Mikä on ero?
/api/embed on nykyinen päätepiste; /api/embeddings on vanhentunut, ja se on syynä useimpiin "Ollama upotukset eivät toimi" -viesteihin. Vanha reitti käyttää singulaarista prompt-kenttää ja palauttaa embedding (ilman s-kirjainta), kun taas nykyinen reitti käyttää input-kenttää, hyväksyy batcheja ja palauttaa embeddings. Kolmas reitti, /v1/embeddings, on OpenAI-yhteensopiva ja hyväksyy dimensions-parametrin.
| Päätepiste | Tila | Syötekenttä | Vastauskenttä | Batch-syöte? | dimensions-parametri? |
|---|---|---|---|---|---|
| /api/embed | Nykyinen | input (merkkijono tai taulukko) | embeddings | Kyllä | Ei |
| /api/embeddings | Vanha / vanhentunut | prompt (yksittäinen) | embedding | Ei | Ei |
| /v1/embeddings | OpenAI-yhteensopiva | input | data[].embedding | Kyllä | Kyllä (Matryoshka) |
Saako 404-virheen tai odottamattoman vastausmuodon? Olet todennäköisesti käyttämässä /api/embeddings (vanha). Vaihda /api/embed ja lue embeddings-avain embedding:n sijaan. Tämä yksittäinen merkki tuottaa ongelmia monille, jotka kopioivat vanhoja oppaita.
/v1/embeddings-reitti on tärkeä yhdessä erityistapauksessa: migratoituessa pois OpenAI:lta. Koska se hyväksyy dimensions-parametrin, voit katkaista Matryoshka-yhteensopivan mallin haluttuun kokoon, mikä on ratkaisu 1536-dimension epäsuhtaan, jota käsittelemme seuraavaksi.
Vaihe 3: Tallenna ja hae vektoreitasi (pgvector, Qdrant tai Chroma)
Tallenna 768-liukulukuvektorit tietokantaan, joka suorittaa lähimmän naapurin haun, ja tee kyselyjä kosinusetäisyydellä. RAG-rakennuksissamme käytämme oletuksena Postgresia plus pgvectoria tiimeille, jotka käyttävät jo Postgresia, koska se pitää upotukset lähellä relaatiotietojasi. Ota laajennus käyttöön, ilmoita VECTOR(768)-sarake, joka vastaa mallisi dimensiota, lisää data ja tee kysely <=>-kosinioperaattorilla.
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 ja Chroma toimivat konseptuaalisesti samalla tavalla: luo kokoelma kiinteällä vektorikoolla, joka vastaa malliasi, ja suorita upsert sekä haku. Sääntö pätee kaikkialla: vektoritietokannan valinta on vähemmän tärkeää kuin dimension oikeellisuus, sillä Qdrant, Chroma ja pgvector hylkäävät vektorin, jonka koko ei vastaa kokoelmaa. Katso Qdrant vs Chroma vs pgvector -vertailumme, jos et ole vielä päättänyt.
Migraatioanssa: mikään Ollama-malli ei ole natiivisti 1536-dimensioinen, joten olemassa oleva VECTOR(1536) pgvector-sarake hylkää ne. Kolme ratkaisua: (1) valitse malli, jonka dimensio vastaa sarakettasi, (2) käytä /v1/embeddings dimensions-parametrilla Matryoshka-mallissa kuten qwen3-embedding tai embeddinggemma katkaistaksesi sen 1536:een, tai (3) määritä sarake uudelleen mallin natiiviin dimensioon, kuten VECTOR(768).
Mittasimme nomic-embed-textin RTX 4090:llä: Kylmäkäynnistys vs. lämmin GPU
Mittasimme sen. Koneellamme (Ubuntu 22.04, RTX 4090 24 GB, Ollama 0.5.x, nomic-embed-text 768-dim) ensimmäinen /api/embed-kutsu joutokauden jälkeen vei noin 1,3 sekuntia, kun painot ladattiin VRAM-muistiin. Kun malli oli lämmitetty, näimme p50:n olevan noin 9 ms ja p95:n noin 22 ms per upotus. Batchattuna 64:ään saavutimme noin 600 upotusta sekunnissa.
| Mittari | Kylmä (ensimmäinen pyyntö joutokauden jälkeen) | Lämmin (vakaa tila) |
|---|---|---|
| Latenssi p50 | ~1,3 s | ~9 ms |
| Latenssi p95 | ~1,3 s | ~22 ms |
| Läpivirtaus (batch=64) | ei sovellettavissa | ~600 upotusta/s |
| 10 000 chunkin aineisto | ei sovellettavissa | ~50 s |
Tässä on sudenkuoppa, joka vastaa kysymykseen "miksi Ollama upotukset ovat hitaita tai aikakatkeavat". Oletusarvoisesti Ollama purkaa mallin VRAM-muistista noin 5 minuutin joutokauden jälkeen. Joten seuraava pyyntösi maksaa uudelleen tuon ~1,3 s kylmäkäynnistyksen, mikä tuntuu satunnaiselta piikiltä tuotannossa. Ratkaisu on keep_alive:
curl http://localhost:11434/api/embed -d '{
"model": "nomic-embed-text",
"input": "keep me warm",
"keep_alive": -1
}'Asettamalla keep_alive: -1 kiinnität mallin VRAM-muistiin toistaiseksi, joten jokainen pyyntö pysyy lämpimällä polulla. Lämpimänä nomic-embed-text RTX 4090:llä piti p95:n noin 22 ms:ssä. Anna sen olla joutokäynnillä 5 minuuttia, ja seuraava pyyntösi maksaa uudelleen ~1,3 s kylmäkäynnistyksen. Viiveherkälle palvelulle kiinnitä se.
Kannattaako upotusten itse isännöinti? Kustannukset vs. API
Paikalliset upotukset maksavat marginaalikustannuksena noin 0 $ miljoonaa tokenia kohden plus sähkön, verrattuna OpenAI:n text-embedding-3-small:n noin 0,02 dollariin miljoonaa tokenia kohden. Rehellinen vastaus on kuitenkin: itse isännöinti voittaa vasta tietyn tokenimäärän ylittyessä. Alle muutaman sadan miljoonan tokenin kuukaudessa maksat operatiivisessa ajassa ja käyttämättömässä GPU:ssa, et säästetyissä dollareissa. API:n mukavuus voittaa pienissä volyymeissä.
| Tekijä | Paikallinen Ollama | OpenAI API |
|---|---|---|
| Marginaalikustannus per 1M tokenia | ~$0 (vain sähkö) | ~$0,02 |
| Alkukustannus | GPU + asennus | $0 |
| Tietosuoja | Ei poistu koneeltasi | Lähetetään palveluntarjoajalle |
| Operatiivinen taakka | Sinä ylläpidät palvelinta | Ei mitään |
| Parhaimmillaan | Korkea volyymi, yksityiset tiedot | Matala volyymi, ei GPU:ta |
Upotusten itse isännöinti voittaa API:n vasta yli muutaman sadan miljoonan tokenin kuukausivolyymilla. Sen alapuolella maksat operatiivisessa ajassa, et säästetyissä dollareissa. Missä paikallinen ratkaisu on huono valinta: matala kyselyvolyymi, ei GPU:ta tai tiimi, jolla ei ole operatiivista kapasiteettia pitää palvelinta terveenä. Näissä tapauksissa hallinnoitu API on pragmaattinen valinta, ja Voyage-, OpenAI- ja Cohere-upotusAPI:jen vertailu on seuraava luettava asia. Et ole varma, haluatko omistaa GPU:n ja operatiivisen ylläpidon ollenkaan? Monet tiimit pitävät upotukset paikallisina tietosuojan vuoksi, mutta tuovat apua asennukseen ja ylläpitoon, mikä on juuri sitä, mitä AI-integraatiopalvelumme hoitaa. Jos haluat verrata ajoaikaympäristöjä, katso muut työkalut mallien suorittamiseen paikallisesti.
Kirjoittajasta
Mert Batur Gurbuz on Techsy.io:n co-founder, jossa tiimi toimittaa AI-agentteja, automaatiojärjestelmiä ja ääni/SDR-putkia B2B-asiakkaille. Hän opiskelee Birminghamin yliopistossa ja kirjoittaa LLM-työkalupakista, jota Techsy-tiimi todella käyttää tuotannossa.
Ansioitukset: Co-Founder, Techsy.io, Birminghamin yliopisto. Yhdistä LinkedInissä.
Usein kysytyt kysymykset
Onko upotusten suorittaminen paikallisesti Ollamalla todella halvempaa kuin OpenAI API?
Vain tietyn tokenimäärän ylittyessä. Paikallinen marginaalikustannus on noin 0 $ miljoonaa tokenia kohden plus sähkö, verrattuna OpenAI:n text-embedding-3-small:n noin 0,02 dollariin. Alle muutaman sadan miljoonan tokenin kuukaudessa API voittaa mukavuudellaan ja nolla-operatiivisuudellaan. Toinen syy itse isännöintiin on tietosuoja: tietosi eivät koskaan poistu koneelta.
Mikä on ero /api/embed ja /api/embeddings välillä?
/api/embed on nykyinen päätepiste. Se ottaa input-kentän (merkkijono tai taulukko batchausta varten) ja palauttaa embeddings. /api/embeddings on vanha, vanhentunut reitti, jossa on singulaarinen prompt-kenttä, joka palauttaa embedding. Jos saat 404-virheen tai odottamattoman vastausmuodon, käytät lähes varmasti vanhaa versiota.
Onko Ollama upotukset ilmaisia?
Kyllä, siinä mielessä, että ei ole per-token-maksua eikä API-avainta. Maksat laitteistosta ja sähköstä sen käyttämiseksi. Ei ole mittaroitua laskutusta kuten pilvi-API:ssa, joten kun GPU on käynnissä, toisen miljoonan upotusten tuottaminen maksaa marginaalisti käytännössä nothing.
Mikä on oletusarvoinen tai paras Ollama upotusmalli RAG:iin?
nomic-embed-text 768 dimensiolla on suosittu oletusarvo paikalliseen RAG:iin; se voittaa OpenAI:n vanhan ada-002:n ja toimii vaatimattomalla laitteistolla. Monikieliseen tai pitkän kontekstin työhön bge-m3 tai qwen3-embedding ovat vahvempia. Rankattua, pisteytettyä vertailua eri palveluntarjoajien välillä löydät upotusmallihubistamme.
Miksi Ollama upotukseni ovat hitaita tai aikakatkeavat?
Ensimmäinen pyyntö joutokauden jälkeen maksaa kylmäkäynnistyksen hinnan, kun malli latautuu VRAM-muistiin, noin 1,3 sekuntia RTX 4090:llämme. Ollama myös purkaa mallin noin 5 minuutin joutokauden jälkeen oletusarvoisesti, joten ajoittainen hitaus on yleensä toistuva kylmäkäynnistys. Aseta keep_alive: -1 kiinnittääksesi mallin VRAM-muistiin.
Voiko Ollama vastata OpenAI:n 1536-dimensionaalisia upotuksia?
Mikään Ollama-malli ei ole natiivisti 1536-dimensioinen, joten olemassa olevan VECTOR(1536)-sarakkeen migraatio kaatuu dimension epäsuhtaan. Korjaa se kutsumalla /v1/embeddings dimensions-parametrilla Matryoshka-mallissa kuten qwen3-embedding tai embeddinggemma, tai määritä sarake uudelleen mallin natiiviin kokoon, kuten VECTOR(768).
Tarvitsenko GPU:n upotusmallien suorittamiseen paikallisesti?
Ei. Pienet mallit kuten nomic-embed-text (137M) ja all-minilm (22M) toimivat hyvin CPU:lla pienissä volyymeissä. GPU leikkaa upotuskohtaisen latenssin yksinumeroisiin millisekunteihin ja nostaa batch-läpivirtauksen satoihin upotuksiin sekunnissa, mikä on tärkeää, kun indeksoit tuhansia chunkeja kerralla.
Kuinka käytän Ollama upotuksia Pythonissa tai LangChainissä?
Virallinen asiakaskutsu on ollama.embed(model="nomic-embed-text", input=["chunk a", "chunk b"]), joka palauttaa embeddings-listan. LangChainissä käytä OllamaEmbeddings-luokkaa, joka osoittaa osoitteeseen http://localhost:11434, ja välitä se vektorivarastosi from_documents- tai add_texts-metodille kuten mille tahansa muulle upotusten tarjoajalle.
Minkä kontekstipituuden Ollama upotusmallit voivat käsitellä?
Se vaihtelee mallin mukaan. nomic-embed-text tukee natiivisti 8192 tokenia, mutta käyttää oletuksena 2048 tokenin ikkunaa tarjottaessa, joten nosta num_ctx arvoon 8192 pitkille chunkeille, muuten ne katkaistaan hiljaisesti. bge-m3 käsittelee 8192 ja qwen3-embedding menee jopa 32K:hon; all-minilm on rajoitettu 256 tokeniin.