Back to course overview
Module 4Building the pipeline 12 min

Query flow

The request path: query rewriting for real user input, retrieval, context assembly, and the grounded generation call — end to end.

Now the read path — what happens in the seconds between a user's question and a cited answer. Four stages, each doing one job.

Stage 1 — Query processing

Users don't submit clean queries; they submit turns in a conversation. 'What about for trade customers?' retrieves nothing by itself — its meaning lives in the previous turn. The standard fix is query rewriting: a small, fast LLM call that turns conversational input into a standalone search query ('trade program return policy differences'). Rewrite when there's history; skip the extra hop for cold single questions. This is also where your identifier-routing regex (Module 3) and any filter extraction ('category: returns') live.

Stage 2 — Retrieval

Your frozen retrieval-v1: hybrid search wide, rerank narrow, pre-filtered by metadata. One addition for the pipeline: return the scores alongside the chunks — downstream stages use them (low top-score → the abstention path in Module 5).

Stage 3 — Context assembly

Everything you built in Prompt Engineering Module 4, now automated: number the chunks [S1]…[Sk], prepend each with its display metadata (title → section), fence the block, and enforce a context token budget — if the chunks exceed it, drop from the bottom of the ranking, never truncate mid-chunk.

Stage 4 — Grounded generation

answer.pypython
import anthropic

SYSTEM = """You answer questions about Harbor Lane policies and products
using ONLY the sources provided. Every factual claim must cite its source
as [S#]. If the sources don't contain the answer, say so plainly —
never fill gaps from general knowledge.
Return JSON: {"answer": str, "citations": [{"source_id": str,
"quote": str}], "answerable": bool}"""

def answer(question: str, context_block: str) -> str:
    client = anthropic.Anthropic()
    msg = client.messages.create(
        model="claude-sonnet-5",
        max_tokens=1024,
        system=SYSTEM,
        messages=[{"role": "user",
                   "content": f"{context_block}\n\nQuestion: {question}"}],
    )
    return msg.content[0].text

Model IDs change — if you get a model-not-found error, check Anthropic's current model list and update this string. (The claude-sonnet-5 id is used in the rewriter and the reranker too; the same note applies everywhere it appears.)

Recognize every line: the closed-book rule, the citation schema with verbatim quotes, the honest exit — your Prompt Engineering toolkit, wired to a live retrieval feed. The one new decision is the division of labor: retrieval decides what the model may know; the prompt decides how it must behave. When an answer is wrong, that division is your debugging map — and the first question is always the one you learned in the RAG overview: was the right chunk even retrieved?

Log the whole trace

For every query, log: raw input → rewritten query → retrieved ids + scores → context token count → model output. This trace is Module 6's raw material and Module 7's monitoring feed. Pipelines without traces are debugged by vibes.