Your team at Razorpay ships a support bot. It uses GPT-4-class model for every single query, including "what are your business hours." The bill for the first month is 40,000 rupees higher than projected, and half the responses are three paragraphs long when a one-line answer would do. Nobody misconfigured anything. The team just skipped the step this module covers: understanding what the model is actually doing before deciding which one to call and how to talk to it. Everything downstream in your AI engineering work - RAG, agents, fine-tuning, evaluation - sits on top of three decisions you make constantly: which model, what prompt, what parameters. Get those wrong and no amount of clever retrieval or agent orchestration fixes it. This module builds that foundation in the order it actually gets used on the job: what an LLM is, how you pick one, how inference works, how the API contract works, and only then, prompting technique. ### Why prompting comes last, not first Most tutorials open with prompting tricks. That is backwards for an engineer. Prompting is one lever among several, and it is often not the right one. A badly chosen model, or a request format the model was never trained to expect, will not be fixed by a cleverer prompt. Understand the machine first, then learn to talk to it. ---
A language model is trained to model sequences of **tokens**. For the autoregressive LLMs this module focuses on, the core pretraining objective is next-token prediction: given all the tokens before it, predict what comes next, across trillions of examples pulled from massive amounts of text. Modern LLMs then typically go through additional post-training for instruction following, reasoning, tool use, and safety, which is covered below. Much of what the model appears to "know" - facts, code syntax, reasoning patterns, tone - is a side effect of getting extremely good at that core prediction task. **Tokens** are the units the model actually processes. Not words, not characters - sub-word chunks from a fixed vocabulary. The word "tokenization" might split into `Token`, `ization`. A rare word might split down to individual characters. A common rough heuristic: for typical English text, one token is often around three-quarters of a word - but this ratio varies significantly by tokenizer, language, code, and text structure, so treat it as a starting estimate, not a universal rule. > 💡 **Tip:** Every model provider exposes a tokenizer you can test against. Paste a sentence in and look at how it splits - this builds intuition fast, is the most reliable way to measure actual token counts for your text, and explains why prompts in some languages cost more tokens than the same meaning expressed in English. Two things make up a model: the **weights** (billions of learned numbers) and the **architecture** (almost always a Transformer) that runs those weights to produce output. When people say "GPT-4" or "Claude," they mean a specific set of weights running on a specific architecture. ### How a model goes from text-predictor to assistant A freshly pretrained model - a **base model** - is primarily optimized to continue token sequences plausibly. It may answer questions or follow some instructions incidentally, since those patterns exist in its training data, but it has not been specifically post-trained to reliably behave like a helpful assistant. Ask it a question and it might answer, or it might just keep writing more questions, because "predict the next token" does not inherently mean "be helpful." Getting from base model to assistant takes additional post-training stages: * **Supervised fine-tuning (SFT)** - the model is shown curated examples of good assistant behavior: answering clearly, declining harmful requests, following instructions. This is what teaches it to act like an assistant instead of an autocomplete engine. * **Preference-based post-training** - human or other preference data is used to make desirable responses more likely. Traditional reinforcement learning from human feedback (RLHF) trains a reward model from human comparisons of response pairs, then optimizes the policy against that reward; newer approaches can use direct preference-optimization methods instead. Either way, this stage helps the model learn judgment calls with no single correct answer, like "is this response too terse or appropriately concise." * **Reasoning-focused post-training** - some models are further trained to spend additional computation on difficult reasoning tasks, particularly math, logic, and code, where there is a checkable right answer to reward. > 📌 **Remember:** A base model completes text without reliably following instructions. A post-trained assistant model follows instructions and reflects human preferences. A reasoning-trained model spends extra computation on hard problems, at the cost of more tokens and higher latency. Knowing what stages a model went through tells you what to expect from it before you write a single prompt. ### Why this matters for engineering, not trivia You do not need to reproduce this training pipeline. You need it to explain behavior you will see constantly: why a cheap, lightly-tuned model sometimes rambles or ignores instructions, why a reasoning model is slower and pricier but more reliable on multi-step logic, and why "just prompt harder" cannot fix a model that was never trained on the behavior you are asking for. ---
Picking a model is an engineering tradeoff, not a leaderboard lookup. The strongest available model is rarely the correct default for a production feature. ### The four dimensions you are actually trading off Every model choice balances five things, and you cannot maximize all of them at once: * **Capability** - reasoning depth, language quality, how well it handles ambiguity * **Latency** - how fast a response comes back * **Cost** - price per token, input and output counted separately * **Controllability** - how reliably it follows a requested format, like strict JSON * **Reliability** - uptime, rate limits, throughput, and regional availability; a model can be brilliant and cheap but useless if it cannot meet your production SLA A frontier reasoning model wins on capability and loses on latency and cost. A small, fast model wins on latency and cost but may need more careful prompting to stay controllable. | Task type | Needs a frontier model? | |:---|:---| | Casual text generation, drafting | No | | Customer support replies | Usually no | | Structured JSON extraction | Usually no | | Multi-step logical reasoning | Yes | | Code generation | Depends on complexity | | Embeddings | Use a dedicated embedding model instead | Most application features do not need the strongest model on the market. They need the cheapest model that reliably clears the bar for that specific task. ### Closed versus open-weight models **Closed models** (accessed only through an API, weights never released) trade control for convenience: no infrastructure to manage, frequent capability upgrades, but you are dependent on the provider's uptime, pricing, and data policies. **Open-weight models** (weights downloadable, self-hostable) trade convenience for control: you can run them on your own infrastructure, which matters for data residency or cost at very high volume, but you take on the operational burden of serving them yourself. > 📌 **Engineering Decision:** Default to a managed API unless you have a concrete reason to self-host - such as data residency, network isolation, offline requirements, vendor independence, deep model customization, or measured economics at sufficiently high volume. "Measured" is the operative word: a cost comparison based on real numbers, not a hunch that self-hosting must be cheaper. ### Reading a model card before you commit Before wiring a model into your application, check its model card or documentation for: context window size, whether it supports structured/JSON output natively, whether it supports tool/function calling, its knowledge cutoff date, and published benchmark scores for tasks similar to yours. Skipping this step is how teams discover mid-project that their chosen model has no native JSON mode. ### Model routing: using more than one model at once Mature production systems rarely call one model for everything. A common pattern is tiering: Incoming Request | Router / Rules / | \ Simple Medium Complex | | | Cheap Mid Strong Model Model Model Route the majority of simple requests - FAQ-style questions, basic classification - to a cheap, fast model, once evaluation shows that model actually meets your quality bar for that task. Route ambiguous, high-value, or multi-step requests up to a stronger model. This is not premature optimization; it is usually one of the biggest levers on both cost and latency in a real deployment. Deciding what counts as "simple enough for the cheap model" is not a one-time guess - it follows a repeatable loop: Define the task | Build an evaluation set | Test candidate models against it | Compare quality, latency, and cost | Choose a model / routing rule | Monitor in production | Re-evaluate periodically ---> back to the top **Fallback models** are a related pattern: if your primary model's API times out, hits a rate limit, or the provider has an outage, retry against a secondary model rather than failing the request outright. > **Note:** A fallback is only safe when the secondary model supports the same output schema, tool-calling capabilities, latency budget, and safety constraints as the primary. Falling back to a model that can't produce the format your application expects just trades one failure mode for a different, harder-to-debug one. > 🔴 **Common Mistake:** Defaulting to the most expensive model available "to be safe," then never measuring whether a cheaper model would have worked, or the reverse - assuming a fixed percentage of traffic can always go to the cheap tier without ever building an evaluation set to check. Start with a mid-tier model, measure quality and cost against real examples, and only upgrade when you have evidence the weaker model is genuinely failing - not just a feeling that it might. ---
When you send a request to an LLM, it does not compose the whole answer at once. It generates one token at a time, in a loop: 1. Your full prompt - system instructions, conversation history, user input - is converted to tokens. 2. The model looks at the entire sequence so far and produces a probability distribution over every possible next token. 3. One token is selected from that distribution. 4. Conceptually, that new token becomes part of the growing sequence, and the model uses the full sequence to generate the next token. Production inference engines use techniques like KV caching (below) so previously computed attention states do not need to be recomputed from scratch at every step. 5. This repeats until the model emits a stop signal or hits a length limit. This is why LLMs have a fixed **context window**: the model's input and generated output must fit within the limits defined by that model and API - system instructions, conversation history, any retrieved documents, and the response being generated, all sharing the same budget. A model with a 128,000 token context window is not promising you 128,000 tokens of "memory" in the human sense; it is telling you the maximum size of everything that can be in view at once. > 📌 **Engineering Decision:** More context is not automatically better. Include the smallest amount of relevant context that lets the model solve the task. A bloated prompt increases token cost, can increase latency, and can bury the relevant information in noise the model has to sift through. This becomes especially important once you're assembling context from retrieval - covered in the RAG module. Context Window (e.g. 128K tokens) +--------------------------------------------------+ | System | History | User | <- Response tokens ->| | prompt | | input | | +--------------------------------------------------+ > **Note:** Because generation is token-by-token, longer responses take proportionally longer to produce. This is why streaming - sending each token to the user as it is generated, rather than waiting for the full response - is standard practice in production chat and agent interfaces. Without it, a long response feels like the application has frozen. ### Why the first token is slower than the rest Production inference engines cache the intermediate computation for tokens already processed, so generating the next token does not require reprocessing the entire sequence from scratch. The initial processing of the full input prompt is called the **prefill** phase. Once prefill finishes, the model enters the **decode** phase, generating output tokens one at a time using that cache. Prefill is why there's often a noticeable delay before the very first output token appears - if your application has ever felt like it "hangs" for a moment before streaming starts, this is why. ---
Many LLM APIs expose a conversational, message-based interface - you send a list of structured messages and the model returns the next message in that sequence - though the exact request and response schema differs by provider, and some also expose structured outputs, tool calls, and multimodal inputs beyond this basic shape. | Role | Purpose | |:---|:---| | System | Sets behavior, persona, and constraints | | User | The human's question or instruction | | Assistant | The model's own prior responses, for multi-turn context | The following is a conceptual, chat-style representation of a request: ```json { "messages": [ { "role": "system", "content": "You are a support assistant for a Zerodha-style trading app. Answer only questions about account setup and order status." }, { "role": "user", "content": "Why is my order still pending after 10 minutes?" } ] } ``` > **Note:** Under the hood, these role-tagged messages get converted into a single token sequence the model actually reads, often using special formatting tokens the provider handles for you. You do not need to construct this by hand - the API does it - but knowing it happens explains why system, user, and assistant messages all consume tokens from the same context window budget. This request-response pattern is stateless: the model does not remember your previous call. Every piece of context it needs - including earlier turns of the conversation - has to be resent in the messages list each time. Later modules on memory and sessions build directly on top of this fact. ### Getting structured output back Applications rarely want free-form prose; they want data they can parse. Most providers support a structured or JSON output mode where you specify a schema, or you can prompt for JSON directly and validate what comes back. ```python def extract_order_details(raw_message: str) -> dict: """ Sends a support message to the model and asks for structured JSON containing the order ID and the customer's issue category. Returns a validated dict, or raises if the output doesn't match what the application actually needs. """ # System prompt pins the exact schema - without this the model # may add extra fields or return prose instead of JSON system_prompt = ( "Extract order_id and issue_category from the message. " "Respond with only valid JSON: {\"order_id\": str, \"issue_category\": str}" ) # Prefer the provider's native structured-output/schema mode when # available - it enforces the shape at the model interface itself, # rather than relying on the model choosing to follow instructions response = call_llm(system_prompt, raw_message, temperature=0) parsed = json.loads(response) # will raise if not even valid JSON # Even with a schema-enforced response, validate against your own # business rules before trusting it - a schema-valid order_id can # still be one that doesn't exist in your system if not is_known_order_id(parsed["order_id"]): raise ValueError(f"Unrecognized order_id: {parsed['order_id']}") return parsed ``` > 🔴 **Common Mistake:** Asking for JSON in plain English with no explicit schema or format instruction, then being surprised when the model wraps it in explanatory prose or markdown code fences. Always specify the exact shape you want, and where the provider offers a native structured-output mode, prefer it over prompting alone - then still validate the result against your application's business rules, since schema-valid is not the same as correct. ### Fluency is not the same as factuality A model can produce a confident, well-formatted, entirely wrong answer. LLMs generate plausible continuations of a sequence; that is not the same guarantee as "every statement produced is true." This matters most in exactly the structured-output pattern above: a response can be valid JSON, match your schema perfectly, and still contain a fabricated order ID or a made-up policy detail. Production systems handle this with layers outside the model itself: retrieval grounded in real data, tool calls that fetch verified information, deterministic business-logic checks, and evaluation against known-good answers. This is also the seed of the RAG module - retrieval exists specifically because the model's own fluency is not a substitute for actually looking something up. ### Managing tokens, cost, and rate limits Pricing is per-token, input and output counted separately and usually at different rates. Input tokens are everything sent in - system prompt, conversation history, retrieved documents, and the user's message. Output tokens are just the generated response. A long-running conversation can get expensive even when the user's latest message is short, because every earlier turn in the conversation is resent as input tokens on every single call. A few habits prevent silent cost blowups: * Cap `max_tokens` on the response so a runaway generation cannot produce an unexpectedly long, expensive reply. * Trim or summarize conversation history instead of resending an ever-growing transcript on every call. * Build retry logic with exponential backoff for rate-limit errors - do not just fail the request on the first `429`. > ⚠️ **Security:** Never log full prompts or responses containing customer PII to a plaintext file or third-party logging service without checking your data handling policy first. Prompts sent to a managed API may also be subject to the provider's own data retention terms - know what those are before sending sensitive data. ---
**Temperature** controls how much randomness goes into picking the next token from the model's probability distribution. * Low temperature strongly concentrates probability mass around the most likely tokens, producing more repeatable behavior. Often appropriate for extraction, classification, and structured output - though temperature alone doesn't make a model factual, it only makes its choices more consistent. * Higher temperature (commonly around 0.7 to 1.0, though ranges vary by provider) samples more broadly across likely tokens. More varied and creative, better for brainstorming or creative writing, worse for anything that needs to be consistent or precise. > 📌 **Engineering Decision:** Start low (0 to 0.3, where the provider supports it) for anything that feeds into downstream logic - extraction, classification, tool arguments, code generation. Reserve higher temperature for genuinely generative, user-facing creative tasks where variety is the point. > **Note:** Even at low or zero temperature, LLM output is not guaranteed to be perfectly deterministic across calls, due to floating point arithmetic and how requests get batched on the server side, unless a provider explicitly guarantees determinism. Do not design a system that assumes identical input always produces byte-identical output. ---
Your team at Razorpay ships a support bot. It uses GPT-4-class model for every single query, including "what are your bu...
A language model is trained to model sequences of tokens. For the autoregressive LLMs this module focuses on, the core p...
Picking a model is an engineering tradeoff, not a leaderboard lookup. The strongest available model is rarely the correc...
When you send a request to an LLM, it does not compose the whole answer at once. It generates one token at a time, in a ...
Many LLM APIs expose a conversational, message-based interface - you send a list of structured messages and the model re...
Temperature controls how much randomness goes into picking the next token from the model's probability distribution. Low...
Everything above this section exists so that prompting is not the first tool you reach for. A prompt cannot fix a model ...
Every module after this one leans on something taught here. Retrieval-augmented generation depends on understanding the ...
Set up API access to at least two different models - for example, one lightweight/fast model and one stronger reasoning-...
Concept Rule of thumb Token size 0.75 English words per token as a rough estimate; measure actual usage with your tokeni...
Aligns directly with DevOps, Site Reliability (SRE), and Platform Engineering job descriptions.