Open Files and versions before you open anything else
A typical transformers model repository contains eight to fifteen files. Five of them decide whether the model will work for you, and you can read all five in a browser in under a minute: no download, no GPU, no install. This is the cheapest diagnostic on the Hub and almost nobody uses it.
Here is what you are looking at.
config.json: the model’s shape
This is the architecture, in JSON. A trimmed example:
{
"architectures": ["LlamaForCausalLM"],
"hidden_size": 4096,
"num_hidden_layers": 32,
"num_attention_heads": 32,
"max_position_embeddings": 131072,
"vocab_size": 128256,
"torch_dtype": "bfloat16",
"rope_theta": 500000.0
}Four fields earn your attention:
architecturesnames the Python class that will be instantiated.LlamaForCausalLMtells you this is a text generator;BertForSequenceClassificationtells you it is a classifier with a fixed number of labels. If this names a class your installed transformers version does not have, you getKeyErroror a message about an unrecognised model type, and the fix is upgrading transformers rather than anything to do with the model.max_position_embeddingsis the context length. This is the number the model name never tells you and the one that most often decides a project.torch_dtyperecords what precision the weights were saved in. It is a record, not an instruction: loading does not automatically honour it in older versions of transformers, which is how people end up holding a bfloat16 model in float32 and using twice the memory they budgeted.vocab_sizemust match the tokenizer. When it does not (usually after somebody added special tokens and did not resize the embedding matrix) you get an index error deep inside the forward pass, or silent nonsense.
You can read it without a browser:
curl -s https://huggingface.co/meta-llama/Llama-3.2-1B/resolve/main/config.json | head -40The tokenizer files: three of them, doing different jobs
tokenizer.jsonis the fast tokenizer: the full vocabulary and merge rules in one file, loaded by the Rust implementation. Its presence is whyAutoTokenizeris fast.tokenizer_config.jsonholds the settings around it: padding side, maximum length, the special token names, and, on chat models, thechat_template. That template is a Jinja string, and it is the difference between a chat model working and a chat model producing drivel. It is worth reading.special_tokens_map.jsonmaps roles likebos_token,eos_token,pad_tokenonto actual strings.
Older repositories carry vocab.txt, merges.txt or spiece.model instead. They work; they load through the slow Python path unless a converter runs.
The weights, and why there are several files
model.safetensors is the whole thing when the model is small. Above a few gigabytes it is sharded:
model-00001-of-00004.safetensors
model-00002-of-00004.safetensors
model-00003-of-00004.safetensors
model-00004-of-00004.safetensors
model.safetensors.index.jsonThe index is a map from every parameter name to the shard that holds it, plus a total byte count. It is small, it is readable, and the total_size field in it is the fastest honest answer to “how much disk will this cost me”, more reliable than adding up what the file listing shows, because the listing also contains formats you will not download.
Many repositories carry both .safetensors and .bin copies of the same weights. Downloading the repository naively fetches both and doubles your bill. The next lesson explains why you want the safetensors ones specifically.
generation_config.json: the defaults you did not choose
For generative models this file sets temperature, top_p, do_sample, max_new_tokens, eos_token_id and friends. When people compare two models and one seems wilder, the cause is frequently that their published generation defaults differ, not that the model does. If you are benchmarking, set these explicitly rather than inheriting them.
.gitattributes, and files with no purpose
.gitattributes tells git which patterns go to large-file storage. You will never edit it by hand and you should never delete it. Beyond that you will find README.md, which is the model card, plus example images, an onnx/ folder, and sometimes a runs/ directory full of training logs somebody forgot to exclude. That last one is occasionally the most informative thing in the repository.
A repository can also be an adapter
If you see adapter_config.json and an adapter_model.safetensors of a few dozen megabytes, this is not a model. It is a LoRA adapter: a small set of extra matrices that must be applied on top of the base model named inside adapter_config.json. Downloading it alone and wondering why nothing loads is a rite of passage.
Do this now
Open any chat model’s tokenizer_config.json and find the chat_template. Read the Jinja. You are looking at the exact strings the model was trained to expect around a user turn; and once you have seen them, the whole category of “the model ignores my system prompt” bugs becomes legible.
Every lesson here is open. Your progress is recorded once you pass the Image Generation, in Practice exam.
Check your understanding
A repository lists ten files totalling 46 GB, but its model.safetensors.index.json reports a total_size of about 16 GB. What is the most likely explanation?
Pick the one you would defend. Your answer stays private.
Stuck on something?Ask Arjun, your AI tutor