Part 1 — LLM Application Foundations

Anatomy of an LLM application

From software to LLM engineering·Core·5 min read

See the full request path of a real LLM application — from user input through prompt assembly, the model, parsing, validation, and correction — so you can locate where behaviour is shaped and where it breaks. The model is the middle of a pipeline, not the whole thing.

An LLM application is not "a call to a model." It is a pipeline, and the model sits in the middle of it. This chapter has one job: give you the map — the stages a request flows through — and teach you to tell which stage broke when something does. (That a measured score belongs to the whole pipeline, not the model, is the evaluation consequence covered in its own lesson; here we learn the anatomy.)

What you will understand by the end

  • The stages a request passes through, from input to response.
  • What each stage contributes, and how each one can fail.
  • How to localize a failure to the stage that caused it, rather than blaming the model.

The request path

A typical request flows through these stages:

user input
  → prompt assembly   (system prompt + context/retrieval + the user's input)
  → the model         (hosted or self-hosted; produces raw output)
  → parse             (turn raw text into a structured object)
  → validate          (does it satisfy the schema / rules?)
  → correction policy (optional deterministic fixes, retries, fallbacks)
  → post-process      (execute, format, or hand off)
  → response
Key idea

The model turns an assembled prompt into raw text. Everything before it (what context you give) and everything after it (parsing, validation, correction) is ordinary software you control — and it's where most reliability is won or lost. Treat the application as a pipeline you can inspect stage by stage.

The components, and how each fails

  • Prompt template — the assembled instruction: a system prompt (role, rules, output format), any retrieved context, and the user's input. Fails by omitting a needed rule, overflowing the context window, or burying the instruction.
  • Context / retrieval — the facts the model needs that aren't in its weights (from a database, a search index, or the conversation so far). Fails by retrieving the wrong or too little context — the model then answers confidently from nothing.
  • The model — hosted behind an API or self-hosted on your own hardware; produces raw output. Fails by getting the meaning wrong even when everything upstream is right.
  • Output schema — the structure you require (often JSON). Fails by being under-specified, so "valid" output still can't be used.
  • Parser + validator — turn raw text into a checked object. Fails by accepting malformed output, or rejecting good output too strictly.
  • Correction policy — deterministic fixes, retries, or fallbacks for known failure patterns. Fails by over-correcting (breaking good cases) or masking a real problem.
  • Post-processing — executing the result (running a query, calling a tool) or formatting it. Fails by trusting an unvalidated result downstream.
Watch out

A failure at any stage looks like "the model was wrong." An empty answer might be a retrieval miss; a broken response might be a parsing bug; a subtly wrong query might be a schema that didn't constrain enough. Diagnosing an LLM app means asking which stage failed — not blaming the model reflexively.

A concrete example

The evaluation case study used throughout this book is a natural-language-to-query application. Its pipeline is exactly the anatomy above:

"Revenue by region last quarter"
  → prompt: schema + glossary + rules + the question
  → model: produces a structured QueryIntent (metric, dimensions, filters, sort, limit)
  → validate the intent against the schema
  → optional correction policy (fix a known intent mistake)
  → deterministic SQL builder turns the intent into SQL
  → run the query

Notice the model never writes SQL directly — it produces a validated intent, and deterministic code does the rest. Each arrow above is a stage you can log and inspect on its own — which is the entire point of drawing the anatomy. Open the real trials of this system in the live experiment.

Common mistakes

  • Equating the app with the model call. The prompt, retrieval, parsing, and validation are stages of the app too — debug the pipeline, not just the model.
  • No validation stage. Passing raw model output straight to downstream code is how a valid-but-wrong answer becomes a production incident.
  • Blaming the model for an upstream miss. Empty or off answers are often retrieval or prompt problems.
  • Letting deterministic work leak into the model. If code can do it reliably (build a query, enforce a format), don't ask the model to.

Practical guidance

  • Draw your app as this pipeline and name every stage — it becomes your debugging map.
  • Put a validation stage between the model and anything downstream.
  • Keep as much as possible deterministic (formatting, query building, execution); use the model only for the genuinely language-shaped step.
  • Log each stage's input and output — you'll need it for the failure analysis later in this book.

Summary

  • An LLM app is a pipeline: prompt assembly → model → parse → validate → correct → post-process.
  • Every stage contributes and every stage can fail; "the model was wrong" is often a stage-elsewhere problem.
  • Keeping deterministic work out of the model and validating its output are the two highest-value structural choices.

Knowledge check

A user gets an empty answer. Name two non-model stages that could be the real cause.

Retrieval/context (nothing relevant was fetched, so the model had nothing to work with) and parsing/validation (the model produced something, but the parser or a too-strict validator dropped it). The fix depends on which stage actually failed — hence the value of per-stage logging.

Why does the example system have the model produce an intent object instead of SQL directly?

So the language-shaped step (understand the question → a structured intent) is separated from the deterministic step (intent → SQL). The intent is easy to validate and score, and deterministic code builds correct SQL — narrowing what the model must get right and making the system far easier to evaluate and debug.

Related chapters