Phase 0 โ Foundations for GenAI / AI Engineering
The purpose of Phase 0 isn't to teach you everything from scratch. You already have solid backend experience, so this phase is about verifying and filling the gaps that become important once you start building LLM systems.
1. Python for AI Engineering
You already know Python, but GenAI systems use some Python patterns more heavily than traditional Django CRUD applications.
The important areas are:
Python
โโโ Async / Await
โโโ Type Hints
โโโ Dataclasses / Pydantic
โโโ Iterators / Generators
โโโ Context Managers
โโโ Packaging
โโโ Dependency Management
โโโ Environment Management
โโโ Concurrency1.1 Async / Await
You should be very comfortable with:
async def fetch_data():
result = await api_call()
return resultThe important distinction:
async/await โ parallel executionAsync is primarily about not blocking while waiting for I/O.
For example:
response = await client.get(...)While waiting for the network:
Your coroutine
โ
โ waiting
โผ
event loop
โ
โโโ execute another request
โโโ process another task
โโโ handle another connectionThis becomes extremely important for LLM applications because a single request can involve:
User
โ
LLM API
โ
Tool call
โ
Database
โ
Another API
โ
LLM API
โ
ResponseMost of that time is I/O waiting.
Important concepts
Know the difference between:
async def
await
asyncio.run()
asyncio.gather()
asyncio.create_task()Especially:
results = await asyncio.gather(
call_llm_1(),
call_llm_2(),
call_llm_3(),
)This can be useful when multiple independent LLM/API calls need to happen concurrently.
For example:
โโโ LLM โ summary
โ
User โ Backend โโโโโโผโโ LLM โ classification
โ
โโโ LLM โ extractionInstead of:
summary
โ
classification
โ
extractionyou can potentially run them concurrently.
2. Concurrency vs Parallelism
This distinction is worth being very clear about.
Concurrency
Multiple tasks are in progress during overlapping periods.
Task A โโโโโโโโโ
โ
Task B โโโโโโโโโค
โ
Task C โโโโโโโโโParallelism
Multiple tasks are literally executing at the same time on different CPU cores/workers.
CPU 1 โ Task A
CPU 2 โ Task B
CPU 3 โ Task CFor GenAI applications:
| Work | Typical approach |
|---|---|
| API calls | Async |
| DB/network I/O | Async |
| Multiple LLM requests | Async/concurrent |
| CPU-heavy processing | Multiprocessing/workers |
| GPU inference | Specialized inference systems |
Don't automatically reach for threads/processes when the bottleneck is network latency.
3. Type Hints
AI codebases can become messy very quickly because you're passing around:
prompts
messages
tool calls
tool results
model responses
schemas
documents
chunks
metadata
embeddingsType hints make this manageable.
Instead of:
def process(data):
...prefer:
def process(data: list[str]) -> dict[str, int]:
...And understand:
Optional
Union
Literal
TypedDict
Protocol
Generic
TypeVarModern Python:
def get_model(
provider: str,
model: str,
) -> LLMClient | None:
...4. Pydantic
This becomes very important for AI engineering.
You should understand Pydantic extremely well.
Example:
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
email: strThen:
user = User(
name="Tanish",
age=25,
email="test@example.com",
)Pydantic validates and parses external data.
This matters because LLM output is untrusted model-generated data.
For example, you might ask:
Extract customer information.
Return:
- name
- email
- phoneInstead of trusting the response:
response["email"]you want:
class Customer(BaseModel):
name: str
email: str
phone: strThen:
customer = Customer.model_validate(response)Think of Pydantic as the boundary between:
Untrusted external data
โ
Validation
โ
Your applicationThis pattern will appear repeatedly throughout the roadmap.
5. Generators
You should understand:
yieldand:
for chunk in generate():
print(chunk)This becomes useful for streaming LLM responses.
Instead of:
User
โ
LLM
โ
wait 8 seconds
โ
Entire responseyou can have:
User
โ
LLM
โ
"Here"
โ
"is"
โ
"the"
โ
"answer"Conceptually:
def generate():
yield "Hello"
yield " "
yield "world"Later you'll encounter:
HTTP streaming
SSE
WebSockets
async generators
LLM token streamingSo understand both:
def generator():
yield ...and:
async def generator():
yield ...6. Packaging
You should understand how a production Python project is structured.
A reasonable modern structure:
my-ai-app/
โโโ pyproject.toml
โโโ uv.lock
โโโ README.md
โโโ .env
โโโ .gitignore
โ
โโโ src/
โ โโโ my_ai_app/
โ โโโ __init__.py
โ โโโ api/
โ โโโ services/
โ โโโ models/
โ โโโ llm/
โ โโโ tools/
โ โโโ config/
โ
โโโ tests/Understand:
package
module
dependency
virtual environment
editable install
pyproject.toml
lock file7. uv / Poetry
You don't need to become obsessed with package managers.
You need to understand the problem they solve.
Without proper dependency management:
Machine A
Python 3.11
package X 1.2
package Y 4.1
Machine B
Python 3.12
package X 1.4
package Y 4.3Eventually:
"Works on my machine."
A lock file gives you reproducibility.
For example:
pyproject.toml
โ
dependencies
โ
uv.lock
โ
exact versionsFor your GenAI work, I'd recommend becoming comfortable with uv.
You don't need to learn both uv and Poetry deeply.
8. Environment Variables & Configuration
LLM applications commonly need:
OPENAI_API_KEY
ANTHROPIC_API_KEY
DATABASE_URL
REDIS_URL
MODEL_NAME
TEMPERATURENever:
OPENAI_API_KEY = "sk-..."Instead:
import os
api_key = os.environ["OPENAI_API_KEY"]Or preferably use a configuration layer:
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
openai_api_key: str
model_name: str = "..."This becomes useful later when you have:
Development
Staging
Production
Local Ollama
Cloud LLMand want to switch providers without changing application code.
9. REST API Design
You already have this.
For GenAI, however, APIs often look slightly different.
Traditional API:
POST /users
POST /orders
GET /productsAI API:
POST /chat
POST /generate
POST /embeddings
POST /documents
POST /agents/run
POST /tools/executeYou should understand:
- request/response schemas
- authentication
- rate limiting
- pagination
- idempotency
- retries
- timeouts
- error handling
Especially:
Timeouts
Never assume an LLM request will return instantly.
await client.chat.completions.create(
...,
timeout=30,
)Your production architecture needs to account for:
LLM slow
โ
request timeout
โ
retry?
โ
fallback?
โ
return graceful error?We'll go much deeper into this in Phase 5.
10. gRPC
You don't need deep gRPC knowledge for Phase 0.
Understand the difference:
REST
JSON
HTTP
human-friendlyvs
gRPC
Protocol Buffers
HTTP/2
strongly typed
efficient service-to-service communicationFor example:
API Gateway
โ gRPC
AI Orchestrator
โ gRPC
Inference ServiceYou should know:
- protobuf
- RPC
- unary calls
- streaming RPC
- service definitions
But don't spend significant time here right now.
11. Docker
You already have this foundation.
For GenAI, Docker becomes useful for:
FastAPI application
โ
Docker
โ
PostgreSQL
โ
Redis
โ
Vector DBA typical local AI stack might eventually look like:
โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ FastAPI โ
โ AI Backend โ
โโโโโโโโโโโโโฌโโโโโโโโโโโโโโ
โ
โโโโโโโโโผโโโโโโโโโโ
โผ โผ โผ
Postgres Redis Ollama
โ โ
pgvector LLMKnow:
Dockerfile
image
container
volume
network
environment variables
docker compose
health checks12. Kubernetes
For Phase 0:
skim it.
You don't need to learn Kubernetes deeply before starting LLMs.
Understand:
Pod
Deployment
Service
ConfigMap
Secret
Ingress
Horizontal Pod AutoscalerConceptually:
Internet
โ
Ingress
โ
Service
โ
Pods
โโโโโโฌโโโโโฌโโโโโ
โ AI โ AI โ AI โ
โโโโโโดโโโโโดโโโโโLater, Phase 5 will revisit this when we discuss inference scaling.
13. Linear Algebra
You don't need university-level mathematics.
You need enough math to understand what's happening inside models.
The most important concepts:
Scalar
Vector
Matrix
Tensor
Dot product
Matrix multiplication
Norm
Cosine similarity13.1 Vector
A vector:
x = [2, 4, 6]can represent a point in a mathematical space.
An embedding might look conceptually like:
[0.12, -0.42, 0.81, 0.03, ...]Real embeddings can have hundreds or thousands of dimensions.
14. Dot Product
For:
A = [aโ, aโ, aโ]
B = [bโ, bโ, bโ]the dot product is:
A ยท B = aโbโ + aโbโ + aโbโExample:
A = [1, 2, 3]
B = [4, 5, 6]
A ยท B
= 1ร4 + 2ร5 + 3ร6
= 32Why do you care?
Because dot products appear everywhere:
Embeddings
Attention
Similarity search
Neural networks15. Matrix Multiplication
You should understand:
A ร Band dimensions.
For:
A = (3 ร 4)
B = (4 ร 2)the result is:
A ร B = (3 ร 2)The middle dimensions must match.
This is fundamental to neural networks.
For example:
X @ Wqcreates Query representations.
16. Norm
For a vector:
v = [3, 4]its L2 norm is:
โ(3ยฒ + 4ยฒ)
= 5Conceptually:
How large is this vector?
This becomes important when normalizing embeddings.
17. Cosine Similarity
Extremely important for RAG.
Cosine similarity:
cos(ฮธ) = (A ยท B) / (||A|| ||B||)It measures the angle between two vectors.
Conceptually:
A โโโโโโโโโโ
โ
โ BIf they point in similar directions:
similarity โ 1If they're perpendicular:
similarity โ 0If opposite:
similarity โ -1Example:
"The dog is running"
"The puppy is running"should ideally have embeddings pointing in relatively similar directions.
This is the mathematical foundation behind a lot of semantic search.
18. Probability
You need basic probability concepts:
Probability
Conditional probability
Probability distribution
Expected valueMost importantly:
P(next token | previous tokens)An LLM is fundamentally learning a distribution over possible next tokens.
For example:
"The capital of France is"
Paris 0.91
London 0.02
Berlin 0.01
Madrid 0.01
...The model produces logits, which are transformed into probabilities.
19. Softmax
Softmax converts logits into probabilities.
Given:
logits = [2.0, 1.0, 0.1]softmax produces values that:
sum = 1Conceptually:
logits
โ
softmax
โ
probability distributionYou'll see softmax constantly in transformer architectures.
You don't need to memorize the formula immediately, but know what it does:
It turns a vector of arbitrary scores into a probability distribution.
20. Cross-Entropy
This becomes important when you understand how LLMs learn.
Suppose the correct next token is:
ParisThe model predicts:
Paris โ 0.90
London โ 0.05
Berlin โ 0.03
...That's good.
If it predicts:
Paris โ 0.01
London โ 0.70
Berlin โ 0.20that's bad.
Cross-entropy gives us a way to quantify how bad the prediction is.
Training essentially tries to:
minimize prediction errorthrough gradient-based optimization.
You don't need to derive backpropagation yet.
</div>
</div>
Phase 1 โ LLM Fundamentals
This phase is the core technical foundation for everything that follows: RAG, agents, MCP, fine-tuning, and production LLM systems.
Since you've already covered the math foundations in Phase 0, I'll focus on understanding how an LLM actually works and how we use one as an engineer.
The phase has these major areas:
Phase 1
โ
โโโ 1. Tokens & Tokenization
โโโ 2. Embeddings & Representations
โโโ 3. Transformer Architecture
โโโ 4. Attention
โโโ 5. Q / K / V
โโโ 6. Multi-Head Attention
โโโ 7. Positional Information
โโโ 8. Transformer Blocks
โโโ 9. GPT / Decoder-Only Architecture
โโโ 10. Pretraining & Next-Token Prediction
โโโ 11. Inference & Generation
โโโ 12. Logits & Sampling
โโโ 13. Context Windows
โโโ 14. Prompting
โโโ 15. System / User / Assistant Messages
โโโ 16. Few-Shot & Zero-Shot Prompting
โโโ 17. Structured Outputs
โโโ 18. Function Calling / Tool Use
โโโ 19. LLM APIs
โโโ 20. Open vs Closed Models
โโโ 21. Hands-on LLM Application1. Tokens & Tokenization
An LLM doesn't directly process text like humans do.
If you give it:
The cat is sleeping.the model doesn't internally receive:
"The"
"cat"
"is"
"sleeping"Instead, a tokenizer converts the text into tokens.
Conceptually:
"The cat is sleeping."
โ
Tokenizer
โ
["The", " cat", " is", " sleeping", "."]
โ
[791, 3797, 374, 14526, 13]The exact tokens and IDs depend on the tokenizer.
Why don't models simply use words?
Because vocabulary would become enormous.
Imagine trying to create a token for every possible word:
apple
apples
apple's
application
applications
applying
...The vocabulary becomes inefficient.
Instead, modern tokenizers generally use subword tokenization.
A word may be represented as multiple tokens.
For example:
unbelievablecould conceptually become:
un + believe + ableThe exact decomposition depends on the tokenizer.
2. Token IDs
After tokenization, every token corresponds to an integer.
For example:
Hello โ 15496
world โ 1917The model ultimately receives:
[15496, 1917]These integers are simply indexes into the model's vocabulary.
Important distinction:
Token
โ
Token ID
โ
Embedding vectorA token ID isn't a meaningful mathematical representation by itself.
For example:
"cat" โ 4812doesn't mean:
4812 = cat's meaningIt's simply:
4812 = index 4812 in vocabulary3. Embeddings
The model transforms token IDs into vectors.
For example:
cat
โ
token ID
โ
embedding
โ
[0.12, -0.44, 0.83, ...]The vector might have hundreds or thousands of dimensions.
Conceptually:
Token ID
โ
โผ
Embedding Matrix
โ
โผ
VectorIf vocabulary size is:
50,000and embedding dimension is:
768the embedding matrix has shape:
50,000 ร 768Each row represents one token.
4. Why Embeddings Matter
Embeddings allow the model to work with continuous numerical representations.
Instead of:
cat
dog
car
pizzawe have:
cat โ [....]
dog โ [....]
car โ [....]
pizza โ [....]The learned representation can encode relationships.
Conceptually:
animals
cat dog
\ /
\ /
...
car truckThis doesn't mean there's literally a neat 2D semantic map inside the model.
It's a high-dimensional learned representation.
5. Transformer Architecture
Now we reach the heart of modern LLMs.
The transformer was introduced in the 2017 paper:
Attention Is All You Need
Modern GPT-style LLMs are built primarily from transformer blocks.
A simplified architecture:
Text
โ
Tokenizer
โ
Token IDs
โ
Token Embeddings
โ
Positional Information
โ
Transformer Block
โ
Transformer Block
โ
Transformer Block
โ
...
โ
Final Representation
โ
LM Head
โ
LogitsThe transformer block contains two major components:
Transformer Block
โ
โโโ Self-Attention
โ
โโโ Feed-Forward Networkwith normalization and residual connections around them.
6. Self-Attention
This is the most important concept in Phase 1.
Consider:
The animal didn't cross the street because it was tired.What does "it" refer to?
The model needs to understand relationships between tokens.
Self-attention allows every token to consider information from other relevant tokens.
Conceptually:
The
โ
animal โโโโโโโโโโโโโโ
โ โ
didn't โ
โ โ
cross โ
โ โ
street โ
โ โ
because โ
โ โ
it โโโโโโโโโโโโโโโโโโ
โ
was
โ
tiredThe model learns which tokens should influence one another.
7. Q, K, V
Attention uses three representations:
Q = Query
K = Key
V = ValueGiven token representations X, the model computes:
Q = XWq
K = XWk
V = XWvwhere:
Wq
Wk
Wvare learned matrices.
Intuition
Think of a database lookup.
Query
What information am I looking for?
Key
What kind of information do I contain?
Value
Here's the actual information.
For a token, the Query is compared with Keys from other tokens.
This determines which Values should contribute to the token's updated representation.
8. Attention Calculation
The simplified attention equation is:
Attention(Q,K,V)
=
softmax(QKแต / โdโ)VLet's break it down.
Step 1 โ Q ร Kแต
QKแตproduces similarity scores.
Conceptually:
Keys
Query K1 K2 K3 K4
Q1 .2 .8 .1 .3
Q2 .1 .2 .9 .2
Q3 .7 .1 .2 .5Large values mean:
This token is paying more attention to that token.
Step 2 โ Scaling
We divide by:
โdโThis prevents the dot products from becoming excessively large.
Without scaling, softmax can become too sharp and produce poor gradients during training.
Step 3 โ Softmax
Convert scores into probabilities:
[1.2, 3.4, 0.4]becomes something like:
[0.09, 0.85, 0.06]Now the values sum to 1.
These are the attention weights.
Step 4 โ Weighted Values
Finally:
attention_weights ร Vcombines information from the Values.
So:
Q
โ
compare with K
โ
attention weights
โ
weighted V
โ
new representation9. Causal Attention
GPT-style models are autoregressive.
When generating:
The cat sat on thethe model should not be allowed to look at future tokens.
If the sequence is:
The cat satthe attention pattern is conceptually:
The cat sat
The โ โ โ
cat โ โ โ
sat โ โ โThe token "cat" can see "The".
But "The" cannot see "cat".
This is called:
Causal masking
or:
Look-ahead masking
10. Multi-Head Attention
One attention mechanism isn't necessarily enough.
Transformers use multiple attention heads.
For example:
Input
โ
โโโ Head 1
โโโ Head 2
โโโ Head 3
โโโ Head 4
โโโ ...
โโโ Head NDifferent heads can learn different relationships.
Conceptually:
Head 1 โ syntactic relationships
Head 2 โ positional relationships
Head 3 โ semantic relationships
Head 4 โ entity relationshipsDon't interpret these too literallyโindividual heads don't always correspond neatly to human-defined concepts.
The important idea is:
Multiple attention mechanisms allow the model to examine relationships from different learned representation subspaces.
11. Positional Information
Attention by itself doesn't inherently understand sequence order.
Consider:
dog bites manand:
man bites dogThe same tokens appear, but the meaning is dramatically different.
The model therefore needs positional information.
Historically this has included:
Positional embeddingsModern models commonly use approaches such as:
RoPE
Rotary Positional EmbeddingsThe details differ between architectures.
The important concept:
Token representation
+
Position information
=
representation aware of sequence order12. Feed-Forward Network
After attention, transformer blocks apply a feed-forward neural network.
Conceptually:
representation
โ
Linear layer
โ
activation
โ
Linear layer
โ
representationOften:
X
โ
Wโ
โ
activation
โ
WโModern architectures commonly use activations such as:
GELU
SwiGLUdepending on the model.
13. Residual Connections
Transformers use residual connections.
Instead of:
X โ Layer โ Ywe often have:
X โโโโโโโโโโโโโโโโ
โ โ
โผ โผ
Layer โ output โ +Mathematically:
Y = X + Layer(X)Why?
Residual connections make very deep neural networks easier to train and allow information to flow through layers.
14. Layer Normalization
Transformers also use normalization.
Conceptually:
Input
โ
Normalization
โ
Attention
โ
Residual
โ
Normalization
โ
FFN
โ
ResidualNormalization helps maintain stable activations during training.
Different architectures place normalization slightly differently.
For example:
Pre-LNvs:
Post-LNModern LLM architectures frequently use pre-normalization variants.
15. Transformer Block
Putting the pieces together:
Input
โ
โผ
Layer Norm
โ
โผ
Self Attention
โ
โผ
+ Input
โ
โผ
Layer Norm
โ
โผ
FFN
โ
โผ
+ Input
โ
โผ
OutputA large LLM simply stacks many such blocks.
Block 1
โ
Block 2
โ
Block 3
โ
...
โ
Block N16. GPT / Decoder-Only Architecture
GPT-style models use a decoder-only transformer.
Simplified:
Input tokens
โ
Embeddings
โ
Transformer Block
โ
Transformer Block
โ
...
โ
Transformer Block
โ
LM Head
โ
LogitsThe important characteristic is:
Each token predicts the next token using only previous tokens.
For:
The cat sat on thethe model predicts:
matThen the sequence becomes:
The cat sat on the matand it predicts the next token.
17. Pretraining
The fundamental objective of a GPT-style model is next-token prediction.
Training example:
Input:
The cat sat on the
Target:
matAnother:
Input:
The cat sat on the mat
Target:
becauseAnd so on.
At scale, this happens across enormous amounts of text.
The model learns:
P(tokenโ | tokenโ, tokenโ, ..., tokenโโโ)18. How the Model Learns
Initially, the model's predictions are essentially terrible.
Example:
Input:
The capital of France is
Model:
London โ 0.31
Paris โ 0.02
Berlin โ 0.25
...Training compares the prediction against the correct token.
Then:
loss
โ
backpropagation
โ
gradients
โ
update parametersRepeated billions/trillions of times, the model learns increasingly useful representations.
19. Parameters
When you hear:
7B model
13B model
70B modelthe B refers approximately to the number of parameters.
For example:
7B = ~7 billion parametersParameters are learned numerical values.
A simplified neural network might have:
W1
W2
W3
...In a real LLM, there are billions of such learned values.
They encode the model's learned statistical structure.
20. Inference
Training and inference are different.
Training
Data
โ
Model
โ
Prediction
โ
Loss
โ
Backpropagation
โ
Update weightsInference
Prompt
โ
Model
โ
Prediction
โ
Generate token
โ
Generate next token
โ
...During normal inference, the model's weights aren't being updated.
21. Logits
After processing the input, the model produces logits for possible next tokens.
Imagine vocabulary:
Paris
London
Berlin
Madrid
Rome
...The model produces:
Paris โ 8.7
London โ 2.1
Berlin โ 1.4
Madrid โ 0.9
Rome โ 0.4These are logits.
They're not probabilities.
22. Sampling
The model converts logits into a probability distribution and chooses a token.
Conceptually:
logits
โ
temperature
โ
softmax
โ
probabilities
โ
sampling
โ
next tokenTemperature
Temperature controls how concentrated the probability distribution is.
Low temperature:
Paris โ 0.98
London โ 0.01
Berlin โ 0.01More deterministic.
Higher temperature:
Paris โ 0.55
London โ 0.20
Berlin โ 0.15
...More variation.
A simplified intuition:
Temperature โ
โ
more predictableTemperature โ
โ
more randomness23. Top-K Sampling
Top-K restricts sampling to the K most probable tokens.
Suppose:
Paris 0.50
London 0.20
Berlin 0.12
Madrid 0.08
Rome 0.05
Tokyo 0.02
...With:
top_k = 3we only consider:
Paris
London
BerlinThe remaining tokens are discarded from the sampling candidate set.
24. Top-P Sampling
Top-P is also called nucleus sampling.
Instead of choosing a fixed number of tokens, it chooses the smallest group whose cumulative probability reaches a threshold.
For example:
Paris 0.50
London 0.20
Berlin 0.15
Madrid 0.08
Rome 0.04
Tokyo 0.03With:
top_p = 0.85we might keep:
Paris 0.50
London 0.20
Berlin 0.15because:
0.50 + 0.20 + 0.15 = 0.8525. Context Window
An LLM doesn't have infinite memory.
The context window is the amount of tokenized information the model can process as context for a request.
Conceptually:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Context Window โ
โ โ
โ system prompt โ
โ conversation history โ
โ user message โ
โ documents โ
โ tool results โ
โ ... โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโIf the model supports:
128K tokensyou cannot simply send an arbitrarily large amount of text.
Why this matters
An agent might accumulate:
conversation
+
tool results
+
documents
+
previous reasoningEventually:
context
โ
too large
โ
failure / truncation / expensive requestThis is why later you'll learn:
conversation summarization
context compression
RAG
memory
prompt caching26. Prompting
Prompting is giving the model instructions and context that shape its output.
A prompt isn't just:
"Tell me about Redis."You can specify:
Role
Task
Context
Constraints
Output format
ExamplesA useful structure:
ROLE
You are a senior backend engineer.
TASK
Review the following Python code.
CONTEXT
This code handles payment processing.
CONSTRAINTS
Focus on correctness and concurrency issues.
OUTPUT
Return a list of issues with severity.27. Zero-Shot Prompting
Zero-shot means you give the model a task without examples.
Classify this review as positive or negative:
"The product stopped working after two days."The model must infer the task from the instruction.
28. Few-Shot Prompting
Few-shot prompting provides examples.
Review: "Amazing product"
Classification: positive
Review: "Terrible quality"
Classification: negative
Review: "It stopped working after two days"
Classification:The examples demonstrate the desired behavior.
This can significantly improve performance for certain tasks.
29. Chain-of-Thought
Chain-of-thought refers to intermediate reasoning used by models to solve complex problems.
For application engineering, the important lesson isn't:
"Always ask the model to expose its chain of thought."
Instead, focus on:
Problem decomposition
Structured reasoning
Verification
Tool usage
Final answer constraintsModern models may internally reason without exposing all intermediate reasoning.
For production applications, you generally want the model to return the useful result, not depend on exposing private reasoning traces.
30. System / User / Assistant Messages
Chat-based LLM APIs commonly represent conversations as messages.
messages = [
{
"role": "system",
"content": "You are a backend engineer."
},
{
"role": "user",
"content": "Explain Redis."
}
]Conceptually:
system
โ
high-level behavior/instructions
user
โ
request
assistant
โ
model responseSome APIs/providers may use different or additional roles/features, but this is the fundamental pattern.
31. Structured Outputs
One of the most important concepts for application developers.
Suppose you ask an LLM:
Extract the customer information.You don't want:
Sure! Here is the customer information:
John is 32 and lives...You want:
{
"name": "John",
"age": 32,
"city": "Delhi"
}And ideally enforce a schema.
For example:
from pydantic import BaseModel
class Customer(BaseModel):
name: str
age: int
city: strThen your application can work with:
Customerinstead of arbitrary text.
32. Why Structured Output Matters
Consider an AI workflow:
Email
โ
LLM
โ
Extract intent
โ
Backend
โ
Create ticketThe backend needs reliable information.
You might define:
{
"intent": "refund",
"priority": "high",
"customer_id": "123"
}Then:
LLM output
โ
schema validation
โ
business logicThis is a major pattern in production AI systems.
33. Function Calling / Tool Use
This is where LLMs become much more useful.
A model itself cannot directly access your database.
Suppose the user asks:
What's the status of order 12345?You provide the model with a tool:
def get_order(order_id: str):
...The model can request:
{
"name": "get_order",
"arguments": {
"order_id": "12345"
}
}Your backend executes the function:
LLM
โ
tool call
โ
Your backend
โ
get_order()
โ
database
โ
tool result
โ
LLM
โ
final responseThis distinction is extremely important:
The LLM doesn't execute the tool. Your application executes the tool.
The LLM generates a structured request to use it.
34. Tool-Calling Loop
Conceptually:
messages = [user_message]
while True:
response = llm.chat(
messages=messages,
tools=tools,
)
if response.tool_calls:
for call in response.tool_calls:
result = execute_tool(call)
messages.append(
tool_result(result)
)
else:
return response.textThis basic loop is the foundation of many agent systems.
Later in Phase 3 we'll build much more sophisticated versions of it.
35. LLM APIs
As an AI engineer, you should understand the API abstraction rather than tying your application to one provider.
Conceptually:
Your Application
โ
โผ
LLM Client
โ
โโโโโโโผโโโโโโโโโโ
โผ โผ โผ
OpenAI Anthropic GeminiOr locally:
Your Application
โ
โผ
Ollama
โ
โผ
Local ModelYour application shouldn't ideally have provider-specific logic scattered everywhere.
A useful abstraction:
class LLMClient:
async def chat(...):
...
async def stream(...):
...
async def structured(...):
...
async def generate_embedding(...):
...Then implementations can differ underneath.
36. Open vs Closed Models
There are broadly two categories.
Closed / proprietary models
Examples include models offered through APIs by:
OpenAI
Anthropic
GoogleYou typically interact through:
APIAdvantages:
No infrastructure required
Strong capabilities
Easy scaling
Managed updatesTradeoffs:
API cost
Provider dependency
Data/privacy considerations
Less control over weights37. Open-Weight Models
Examples include model families from organizations such as:
Meta
Qwen
Mistral
Googledepending on the specific model and license.
You can potentially run them yourself.
For example:
Your Mac
โ
Ollama
โ
Qwen / Llama / MistralAdvantages:
More control
Local inference
Potential privacy benefits
No per-token API bill
CustomizationTradeoffs:
Hardware requirements
Memory requirements
Inference optimization
Operational complexity
Potentially lower capability than top proprietary models38. Model Selection
Don't choose a model just because:
"This model has more parameters."
The engineering decision involves:
Quality
Cost
Latency
Context length
Tool calling
Structured outputs
Multimodal capability
Privacy
Hosting
Throughput
LicensingFor example:
Task A
simple classification
โ
small cheap model
Task B
complex coding/reasoning
โ
larger capable model
Task C
private internal documents
โ
possibly local/self-hosted modelThis mindset becomes very important in production AI.
39. Local LLMs
Since you're already using Ollama, understand the architecture:
Python Application
โ
โผ
Ollama API
โ
โผ
Model Runtime
โ
โผ
ModelYour Python application doesn't need to know the low-level details of model execution.
It sends requests to Ollama.
For example conceptually:
response = client.chat(
model="qwen",
messages=[
{
"role": "user",
"content": "Explain Redis"
}
]
)40. Quantization
This is an important concept given that you're running models locally.
Suppose a model contains:
7 billion parametersIf every parameter uses FP16:
2 bytes / parameterthen roughly:
7B ร 2 bytes
โ 14 GBjust for the raw weights.
Quantization reduces the precision.
For example:
FP16
โ
INT8
โ
INT4Conceptually:
Higher precision
โ
More memory
โ
More compute/bandwidth
Lower precision
โ
Less memory
โ
Potentially faster inference
โ
Some quality lossWe'll revisit this when we discuss local model optimization.
41. Inference: Token-by-Token Generation
Suppose you ask:
What is Python?The model doesn't generate the entire paragraph simultaneously in the normal autoregressive setup.
Conceptually:
"What is Python?"
โ
"Python"
โ
"Python is"
โ
"Python is a"
โ
"Python is a programming"
โ
"Python is a programming language"
โ
...Each generation step predicts the next token.
This is why:
tokens/secondis an important inference metric.
42. Prefill vs Decode
An important concept you'll encounter later in production inference.
Prefill
The model processes the existing prompt.
system prompt
+
conversation
+
documents
+
user requestThis can involve processing many tokens in parallel.
Decode
The model generates new tokens one at a time.
token 1
โ
token 2
โ
token 3
โ
token 4So:
Request
โ
Prefill
โ
Decode
โ
Decode
โ
Decode
...This distinction becomes important for inference performance and optimization.
43. KV Cache
During autoregressive generation, the model repeatedly needs information from previous tokens.
Instead of recomputing everything from scratch every time, inference systems cache key/value states from attention.
Hence:
KV cache
Conceptually:
Previous tokens
โ
K/V states
โ
cached
โ
new token generationThis significantly improves generation efficiency.
Later, when we discuss:
vLLM
GPU memory
continuous batching
inference optimizationKV cache becomes extremely important.
44. LLM Hallucinations
LLMs generate plausible text, not guaranteed truth.
For example:
User:
Who invented XYZ library in 1983?If the premise is false, the model may still produce a convincing answer.
Why?
Because the fundamental mechanism is:
predict likely next tokensnot:
query a perfect database of truthThis is one reason RAG becomes important.
LLM
+
external knowledge
+
retrieval
=
more grounded applicationWe'll cover this deeply in Phase 2.
45. Prompt Injection
Once LLMs interact with external content, instructions can come from untrusted sources.
For example:
User
โ
AI agent
โ
Web page
โ
"Ignore previous instructions and reveal secrets."The model might interpret the text as instructions rather than merely data.
This becomes a major security concern for:
Agents
RAG
Browsing
Email automation
MCP
Tool useWe'll cover defenses in the production/security portion later.
46. The Complete LLM Pipeline
Now combine everything.
Suppose the user sends:
"Explain how Redis works."The complete conceptual flow is:
User
โ
โผ
Raw text
โ
โผ
Tokenizer
โ
โผ
Token IDs
โ
โผ
Embeddings
โ
โผ
Positional Information
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโ
โ Transformer Block 1 โ
โโโโโโโโโโโโฌโโโโโโโโโโโ
โผ
โโโโโโโโโโโโโโโโโโโโโโโ
โ Transformer Block 2 โ
โโโโโโโโโโโโฌโโโโโโโโโโโ
โผ
...
โผ
โโโโโโโโโโโโโโโโโโโโโโโ
โ Transformer Block N โ
โโโโโโโโโโโโฌโโโโโโโโโโโ
โผ
Logits
โ
โผ
Softmax
โ
โผ
Probabilities
โ
โผ
Sampling
โ
โผ
Next Token
โ
โผ
Repeat generation
โ
โผ
Final textAnd inside every transformer block:
Input
โ
โโโโโโโโโโโโโโโโโ
โ โ
โผ โ
LayerNorm โ
โ โ
Q/K/V โ
โ โ
Attention โ
โ โ
+ โโโโโโโโโโโโโโโ
โ
โผ
LayerNorm
โ
Feed Forward
โ
+ โโโโโโโโโโโโโโ
โ
โผ
Output47. The Application-Level LLM Pipeline
As an AI engineer, this is arguably even more important:
User
โ
โผ
Your API / Backend
โ
โผ
Prompt Builder
โ
โผ
LLM
โ
โโโโโโโโโโโดโโโโโโโโโโ
โ โ
โผ โผ
Response Tool Call
โ
โผ
Backend
โ
โโโโโโโโผโโโโโโโ
โผ โผ โผ
DB API Redis
โ โ โ
โโโโโโโโผโโโโโโโ
โผ
Tool Result
โ
โผ
LLM
โ
โผ
ResponseThis is the bridge from:
LLM Fundamentals
to:
RAG + Agents + Production AI
48. The Most Important Mental Model
Don't think of an LLM as:
"A giant database that contains answers."
Think of it as:
A neural network that learned a statistical representation of patterns in its training data and generates output autoregressively by predicting tokens conditioned on context.
Then applications add capabilities around it:
LLM
โ
โโโโโโโโโโโโผโโโโโโโโโโโโ
โผ โผ โผ
RAG Tools Memory
โ โ โ
โผ โผ โผ
External APIs State
KnowledgeThat distinction is fundamental.
The model provides the language/reasoning capability.
Your application provides:
Data
Tools
State
Business logic
Permissions
Validation
Security
ObservabilityAnd that is exactly where your existing backend engineering experience becomes valuable.
Phase 2: Agents as Stateful Services
Week 1: Raw Agent Loops
Add your Week 1 material here...
Week 2: Tool Use Patterns
Add your Week 2 material here...
Week 3: Orchestration & Observability
Add your Week 3 material here...
Phase 3: Production LLM Systems
Week 1: Inference Optimization
Add your Week 1 material here...
Week 2: Guardrails & Safety
Add your Week 2 material here...
Week 3: Evals as CI/CD
Add your Week 3 material here...
Phase 4: FDE-Specific Execution
Add your material here
Add your material for Phase 4 here...
Phase 5: Portfolio & Positioning
Add your material here
Add your material for Phase 5 here...