Retrieval-Augmented Generation, end to end — type a question and watch it chunk → embed → retrieve → ground → generate, fully offline, no API calls.
A large language model is, at heart, a very sophisticated autocomplete: it predicts the next word using patterns frozen into its weights during training. That gives it two stubborn limitations. First, its knowledge is frozen and generic — it knows nothing about your company's wiki, last night's incident report, or a PDF you just downloaded. Second, when it doesn't know something, it often makes up a fluent, confident, wrong answer (a "hallucination"), because generating plausible text is exactly what it was trained to do.
You could re-train the model on your documents, but that's slow, expensive, and goes stale the moment your data changes. Retrieval-Augmented Generation (RAG) takes a cheaper, smarter route: instead of forcing the model to memorize your knowledge, you let it look things up at the moment it answers.
RAG is two halves glued together. Retrieval finds the passages most relevant to the question; generation writes an answer using only those passages. The trick that makes retrieval work is embeddings: every passage (and the question) is converted into a vector of numbers so that text with similar meaning ends up close together in vector space. We then rank passages by how close they are to the question — usually with cosine similarity (the angle between two vectors). The closest few get pasted into the prompt as context.
Below is a tiny but real RAG engine running entirely in your browser — a bag-of-words embedder, cosine search, and a templated generator (no API calls). Type a question and watch each stage light up; the same five stages run in every production RAG system, just with stronger components.
Try: “what is a vector database?”, “what is prompt injection?”, “why split documents?”
This is the heart of RAG, so it's worth slowing down. To find "relevant" passages we need a way to
measure relevance mathematically. The idea: convert each passage into a list of numbers (a
vector, or "embedding") chosen so that passages about similar things have similar vectors. Real
systems use a trained neural network (like sentence-transformers) for this; our toy uses a
simpler bag-of-words vector — one slot per vocabulary word, counting how often it appears — which
is enough to see the mechanics.
To compare two vectors we use cosine similarity: the cosine of the angle between them. It runs
from 1.0 (pointing the same way → very similar) through 0 (perpendicular →
unrelated). We use the angle, not the distance, so a long document and a short query can still
match if they point the same direction. We embed the question, compare it to every passage, and keep the
top-k highest-scoring ones. (Curious about the geometry? The
embeddings explainer lets you drag vectors and watch cosine change.)
One detail hides a real tradeoff: chunking. Documents are split into small passages before embedding. Chunks too large dilute the signal (one vector tries to represent many ideas); too small and you lose context. Chunk size and overlap are among the biggest levers on RAG quality.
Each passage is embedded into a vector; we rank passages by cosine similarity to the question. Retrieved passages are highlighted.
Now we do something almost embarrassingly simple: we paste the retrieved passages straight into the prompt, with an instruction like "Answer using only the context below, and cite your sources." The model never "knew" these facts — it's reading them right now, the way you'd read the page you just flipped to in an open-book exam. This single move is what makes RAG answers grounded: the facts come from your documents, and instructing the model to stick to them sharply reduces hallucination.
The numbered tags [1], [2] aren't decoration — they let the model (and the
reader) cite exactly which passage supports each claim, so a human can verify the answer instead
of trusting it. In regulated domains (finance, security, medicine) this traceability is often the whole
point. Watch the prompt rebuild as you change the question or top-k.
RAG shines when answers should come from a specific, changing, or private body of knowledge: company docs, product manuals, legal/financial filings, a security knowledge base. You can update the knowledge by changing documents — no retraining — and every answer can cite its evidence.
But RAG is only as good as its retrieval. If the right passage isn't retrieved, the model can't use it — "garbage in, garbage out." Common failure modes and their fixes:
sentence-transformers, the in-memory
search for a real vector database, and the templated generator for an LLM, and you have a production RAG
app. Build exactly that, piece by piece, in BYO-9, and
see the retrieval internals in the vector-search explainer.