Hugging Face, End to End
Read a model card licence-first, run a Space for free, keep a token safe, publish something of your own.
- Level
- Some background helps
- Lessons
- 75
- Reading time
- 659 min
- Price
- Free, no sign-up to read
The Hub is a host for git repositories that happen to contain neural networks, and that framing explains the rest. You will read a model card licence-first, tell the four shelves apart, run and duplicate Spaces on free hardware, keep tokens out of public code, load models and stream datasets without filling your disk, judge a leaderboard sceptically, and publish a card a stranger can act on.
Opens after the Image Generation, In Practice exam
Sign in, finish that course, and pass its exam. You can read this syllabus meanwhile.
Go to Image Generation, In PracticeModule 1
The Hub, read properly
The Hub holds over a million model repositories and the search box is the worst way into them. This block teaches the Hub as what it is — a git host with a filter sidebar, a file layout, a naming convention and a set of counters — so that you can find a specific model among millions, tell from its files alone what will load it, and know which of its numbers mean anything.
By the end you can
Find a specific model on the Hub using filters and the Python API rather than the search box, read its repository files to say what architecture it is, what format its weights are in and what code will run when you load it, and explain what the download counter is actually counting
- 1The Hub is git, and that explains everything elseA model on the Hub is a git repository with big files stored beside it, so it has versions, history and pull requests — and if you do not pin a revision, the model under your code can change without your code changing.
- 2The search box is the worst way inHub search matches repository names and card text rather than meaning, so the filter sidebar — task tag, library, licence, and the base-model links to fine-tunes and quantizations — is the real interface, and the sort order answers popularity rather than quality.
- 3Read the licence before you read the demoCheck the licence family and the base model before anything else, because a fine-tune inherits its parent's terms no matter what its own card claims.
- 4A model's name is a specification, if you can read itA repository name usually encodes owner, family, parameter count, tuning style and weight format, which is enough to compute memory and rule a model in or out — but it never encodes context length or licence, and a mixture-of-experts name like 8x7B states resident memory rather than compute.
- 5What the files in a model repository are forFive files answer the questions a model card often does not: config.json gives the architecture and context length, the tokenizer files carry the chat template, the safetensors index gives the true download size, generation_config sets sampling defaults you did not choose, and an adapter_config means you are looking at a LoRA rather than a model.
- 6Loading a model can run someone else's codeA pickle checkpoint executes code when loaded, while safetensors is a JSON header plus raw bytes with no code path at all — but `trust_remote_code=True` reopens the hole by importing Python from the repository, so the weights format and the loading code are two separate decisions.
- 7Four shelves, and picking the wrong one costs a weekendModels are parts, datasets are material, Spaces are finished tools and inference is rented hardware — choose the shelf by how often the job runs and whether the data may leave your machine.
- 8Ask the Hub questions instead of browsing it`huggingface_hub` turns the Hub into a queryable service, and the single highest-value call is `model_info(..., files_metadata=True)`, which tells you exactly what a repository will cost in disk and what formats it duplicates before you spend a byte.
- 9What a download count is countingDownloads are a thirty-day count of file fetches dominated by CI, library defaults and ephemeral containers, so they are a floor on how well-exercised a model is and not a ranking — while fine-tune, adapter and Space counts cost real effort and carry more information.
Module 2
Transformers, from characters to output
The transformers library is three layers stacked: a tokenizer that turns text into integers, a model that turns integers into logits, and a decoder that turns logits back into text. Most of the bugs people report as bad models are one of those three layers being used wrongly. This block walks the whole path with real numbers, then gives you an ordered checklist for the case where everything loads and the output is still rubbish.
By the end you can
Trace a piece of text from characters through a tokenizer to logits and back to text with the transformers library, and say which of the Auto class, the tokenizer, the padding side, the chat template or the generation config is at fault when a model loads without error and produces nonsense
- 10One line that hides five steps`pipeline` resolves, tokenizes, runs, post-processes and formats in one call, and when you do not name a model it silently picks a small English-only default whose confidence score is a softmax over two numbers rather than a probability of being right.
- 11AutoModel gives you numbers, not answers`AutoModel` loads the network body and returns hidden states, while `AutoModelForX` attaches a task head — and when the checkpoint has no such head, transformers initialises it randomly and warns rather than failing, so a classifier that returns confident noise is the expected outcome of loading a base checkpoint.
- 12Your text is integers, and the count is not the word countA tokenizer maps text to integers from a fixed vocabulary, and the tokens-per-word ratio depends on whose language the vocabulary was built from — so the same sentence can cost two to four times as much in an Indic script as in English on an English-centric model.
- 13Padding on the wrong side ruins generation quietlyThe attention mask makes padding invisible to the model, but a decoder-only model generates from the last position, so right padding makes it continue from a pad token and quietly degrades batched output while single requests still look fine.
- 14Logits, and the four knobs between them and wordsA model outputs one unnormalised score per vocabulary token and the decoding strategy picks from them, so temperature, top-p and repetition penalties are choices you make after the model has finished — and a `do_sample: false` default in generation_config silently discards every sampling parameter you pass.
- 15The chat template is not optionalAn instruction-tuned model was trained on one exact string format that ships inside `tokenizer_config.json`, so `apply_chat_template(..., add_generation_prompt=True)` is the only reliable way to build a prompt — hand-written `User:`/`Assistant:` text puts the model outside its training distribution with no error to show for it.
- 16Throughput and latency are different problemsBatching trades latency for throughput by amortising weight reads, so it pays on GPUs and often not on CPUs — and because a generation batch runs until its slowest member finishes, sorting by length and watching the KV cache matter more than raising the batch size.
- 17Showing tokens as they arrive, and making them stopStreaming changes perceived latency rather than compute, and it works by running `generate` on a second thread feeding a queue — while a model that never stops usually has a mismatch between the end token its template emits and the `eos_token_id` its generation config is watching for.
- 18It loaded, it ran, the output is nonsenseFluent-but-wrong output has a short list of causes to check in order — base instead of instruct, missing chat template, mismatched tokenizer, padding side, dtype overflow, over-aggressive quantization, inherited generation defaults and silent truncation — and the model itself is the last suspect, not the first.
Module 3
Running it on the hardware you actually have
Most of this readership is on a phone, a shared laptop, or a free Colab session that disconnects after a few hours. This block is the arithmetic and the tooling for that reality: how to compute the memory a model needs before downloading it, what quantization buys and costs, the formats that run well without a GPU, where free compute genuinely exists and where its limits are, and how to measure whether a change helped.
By the end you can
Compute from a model's parameter count and dtype whether it will fit the machine in front of you, pick between a full-precision, quantized, GGUF or ONNX route for a stated constraint, and measure peak memory, first-token latency and quality loss well enough to defend the choice
- 19Your disk fills up before your patience doesWeights cost parameters times bytes-per-parameter and everything downloaded lands in one shared cache, where deleting the readable filenames frees nothing because they are only links to the blobs.
- 20The memory arithmetic you can do in your headWeights cost parameters times bytes-per-dtype, but the bill that decides whether generation fits is weights plus a KV cache that grows with sequence length and batch — and bfloat16 is preferred over float16 not for size but because it keeps float32's exponent range and so does not overflow to NaN.
- 21Spreading a model across whatever you have`device_map="auto"` places layers across GPU, CPU and disk and streams weights shard by shard, which makes oversized models run correctly and extremely slowly — so offloading suits one-off jobs while quantization is the right answer for anything interactive.
- 22Quantization: what you buy and what you payQuantization buys memory at a quality cost that concentrates in arithmetic, structured output and rare languages rather than spreading evenly — and at a fixed memory budget a heavily quantized large model usually beats a small model at full precision.
- 23GGUF, and the laptop that has no GPUGGUF packs weights, tokenizer and template into one self-contained file that llama.cpp runs on CPU, Apple silicon or a phone with no CUDA and no Python, making `Q4_K_M` the default free path for anyone without a graphics card.
- 24ONNX, Optimum, and models that run in a browser tabONNX freezes a model into a portable graph that runs without PyTorch, and through transformers.js that graph runs inside a browser tab — which makes a static file a free, private, infinitely scalable deployment for any model small enough to download.
- 25Where the free GPUs actually areFree GPU compute genuinely exists — Colab, Kaggle, Spaces CPU and ZeroGPU — and every one of them is temporary, so the discipline that makes it usable is pushing artefacts to the Hub, checkpointing to resume, and debugging on a tiny model before switching the name.
- 26What actually runs on eight gigabytesOn 8 GB and no GPU, embeddings, encoder classifiers, small Whisper models and 1–3B generative models at 4-bit all run usefully — and for a fixed narrow task a small specialised model usually beats a large general one on accuracy, speed and cost at the same time.
- 27Proving the change helpedA hardware change has to be reported as peak memory, time to first token, throughput and quality on your own thirty examples together, because each configuration trades along all four axes at once and any one number alone can be improved while the system gets worse.
Module 4
Spaces: putting something in front of people
A Space is a git repository that the Hub builds and runs, with a public URL and a free tier that never expires. This block takes you from a forty-line Gradio script to an application with state, secrets, storage and a build you can debug — and then shows how to call somebody else's Space as an API, which turns the whole platform into infrastructure rather than a gallery.
By the end you can
Build, configure and debug a Space that other people can use — choosing the SDK, pinning versions in the README, holding secrets and state correctly, picking hardware against a sleep policy — and call an existing Space programmatically as an API instead of reimplementing it
- 28A Space is someone else's computer, already configuredFree CPU hardware runs one-file-at-a-time work well and cannot run image generation or fast chat, and a slow Space is usually a cold start or a shared queue rather than a fault.
- 29Forty lines from nothing to a public URL`gr.Interface` turns a Python function plus input and output components into a public web application, and the two things that decide whether strangers can use it are loading the model once at import rather than per request, and shipping examples plus an honest statement of the limits.
- 30Blocks, when Interface is no longer enough`gr.Blocks` separates layout from event wiring, and the rule that prevents the worst class of Space bug is that module-level variables are shared by every visitor while `gr.State` is per-session — so the model is shared and everything about a user is not.
- 31Duplicate it, and the app becomes yours to changeDuplicating a Space gives you a private copy with no queue, but paid hardware bills for wall-clock time and does not sleep the way free hardware does — set the sleep timer before you upgrade.
- 32The README front matter is the deployment configA Space's deployment configuration is YAML front matter in `README.md`, so it is versioned like code — and the two fields that decide whether it still builds in six months are `sdk_version` and pinned dependency versions in `requirements.txt`.
- 33Hardware, sleep, and the bill that runs while you are asleepPaid Space hardware bills for wall-clock uptime rather than requests and does not sleep unless you set the timer first, while ZeroGPU attaches a GPU per function call — which is the only route to a free public demo that needs real acceleration.
- 34The filesystem disappears, and what to do about itA Space's local filesystem does not survive restarts, so state belongs in `gr.State` for a session, a paid `/data` volume for the model cache, or a private Hub dataset repository for anything collected — and collecting user text at all is a commitment that has to be stated on the page.
- 35Streamlit, Docker and a Space with no server at allGradio, Streamlit, Docker and static are four different deployment shapes, and the static Space running transformers.js is the one people overlook — no server, no sleep, no cost, and the user's data never leaves their device.
- 36Every Space is an API you can callGradio exposes every event handler as an API endpoint automatically, so any public Space is a callable service — but it can sleep, change or vanish and you cannot see its logs, so anything you depend on should be a private duplicate you control.
- 37It built, it started, it is redBuild logs and container logs describe different phases and most confusion comes from reading the wrong one, while a container killed with no traceback is the out-of-memory signature — and a factory reboot rather than a restart is the fix when the code cannot explain the failure.
Module 5
Datasets, and the work that happens before any model
Most of the real job is data, and the datasets library exists so that a 500 GB corpus behaves like a Python list on a laptop. This block covers loading and streaming, the Arrow format that makes it possible, transforming at scale, querying the Hub's parquet copies with SQL before downloading a byte, and then the unglamorous checks — duplicates, leakage, class balance, label noise — that decide whether anything trained on it means anything.
By the end you can
Inspect, stream, filter and transform a dataset far larger than your RAM, query the Hub's parquet conversion with SQL before downloading anything, run duplicate, leakage and class-balance checks on your own data, and publish it with a card stating provenance and licence
- 38Do not download the datasetInspect a dataset in the viewer and stream it with `streaming=True` rather than downloading, and treat licence obligations as surviving fine-tuning until a lawyer in your country tells you otherwise.
- 39A dataset that behaves like a list and is not oneA `Dataset` is a typed table where indexing a row returns a dict and slicing returns a dict of lists, and operations like shuffle and select build an indices map rather than copying data — which is why reordering a dataset far larger than RAM is instantaneous.
- 40Why a 300 GB dataset opens instantlyDatasets are memory-mapped columnar Arrow files, so size is limited by disk rather than RAM and row access faults in only the pages it needs — while `streaming=True` drops random access and true shuffling in exchange for needing no disk at all.
- 41Transforming a million rows without waiting an hour`map(batched=True)` hands your function a dict of lists and can return a different number of rows than it received, which makes it both the fast path and the tool for chunking — while `set_transform` applies on access for anything random that should not be cached.
- 42Query a dataset with SQL before downloading itThe Hub auto-converts public datasets to parquet, so DuckDB can run SQL against them over HTTP and answer class balance, length distribution, duplication and train–test overlap in seconds without downloading anything.
- 43Turning your files into a datasetBuilding a dataset is `from_dict`, `from_generator` or a folder convention plus explicitly typed `Features`, and publishing is one call — so the decisions that matter are the ones before the push: personal data, the right to redistribute, a licence, and starting private because public cannot be undone.
- 44The card is where a dataset stops being a fileA dataset card's job is provenance — where rows came from, under what terms, labelled by whom, with what agreement — because a licence tag cannot grant rights the compiler never held, and a dataset without recorded provenance can never be assessed against whatever the law turns out to be.
- 45Media columns decode when you touch them`Audio` and `Image` columns decode lazily on access, so `cast_column` can resample or defer decoding for free — and the silent failures in media work are a sampling rate that does not match the model, processor constants borrowed from another model, and augmentation frozen into a cache by `map`.
- 46Duplicates, leakage, balance, and label noiseBefore training, four checks decide whether a result means anything: exact and near duplicates, leakage along the axis deployment must generalise across, class balance against the metric you will quote, and label noise that sets a ceiling no model can pass.
- 47From a dataset to batches a trainer can eatTraining needs `input_ids`, `attention_mask` and a column literally named `labels`, with padding done per batch by a collator rather than at map time — and for instruction tuning the prompt positions are set to `-100` so loss is computed only on the response.
Module 6
Embeddings, and search that understands
An embedding is a list of numbers that places a piece of text, an image or a clip of audio somewhere in a space where nearby means similar. It is the concept under semantic search, retrieval-augmented generation, recommendation, clustering and deduplication — and it runs on a phone. This block builds a working search over your own documents from first principles, then measures it honestly instead of trusting a leaderboard.
By the end you can
Build and measure a semantic search over your own documents — choosing an embedding model against your language and text length, chunking deliberately, normalising vectors for the similarity you use, adding a cross-encoder reranker, and reporting recall@k on questions you wrote yourself
- 48A list of numbers where near means similarAn embedding is a fixed-length vector whose geometry encodes meaning, produced by a model trained contrastively to place similar texts close together — so search, clustering, deduplication and few-shot classification are all the same operation, and its central weakness is that similarity is not relevance and negation barely moves the vector.
- 49The library, and the four calls you need`SentenceTransformer.encode` with `normalize_embeddings=True` plus one matrix multiply is a complete search engine over a hundred thousand documents, and the two details that silently cost accuracy are forgetting a family's query prefix and letting a vectors array drift out of order with its metadata.
- 50Picking the model, and reading MTEB without being fooledMaximum sequence length and language coverage decide an embedding model more often than its benchmark rank does, and MTEB's average column mixes tasks you do not have — so use it for a shortlist of three and settle it with thirty questions of your own.
- 51Cosine, dot product, and the normalisation that connects themOn unit-length vectors cosine, dot product and Euclidean distance rank identically, so normalising at encode time removes the choice — and because each model spreads its space differently, similarity scores are for ranking rather than for thresholds copied from anyone else.
- 52Chunking decides what your search can findChunk size and boundaries decide what retrieval can find at all, so split on structure rather than character counts, count in the model's own tokens because scripts differ, carry the document and section title into the embedded text, and consider retrieving small chunks while passing their parent sections to the model.
- 53NumPy first, FAISS second, a database rarelyExact search with one matrix multiply handles a million vectors in tens of milliseconds, so NumPy is the right first index and FAISS or a vector database earns its place only at genuine scale or when filtered, updating, shared indexes are needed — and adding BM25 alongside fixes what embeddings are worst at.
- 54The second pass that fixes the firstA bi-encoder compares precomputed vectors and scales, while a cross-encoder reads query and document together and judges whether one answers the other — so retrieving 50 cheaply and reranking them expensively buys most of the accuracy at a fraction of the cost.
- 55One space for pictures and wordsCLIP-style models place images and their captions in one shared space, so photographs become searchable by typed sentences and classifiable with no training — while the same shape does not mean the same space, and mixing vectors from different models in one index produces confident nonsense.
- 56Thirty questions, and the numbers they give youThirty questions of your own with known correct chunks turn every dial in a retrieval system into a measurable decision, and the failures sort into a short list of distinct causes — but a set that size detects fifteen-point differences and not three-point ones, so it should settle big choices and never small ones.
Module 7
Training and adapting, with the libraries the Hub is built on
Adapting a model on the Hub is a different job from training one from scratch, and the libraries reflect that: Trainer for the loop, PEFT for adapters that are a thousandth the size of the model, TRL for instruction and preference tuning, and the Hub itself as durable storage for a run that will be interrupted. This block starts by arguing you probably should not fine-tune, then teaches you to do it properly when you should.
By the end you can
Decide from evidence whether a task needs fine-tuning at all, run a LoRA or QLoRA adaptation with Trainer or SFTTrainer on a single free GPU, read a loss curve well enough to name what is wrong, and publish an adapter a stranger can apply to the base model
- 57Three cheaper things to try firstFine-tuning teaches behaviour and retrieval supplies knowledge, so a gap made of facts should never be trained into weights — and prompting, a larger model and a small specialised classifier all sit between the problem and a training run that will need redoing when the base model is replaced.
- 58Trainer, and what it saves you writing`Trainer` implements the loop, scheduling, mixed precision, checkpointing and resumption that are individually easy and collectively error-prone, and the two arguments that most often decide whether a run is usable are `id2label` at construction and `resume_from_checkpoint` on restart.
- 59The six arguments worth understandingLearning rate sets the scale of everything and differs tenfold between full fine-tuning and LoRA, while gradient accumulation buys a large effective batch on small hardware and `gradient_checkpointing`, 8-bit optimisers and shorter sequences are the ordered responses to running out of memory.
- 60LoRA: training 0.1% of the parametersLoRA freezes the base weights and learns a low-rank update, so optimiser state shrinks by the same hundredfold factor and the result is a few megabytes tied to one exact base model — which is what makes fine-tuning a 7B model on free hardware possible at all.
- 61QLoRA, and fine-tuning a 7B model on a free GPUQLoRA keeps a frozen base in 4-bit and trains precise adapters over it, dequantizing per matrix multiply — so a 7B model fits a free GPU at the cost of speed rather than memory, and `prepare_model_for_kbit_training` is the line whose absence makes training quietly fail instead of raising.
- 62TRL, and training on conversations`SFTTrainer` renders chat templates, masks the prompt, packs and truncates conversations for you, so the remaining decisions are about data — a few hundred diverse, well-written examples in the messages format beat tens of thousands of scraped ones, and the register of your responses becomes the model's register.
- 63Watching a run you cannot sit next toLog training loss, validation metric, learning rate and gradient norm somewhere that outlives the machine, checkpoint with `hub_strategy="checkpoint"` so a killed session costs minutes, and resume with `resume_from_checkpoint` because reloading only the weights restarts the learning-rate schedule.
- 64Loss is NaN, memory is gone, nothing is learningTraining failures sort into memory, NaN, flat loss, good loss with a useless model, and a training–inference mismatch — and the test that separates a pipeline bug from a data problem is deliberately overfitting ten examples, because a model that cannot memorise ten rows is not learning at all.
- 65Shipping the thing you trainedPublish the adapter rather than a merged republication of somebody else's weights, record the base model, training configuration and a measured result against a baseline in the card — and keep the dataset and evaluation set, because the adapter expires when its base is superseded and the data does not.
Module 8
Depending on it, and publishing so others can
The last block is about the parts that decide whether your work survives contact with other people: what a licence actually permits and where the law is genuinely unsettled, how to judge a model with your own examples rather than a leaderboard, where inference should run and what it costs, what a card must contain to be auditable, how to contribute back, and how to pin everything so the thing you shipped still works next year.
By the end you can
State what a model's licence permits for your intended use and where the question is unresolved rather than answered, choose between a provider, a dedicated endpoint and your own hardware on stated cost and privacy grounds, judge a model with thirty examples of your own, and publish work a stranger can audit and reproduce
- 66A token in a public Space is a token you have given awayScope tokens as narrowly as the job allows, keep them in environment variables and Space secrets rather than in code, and revoke on suspicion rather than reasoning about whether a leak was seen.
- 67What the licence tag does and does not settleA fine-tune inherits its base model's terms however its own tag reads, so licence checking means following `base_model` to the root — and the questions the licence does not answer, about training data and output ownership, are genuinely unresolved and differ by country rather than merely being undocumented.
- 68The leaderboard is not measuring your taskA leaderboard narrows the field and cannot pick the winner, because contamination, selective reporting and style effects all sit between a public score and your task — thirty of your own examples decide it.
- 69The evaluation that decides itA leaderboard narrows the field and thirty examples of your own decide it, because only your set contains your languages, formats and hard cases — and at that size it reliably detects large differences and must never be used to justify small ones.
- 70Renting the compute instead of owning itThe Hub routes inference to third-party providers behind one OpenAI-compatible interface, and the choice between serverless, a dedicated endpoint, your own server and the user's device turns on token volume against GPU utilisation — with the crossover much higher than teams assume and privacy deciding it outright for sensitive data.
- 71When transformers stops being the right serverPurpose-built servers beat a transformers loop structurally rather than by tuning — continuous batching keeps the GPU full, paged attention stops the KV cache fragmenting, and prefix caching reuses a shared system prompt — and unlike at training time, quantization under these stacks buys speed as well as memory.
- 72Publish it so a stranger can use it without writing to youA card with a runnable snippet, a named limitation and a deliberate licence makes your work usable by strangers, and everything you would regret publishing must be decided before the first push, because copies survive deletion.
- 73Writing a card somebody can auditA card written for an auditor — documented data, stated intended and out-of-scope use, measured evaluation against a baseline with per-group results, a specific named limitation and a contact — is also the card a careful user needs, and it is the practice that survives whatever the specific regulation turns out to be.
- 74Pull requests, discussions and being usefulAny Hub repository accepts pull requests and proposals can be loaded with `revision="refs/pr/N"` before merging, so the highest-value contributions are small — a missing licence or chat template, a safetensors conversion, a card translation, a named limitation — and the discussions tab usually holds the documentation the card does not.
- 75Still working next yearFour things move independently under a working system — the model's `main` branch, the libraries, the platform defaults and your own corpus — so pin every `from_pretrained` to a revision, pin dependency versions, read deprecation warnings as dated outage notices, and mirror any model you genuinely cannot lose.