The Most-Used Open-Source Models on Hugging Face and How to Run Them in Python

Stop Picking Models by Vibes

Hugging Face hosts over a million models. The most-downloaded ones are not necessarily the biggest, the newest, or even the best on a leaderboard — they’re the ones people can actually load, run, and ship. Before you reach for whatever 70B model is trending, it’s worth knowing what the most-used models actually are, what they’re good at, and exactly how much Python it takes to run them.

This post compares the most-downloaded open-source weights families on the Hub by task, footprint, and ecosystem fit, then shows the minimal Python to load and run each one with transformers. The goal is a decision you can make from facts, not from marketing.

What “Most Used” Actually Means

Hugging Face does not publish one canonical “most used” list, but the download counts and community popularity paint a clear, well-known picture across families:

Family Released Size range Primary job Why it’s everywhere
BERT 2018 Base 110M / Large 340M Embeddings, classification, NER, search The default encoder; huge fine-tuned ecosystem
GPT-2 2019 124M–1.5B Text generation (small) Tiny, fast, easy to run anywhere
RoBERTa 2019 125M–355M Drop-in BERT upgrade Better-trained BERT for classification
T5 2019 60M–11B Text-to-text: summarization, translation One architecture for every NLP task
BART 2019 140M–400M Summarization, denoising Strong seq2seq summarizer
DistilBERT 2019 66M Distilled encoder 40% smaller BERT, nearly same quality
Llama 2023 7B–405B Instruction chat, general LLM The open decoder baseline everyone builds on
Mistral 2023 7B–123B Instruction chat Cheap, efficient decoder with sliding windows
Gemma 2024 2B–27B Open decoder (Google) Permissive, small enough for dev boxes
Phi 2023–24 1.1B–14B “Textbook” small models Tiny models that punch above their size
Qwen 2023 0.5B–72B Multilingual decoder Strong multilingual + code/coding support
Falcon 2023 7B–180B Decoder Open weights, TII flagship

Two families dominate downloads: the encoder line (BERT / RoBERTa / DistilBERT) that powers embeddings, search, and classification in production, and the decoder line (Llama / Mistral / Gemma / Qwen) that powers chat and completion. Everything below is about picking the right one per use case.

The Encoder Family: BERT and Its Descendants

Encoders produce a dense embedding of a whole sequence. They are the workhorses of semantic search, classification, named-entity recognition, and reranking. They are not chat models — they don’t generate; they represent.

BERT — the default encoder

from transformers import AutoTokenizer, AutoModel
import torch

model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

texts = ["The ship leaves port at dawn.", "Invoice 374651 was paid."]
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")

with torch.no_grad():
    out = model(**inputs)

embeddings = out.last_hidden_state.mean(dim=1)   # mean-pooled sentence embedding
print(embeddings.shape)                          # (2, 768)

The [CLS] token’s hidden state, or the mean of last_hidden_state, becomes the sequence vector you compare or feed to a classifier head. BERT’s real value is the enormous pool of fine-tuned checkpoints on the Hub that solve niche tasks out of the box.

RoBERTa — BERT with better training

RoBERTa uses the same architecture but was trained longer, on more data, with no next-sentence prediction and dynamic masking. On classification and NER it usually edges out BERT. Implementation is identical — you only change the model name:

from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch

model_name = "roberta-base"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2)

inputs = tokenizer(
    "The container is delayed by weather.",
    return_tensors="pt",
)
with torch.no_grad():
    logits = model(**inputs).logits
print(logits.argmax(dim=-1).item())

DistilBERT — the cheap encoder

DistilBERT distills BERT down to 66M parameters. It loses a little accuracy but runs ~60% faster and uses half the memory:

from transformers import AutoTokenizer, AutoModel

distilled = AutoModel.from_pretrained("distilbert-base-uncased")
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
# Same forward call as BERT; the only change is the checkpoint name.

The encoder decision: if you need a sentence or token embedding, search, or classification, start with BERT; move to RoBERTa for a few points of accuracy at the same cost, and use DistilBERT when the CPU or memory budget is tight.

The Seq2Seq Family: T5 and BART

Seq2seq models take text in and produce text out, which makes them the natural choice for summarization, translation, and question answering from context.

T5 — one architecture for every text task

T5 frames everything as text-to-text: “summarize: …”, “translate English to French: …”. It’s the cleanest “give it a task prefix, get text back” model:

from transformers import AutoTokenizer, AutoModelForSeq2SeqLM

