Hugging Face Transformers tutorial: pipeline, tokenizer, and models in 2026
The Hugging Face Transformers crash course rewritten for v5 — pipeline, tokenizer, models, saving, the Hub, and fine-tuning, plus the 2022 syntax that no longer runs.



Four years ago we published a 15-minute crash course on the Hugging Face Transformers library. It's been watched more than 625,000 times, and a good chunk of what it teaches is now wrong.
Not conceptually wrong. The mental model in that video—a pipeline is a tokenizer plus a model plus some post-processing—is still exactly right, and it's still the fastest way to understand the library. But the library shipped a major version since then. Transformers v5 dropped TensorFlow and Flax entirely, removed several pipelines the video demonstrates, and renamed a handful of arguments that every 2022-era tutorial still uses.
So this is the video, rewritten against the current library. Same seven beats: install, pipeline, tokenizer and model, PyTorch, save and load, the Model Hub, fine-tuning. Every snippet below is grounded in the current Transformers documentation, and where the video's approach no longer works, we say so instead of quietly fixing it.
What changed between 2022 and now
Start here, because if you're following an older tutorial this table is the whole problem. The version on PyPI at the time of writing is Transformers v5, and main is on 5.16.0.dev0.
The GitHub star count in the video—60,000—is now about 164,000. That part aged well.
Installing Transformers
The 2022 advice was "install your favorite deep learning library first, then pip install transformers." Half of that still holds. There's no favorite to pick anymore.
Hugging Face's own installation page is blunt about it: "Transformers works with PyTorch." The library has been tested on Python 3.10+ and PyTorch 2.5+. The extras-based install pulls torch in for you:
uv pip install "transformers[torch]"Or with conda:
conda install conda-forge::transformers
If you're following along in a notebook, the quickstart's install line adds the libraries you'll want for anything past inference:
# remove ! if installing from the CLI
!pip install -U transformers datasets evaluate accelerate timm
That's it. No framework decision, no tensorflow extra, no Flax. If you're curious how the ecosystem got here, the short version is that the PyTorch vs. TensorFlow debate resolved in research, and Hugging Face eventually stopped paying the maintenance cost of pretending otherwise.
The pipeline: three lines to a working model
A pipeline is the library's highest-level abstraction. You name a task, it picks a sensible default model, and you get results. Everything about tokenization, tensor shapes, and decoding is handled.
>>> from transformers import pipeline
>>> pipe = pipeline("text-classification")
>>> pipe("This restaurant is awesome")
[{'label': 'POSITIVE', 'score': 0.9998743534088135}]
One small mercy for anyone following the old video: "sentiment-analysis" still works. It's an alias, mapped in the library's TASK_ALIASES dict to "text-classification", alongside "ner" → "token-classification" and "text-to-speech" → "text-to-audio". The canonical name is text-classification, so prefer that in new code.
Under the hood, the pipeline is doing three things in sequence—and this is the part of the video that hasn't aged a day:
- Pre-processing. Run the text through a tokenizer to turn it into numbers the model can consume.
- The model. A forward pass that produces raw logits.
- Post-processing. Turn those logits back into something you asked for—a label and a score, generated text, a ranked list.
Swap the task string and you get a different pipeline. Text generation, with a specific model rather than the default:
from transformers import pipeline
pipeline = pipeline(task="text-generation", model="google/gemma-2-2b")
pipeline("the secret to baking a really good cake is ")
Zero-shot classification is the demo that still makes people sit up, because you never trained anything on your labels:
>>> from transformers import pipeline
>>> oracle = pipeline(model="facebook/bart-large-mnli")
>>> oracle(
... "I have a problem with my iphone that needs to be resolved asap!!",
... candidate_labels=["urgent", "not urgent", "phone", "tablet", "computer"],
... )
{'sequence': 'I have a problem with my iphone that needs to be resolved asap!!',
'labels': ['urgent', 'phone', 'computer', 'not urgent', 'tablet'], 'scores':
[0.504, 0.479, 0.013, 0.003, 0.002]}
There are 23 supported task keys in v5, spanning text, audio, images, video, and multimodal—including automatic-speech-recognition, which we'll come back to. But check the list before you write code against a task you remember from a tutorial. summarization, question-answering, translation, and text2text-generation are gone. The migration path for all of them is text-generation with a chat model.
Behind the pipeline: tokenizer and model
The pipeline is convenient right up to the moment you need control. Then you reach for the two classes it was hiding: an Auto tokenizer and an Auto model head.
from transformers import AutoTokenizer, AutoModelForSequenceClassification
model_name = "distilbert/distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name)
That model ID is the default the text-classification pipeline uses. The name tells you everything: DistilBERT, base size, uncased, fine-tuned on SST-2, English. Hub naming conventions are load-bearing, and reading them is a real skill.
from_pretrained is the method you'll type more than any other in this library. It downloads weights or config from the Hub, caches them, and instantiates the class. Two arguments worth knowing on the model side—both shown in the current quickstart—are dtype and device_map:
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf", dtype="auto", device_map="auto")
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")
Note dtype, not torch_dtype. That rename is one of the most common breakages when you paste 2022 code into a 2026 environment.
The Auto classes are generic dispatchers—they read the model's config and hand you the right concrete class. If you know exactly what you want, the specific classes still exist, which is what the video meant by "there's also a BERT tokenizer class and a BERT model class." Reach for Auto unless you have a reason not to.
Once you have both objects, you can hand them back to a pipeline and get identical results to the default—useful for confirming your understanding, and essential once you're loading a fine-tuned model from disk:
classifier = pipeline("text-classification", model=model, tokenizer=tokenizer)
If you want the theory underneath all of this—attention, encoders, why any of it works—we have a beginner's introduction to Transformers that covers the architecture rather than the library.
What a tokenizer actually does
A tokenizer converts text into a numerical representation the model can process. Call it directly and you get a dictionary back:
>>> inputs = tokenizer("I've been waiting for a Hugging Face course my whole
life.", return_tensors="pt")
>>> inputs
{'input_ids': tensor([[...]]), 'attention_mask': tensor([[...]])}
Two keys matter. input_ids are the token IDs. attention_mask is a list of zeros and ones where a zero tells the attention layers to ignore that position—which is how padded batches work without the padding polluting the result.
You can also run the steps individually, which is the clearest way to see what's happening:
tokens = tokenizer.tokenize("I've been waiting for a Hugging Face course my whole
life.")
ids = tokenizer.convert_tokens_to_ids(tokens)
decoded = tokenizer.decode(ids)
Run that and compare ids against the input_ids from the direct call. They're the same sequence, except the direct call adds two extra IDs—one at each end. Those are the special tokens marking the beginning and end of the sequence, and the model expects them. That's the argument for always calling the tokenizer directly rather than assembling IDs yourself.
The other thing to notice: with an uncased model, decode gives you back lowercase text. Capitalization is destroyed at tokenization time. It's not a bug, it's what "uncased" means, and it's a genuine gotcha if you're planning to display the decoded output to a user.
One v5 change here: encode_plus() is gone, folded into __call__(), and decode() now handles both single and batch inputs. additional_special_tokens was renamed to extra_special_tokens.
Running the model directly in PyTorch
This is where the video's PyTorch/TensorFlow chapter used to fork. In v5 there's no fork. You tokenize a batch, run a forward pass, and post-process yourself:
>>> import torch
>>> from transformers import AutoTokenizer, AutoModelForSequenceClassification
>>> tokenizer = AutoTokenizer.from_pretrained("stevhliu/my_awesome_model")
>>> inputs = tokenizer(text, return_tensors="pt")
>>> model = AutoModelForSequenceClassification.from_pretrained("stevhliu/my_awesome_model")
>>> with torch.no_grad():
... logits = model(**inputs).logits
>>> predicted_class_id = logits.argmax().item()
>>> model.config.id2label[predicted_class_id]
'POSITIVE'
Three details from the video are still exactly right. **inputs unpacks the tokenizer's dictionary into keyword arguments. torch.no_grad() skips gradient tracking for inference, and it's still what the current docs use. And model.config.id2label is the mapping that turns index 1 into POSITIVE—the thing the pipeline's post-processing step was doing for you all along.
For real batches, the tokenizer arguments from the video carry over unchanged:
batch = tokenizer(x_train, padding=True, truncation=True, max_length=128,
return_tensors="pt")padding=True pads to the longest sequence in the batch, truncation=True cuts anything over the limit, and return_tensors="pt" gives you torch tensors instead of Python lists. Drop that last argument and you're back to formatting tensors by hand.
If you want to send the batch straight to the model's device, the quickstart chains it:
model_inputs = tokenizer(["The secret to baking a good cake is "],
return_tensors="pt").to(model.device)Saving and loading
Symmetric and unremarkable, which is the point:
save_directory = "saved"
tokenizer.save_pretrained(save_directory)
model.save_pretrained(save_directory)
tokenizer = AutoTokenizer.from_pretrained(save_directory)
model = AutoModelForSequenceClassification.from_pretrained(save_directory)
One v5 note: safetensors is now mandatory. safe_serialization=False is no longer supported, so you can't write pickle-based checkpoints anymore. The default shard size also went from 5GB to 50GB, which matters if you have tooling that assumed the old value.
Finding models on the Hub
In 2022 the video marveled at "almost 35,000 models." The Hub now lists more than three million, and Hugging Face's own Transformers docs put the number of compatible checkpoints at over 1M. Browsing is no longer a viable strategy.
The workflow is the same, just with the filters doing more work. Filter by pipeline task, library, dataset, and language in the left sidebar. Search for what you need. Then use the copy icon next to the model name to grab the full ID, and drop it into a pipeline:
pipe = pipeline("text-classification",
model="distilbert/distilbert-base-uncased-finetuned-sst-2-english")Here's the trap for anyone working from the old video: its Hub demo ends by building a summarization pipeline from a model card. That pipeline no longer exists. You'll still find thousands of summarization models on the Hub—the model cards are fine, the weights are fine—but the pipeline abstraction for that task was removed in v5. Load the model with the appropriate Auto class, or use a chat model through text-generation.
Once you have something working, wrapping it in a Gradio app is the fastest way to hand a demo to someone who doesn't want to run your notebook.
Fine-tuning with Trainer
The video kept this section deliberately short and pointed at the docs. Good instinct—fine-tuning is its own article. But the shape of it is worth seeing, because two of the argument names changed.
training_args = TrainingArguments(
output_dir="qwen3-finetuned",
num_train_epochs=3,
per_device_train_batch_size=2,
gradient_accumulation_steps=8,
gradient_checkpointing=True,
bf16=True,
learning_rate=2e-5,
logging_steps=10,
eval_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=dataset["train"],
eval_dataset=dataset["test"],
processing_class=tokenizer,
data_collator=DataCollatorForLanguageModeling(tokenizer, mlm=False),
)
trainer.train()
trainer.push_to_hub()
It's eval_strategy, not evaluation_strategy. And it's processing_class=tokenizer, not tokenizer=tokenizer. Both of those will throw on v5, and both appear in essentially every fine-tuning tutorial written before 2025. Several other TrainingArguments parameters were dropped outright, including overwrite_output_dir, logging_dir, tpu_num_cores, and no_cuda.
If you want the full walkthrough with real datasets and results, we published a guide to fine-tuning Transformers for NLP that fine-tunes DistilBERT and BERT on SST-2 and reports the accuracy numbers.
When a hosted speech-to-text API beats running a model yourself
Everything above is genuinely useful, and for a lot of tasks it's the right answer. Text classification on your own labels, embeddings, a fine-tuned model on domain text—run it yourself. The pipeline abstraction is three lines and the economics are fine.
Speech is where the calculus changes, and it's worth being specific about why rather than hand-waving at it.
Transformers has an automatic-speech-recognition pipeline. You can load an open ASR checkpoint and get a transcript on your laptop today, and if you're prototyping, you should. We've written about free speech-to-text APIs and open-source engines, and we've walked through building an end-to-end speech recognition model in PyTorch. Neither of those posts tells you not to.
What tends to bite is the second half of the project. Automatic speech recognition in production isn't the forward pass. It's long-audio chunking, punctuation and casing, speaker labels, timestamps, and code-switching—plus a GPU fleet that has to stay up when your queue depth triples. Each of those is a separate model, a separate failure mode, or a separate on-call rotation. The forward pass was the easy part.
The honest comparison is total cost, and it depends on volume. Below a few hundred hours a month, a hosted speech-to-text API is almost always cheaper than the GPU time plus the engineering time. AssemblyAI's current flagship async model, Universal-3.5 Pro, runs at $0.21 per hour of audio, billed per second with no minimums, with native code-switching across 18 languages and speaker diarization in the same pass. Above that, self-hosting starts to pencil out—if you have the team.
Veed, which builds a browser-based video editor, framed the trade-off this way:
Assembly allowed our team to focus on what they are best at: Building a collaborative, browser-based video editor and distributing that product at speed and at velocity to our user base.
— Sabba Keynejad and Tim Mamedov, Veed
That's the actual question. Not "can I run this model"—you can, and you just learned how. It's whether transcription is the thing you're building or the thing underneath it. If you do decide to benchmark your own model against a hosted one, our guide on how to evaluate speech recognition models covers doing it fairly, and the API docs have a Python quickstart if you want a number to compare against.
What to take from a four-year-old tutorial
Here's the thing that struck us in re-doing this: the concepts survived a major version bump completely intact, and almost none of the syntax did.
Pipeline as three stages. Tokenizer as a text-to-numbers converter with special tokens you shouldn't hand-roll. from_pretrained everywhere. Auto classes as dispatchers. Model IDs that describe themselves. Every one of those still holds, and they're why the 2022 video is still worth 15 minutes even though its code isn't.
The syntax, meanwhile, needs checking against the docs every time. Which suggests a practical habit: learn the shape of a library from tutorials, and get the exact call signature from the reference. The Transformers docs and the v5 migration guide are both good, both current, and both take less time to check than debugging a TypeError from a renamed keyword.
Frequently asked questions
What is Hugging Face Transformers used for?
Transformers is a Python library for downloading, running, and fine-tuning pretrained AI models across text, audio, images, and multimodal tasks. Developers use it for text classification, text generation, zero-shot classification, speech recognition, and object detection—among 23 supported pipeline tasks in v5—without training a model from scratch. It pairs with the Hugging Face Hub, which now hosts over three million models.
Does Hugging Face Transformers still support TensorFlow?
No. Transformers v5 removed TensorFlow and JAX/Flax support entirely, and PyTorch is now the only supported backend. Every TF-prefixed class from older tutorials is gone, and the library's installation docs simply state that "Transformers works with PyTorch." If you need TensorFlow, you'll have to pin an older 4.x release.
What's the difference between a pipeline and using AutoModel directly?
A pipeline bundles tokenization, the model forward pass, and post-processing into one call, so pipeline("text-classification")("great movie") returns a label and a score. Using AutoTokenizer and AutoModelForSequenceClassification directly gives you the same result in more steps, but lets you control batching, padding, device placement, and what you do with the raw logits. Start with the pipeline; drop down when you need control or you're feeding a training loop.
How do I fix "evaluation_strategy" and "tokenizer" errors in Trainer?
Rename them: evaluation_strategy became eval_strategy in TrainingArguments, and tokenizer= became processing_class= in Trainer. These are the two most common errors when running pre-2025 fine-tuning code on Transformers v5. overwrite_output_dir, logging_dir, no_cuda, and tpu_num_cores were removed from TrainingArguments too.
Can I use Hugging Face Transformers for speech-to-text in production?
Yes, the automatic-speech-recognition pipeline works and open ASR checkpoints on the Hub are strong, but the model is the smallest part of a production system. You'll also own long-audio chunking, punctuation and casing, speaker diarization, timestamps, and GPU autoscaling. Below roughly a few hundred hours of audio a month, a hosted API is usually cheaper once engineering time is counted; above that, self-hosting can pencil out if you have a team for it.
Is the Hugging Face Transformers tutorial from 2022 still worth watching?
The concepts are, the code isn't. The pipeline-tokenizer-model mental model, from_pretrained, the Auto classes, and Hub naming conventions all survived the v5 rewrite unchanged. But TensorFlow support, the summarization pipeline, torch_dtype, evaluation_strategy, and tokenizer= in Trainer did not—so check every call signature against the current docs before you run it.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
