The plain version
A language model knows only what was in its training data. It has never seen your tax folder, your lab notebook or your company wiki. You could fine-tune it on them, but that's slow, expensive, and bad at precise facts. Retrieval-augmented generation takes the practical route instead: find the right paragraphs first, then hand them to the model along with your question.
An everyday analogy. An open-book exam. The student (the model) doesn't memorise the textbook; they get a few marked pages to read before answering. A good index makes all the difference. If you bookmark the wrong pages, even a brilliant student gets it wrong.
What's an embedding? An embedding model is a small neural network that turns a piece of text into a list of numbers, typically a few hundred to a few thousand of them. Texts with similar meaning end up with similar lists, even if they share no words: "car insurance renewal" lands near "the policy on the Honda expires in May". Searching means turning your question into the same kind of list and finding the stored passages whose lists are closest.
Embedding models are tiny compared with chat models. nomic-embed-text, a common default in Ollama, is a 274 MB download, so indexing runs comfortably on a CPU.
The four settings that matter most:
- Chunk size. Documents are cut into pieces before embedding. Too small and a chunk loses context; too big and it blurs several topics together. A few hundred tokens with some overlap is the usual starting point.
- How many chunks you retrieve (top-k). More chunks raise the chance the answer is included, but they also fill the prompt and slow the reply.
- The model's context window. Every retrieved chunk has to fit. Ollama sets its default context length from your VRAM, and below 24 GiB that's 4K tokens. Open WebUI's own troubleshooting guide flags this as a common reason retrieval "doesn't work": the passages were found and then cut off.
- The embedding model. Pick one that's good at your language and domain. The MTEB leaderboard compares them on retrieval tasks.
When RAG struggles. Questions that need the whole collection ("what are the common themes across all 400 reports?") don't fit the find-a-few-passages pattern. Neither do scanned PDFs without text, tables split across chunks, or questions phrased very differently from the source. Hybrid search (embeddings plus classic keyword search), reranking, and better PDF parsing fix most of these.
Similarity
Most stacks use cosine similarity, cos θ = (a · b) / (‖a‖ ‖b‖). Many embedding models output normalised vectors, so a plain dot product gives the same ranking. Indexes such as HNSW find approximate nearest neighbours in milliseconds, even across millions of chunks.
Prompt budget
prompt_tokens ≈ system + question + top_k × chunk_tokens TTFT ≈ prompt_tokens / prefill_tps KV_memory grows with prompt_tokens (see the KV cache explainer)Keep
top_k × chunk_tokenswell under the context you've actually configured, not the model's advertised maximum.Embedding with Ollama
ollama pull nomic-embed-text curl http://localhost:11434/api/embed -d '{"model": "nomic-embed-text", "input": "Why is the sky blue?"}'The response has an
embeddingsarray with one vector per input. llama.cpp can serve embeddings too: startllama-serverwith--embeddingand an embedding GGUF.Pitfalls
- Change the embedder, rebuild the index. Vectors from different models aren't comparable. Open WebUI asks you to reindex after switching.
- Query and document prefixes. Some models (nomic, e5) expect task prefixes such as
search_query:andsearch_document:; check the model card. - Evaluate retrieval separately. Before blaming the chat model, check whether the right chunk appears in the top-k at all.