model_name = "t5-base"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSeq2SeqLM.from_pretrained(model_name)

input_text = "summarize: The vessel departed Hong Kong carrying 12,000 TEU and is expected at Rotterdam in 18 days."

inputs = tokenizer(input_text, return_tensors="pt")
outputs = model.generate(**inputs, max_new_tokens=60, num_beams=4)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

The T5Small (60M) to T5Base (220M) are light enough for a CPU or small GPU, which is why T5 remains a favorite for on-prem summarization.

BART — denoising autoencoder for summarization

BART is an autoencoder trained to reconstruct corrupted text, which makes it excellent at summarization specifically. Same API:

from transformers import AutoTokenizer, AutoModelForSeq2SeqLM

model_name = "facebook/bart-base"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSeq2SeqLM.from_pretrained(model_name)

article = "An export container berth opened in Antwerp, cutting average dock dwell time from four days to one."

inputs = tokenizer("summarize: " + article, return_tensors="pt", max_length=512, truncation=True)
outputs = model.generate(**inputs, max_new_tokens=64, num_beams=4)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

The seq2seq decision: BART tends to produce tighter, more fluent summaries; T5 is more flexible across tasks because of the task prefix. For a summarization-only workload, BART is usually the better default; for “I need translation and summarization and Q&A,” T5’s text-to-text framing wins.

The Decoder Family: Chat and General Generation

Decoders are causal language models: they generate token-by-token. Everything from Llama 2 onward drives agentic and chat workloads. The good news for implementers is the API is essentially the same — AutoModelForCausalLM + torch_dtype + the right device placement.

Llama — the open baseline

from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

model_name = "meta-llama/Llama-3.1-8B-Instruct"   # requires an HF access token / approval
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype=torch.bfloat16,
    device_map="auto",
    attn_implementation="sdpa",
)

messages = [{"role": "user", "content": "Summarize this shipping schedule in one line."}]
inputs = tokenizer.apply_chat_template(messages, return_tensors="pt", add_generation_prompt=True).to(model.device)

out = model.generate(**inputs, max_new_tokens=128, do_sample=True, temperature=0.7)
print(tokenizer.decode(out[0][inputs.shape[1]:], skip_special_tokens=True))

Note the three heavy-lifting options in one call:

  • torch_dtype=torch.bfloat16 halves the footprint versus fp32.
  • device_map="auto" spreads weights across available GPUs.
  • attn_implementation="sdpa" uses the fast scaled-dot-product-attention path.

Mistral — efficiency via sliding windows

Mistral (specifically mistralai/Mistral-7B-Instruct-v0.3) is Llama-class quality at lower cost, using sliding-window attention so the KV cache (and thus memory) grows more slowly for long contexts:

from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

model_name = "mistralai/Mistral-7B-Instruct-v0.3"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.bfloat16, device_map="auto")

prompt = tokenizer.apply_chat_template(
    [{"role": "user", "content": "Explain sliding-window attention in one sentence."}],
    tokenize=False, add_generation_prompt=True,
)
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=80)
print(tokenizer.decode(out[0][inputs.shape[1]:], skip_special_tokens=True))

Gemma — small and permissive

Google’s Gemma family is notable for being small enough to run on a laptop and permissively licensed:

from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

model_name = "google/gemma-2-2b-it"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.bfloat16, device_map="auto")
# Identical chat-template + generate pattern as Mistral / Llama.

Qwen — the multilingual + code option

Qwen (Qwen/Qwen2.5-7B-Instruct) is the strongest choice when you need multilingual support (including strong Chinese) or coding help, often at a favorable accuracy-to-size ratio:

from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

model_name = "Qwen/Qwen2.5-7B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.bfloat16, device_map="auto")
# Same causal-LM generate path, just a different tokenizer / template.

Phi — “textbook quality” tiny models

Phi (microsoft/Phi-3-mini-4k-instruct, 3.8B) is trained on curated “textbook-quality” data and is famous for beating far larger models on math and reasoning benchmarks while running on modest hardware:

from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

model_name = "microsoft/Phi-3-mini-4k-instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.bfloat16, device_map="auto")

prompt = "Reason step by step: A train leaves at 08:40 and arrives 2h15m later. What time is it?"
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=96)
print(tokenizer.decode(out[0][inputs.shape[1]:], skip_special_tokens=True))

The decoder decision: Llama is the safe, well-supported default; Mistral is Llama quality with lower memory; Gemma is the legal-and-laptop-friendly option; Qwen wins multilingual and code; Phi is the best small-model for math/reasoning on constrained hardware.

