AI AI-16.02
How to read a model page
Read a Hugging Face model page like an engineer: owner, task and library tags, license, gating, the model tree, file formats and which file to trust.
The big idea
You search the Hub for a small chat model and get 30 results with nearly the same name. One is from the company that trained it, one is a 400 MB copy by a community member, one needs you to apply for access, one is a "base" model that will not hold a conversation, and one ships its weights in a format that can run code on your machine when you load it. All five pages look alike at first glance. Reading them properly takes two minutes and saves hours.
A model page is the label on the box. Like the label on packaged food, it has a few fixed fields in fixed places (who made it, what is inside, the rules for using it) and a block of free text that is only as good as the person who wrote it. Under the hood the page is the repository's README.md, called the model cardThe README.md file of a model repository: a YAML metadata block (license, task, base model, datasets) followed by free text about the model's uses, limits, training and evaluation., plus metadata the Hub reads from its YAML header and from the files in the repo.
This lesson walks one real page, Qwen/Qwen2.5-0.5B-Instruct (the model you chatted with in the last lesson), section by section, then compares it with two neighbours: a community quantization of it and a gated model.
How it works
- 1. Who published it The repo id is owner/name. An official organization or a community member re-uploading or converting someone else's model?
- 2. What it does and how to load it The task tag (Text Generation) says what goes in and comes out. The library tag (Transformers, GGUF...) says which software loads it.
- 3. The rules The license says what you may do with it. A gate means you must log in and agree to share your username and email before you can download.
- 4. The family The model tree shows the base model this one came from, and the fine-tunes, adapters, quantizations and merges made from it.
- 5. The card text Intended uses, limitations, training data and evaluation. Missing sections are a signal too.
- 6. The files Files and versions lists every file with its size. The format of the weight files decides what you need to run it, and whether loading them is safe.
- 7. Popularity Downloads last month, likes and the Community tab. Useful for spotting problems, not for choosing what fits your task.
- 8. Use this model Copy-paste snippets for libraries, local apps and hosted inference. They assume you have the hardware.
1. The repo id: who published it
Every model lives at huggingface.co/owner/name, and that owner/name string is also what you pass to code: pipeline(model="Qwen/Qwen2.5-0.5B-Instruct"), llama-cli -hf bartowski/Qwen2.5-0.5B-Instruct-GGUF:Q4_K_M. The owner is a user or an organization. Qwen is the team that trained the model; bartowski is a community member who converts other people's models into GGUF files. Both are legitimate, but they are different promises: the original comes from the people who trained it, a conversion is only as careful as the person who made it.
2. Task and library tags: what it does and what loads it
The task tagThe model card field (pipeline_tag) that names the model's task, such as text-generation or image-classification. The Hub uses it for search filters and to pick the page's widget and inference API. (pipeline_tag in the metadata) names the shape of the model's inputs and outputs: Text Generation, Image Classification, Automatic Speech Recognition. It is the same word you pass to pipeline(task=...). The library tag says which software can load the files: Transformers, Diffusers, sentence-transformers, GGUF for llama.cpp and Ollama, and dozens more. For repos created after August 2024 the Hub no longer assumes that a config.json means a Transformers model, so authors are expected to set the library explicitly.
Two traps hide here:
- Base versus chat.
Qwen/Qwen2.5-0.5BandQwen/Qwen2.5-0.5B-Instructhave the same task tag. The Transformers docs put it plainly: models that do not support chat are often called "base" or "pretrained" models, and chat models are often called "instruct" or "instruction-tuned". A base model continues text; it does not answer questions. For a chatbot, look for Instruct or Chat in the name and a chat template in the files. - A tag is not a test. Tags come mostly from the metadata the author wrote. They tell you what the author intended, not what works well.
3. License and gate: the rules
The license tag (apache-2.0, mit, llama3.2, or "other" with a link to a custom license) says what you may do with the weights. Open source licenses like Apache 2.0 allow commercial use; some model licenses add conditions or restrict uses. Read the license file itself before you build a product on a model.
A gated modelA model whose files can be downloaded only after you log in and agree to share your username and email with the authors, sometimes with extra form fields and a manual review. shows a box asking you to agree before the files open. Per the Hub docs: you must be logged in, you agree to share your username and email with the authors (sometimes plus extra fields), and access is granted either automatically or after a manual review that can take time. The authors can revoke access at any time. The page itself stays public; only the files are locked. Here is what a script sees when it asks for a file from a gated model without logging in:
from huggingface_hub import hf_hub_download
try:
hf_hub_download("meta-llama/Llama-3.2-1B", "config.json") # no token, no access
except Exception as e:
print(type(e).__name__)
print("\n".join(str(e).splitlines()[2:4]))
GatedRepoError
Cannot access gated repo for url https://huggingface.co/meta-llama/Llama-3.2-1B/resolve/main/config.json.
Access to model meta-llama/Llama-3.2-1B is restricted. You must have access to it and be authenticated to access it. Please log in.
Agreeing in the browser is not enough for a script: the script needs an access token, which Accounts, tokens, downloads and datasets sets up.
4. The model tree: where it came from
Most models on the Hub are built from other models. The base_model field in the card's metadata records that, and the Hub shows it on the page as a model tree. The Hub infers one of four relationships, and each one tells you something different:
- A fine-tune retrained the whole model on new data. It can behave very differently from its parent.
- An adapter is a small set of extra weights, such as a LoRA ( Parameter-efficient fine-tuning: LoRA and QLoRA ), that only works on top of its base model. You download both.
- A quantization stores the same model with fewer bits per weight, so it is smaller and a little less accurate ( Quantization for inference ). The GGUF files you ran with llama.cpp are one.
- A merge blends two or more models' weights into one.
Whatever the relation, the base model's limits and license come along. A quantized copy of a model with a restrictive license is still bound by that license, even if the copy has no gate.
5. The card text: uses, limits, data, evaluation
Below the header is the free text. The Hub's guidance says a card should describe the model, its intended uses and limitations (including biases), its training parameters, the datasets it was trained on and its evaluation results. Good cards also show a short code example and the prompt format. Read the limitations section first: it is where authors tell you what the model is bad at. A card that is only a title and a code snippet is not proof of a bad model, but it means you will have to test everything yourself.
6. Files and versions: what you actually download
The Files and versions tab is a Git repository: every file, its size, and the history of commits. Three kinds of file matter:
- Configuration and tokenizer:
config.json(the architecture and its sizes),tokenizer.jsonand friends (how text becomes tokens, Tokenization ). Small, and always needed. - Weights: the big files. Their size is your first hint of how much memory the model needs, which Can I run it? What a model needs turns into arithmetic.
- The format of the weights, which decides what loads them and whether loading is safe.
One repo can hold the same weights several times. The sentiment model from the last lesson ships five copies of its 268 MB of weights: model.safetensors, pytorch_model.bin, tf_model.h5, rust_model.ot and onnx/model.onnx, one per framework. When we ran it with Transformers, only model.safetensors was downloaded. You never need all of them.
Pickle files can run code. .bin, .pt, .pth and .pkl weights are usually Python picklePython's built-in serialization format. A pickle file is a list of instructions that can import and call any function while it is being loaded. files, PyTorch's classic format. The Hub's security docs explain the danger: a pickle is a small program of instructions, and loading it can import any function and call it. The Hub scans every pickle that is pushed and lists the imports it finds next to the file, flagging suspicious ones, but warns the scan is not foolproof. safetensorsA weights format from Hugging Face: an 8-byte length, a JSON header naming each tensor's type, shape and byte range, then the raw numbers. Loading it cannot run code. files hold only a JSON header and raw numbers, so there is nothing in them to run. Prefer .safetensors whenever a repo offers it, and only load pickles from owners you trust. The difference is easy to see in a few lines of Python, below in Try it.
GGUF repos hold many sizes of one model. A GGUF file packs the tensors together with a standard set of metadata, ready for llama.cpp, Ollama and LM Studio. Quantizers usually upload one file per quantization, and you download just one. The community repo for our model has 24 of them, from 329 MB to 994 MB:
| File in bartowski/Qwen2.5-0.5B-Instruct-GGUF | Size | Bits per weight (for the K types) |
|---|---|---|
Qwen2.5-0.5B-Instruct-Q2_K.gguf | 339 MB | Q2_K: 2.625 |
Qwen2.5-0.5B-Instruct-Q4_K_M.gguf | 398 MB | Q4_K: 4.5 |
Qwen2.5-0.5B-Instruct-Q8_0.gguf | 531 MB | 8-bit, legacy type |
Qwen2.5-0.5B-Instruct-f16.gguf | 994 MB | 16 |
The bits per weight come from the Hub's GGUF documentation. Q4_K_M is the usual starting point: Ollama picks it by default when a repo has it. The Hub also has a GGUF viewer: open any .gguf file on the Files tab to see its metadata and every tensor's name, shape and precision without downloading it.
Versions. Because the repo is Git, a model can change under the same name. For anything you ship, pin a specific commit (most loading functions take a revision argument) so a later upload cannot change your results.
7. Downloads, likes and discussions
Downloads last month and likes tell you what many people use, which means more answered questions and more tools that support it. The Community tab holds discussions and pull requests: search it for your error message before you debug alone. Popular does not mean right for your task or your hardware.
8. Use this model
The Use this model button opens copy-paste instructions for libraries (Transformers code), local apps (llama.cpp, Ollama, LM Studio, Jan, once you enable them in your Local Apps settings) and hosted inference. It is the fastest path from page to running code, with one catch: the snippet assumes the model fits on your machine. Check that first (lesson 16.03).
Try it
Sort these file names from real repos by what happens when you load them:
Now see the difference between the two weight formats. This program builds a tiny pickle and a tiny safetensors file in memory, both holding the same two numbers. The pickle also carries a "surprise": an instruction to call print while it is being loaded. A real attack would call something worse.
# Two ways to store weights, built in memory with the standard library only.
import io, json, pickle, pickletools, struct
# 1. Pickle (.bin, .pt, .pth, .pkl): a little program the loader runs.
class Surprise:
def __reduce__(self): # "to rebuild me, call print(...)"
return (print, (" !! this line ran while the file was LOADING",))
blob = pickle.dumps({"weight": [0.5, -1.25], "extra": Surprise()}, protocol=4)
print("Pickle: instructions found without running them")
strings = []
for op, arg, _ in pickletools.genops(blob):
if isinstance(arg, str):
strings.append(arg)
if op.name in ("STACK_GLOBAL", "GLOBAL"):
print(" import", ".".join(strings[-2:]))
if op.name == "REDUCE":
print(" call it (REDUCE)")
print("Pickle: now actually loading it")
weights = pickle.loads(blob)
print(" got", weights["weight"])
# 2. safetensors: 8 bytes of header length, a JSON header, then raw numbers.
data = struct.pack("<2f", 0.5, -1.25)
header = json.dumps({"weight": {"dtype": "F32", "shape": [2], "data_offsets": [0, len(data)]}}).encode()
f = io.BytesIO(struct.pack("<Q", len(header)) + header + data)
print("safetensors: loading it")
n = struct.unpack("<Q", f.read(8))[0]
meta = json.loads(f.read(n)) # just JSON: nothing in it can run
start, end = meta["weight"]["data_offsets"]
raw = f.read()[start:end]
print(" header:", meta)
print(" got", list(struct.unpack("<2f", raw)))Output
Pickle: instructions found without running them
import builtins.print
call it (REDUCE)
Pickle: now actually loading it
!! this line ran while the file was LOADING
got [0.5, -1.25]
safetensors: loading it
header: {'weight': {'dtype': 'F32', 'shape': [2], 'data_offsets': [0, 8]}}
got [0.5, -1.25] The first part reads the pickle's instructions with pickletools without running them, the same idea the Hub's scanner uses, and finds an import of builtins.print followed by a call. Then loading it runs that call. The safetensors half is just json.loads and a byte slice: there is no instruction in the file that could run.
Finally, you can read the important parts of a model page from Python, without downloading any weights. This uses huggingface_hub and was run against the three repos from this lesson:
# pip install huggingface_hub (tested with huggingface_hub 2.2.0)
from huggingface_hub import model_info
WEIGHTS = (".safetensors", ".bin", ".pt", ".pth", ".gguf")
SHOW_GGUF = ("Q2_K.", "Q4_K_M", "Q8_0", "f16") # 4 of the many quantizations
for repo in ["Qwen/Qwen2.5-0.5B-Instruct",
"bartowski/Qwen2.5-0.5B-Instruct-GGUF",
"meta-llama/Llama-3.2-1B"]:
info = model_info(repo, files_metadata=True) # the page's data, no weights
card = info.card_data or {}
print(repo)
print(" task:", info.pipeline_tag, "| library:", info.library_name,
"| license:", card.get("license"))
print(" gated:", info.gated, "| base_model:", card.get("base_model"))
print(" downloads last month:", info.downloads, "| likes:", info.likes)
for f in info.siblings:
if f.rfilename.endswith(WEIGHTS):
if f.rfilename.endswith(".gguf") and not any(q in f.rfilename for q in SHOW_GGUF):
continue
print(f" {f.rfilename} {f.size / 1e6:,.0f} MB")
Qwen/Qwen2.5-0.5B-Instruct
task: text-generation | library: transformers | license: apache-2.0
gated: False | base_model: Qwen/Qwen2.5-0.5B
downloads last month: 5751568 | likes: 701
model.safetensors 988 MB
bartowski/Qwen2.5-0.5B-Instruct-GGUF
task: text-generation | library: None | license: apache-2.0
gated: False | base_model: Qwen/Qwen2.5-0.5B-Instruct
downloads last month: 115833 | likes: 19
Qwen2.5-0.5B-Instruct-Q2_K.gguf 339 MB
Qwen2.5-0.5B-Instruct-Q4_K_M.gguf 398 MB
Qwen2.5-0.5B-Instruct-Q8_0.gguf 531 MB
Qwen2.5-0.5B-Instruct-f16.gguf 994 MB
meta-llama/Llama-3.2-1B
task: text-generation | library: transformers | license: llama3.2
gated: manual | base_model: None
downloads last month: 583606 | likes: 2707
model.safetensors 2,472 MB
original/consolidated.00.pth 2,472 MB
Read the output like a page: the Instruct model names its base, the GGUF repo names the Instruct model as its base and has no library set in its metadata (its tags say gguf instead), and Llama is gated with manual approval and ships a pickle .pth next to its safetensors. The numbers are from 2026-10-20.
- Change the first repo to
Qwen/Qwen2.5-0.5B. What base model and task does the base model report? - Pick a model you are curious about and run the script. Does it offer
.safetensors? Is it gated?
Before you download a model
A two-minute checklist, in the order of Figure 1:
- Owner: is this the original publisher, or a copy or conversion? If a copy, open its base model too.
- Task and type: does the task tag match what you want, and is it a chat (Instruct) model if you want to chat?
- Library: can your tool load it (Transformers, GGUF for llama.cpp or Ollama, something else)?
- License and gate: may you use it for your purpose? If gated, have you been granted access, and will your script have a token?
- Card: read intended uses and limitations. Is the prompt format documented?
- Files: is there a
.safetensorsfile (or a GGUF)? If only pickles, do you trust the owner? Which single file do you need, and how big is it? - Fit: will that file fit in your memory with room to spare? Lesson 16.03 shows how to check.
- Pin: note the commit you tested so you can load exactly that version again.
Trade-offs
| Option | Wins when | Loses when |
|---|---|---|
| .safetensors | Default for Transformers and Diffusers; loads fast; cannot run code | Needs a Python library that understands the architecture |
| Pickle (.bin, .pt, .pth) | Older repos that have nothing else, from owners you trust | Loading can execute code; the Hub scan helps but is not foolproof |
| GGUF | Local apps (llama.cpp, Ollama, LM Studio) on CPU or a small GPU; one file per size | Mostly used for language models; quality drops at very low bits |
| Original repo | Reference quality, documentation and updates from the trainers | Often 16-bit only, which may be too big for your machine |
| Community conversion | Ready-made quantizations that fit small machines | Only as careful as the converter; check its base model and license |
Common mistakes
- Downloading a base model for a chatbot and wondering why it rambles instead of answering.
- Trusting a re-upload or conversion without opening its base model, so missing the original license or limits.
- Loading a
pytorch_model.binfrom an unknown account when a.safetensorscopy of the same model exists. - Downloading a whole GGUF repo (every quantization) instead of the one file you need.
- Clicking Agree on a gated model in the browser, then being surprised that a script without a token gets a
GatedRepoError.
In the wild
Hugging Face
Model cards documentation (opens in a new tab)The Hub's documentation explains that a model card is the repo's README.md: a YAML metadata block followed by text. The metadata drives what you see on the page: the license, the task tag that picks the widget and the inference API, the library, the datasets, and the base_model field that builds the model tree, with the relation (adapter, merge, quantized, fine-tune) inferred by the Hub. For the text, it asks authors to cover intended uses, limitations and biases, training details, datasets and evaluation results, which is exactly the reading order of this lesson.
Check yourself
-
The page bartowski/Qwen2.5-0.5B-Instruct-GGUF lists Qwen/Qwen2.5-0.5B-Instruct as its base model. What is it most likely to be?
Show answer
B. A quantized copy of the Instruct model made by a community member The owner is a community member, the files are GGUF quantizations, and base_model points to the original. Its abilities, limits and license terms come from that base.
-
You want a chatbot. You find Qwen/Qwen2.5-0.5B, tagged Text Generation, and Qwen/Qwen2.5-0.5B-Instruct, also tagged Text Generation. Which one, and why?
Show answer
C. The Instruct model, because base models continue text rather than follow a conversation The task tag only says text comes out. Instruct or chat models are trained to follow a conversation; base models just continue whatever text you give them.
-
A repo from an account you do not know offers only pytorch_model.bin. Another repo of the same model offers model.safetensors. What should you do?
Show answer
B. Use the .safetensors copy: it holds only a header and numbers, so loading it cannot run code Pickle files can run code when loaded, and the Hub's import scan is explicitly not foolproof. A safetensors file is a JSON header and raw bytes.
-
You clicked Agree on a gated model and can see its files in the browser, but your script fails with GatedRepoError. Why?
Show answer
B. The script is not authenticated: it needs an access token from your account Access is tied to your account. The browser is logged in; the script is not until you log in with a token (hf auth login or a token argument).
-
A GGUF repo has 24 files between 329 MB and 994 MB. What do you download?
Show answer
C. One quantization that fits your memory with room to spare, often Q4_K_M to start Each file is the whole model at a different precision. Pick one: Q4_K_M is a common default (Ollama picks it when present), and lesson 16.03 shows how to check the fit.
Recap
- A model page is the repo's model card (README.md with YAML metadata) plus what the Hub reads from its files.
- Read in order: owner, task and library tags, license and gate, model tree, card text, files, popularity, then Use this model.
- The model tree says whether a model is a fine-tune, adapter, quantization or merge; the base model's limits and license come along.
- Prefer .safetensors: pickle weights (.bin, .pt, .pth, .pkl) can run code when loaded. From a GGUF repo, download one quantization.
- Gated models need you logged in and approved, and scripts need a token; check license, fit and the exact commit before you build on a model.