~/ / Artigos sobre IA / LLMs locais em uma VPS / Embeddings com o Ollama: o básico para busca e RAG
Embeddings com o Ollama: o básico para busca e RAG
Uma busca que encontra trechos pelo significado e o RAG, em que um modelo de chat responde a partir dos seus próprios documentos, começam os dois com embeddings. O Ollama pode criá-los no mesmo servidor que executa o seu modelo de chat. Este artigo trata da requisição, dos modelos que a biblioteca do Ollama lista, das configurações que mudam o resultado e de como comparar os vetores, usando apenas o que dizem a documentação e as páginas da biblioteca do Ollama. Duas ferramentas desta página permitem testar os passos no navegador.
Publicado: · 5 min de leitura · Fatos conferidos na documentação e nas páginas da biblioteca do Ollama em 2026-11-04. Modelos e campos mudam, por isso consulte as páginas atuais antes de depender deles.
O que é um embedding
A página de embeddings do Ollama diz que os embeddings transformam texto em vetores numéricos que podem ser guardados em um banco de dados vetorial, pesquisados com a similaridade de cosseno ou usados em pipelines de RAG. O comprimento do vetor depende do modelo; a página indica que costuma ir de 384 a 1024 dimensões.
Uma busca cria o embedding da pergunta com o mesmo modelo e procura os vetores guardados que mais se parecem com ele.
Criar embeddings com /api/embed
O endpoint é POST /api/embed. A requisição precisa de model e input, e input pode ser uma única string ou um array de strings. Com um array, a resposta traz um vetor por string no campo embeddings, na mesma ordem, de modo que um lote de trechos precisa de apenas uma requisição.
A documentação também mostra a linha de comando: ollama run embeddinggemma "Hello world" imprime o vetor como um array JSON, e o texto pode ser enviado por pipe com echo.
| Campo | O que diz a referência da API |
|---|---|
| model | Obrigatório. O nome do modelo. |
| input | Obrigatório. Um texto ou um array de textos. |
| truncate | Padrão true: entradas que excedem a janela de contexto são truncadas. Se for false, um erro é retornado. |
| dimensions | O número de dimensões para as quais os embeddings são gerados. |
| keep_alive | Por quanto tempo o modelo permanece carregado. |
| options | Opções de execução, como num_ctx para o comprimento do contexto. |
O Ollama também tem um endpoint compatível com a OpenAI, /v1/embeddings. Sua documentação lista como compatíveis model, input como string ou array de strings, encoding format e dimensions, e como não compatíveis os arrays de tokens e user.
Modelos de embeddings na biblioteca do Ollama
A biblioteca do Ollama tem uma categoria de embeddings. A tabela mostra seis dos modelos listados ali, com o tamanho e a janela de contexto que a página de tags de cada modelo informa para a tag latest. Quatro dos seis têm menos de 1GB.
| Modelo | Tamanho da tag latest | Janela de contexto |
|---|---|---|
| all-minilm | 46MB | 512 |
| nomic-embed-text | 274MB | 2K |
| embeddinggemma | 622MB | 2K |
| mxbai-embed-large | 670MB | 512 |
| bge-m3 | 1.2GB | 8K |
| qwen3-embedding | 4.7GB | 40K |
Outras tags mudam o tamanho: por exemplo, a biblioteca lista qwen3-embedding:0.6b com 639MB e janela de contexto de 32K, e embeddinggemma:300m-qat-q4_0 com 239MB. Não comparamos a qualidade desses modelos; as páginas da biblioteca não os classificam. Ao testarmos o all-minilm no Ollama 0.40.11, o ollama show mostrou um comprimento de contexto de 512 e um parâmetro num_ctx de 256, e uma entrada longa foi cortada em 256 tokens. Confira o ollama show do modelo que você usa.
Texto longo é cortado sem nenhum erro
A janela de contexto é contada em tokens. Como truncate é true por padrão, um texto mais longo que a janela de contexto do modelo é encurtado e mesmo assim devolve um vetor, sem nenhum erro. Um documento longo enviado como uma única entrada pode perder o final dessa forma.
Duas coisas ajudam. Dividir os documentos longos em pedaços (chunks) menores e criar o embedding de cada um, o que também permite que uma busca devolva a parte que responde à pergunta. E enviar truncate com o valor false, para que o Ollama devolva um erro em vez de encurtar um pedaço que ainda é longo demais.
O divisor abaixo separa o texto por parágrafos, linhas, frases e espaços, com uma sobreposição (overlap), e monta uma única requisição /api/embed para todos os pedaços. Ele conta caracteres, não tokens, porque cada modelo tem seu próprio tokenizador, então deixe uma margem abaixo da janela de contexto.
Experimente: RAG Text Chunker
Os comprimentos estão em caracteres. A janela de contexto do modelo está em tokens, e quantos tokens um texto usa depende do modelo, então deixe uma margem.
Comando curl
Execute em uma máquina que alcance o Ollama. A resposta tem um vetor por pedaço, nesta ordem.
curl http://localhost:11434/api/embed -d '{
"model": "embeddinggemma",
"input": [
"Embeddings turn text into numeric vectors. You can store them in a vector database and search them with cosine similarity, or use them in a RAG pipeline.\n\nThe length of each vector depends on the embedding model. Use the same model when you index your documents and when you embed a question.\n\n",
"Ollama'\''s /api/embed endpoint takes a single string or an array of strings. By default, input that is longer than the model'\''s context window is truncated. Set truncate to false to get an error instead.\n\n",
"Split long documents into smaller chunks before you embed them, so that each chunk fits in the context window and a search can return the part that answers the question."
],
"truncate": false
}'Pedaços
3 pedaços. O mais longo tem 294 caracteres.
#0 · 294 caracteres · começa na posição 0
Embeddings turn text into numeric vectors. You can store them in a vector database and search them with cosine similarity, or use them in a RAG pipeline. The length of each vector depends on the embedding model. Use the same model when you index your documents and when you embed a question.
#1 · 202 caracteres · começa na posição 294
Ollama's /api/embed endpoint takes a single string or an array of strings. By default, input that is longer than the model's context window is truncated. Set truncate to false to get an error instead.
#2 · 169 caracteres · começa na posição 496
Split long documents into smaller chunks before you embed them, so that each chunk fits in the context window and a search can return the part that answers the question.
Corpo JSON para /api/embed
{
"model": "embeddinggemma",
"input": [
"Embeddings turn text into numeric vectors. You can store them in a vector database and search them with cosine similarity, or use them in a RAG pipeline.\n\nThe length of each vector depends on the embedding model. Use the same model when you index your documents and when you embed a question.\n\n",
"Ollama's /api/embed endpoint takes a single string or an array of strings. By default, input that is longer than the model's context window is truncated. Set truncate to false to get an error instead.\n\n",
"Split long documents into smaller chunks before you embed them, so that each chunk fits in the context window and a search can return the part that answers the question."
],
"truncate": false
}Campos da requisição conforme a referência da API do Ollama para /api/embed, conferidos em 2026-11-04. Ollama API: Generate embeddings
Tudo é feito no seu navegador. A ferramenta apenas escreve o comando e não envia nada.
Use um só modelo para indexar e para buscar
A página de embeddings diz para usar o mesmo modelo de embeddings tanto para indexar quanto para consultar. O comprimento do vetor depende do modelo, então vetores de dois modelos diferentes podem nem ter o mesmo número de dimensões.
O mesmo vale para dimensions: se você o definir ao indexar seus documentos, defina o mesmo valor ao criar os embeddings das perguntas. Se mudar o modelo ou esta configuração, crie de novo os embeddings dos documentos guardados.
Comparar os vetores
A documentação recomenda a similaridade de cosseno para a maioria dos casos de busca semântica e diz que /api/embed devolve vetores normalizados em L2, de comprimento unitário. Para vetores de comprimento unitário, a similaridade de cosseno e o produto escalar são o mesmo número, portanto um banco de dados vetorial configurado com qualquer um dos dois classificará os resultados da mesma forma.
Para testar um modelo com seus próprios textos antes de construir qualquer coisa, crie em uma única requisição o embedding de uma pergunta e de alguns trechos, com a pergunta primeiro. Cole a resposta abaixo: os trechos são classificados por sua similaridade de cosseno com a pergunta, e a ferramenta mostra se todos os vetores têm comprimento unitário e as mesmas dimensões.
Experimente: Embedding Similarity Calculator
O exemplo usa vetores inventados, de comprimento unitário e com 4 dimensões, para que dê para lê-los. Embeddings reais têm centenas ou milhares de dimensões.
Lido como uma resposta do Ollama /api/embed: 4 vetores com 4 dimensões. Todos os vetores têm comprimento 1, então a similaridade de cosseno e o produto escalar são iguais.
Classificação por similaridade de cosseno
Comparado com #0 How do I keep a model loaded in Ollama?. Quanto maior, mais similar.
| Posição | Texto | Cosseno | Produto escalar | Distância |
|---|---|---|---|---|
| 1 | #1 keep_alive controls how long the model stays in memory | 0.9962 | 0.9962 | 0.0876 |
| 2 | #2 Protect Ollama with nginx and a password | 0.4037 | 0.4037 | 1.0921 |
| 3 | #3 Tomorrow's weather forecast | 0.0100 | 0.0100 | 1.4071 |
Matriz de similaridade de cosseno
Cada célula compara o vetor da linha com o vetor da coluna.
| #0 | #1 | #2 | #3 | |
|---|---|---|---|---|
| #0 | 1.000 | 0.996 | 0.404 | 0.010 |
| #1 | 0.996 | 1.000 | 0.475 | -0.005 |
| #2 | 0.404 | 0.475 | 1.000 | -0.377 |
| #3 | 0.010 | -0.005 | -0.377 | 1.000 |
Vetores
| Texto | Dimensões | Comprimento (norma L2) | Comprimento unitário |
|---|---|---|---|
| #0 How do I keep a model loaded in Ollama? | 4 | 1.000000 | Sim |
| #1 keep_alive controls how long the model stays in memory | 4 | 1.000000 | Sim |
| #2 Protect Ollama with nginx and a password | 4 | 1.000001 | Sim |
| #3 Tomorrow's weather forecast | 4 | 1.000000 | Sim |
Com base na documentação de embeddings e na referência da API do Ollama, conferidas em 2026-11-04. Ollama: Embeddings / Ollama API: Generate embeddings
Tudo é calculado no seu navegador. Nada é enviado para lugar nenhum.
Memória em um servidor pequeno
Um modelo de embeddings é carregado como qualquer outro modelo. O FAQ do Ollama diz que OLLAMA_MAX_LOADED_MODELS, o número de modelos que podem ficar carregados ao mesmo tempo se couberem na memória, tem como padrão 3 vezes o número de GPUs, ou 3 para inferência em CPU. Assim, um modelo de chat e um modelo de embeddings podem ficar carregados juntos quando a memória permite.
Nosso artigo sobre como acompanhar a memória do Ollama explica ollama ps, keep_alive e as outras configurações que decidem o que fica na memória.
Fontes
Leia a seguir
- Guarde e pesquise embeddings do Ollama no PostgreSQL com o pgvectorGuarde embeddings do Ollama no PostgreSQL com o pgvector, pesquise-os com HNSW ou IVFFlat e passe os resultados para o /api/chat para que a resposta cite suas fontes.
- Acompanhe a memória do Ollama em uma VPS pequenaVeja o que o Ollama mantém na memória, por quanto tempo e quais configurações mudam isso: ollama ps, keep_alive e os limites, a partir do FAQ oficial.
- Conectar o Dify ao Ollama no seu próprio VPSExecute o Dify no seu próprio VPS e use o Ollama como modelo: instalação, campos do plugin, o problema do endereço no Docker e embeddings, segundo a documentação oficial.
- Rodar um LLM local sem um PC caro: guia para iniciantes sobre como usar uma VPSSem um PC potente? Alugue uma VPS e rode um pequeno LLM local pelo navegador: seis passos, da estimativa de memória até uma tela de chat protegida, com os limites ditos com honestidade.