Running Them Without Blowing Up Your Machine

The single most important transformers skill is matching the model to your hardware. Two flags do most of the work:

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.1-8B-Instruct",
    torch_dtype=torch.bfloat16,   # halves memory vs fp32 (with quality retained on modern GPUs)
    device_map="auto",            # spread across all GPUs, or CPU-offload if needed
    low_cpu_mem_usage=True,       # don't spike RAM loading weights in fp32 first
)

Rough on-disk rules of thumb:

Parameters fp32 bf16 Int8 (bitsandbytes) Int4 (bitsandbytes)
1B 4 GB 2 GB 1 GB 0.5 GB
7B 28 GB 14 GB 7 GB 3.5 GB
13B 52 GB 26 GB 13 GB 6.5 GB
70B 280 GB 140 GB 70 GB 35 GB

Add the KV cache (which grows with input + output length) on top of the weights number. That’s why a 70B in fp32 “fits” nowhere useful, while a 7B at Int4 runs inside 8 GB of VRAM for modest contexts.

Don’t forget decoding memory

The generate call allocates KV cache proportional to (input + output tokens) × layers × heads × head_dim. For a long-context document-extraction job, the KV cache can be a bigger consumer than the weights. Shorten max_new_tokens, trim max_length, and keep contexts bounded unless the workload genuinely needs them. This is the same memory reality that drives prefix caching in serving.

Picking Production Tooling vs. Raw transformers

transformers in Python is the right tool for prototyping, batch jobs, and fine-tuning. It is not the high-throughput serving answer. When the model is going to be hit by real traffic:

  • vLLM (PagedAttention, continuous batching, prefix caching) — this is what the sibling serving posts are about.
  • Text Generation Inference (TGI) from Hugging Face — a purpose-built LLM server with a compatible API.
  • ONNX / TensorRT — for encoder models (BERT-family embeddings) you can freeze and serve at low latency.

Use transformers to validate the model and build the pipeline; move to vLLM/TGI the moment concurrency matters.

# Validate weights and a prompt quickly before committing to a serving stack.
pip install torch transformers accelerate bitsandbytes
# The universal test: can I load it, run one generation, and free it?
import gc, torch
from transformers import AutoModelForCausalLM, AutoTokenizer

name = "mistralai/Mistral-7B-Instruct-v0.3"
tok = AutoTokenizer.from_pretrained(name)
model = AutoModelForCausalLM.from_pretrained(
    name, torch_dtype=torch.bfloat16, device_map="auto"
)
ids = tok("Hello!", return_tensors="pt").to(model.device)
out = model.generate(**ids, max_new_tokens=16)
print(tok.decode(out[0], skip_special_tokens=True))
model.to("meta"); gc.collect()   # release VRAM when done

The Decision Cheat-Sheet

What you’re building Start with Why
Semantic search / embeddings Sentence-BERT (sentence-transformers) on a BERT/RoBERTa base Dense vector per text, mature ecosystem
Text classification / NER RoBERTa or DistilBERT Best accuracy-per-cost for encoders
Summarization BART Tight, fluent summaries out of the box
Translation + generation mix T5 Text-to-text framing covers all tasks
General chat on a GPU box Llama-3.1-8B-Instruct or Mistral-7B Well-supported, best tooling
Chat on a laptop / permissive license Gemma-2 or Phi-3 Small enough to run locally
Multilingual / code generation Qwen2.5 Strong non-English + coding coverage
Serving at high concurrency Move to vLLM / TGI, not raw transformers Paged attention and batching

Summary

  • “Most used” splits into two families: encoders (BERT / RoBERTa / DistilBERT) for embeddings and classification, and decoders (Llama / Mistral / Gemma / Qwen / Phi) for chat and generation.
  • T5 and BART cover the seq2seq middle: summarization, translation, and text-to-text.
  • The transformers API is nearly identical across all of them — swapping in a model is usually just changing the checkpoint name.
  • Match torch_dtype, device_map, and quantized bits to your VRAM plus the KV cache; don’t load fp32 unless you have to.
  • Prototype with transformers, but serve production traffic with vLLM or TGI.

Pick the model by what it must do and what hardware you own, not by bytes on a leaderboard. The downloads are a popularity signal; your latency and memory budget are the actual constraints.

Comments

Leave a comment

What is 2 + 3?
Please solve the arithmetic question above to verify you're human.