Vocabulary for this course

The terms the chapters assume, in plain words. You can open this from any chapter.

BM25
A word-matching score that ranks a document higher when it contains rare query words, with a cap on repetition.
chunk
A short passage cut from a longer document, small enough to retrieve and cite on its own.
citation
A pointer from an answer back to the exact passage it came from, so a reader can check it.
context window
The fixed amount of text a model can read in one request, counting the question and everything retrieved.
corpus
The whole collection of documents a system searches.
cosine similarity
A score from -1 to 1 for how closely two arrows point in the same direction, ignoring their lengths.
dot product
Multiply matching numbers in two lists and add the results; a larger total means closer agreement.
embedding
A list of numbers that places a piece of text in a space where similar meanings sit close together.
grounded answer
A reply built only from the passages that were retrieved, so its claims can be traced to them.
index
A structure built ahead of time so the system can find relevant passages without reading everything.
lexical search
Finding passages by the words they contain, matching the query's terms rather than its meaning.
magnitude
The length of a vector, found by squaring its numbers, adding them and taking the square root.
reranking
Scoring a short list of results again with a slower, more careful method and putting the best first.
retrieval
The step that selects passages from the corpus to put in front of the model.
top-k
The shortlist a search returns: its best few results, cut off at a number chosen in advance.
vector
An ordered list of numbers, where each position is one measured property.

RAG from the ground up

Capstone: RAG end to end

One corpus, from splitting to a cited answer, with no external services. Every stage the course covered appears once, in the order a real pipeline runs them.

Part 10 of 10

Advanced20 min readBack to Courses

The whole pipeline, in order

A document is split into chunks, each chunk is turned into a vector, the vectors go into a store, a question is embedded the same way, the nearest chunks are retrieved, and a prompt asks for an answer that cites them. Seven steps, each small enough to test alone.

The capstone builds all seven with plain Python. The vectors are hand-built concept coordinates rather than a model’s output, and the “generation” is a template rather than a language model — but every boundary is in the right place, which is what matters.

Name what each step returns: that is the contract between stages. Splitting returns chunks with ids. Embedding returns one vector per chunk. The store returns scored ids. Retrieval returns the top k. Generation returns text plus the passages it used. A change inside one stage should not change its neighbour’s shape.

Measure before you tune

The second example adds the evaluation loop: a handful of questions with known answers, a recall check, and a printed report. It is deliberately crude, and it is the difference between a demo and a system.

Once that loop exists, every change — a different chunk size, a reranker, a new embedding model — becomes a number rather than an opinion. That is the habit worth keeping from this course.

A realistic decision looks like this. Recall at four is 0.72 with 500-character chunks and 0.81 with 800, but the prompt grows by a third and latency rises. The larger chunks are better for these questions and worse for the budget, so the next experiment is overlap, not another size change. Without the loop, the same decision is an argument.

The same pipeline with a framework

retriever = vector_store.as_retriever(search_kwargs={"k": 4})

chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | model
    | StrOutputParser()
)

print(chain.invoke("How long do refunds take?"))

From corpus to cited answer

Run the pipeline, then ask a question the corpus does not answer and confirm it refuses. Add a document and check that it can now be found.

Output
Click "Run" to execute your code

What a production system adds

Four things, and none of them changes the shape above: real embeddings, so meaning rather than hand-written concepts drives the search; a persistent store, so the index is built once; a reranker, for precision on the shortlist; and tracing, so a bad answer can be followed back through every step.

The last one is the most valuable in practice. A trace shows the question, the retrieved chunks, the assembled prompt and the reply together, which is the only way to tell a retrieval failure from a generation failure after the fact.

A useful trace carries timings and ids. The embedding call, the search, the rerank and the generation each get a span naming the model or index it used. When a query is slow, the trace says which stage to fix; when an answer is wrong, it says whether the passage was absent, truncated or ignored.

Keep the retrieval results in the response object, not just the answer text. When a user reports a wrong answer, the passages are the evidence you need.

Where the next failure will come from

As the corpus grows, chunking stops being uniform: a ten-page policy document and a one-line FAQ need different treatment. As the product grows, filters multiply and the first question becomes which collection to search, not which passage.

Neither is a reason to redesign. Both are changes inside one stage, which is exactly what the boundaries in this pipeline are for.

The first new failure is usually selection: the corpus has two documents about refunds, one current and one archived, and the search returns both. The fix is a metadata filter on status, not a better embedding. The second is duplication: the same page under three URLs fills the top four. Deduplicate by content hash before you tune anything.

Test each stage alone

Each stage can be tested with a fixed input. Retrieval takes a question and returns ids, so a test asserts that the refund question returns billing#refunds in the top two. The prompt builder returns a string, so a test asserts contiguous numbering and a respected budget. Generation takes a prompt and returns text, so a test can use a recorded prompt and check the citation markers.

A failure then has an address. If the retrieval test passes, the prompt test passes and the answer is still wrong, the fault is in generation or in how the model used the context. That is a much smaller search space than “the RAG system is broken”.

A recall check over the pipeline

Run the three labelled questions, then add a fourth that the corpus cannot answer and decide what the report should say about it.

Output
Click "Run" to execute your code

Check what you learned

One question at a time. A wrong answer explains itself — take another go.

Part 1 of 5

What is the correct order of a RAG pipeline?