The open-weight landscape
Hosted APIs are the default; open weights win on data-residency, offline, control, and high-volume cost. This chapter maps the families, licenses, and the size-vs-hardware reality.
Besides paid APIs like Claude, there are open-weight models (Llama, Mistral, Qwen…) whose files you can download and run on your own hardware. Why bother? Keeping data in-house, working offline, or saving money at scale. This section takes you from "run a model on your laptop in one command" to "serve one properly for a team" — and how to decide honestly when it's worth it versus just using an API.
The words you'll hear (in plain terms):
| Term | What it actually means |
|---|---|
| open-weight model | a model whose files you can download and run yourself (Llama, Mistral, Qwen…). |
| Ollama | the easiest tool to run such a model locally — one command, works on a laptop. |
| vLLM | a production-grade server for running open models fast for many users. |
| GGUF / quantized | a compact model file format that runs even on CPU / Apple Silicon. |
| self-host vs API | run it yourself (control, fixed cost) vs pay a provider per token (easy, no ops). |
What you need before starting:
- The AWS section's cost-model idea is handy background, not required.
- Python basics; comfort running a command in a terminal.
- Any modern laptop works for the local labs; a GPU helps for the serving ones.
New to the topic? Read this box, then take the chapters in order — each section is tagged essential → expert so you always know the depth you're at.
Learning objectives
- Name the major open-weight model families and their licenses.
- Match model size to the hardware needed to run it.
- Explain 'open weights' vs 'open source' and why the license matters.
- Choose a starting model for a given constraint.
Why run open models at all essential
Start with the mistake almost everyone makes first. You discover that models like Llama and Mistral are free to download, and the reflex is instant: "Why would I ever pay Claude or OpenAI per token when I can just run one myself?" So you spin up a GPU box, wrestle with drivers, get a model answering — and three weeks later you're maintaining an inference server, paying for a GPU that sits idle 90% of the day, and getting answers that are a notch behind the hosted model you were trying to avoid. The download was free; the operation was not. That gap between "free to download" and "free to run in production" is exactly what this section is here to make honest.
Here's the mental model to hold onto: think of a hosted API like hailing a taxi and self-hosting like buying a car. A taxi is the right choice almost always — no maintenance, no parking, no insurance, you pay only when you ride. Buying a car only pays off when you have a specific reason: you drive constantly (high volume), you need to go somewhere taxis won't (offline/air-gapped), you're carrying something you can't hand to a stranger (data residency), or you need to modify the vehicle itself (full control). Buying a car "because it's cheaper per mile" while ignoring insurance, fuel, and the driveway you need to park it in is the trap above. So the honest question is never "open or hosted?" in the abstract — it's "do I have one of those four specific reasons?"
The common trap in one line: people compare the API's per-token price against the GPU's per-token price and declare self-hosting cheaper — forgetting that the GPU costs the same whether it serves a million requests or zero. A hosted API scales its cost to your usage; a self-hosted GPU charges you rent around the clock. That's why the diagram below puts "your requirement" first and the hosted API in the middle as the default: you earn your way out of the default by pointing at a concrete need, not by doing napkin math on token prices alone. Read the four reasons that follow as a checklist — if you can't tick at least one honestly, the taxi wins.
Hosted APIs (Claude, etc.) are the right default — managed, capable, no ops. But open-weight models earn their place when you need data to never leave your infra, offline/air-gapped operation, full control of the model, or cost predictability at high volume. This track makes running them practical.
This little flow is the whole decision this chapter is about: should you use a hosted API or run an open model yourself? Read it left to right.
- The left box (Your requirement) is the honest starting point — what does your situation actually demand? Data that can't leave your network? Offline use? Tight control? Low cost at huge volume?
- The middle box (Hosted API) is the default recommendation: a provider like Claude runs the model for you — nothing to manage. Most projects should start here.
- The right box (Open-weight self-host) is the alternative you pick only when your requirement demands it — you download the model's files and run them on your own hardware, trading convenience for control.
- The arrows read as "leads you to consider" — a requirement points you at the default first, then to self-hosting only if the default doesn't fit.
In short: Hosted API is the sensible default; open-weight self-host is what you reach for when data-residency, offline operation, control, or high-volume cost forces the issue.
The families essential
The open-weight world looks chaotic until you realise it's really just a handful of "families." Newcomers get overwhelmed scrolling a model hub — thousands of names, each with cryptic suffixes like -instruct, -70B, -GGUF, -AWQ — and freeze, unsure which is "the real one." The calming truth: nearly all of them descend from a few base families, each published by one big lab, and the thousands of variants are just community re-packagings (different sizes, fine-tunes, or quantizations) of those originals. Learn the families and the chaos collapses into a short, readable menu.
A useful analogy: a family is like a car marque — Toyota, Honda, BMW. "Llama" or "Qwen" is the marque; "Llama 8B Instruct" is a specific model like a "Corolla," and the GGUF you download from some user is that same car with an aftermarket trim. Two things follow. First, models within a family share a lineage — training recipe, tokenizer conventions, prompt format — so once you can drive one Llama, the others feel familiar. Second, and this is the part people miss: the family determines the license, because the license is set by the lab that trained the base model, not by whoever re-uploaded a quantized copy. A Mistral fine-tune is still bound by Mistral's terms no matter whose account it lives under.
So how do you actually pick a family? Not by chasing whoever topped a leaderboard last week — those rankings churn constantly and the differences at the top are often within noise for your task. Pick on the axes that stay true: the size range it offers (can it go small enough for your hardware?), its strengths (Qwen leans multilingual and coding; Phi punches above its weight at tiny sizes; Mistral offers efficient mixture-of-experts options), the ecosystem around it (is it well-supported in the serving tools you'll meet in LM2–LM3?), and — decisively — its license, covered in the warning just below. The table maps the current major families to those axes. Treat the sizes and notes as a general orientation, not a spec sheet: labs ship new versions constantly, so the exact numbers drift, but the shape of the landscape — a few labs, broad size ranges, license as the real differentiator — is stable. Read across each row asking one question: "given my hardware and my legal constraints, could this family even be in the running?"
| Family | Sizes | Note |
|---|---|---|
| Llama (Meta) | 1B–405B | broad ecosystem; community license |
| Mistral / Mixtral | 7B–8x22B | strong small models; MoE options |
| Qwen (Alibaba) | 0.5B–72B+ | strong multilingual + coding |
| Gemma (Google) | 2B–27B | efficient, permissive-ish |
| Phi (Microsoft) | mini–medium | small, punch above weight |
Size vs hardware intermediate
This is the section that saves you from the single most common beginner faceplant: downloading a 70B model onto a laptop and watching it either crash outright or crawl so slowly it's unusable. The instinct is to grab the biggest, best-sounding model — bigger must be better, right? — but a model isn't like a movie file you can stream in chunks. To run at all, essentially all of its weights must sit in fast memory at once. Ask for more than the machine has and it doesn't run slower; it doesn't run. Understanding the size-vs-hardware wall before you download is what turns "why won't this work?" into a five-second sanity check.
The core idea is refreshingly countable, so let's demystify the jargon. A model's "size" — 7B, 70B — is its number of parameters (7 billion, 70 billion), the individual numbers it learned during training. Each parameter has to be stored in memory, and how many bytes each one takes is set by the precision: FP16 (the common full-fidelity format) spends 2 bytes per parameter, so the arithmetic is almost embarrassingly simple — parameters × 2 bytes = memory for the weights. A 7B model is ~14 GB; a 70B is ~140 GB. That's it; that's the wall. (Quantization, the "4-bit" column, is the escape hatch — it stores each weight in roughly half a byte instead of two, shrinking the same model ~4×, which is why a 7B that needs 16 GB at FP16 slips into 5–6 GB at 4-bit. You'll go deep on that in IC2 and LM4.)
Two things trip people up even after they know the formula. First, "VRAM" versus "RAM": the numbers below refer to VRAM — the memory on a GPU, which is fast enough to run a model at a usable speed. Your machine's ordinary system RAM can technically hold a model too, but running there is often painfully slow — one important exception is Apple-Silicon Macs, whose unified memory the GPU can use directly, which is why a MacBook punches above its weight for local models. Second, and the classic mistake: the weights are the floor, not the ceiling. A running model also needs room for the KV cache (the growing memory of the conversation, from IC3) and activations, which is why you never fill a GPU to 100% of the weight size — you leave headroom, typically 20–30%, or you'll run fine on a short prompt and crash on a long one. So read the table below as "what fits with breathing room," not "the exact minimum." Once these numbers are instinct, choosing a model stops being aspirational and becomes arithmetic: your hardware sets a ceiling, and you pick the best model that lives under it.
The practical constraint is memory. A rough rule at common quant levels (from IC2):
| Model size | FP16 VRAM | 4-bit VRAM | Runs on |
|---|---|---|---|
| 7–8B | ~16 GB | ~5–6 GB | one consumer GPU / good laptop (4-bit) |
| 13B | ~26 GB | ~9 GB | one bigger GPU |
| 70B | ~140 GB | ~40 GB | multi-GPU (IC6 tensor-parallel) |
Exercise LM1.1 — Pick your model
Context: The model you choose under a real constraint drives the rest of the track — everything downstream assumes that pick.
Your task: For a real or hypothetical constraint (e.g. "data can't leave our network, one A10 GPU"), pick a family, size, and quant level and justify it against the license and the memory table.
Requirements:
- State the constraint explicitly (hardware, residency, commercial use)
- Pick a model family, size, and quantization level
- Justify the size against the VRAM/memory table
- Justify the choice against the license
💡 Hint: Work from the constraint inward: VRAM sets the size, residency/commercial-use sets the license, and both together pick the family.
🪜 Practice ladder beginner → industry
Six graded exercises, easy to real-world. Try each before opening its solution.
Context: Hosted APIs are the sane default; open weights earn their place only for a specific reason — data-residency, offline/air-gapped, full control, or high-volume cost.
Your task: Write a helper that names which of those four reasons a given requirement triggers (or says the hosted API is the right default).
Requirements:
- Map each of the four open-weights reasons to a triggering requirement
- Return the matching reason when a requirement fires one
- Fall back to "hosted API default" when none applies
- Show a triggering case and a non-triggering case
💡 Hint: A small requirement→reason table with a default; if nothing matches, the managed API is the cheaper, saner choice.
Show solution
Encode the four reasons the lesson gives. Runnable stdlib:
REASONS = {
"data must stay on our infra": "data-residency",
"must work offline / air-gapped": "offline",
"we need full control of the model": "control",
"very high token volume": "cost-at-scale",
}
def why_open(requirement):
for k, reason in REASONS.items():
if k in requirement.lower():
return f"open weights -> {reason}"
return "hosted API is the right default here"
print(why_open("data must stay on our infra")) # data-residency
print(why_open("summarize a few docs a day")) # hosted default
Open weights earn their place for a specific reason — if none applies, the managed API is the cheaper, saner default.
Context: A rough but load-bearing rule: FP16 weights need ~2 bytes per parameter. That one number sets the hardware floor for any open model.
Your task: Write a calculator that, given a parameter count in billions, estimates the VRAM in GB for the weights at FP16.
Requirements:
- Use ~2 bytes per parameter for FP16
- Convert bytes to GB correctly (1024-based)
- Report weights-only VRAM for a few sizes (e.g. 7B, 13B, 70B)
- Note this is the floor, not the total (activations/KV add more)
💡 Hint: params × 1e9 × 2 bytes, divided into GB; a 7B lands near 13 GB, a 70B near 130 GB.
Show solution
2 bytes/param at FP16. Runnable:
def vram_fp16_gb(params_billion):
bytes_per_param = 2 # FP16
return params_billion * 1e9 * bytes_per_param / (1024**3)
for b in [7, 13, 70]:
print(f"{b}B -> ~{vram_fp16_gb(b):.1f} GB (weights only, FP16)")
# 7B -> ~13.0 GB, 13B -> ~24.2 GB, 70B -> ~130.4 GB
Weights alone: a 7B fits a 16GB card, a 70B needs multiple GPUs. Activations/KV cache add more — this is the floor, not the total.
Context: The size→VRAM wall is hard at FP16: given a GPU, only certain model sizes fit — and you must reserve headroom for the KV cache.
Your task: Write a selector that returns which model sizes fit at FP16 on a given GPU, leaving headroom.
Requirements:
- Reuse the FP16 weights estimate
- Reserve a fraction of VRAM for KV cache/activations before filtering
- Return the sizes that fit within the usable budget
- Show a small card and a large card fitting different sets
💡 Hint: Shrink the GPU's VRAM by a headroom fraction, then keep the sizes whose weights fit; quantization (LM4) is what moves the wall later.
Show solution
Reserve headroom for KV cache, then filter. Runnable:
def vram_fp16_gb(pb):
return pb * 1e9 * 2 / (1024**3)
def fits(gpu_gb, sizes=(7, 13, 34, 70), kv_headroom=0.30):
usable = gpu_gb * (1 - kv_headroom) # leave room for KV cache/activations
return [s for s in sizes if vram_fp16_gb(s) <= usable]
print("24GB card fits FP16:", fits(24)) # [7, 13]
print("80GB card fits FP16:", fits(80)) # [7, 13, 34, 70]
Quantization (LM4) shrinks the weights so bigger models fit — but at FP16 the size->VRAM wall is hard.
Context: "Open weights" (downloadable) is not "open source" (permissive license). Whether you can ship a model is governed by its license, not by the download.
Your task: Write a checker that, given a license, says what you may do — commercial use? redistribute? restrictions?
Requirements:
- Cover permissive (Apache/MIT), community (open weights with clauses), and research-only licenses
- Report commercial-use and redistribute permissions per license
- Flag research-only as not shippable to production
- Handle an unknown license by telling the user to read it first
💡 Hint: A license→permissions table; the key lesson is that "you can download it" never means "you can ship it".
Show solution
The license, not the download, governs use. Runnable:
LICENSES = {
"apache-2.0": {"commercial": True, "redistribute": True, "note": "permissive OSS"},
"mit": {"commercial": True, "redistribute": True, "note": "permissive OSS"},
"llama-community": {"commercial": True, "redistribute": True,
"note": "open weights, with acceptable-use + scale clauses"},
"research-only": {"commercial": False, "redistribute": False,
"note": "weights available but NOT for production"},
}
def check(license_id):
L = LICENSES.get(license_id.lower())
if not L:
return "unknown license -- read it before shipping"
return f"commercial={L['commercial']} redistribute={L['redistribute']} ({L['note']})"
print(check("apache-2.0")) # fully permissive
print(check("research-only")) # cannot ship
"You can download it" does not mean "you can ship it". Always check the license against your intended use.
Context: The starting model falls out of the axes together — VRAM, license, and deployment — not from picking the biggest name.
Your task: Given VRAM, whether commercial use is required, and whether offline is required, recommend a size tier and a posture.
Requirements:
- Pick the largest FP16-fitting size for the GPU (with headroom)
- Fall back to a quantized path when nothing fits at FP16
- Require a permissive license when redistribution/commercial use is needed
- Require self-hosting when offline is required
- Return a concrete recommendation combining all three
💡 Hint: Compute the size ceiling from VRAM first, then layer the license and deployment constraints on top; no FP16 fit points to a quantized GGUF (LM4).
Show solution
Fold size + license + deployment into one pick. Runnable:
def vram_fp16_gb(pb): return pb * 1e9 * 2 / (1024**3)
def recommend(gpu_gb, commercial, offline):
usable = gpu_gb * 0.7
biggest = max([s for s in (7, 13, 34, 70) if vram_fp16_gb(s) <= usable] or [0])
if biggest == 0:
return "no FP16 fit -- use a quantized GGUF (LM4) or a smaller model"
lic = "permissive (Apache/MIT) if you must redistribute" if commercial else "any"
deploy = "self-host required" if offline else "self-host optional"
return f"start ~{biggest}B; license: {lic}; {deploy}"
print(recommend(24, commercial=True, offline=True)) # ~13B, permissive, self-host
print(recommend(8, commercial=False, offline=False)) # quantized path
The starting model falls out of hardware + license + deployment — not from picking the biggest name.
Context: Defending a model choice to a team means a repeatable filter (hardware + license) then a quality ranking — a shortlist, not a vibe.
Your task: Build a scorer over candidate models (size, license, quality tier, VRAM need) that filters by hardware and license, then ranks survivors by quality.
Requirements:
- Each candidate carries params, license, and a quality score
- Exclude candidates whose FP16 weights won't fit the GPU (with headroom)
- Exclude non-permissive licenses when commercial use is required
- Rank the survivors by quality, best first
- Show a run excluding a research-only model and ranking the rest
💡 Hint: Filter first (fit + license), then sort by quality; a research-only model should drop out even if it's the highest quality.
Show solution
Turn the landscape into a defensible ranked shortlist. Runnable:
CANDIDATES = [
{"name": "A-8B", "params": 8, "license": "apache-2.0", "quality": 6},
{"name": "B-70B", "params": 70, "license": "llama-community","quality": 8},
{"name": "C-13B", "params": 13, "license": "research-only", "quality": 7},
]
PERMISSIVE = {"apache-2.0", "mit", "llama-community"}
def vram_fp16_gb(pb): return pb * 1e9 * 2 / (1024**3)
def shortlist(cands, gpu_gb, need_commercial):
usable = gpu_gb * 0.7
ok = []
for c in cands:
if vram_fp16_gb(c["params"]) > usable:
continue # won't fit
if need_commercial and c["license"] not in PERMISSIVE:
continue # license blocks prod
ok.append(c)
return sorted(ok, key=lambda c: c["quality"], reverse=True)
for c in shortlist(CANDIDATES, gpu_gb=80, need_commercial=True):
print(c["name"], "quality", c["quality"])
# B-70B first (fits 80GB, commercial-OK), then A-8B; C-13B excluded (research-only)
A repeatable filter (hardware + license) then a quality ranking is how you defend a model choice instead of arguing by vibes.
✓ Checkpoint — you can move on when you can…
- Name the major open-weight families and their sizes.
- Match model size to hardware at FP16 and 4-bit.
- Explain open-weights vs open-source and the license risk.
- Choose a starting model for a constraint.
Knowledge check check yourself
Why does "open weights" not mean "open source," and why is that a legal rather than a technical concern?
Show answer
Roughly what hardware does a 7–8B model need at FP16 versus 4-bit, and why does the chapter recommend starting at 7B/4-bit?