If you only remember one story about modern GenAI, make it this: we went from "finetune a classifier per task" to "prompt a general sequence model," then to "align it with humans," then to "wire it to tools and other modalities." Model names change every quarter; the family shapes below stay useful for years.
What changed over time? Three different jobs for language models:
| Architecture family | Plain-English idea | Best at |
|---|---|---|
| Encoder-only (BERT-like) | Reads the whole input at once, both directions | Classification, extraction, embeddings |
| Decoder-only (GPT-like) | Reads left-to-right, generates one token at a time | Chat, code, agents, summarization |
| Encoder–decoder (T5/BART-like) | Reads full input, writes full output | Translation, structured rewrite |
Everything else — RLHF (Reinforcement Learning from Human Feedback), multimodal towers, "reasoning" post-training — is a refinement on top of one of these skeletons.
Modern foundation models share a two-phase life:
| Era | Example shape | What changed for builders |
|---|---|---|
| Encoder boom | BERT-like | Pretrain once, finetune small heads for NLP tasks |
| Generative scale | GPT-like decoders | In-context learning; less per-task finetuning |
| Text-to-text | T5 / BART-like | One model, many tasks via prefixes and denoising |
| Alignment | Instruct / chat models | Helpful defaults; chat APIs become the product surface |
| Open weights | LLaMA-class, Mistral-class | Self-host, finetune, and compete on cost/latency |
| Multimodal + tools | Vision-language, audio | Same chat loop, richer inputs and function calls |
| Reasoning-heavy | Long CoT / test-time compute | Spend more tokens/latency for harder problems |
Encoder-only (BERT-like). Bidirectional attention over the input. Great for classification, named entity recognition (NER), and dense embeddings. Not a chat generator by default — you usually attach a task head or use the embedding tower.
Decoder-only (GPT-like). Causal (left-to-right) attention. Autoregressive generation is native. Almost every modern chat and coding assistant sits here.
Encoder–decoder (T5/BART-like). Encode the full source, then decode the target. Natural for translation, structured rewrite, and some summarization setups.
A raw language model is trained to continue text, not necessarily to help a user. Instruction tuning and RLHF shift behavior toward answers people prefer:
Why this matters: a smaller aligned model can feel more useful than a larger raw model because it follows instructions, refuses unsafe tasks more often, and formats answers the way users expect.
The recent ecosystem expanded in three directions:
| Direction | Plain-English idea | When it helps |
|---|---|---|
| Open weights | Released parameters you can host or finetune | Privacy, local deployment, cost control |
| Multimodal models | Text + images + audio in one interface | OCR, chart understanding, visual Q&A |
| Reasoning models | Spend more compute at answer time on hard tasks | Math, coding, planning — at higher latency/cost |
You do not need a GPU to practice the decision layer. Model a tiny registry that maps product jobs to family recommendations:
FAMILIES = {
"encoder": {
"jobs": ["classify", "ner", "embed"],
"notes": "Bidirectional; add a head or use embeddings.",
},
"decoder": {
"jobs": ["chat", "code", "agents", "summarize"],
"notes": "Causal LM; default for GenAI products.",
},
"encoder_decoder": {
"jobs": ["translate", "rewrite", "text_to_text"],
"notes": "Strong when input and output are both sequences.",
},
}
def recommend(job: str) -> list[str]:
return [name for name, meta in FAMILIES.items() if job in meta["jobs"]]
print(recommend("embed")) # ['encoder']
print(recommend("agents")) # ['decoder']
Track a fake "release lineage" so product notes stay honest about base vs chat vs reasoning variants:
from dataclasses import dataclass
@dataclass
class Checkpoint:
name: str
family: str
stage: str # base | instruct | preference | reasoning
lineage = [
Checkpoint("corp-7b-base", "decoder", "base"),
Checkpoint("corp-7b-instruct", "decoder", "instruct"),
Checkpoint("corp-7b-chat", "decoder", "preference"),
]
assert lineage[-1].stage == "preference"
# Chat APIs almost always expose a post-trained checkpoint, not the raw base.
Foundation-model history is a shift from task-specific encoders to aligned, tool-using generative families — choose encoder, decoder, or encoder–decoder by job shape, then validate the specific checkpoint.