Mục lục
- Mục tiêu bài học
- Vì sao cần Auto class
- Các Auto class thường dùng
- Workflow 3 bước
- Tokenizer methods
- Output của tokenizer
- Padding và truncation
- Special tokens
- Chat template
- Tham số from_pretrained
- Inspect model
- Model config
- Custom forward
- ModelOutput
- Save và load locally
- Architecture class
- Embedding extraction
- Switch model
- Pipeline vs AutoModel
- Pitfall
- Code Python
- Bài tập
- Tóm tắt
Mục tiêu bài học
Sau bài học, bạn sẽ:
- Hiểu pattern Auto class và lý do tồn tại: viết một lần, dùng cho nhiều kiến trúc khác nhau.
- Biết chọn đúng Auto class cho task (causal LM, seq2seq, classification, MLM, image, audio).
- Thuộc workflow 3 bước:
from_pretrained→ tokenize → forward / generate. - Phân biệt các method
tokenize,encode,decode,__call__của tokenizer. - Dùng được
padding,truncation,apply_chat_template. - Hiểu các tham số quan trọng của
from_pretrained:torch_dtype,device_map,revision,trust_remote_code. - Inspect model: config, số tham số, kiến trúc layer.
- Viết custom forward thay vì
generatekhi cần control sampling thấp cấp. - Tránh các pitfall: thiếu
pad_token, quênmodel.eval(), sai chat template.
Vì sao cần Auto class
Mỗi kiến trúc trong transformers có một class riêng: LlamaForCausalLM, MistralForCausalLM, Qwen2ForCausalLM, BertForSequenceClassification, T5ForConditionalGeneration… Nếu code hard-code tên class, đổi model là phải sửa import + class name.
Auto class giải bài này theo cơ chế factory:
- Bạn truyền tên repo hoặc đường dẫn local vào
AutoModelForCausalLM.from_pretrained(...). - Thư viện đọc file
config.jsontrong repo, lấy trườngmodel_type(vd"llama","mistral","qwen2"). - Mapping nội bộ trỏ
"llama" → LlamaForCausalLM,"mistral" → MistralForCausalLM, v.v. — class thật được khởi tạo phía sau.
Kết quả: cùng một dòng code chạy được cho mọi kiến trúc tương ứng task. Code portable theo nghĩa đổi tên model là đổi xong, không cần thay class.
Các Auto class thường dùng
Chọn Auto class theo task, không theo kiến trúc:
AutoTokenizer— load tokenizer khớp với model.AutoModel— base model không có task head, output là hidden states. Dùng cho embedding hoặc làm backbone.AutoModelForCausalLM— text generation decoder-only (GPT, Llama, Mistral, Qwen, Phi, Gemma).AutoModelForSeq2SeqLM— seq2seq encoder-decoder (T5, BART, mT5, FLAN-T5). Dùng cho summarization, translation.AutoModelForSequenceClassification— classification toàn câu (sentiment, NLI, intent).AutoModelForTokenClassification— label từng token (NER, POS tagging).AutoModelForQuestionAnswering— extractive QA (SQuAD style).AutoModelForMaskedLM— masked language modeling (BERT, RoBERTa).AutoModelForImageClassification— ViT, ConvNeXt, Swin… cho phân loại ảnh.AutoModelForCTC— ASR theo CTC loss (wav2vec2).AutoFeatureExtractor/AutoImageProcessor— preprocess cho image/audio (thay vai trò tokenizer).
Mỗi Auto class chỉ load checkpoint tương thích. Vd dùng AutoModelForCausalLM với bert-base-uncased sẽ báo lỗi vì BERT là encoder, không có LM head causal.
Workflow 3 bước
Cấu trúc chuẩn cho mọi bài toán text generation:
from transformers import AutoTokenizer, AutoModelForCausalLM
# 1. Load tokenizer + model
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.2-1B")
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.2-1B")
# 2. Encode input
inputs = tokenizer("Hello, AI!", return_tensors="pt")
# 3. Forward / Generate
outputs = model.generate(**inputs, max_new_tokens=30)
text = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(text)
Ba bước này lặp lại cho gần như mọi pipeline causal LM. Phần lớn complexity ở thực tế nằm ở cấu hình (dtype, device, batch, sampling) chứ không phải ở 3 bước trên.
Tokenizer methods
Tokenizer có nhiều method, mỗi cái cho một mục đích:
tokenizer.tokenize(text)— text → list các token string (debug, xem cách model cắt từ).tokenizer.encode(text)— text → list các token ID (int). Không trả attention mask.tokenizer.decode(ids)— list ID → text. Tham sốskip_special_tokens=Trueđể loại bỏ BOS, EOS, PAD trong output.tokenizer(text, ...)(__call__) — đầy đủ nhất: trả dict gồminput_ids,attention_mask(vàtoken_type_idsnếu có), hỗ trợreturn_tensors,padding,truncation.tokenizer.batch_decode(ids_batch)— decode cả batch cùng lúc.
Trong code production thường chỉ dùng __call__ và decode / batch_decode. Các method còn lại hữu ích khi debug hoặc thao tác thấp cấp.
Output của tokenizer
Khi gọi tokenizer(text, return_tensors="pt"), output là dict (chính xác là BatchEncoding):
input_ids— tensor shape(batch, seq_len)chứa token ID.attention_mask— tensor cùng shape:1cho token thực,0cho padding.token_type_ids— chỉ có với BERT-style (phân biệt segment A / B), không có ở Llama, Mistral.
Khi forward, chuyển cả dict vào model bằng **inputs; model chỉ lấy field nó cần, bỏ qua field thừa. Tham số return_tensors có thể là "pt" (PyTorch), "tf" (TensorFlow), "np" (NumPy); để mặc định trả Python list.
Padding và truncation
Batch input phải cùng độ dài → cần padding. Câu quá dài → cần truncation. Cú pháp:
texts = ["Hello", "How are you today?", "AI engineering."]
inputs = tokenizer(
texts,
padding=True, # pad đến độ dài câu dài nhất trong batch
truncation=True, # cắt bớt nếu quá max_length
max_length=512,
return_tensors="pt",
)
print(inputs["input_ids"].shape) # (3, seq_len)
print(inputs["attention_mask"].shape) # (3, seq_len)
Các giá trị cho padding:
Truehoặc"longest"— pad tới câu dài nhất trong batch (mặc định khi bật padding)."max_length"— pad tớimax_lengthcố định (thuận lợi cho compile / TorchScript).False— không pad.
attention_mask đảm bảo padding không ảnh hưởng đến attention score; trong gần như mọi trường hợp nên truyền mask này vào model.
Special tokens
Mỗi tokenizer có một số token đặc biệt:
tokenizer.bos_token— beginning of sequence.tokenizer.eos_token— end of sequence.tokenizer.pad_token— padding.tokenizer.unk_token— unknown.- BERT có thêm
cls_token,sep_token,mask_token.
Vài model decoder-only (GPT-2, Llama base) không có pad_token mặc định — khi batch hoặc gọi generate nhiều câu sẽ lỗi. Quy ước phổ biến là tái sử dụng eos_token làm pad:
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
tokenizer.pad_token_id = tokenizer.eos_token_id
Lưu ý: cấu hình này ảnh hưởng cả generate; đảm bảo loss tính lúc training mask đúng pad_token_id để không học từ padding.
Chat template
Mỗi model instruct dùng một chat format riêng: Llama 3 dùng <|begin_of_text|> + <|start_header_id|>, Mistral dùng [INST] ... [/INST], Qwen dùng <|im_start|>… Viết tay format này dễ sai. Tokenizer có sẵn template lưu trong tokenizer.chat_template:
messages = [
{"role": "system", "content": "You are helpful."},
{"role": "user", "content": "Hello!"},
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True,
)
print(text)
Các tham số quan trọng:
tokenize=False— trả string đã format (để xem hoặc gửi qua API).Truetrả token ID.add_generation_prompt=True— thêm phần mở đầu cho lượt assistant (cần khi generate). Khi training, đểFalse.return_tensors="pt"— kết hợp vớitokenize=Trueđể có sẵn tensor.
Dùng template từ tokenizer thay vì viết tay là cách an toàn nhất để không nhầm format khi đổi model.
Tham số from_pretrained
Vài tham số hay dùng:
revision="main"— chọn branch / tag / commit cụ thể. Pin revision cho production để inference ổn định.cache_dir="./cache"— đổi vị trí cache (mặc định~/.cache/huggingface).trust_remote_code=False— chỉ bật khi tin tưởng repo; nhiều model custom yêu cầu chạy code Python từ repo, có rủi ro bảo mật.torch_dtype=torch.bfloat16— load thẳng dưới dạng bf16 / fp16, tiết kiệm một nửa VRAM so với fp32. Trên GPU mới nên ưu tiên bf16.device_map="auto"—acceleratetự phân chia layer lên GPU / CPU / disk. Cần thiết khi model lớn hơn VRAM một thiết bị.low_cpu_mem_usage=True— load incrementally, không giữ 2 bản trên RAM lúc init.quantization_config=...— load model 4-bit / 8-bit (quabitsandbytes) — sẽ deep-dive ở Module 8.
import torch
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen2.5-1.5B-Instruct",
torch_dtype=torch.bfloat16,
device_map="auto",
low_cpu_mem_usage=True,
)
Inspect model
Khi load xong, có vài cách kiểm tra model:
print(model) # tóm tắt kiến trúc layer
print(model.config) # toàn bộ config
print(sum(p.numel() for p in model.parameters())) # tổng số param
print(sum(p.numel() for p in model.parameters() if p.requires_grad)) # param trainable
print(next(model.parameters()).dtype, next(model.parameters()).device)
In model ra cho phép soi từng layer: bao nhiêu transformer block, dimension, MLP intermediate size, attention head. Hữu ích khi cần freeze một số layer hoặc nối thêm head custom.
Model config
model.config chứa toàn bộ siêu tham số đã đọc từ config.json. Một số trường hay dùng:
config.hidden_size— dimension của embedding (vd 2048, 4096).config.num_attention_heads— số head trong multi-head attention.config.num_hidden_layers— số transformer block.config.vocab_size— size vocabulary tokenizer.config.max_position_embeddings— context length tối đa model được train.config.model_type— định danh kiến trúc ("llama","mistral","qwen2"…).
Trường max_position_embeddings đặc biệt quan trọng — vượt quá ngưỡng này không có nghĩa code crash ngay, nhưng chất lượng output thường suy giảm rõ rệt.
Custom forward
generate tiện nhưng đóng kín. Khi cần control thấp cấp (custom sampling, beam search tự code, constrained decoding), gọi forward trực tiếp:
import torch
model.eval()
with torch.no_grad():
outputs = model(**inputs)
logits = outputs.logits # (batch, seq_len, vocab_size)
last_token_logits = logits[:, -1, :] # logit của token cuối
next_token = last_token_logits.argmax(dim=-1) # greedy
print(tokenizer.decode(next_token))
Hai dòng cần nhớ:
model.eval()— tắt dropout / batchnorm training mode. Quên dòng này → output có ngẫu nhiên không cần thiết.torch.no_grad()— không lưu graph backward, giảm VRAM khi inference.
Trên GPU, thêm inputs = {k: v.to(model.device) for k, v in inputs.items()} trước khi forward để tensor cùng device với model.
ModelOutput
Output của model là một subclass của ModelOutput — namespace + ordered dict. Các field tuỳ task:
logits— cho mọi LM (causal, MLM, seq2seq). Shape(batch, seq, vocab).last_hidden_state— cho base model (AutoModel). Shape(batch, seq, hidden).hidden_states— list hidden state từng layer; chỉ có khi truyềnoutput_hidden_states=Truekhi forward.attentions— attention weight từng layer; chỉ có khi truyềnoutput_attentions=True.past_key_values— KV cache, để generate tăng tốc token-by-token.
Truy cập bằng cả attribute (outputs.logits) lẫn key (outputs["logits"]). Bật output_hidden_states và output_attentions chỉ khi cần — tăng VRAM rõ rệt.
Save và load locally
Sau khi fine-tune, hoặc khi muốn pin một bản model cho production, lưu local:
model.save_pretrained("./my_model")
tokenizer.save_pretrained("./my_model")
Thư mục ./my_model sẽ chứa config.json, model.safetensors (hoặc .bin), tokenizer.json, tokenizer_config.json, special tokens map… Load lại y nguyên cách dùng repo Hub:
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("./my_model")
tokenizer = AutoTokenizer.from_pretrained("./my_model")
safetensors là format mặc định từ transformers 4.x — load nhanh, an toàn hơn pickle (không exec code khi load).
Architecture class
Alternative của Auto: import thẳng class kiến trúc.
from transformers import LlamaForCausalLM, BertForSequenceClassification
model = LlamaForCausalLM.from_pretrained("meta-llama/Llama-3.2-1B")
clf = BertForSequenceClassification.from_pretrained("bert-base-uncased")
Cùng functionality. Khác biệt:
- Auto — portable, đổi model name không sửa code. Khuyến nghị cho phần lớn use case.
- Architecture class — tường minh về kiến trúc, IDE auto-complete chính xác hơn, dễ subclass.
Khi viết thư viện hoặc tutorial generic, dùng Auto. Khi viết research code chuyên cho một kiến trúc cụ thể, dùng class architecture cho rõ ý.
Embedding extraction
Không phải lúc nào cũng cần generate; nhiều bài toán cần embedding (semantic search, clustering, classification head riêng). Dùng AutoModel (không head):
import torch
from transformers import AutoModel, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModel.from_pretrained("bert-base-uncased")
model.eval()
inputs = tokenizer(
["Câu thứ nhất.", "Câu thứ hai dài hơn một chút."],
padding=True,
truncation=True,
return_tensors="pt",
)
with torch.no_grad():
outputs = model(**inputs)
# Mean pooling token embedding theo attention mask
token_emb = outputs.last_hidden_state # (batch, seq, hidden)
mask = inputs["attention_mask"].unsqueeze(-1) # (batch, seq, 1)
sentence_emb = (token_emb * mask).sum(1) / mask.sum(1).clamp(min=1)
print(sentence_emb.shape) # (2, 768)
Mean pooling theo attention mask là baseline đơn giản, vẫn ổn cho nhiều task. Khi cần chất lượng cao hơn, dùng model đã train chuyên cho embedding (sentence-transformers, BGE, E5) sẽ tốt hơn BERT thuần.
Switch model
Ưu điểm rõ nhất của Auto pattern: đổi model name là xong. Cùng một file code chạy được nhiều kiến trúc:
from transformers import AutoTokenizer, AutoModelForCausalLM
# Đổi giá trị này để switch model
model_name = "Qwen/Qwen2.5-1.5B-Instruct"
# model_name = "meta-llama/Llama-3.2-1B-Instruct"
# model_name = "microsoft/Phi-3.5-mini-instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)
Lưu ý: dù code không đổi, prompt format và chat template giữa các model khác nhau. Khi switch nên test lại chất lượng output trên benchmark riêng của bạn, không assume một model thay thế hoàn toàn được model kia.
Pipeline vs AutoModel
Hai layer trong cùng thư viện, dùng khi nào:
- Pipeline (Bài 17) — 2-3 dòng code, ẩn tokenizer + model + post-process. Phù hợp: prototype, demo, smoke test, jupyter notebook khám phá.
- AutoModel + AutoTokenizer (bài này) — control đầy đủ: chọn dtype, device, sampling, batch shape, custom forward, extract intermediate state. Phù hợp: production, fine-tune, embedding pipeline, agent / RAG.
Trong codebase thực tế, thường thấy cả hai: pipeline cho script test nhanh, AutoModel cho service production. Hai layer dùng chung cùng một config.json nên switch giữa hai khi cần không phải viết lại.
Pitfall
- Quên
pad_tokenvới GPT-2 / Llama base → batch vàgeneratenhiều câu crash. Settokenizer.pad_token = tokenizer.eos_tokentrước khi batch. - Chọn sai Auto class — vd dùng
AutoModelForCausalLMvới BERT (encoder-only) → lỗi load. Tham khảo lại Bước 3 chọn theo task. - Quên
model.eval()khi inference → dropout vẫn active, output không deterministic. - Quên
torch.no_grad()→ VRAM phình do giữ graph backward. - Quên chuyển tensor lên cùng device với model khi dùng
device_map→ lỗi expected all tensors to be on the same device. - Viết tay chat format thay vì
apply_chat_template→ sai một dấu là output suy giảm rõ rệt, khó debug. - Bật
trust_remote_code=Truebừa với repo không quen → rủi ro bảo mật. - Load model lớn fp32 trên GPU 8 GB → OOM ngay. Dùng
torch_dtype=torch.bfloat16hoặc quantization.
Code Python
1) Load Qwen 2.5-1.5B và generate manual (không dùng pipeline):
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
model_name = "Qwen/Qwen2.5-1.5B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.bfloat16,
device_map="auto",
)
messages = [
{"role": "system", "content": "Bạn là trợ lý ngắn gọn."},
{"role": "user", "content": "Giới thiệu Hugging Face trong 2 câu."},
]
prompt = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True,
)
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
with torch.no_grad():
output_ids = model.generate(
**inputs,
max_new_tokens=120,
do_sample=False,
)
# Chỉ decode phần token mới sinh ra
new_tokens = output_ids[0, inputs["input_ids"].shape[1]:]
print(tokenizer.decode(new_tokens, skip_special_tokens=True))
2) Extract embedding từ BERT:
import torch
from transformers import AutoTokenizer, AutoModel
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModel.from_pretrained("bert-base-uncased")
model.eval()
sentences = [
"Transformers are a type of neural network.",
"Bananas are yellow fruits.",
"Attention is all you need.",
]
inputs = tokenizer(sentences, padding=True, truncation=True, return_tensors="pt")
with torch.no_grad():
outputs = model(**inputs)
mask = inputs["attention_mask"].unsqueeze(-1).float()
emb = (outputs.last_hidden_state * mask).sum(1) / mask.sum(1).clamp(min=1)
print("embedding shape:", emb.shape) # (3, 768)
3) Switch sang Llama 3.2-1B — chỉ đổi model_name (cần đã accept terms + login):
model_name = "meta-llama/Llama-3.2-1B-Instruct" # chỉ đổi dòng này
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.bfloat16,
device_map="auto",
)
# phần còn lại ở snippet (1) chạy nguyên xi
4) In config và đếm param:
cfg = model.config
print(cfg.model_type, cfg.hidden_size, cfg.num_hidden_layers, cfg.num_attention_heads)
print("max ctx:", cfg.max_position_embeddings, "vocab:", cfg.vocab_size)
print("total params:", sum(p.numel() for p in model.parameters()))
Bài tập
Bài 1 — Load và inspect. Chọn một model size nhỏ (Qwen/Qwen2.5-0.5B, microsoft/Phi-3.5-mini-instruct, hoặc HuggingFaceTB/SmolLM2-360M-Instruct). Load bằng AutoModelForCausalLM. In: model_type, hidden_size, num_hidden_layers, num_attention_heads, vocab_size, max_position_embeddings, tổng số tham số.
Bài 2 — Encode batch. Encode 3 câu sau với padding=True, truncation=True, max_length=64: "Học AI thật thú vị.", "Transformers giúp xử lý ngôn ngữ.", "Một câu rất ngắn.". In shape của input_ids và attention_mask. Decode lại 3 câu bằng batch_decode, so sánh với gốc.
Bài 3 — Chat template. Tạo list 5 messages xen kẽ system / user / assistant / user / assistant. Apply chat template với cả add_generation_prompt=True và False. Quan sát khác biệt giữa hai chuỗi kết quả, ghi lại token đặc biệt mà template của model bạn dùng (Llama, Qwen, Phi mỗi loại khác nhau).
Bài 4 — Embedding 1 câu. Dùng AutoModel với bert-base-uncased hoặc sentence-transformers/all-MiniLM-L6-v2. Encode câu "AI engineering is exciting.", lấy last_hidden_state, mean-pool theo attention mask. In shape vector kết quả. Sau đó tính cosine similarity với câu "Machine learning is fun." — kỳ vọng giá trị tương đối cao.
Bài 5 — Custom forward. Load 1 model causal LM nhỏ. Encode "The capital of France is". Forward (không dùng generate), lấy logits[:, -1, :], in top-5 token có logit cao nhất bằng torch.topk + tokenizer.decode. Kiểm tra "Paris" có nằm trong top không.
Tóm tắt
- Auto class = factory tự nhận kiến trúc từ
config.json, giúp code portable giữa các model. - Chọn Auto class theo task:
AutoModelForCausalLMcho generation,AutoModelForSeq2SeqLMcho seq2seq,AutoModelForSequenceClassificationcho classification,AutoModelForMaskedLMcho BERT,AutoModelForCTCcho ASR,AutoModelcho embedding. - Workflow 3 bước:
from_pretrained→ tokenize → forward / generate. - Tokenizer có 4 method chính:
tokenize,encode,decode,__call__; production chủ yếu dùng__call__. - Output tokenizer là dict với
input_ids,attention_mask(đôi khitoken_type_ids). padding=True+truncation=True+max_lengthlà combo chuẩn cho batch.- Special tokens:
bos,eos,pad,unk; GPT-2 / Llama base không cópad_tokenmặc định. - Chat template (
apply_chat_template) là cách an toàn nhất để format hội thoại cho model instruct. - Tham số
from_pretrainedquan trọng:revision,torch_dtype,device_map,trust_remote_code,low_cpu_mem_usage. - Inspect model:
print(model),model.config, đếm param quaparameters(). - Custom forward (
model.eval()+torch.no_grad()) cho control thấp cấp; output làModelOutputvớilogits/last_hidden_state/hidden_states/attentions. save_pretrained+from_pretrainedlocal — pin model cho production.- Pipeline cho prototype, AutoModel cho production và fine-tune.
- Pitfall hay gặp: thiếu
pad_token, quêneval(), viết tay chat format, bậttrust_remote_codebừa, load fp32 OOM. - Bài 19 chuyển sang chạy SLM local với cấu hình thực tế (Phi-3.5, Llama-3.2-1B, Qwen 2.5 1.5B).
- transformers - Auto Classes Documentation
- transformers - Tokenizer Documentation
- transformers - PreTrainedModel Documentation
- transformers - PretrainedConfig Documentation
- transformers - Model Outputs Documentation
- transformers - Chat Templating Guide
- transformers - Generation Documentation
- transformers - Loading Big Models (device_map)
- safetensors Documentation
- accelerate - Big Model Inference
- Qwen2.5-1.5B-Instruct Model Card
- Llama-3.2-1B-Instruct Model Card
- Phi-3.5-mini-instruct Model Card
- bert-base-uncased Model Card
