- Published on
Day 15: Hugging Face Ecosystem
- Authors

- Name
- Trần Mạnh Thắng
- @TranManhThang96
Mục tiêu
Sau bài này, bạn cần làm được các việc sau:
- Hiểu vai trò của
transformers,datasets,tokenizers,accelerate, Model Hub và model card. - Biết load tokenizer/model bằng
AutoTokenizer,AutoModel,AutoModelForSequenceClassification. - Biết dùng
pipelinecho prototype và raw model inference cho production control. - Biết dùng
datasetsđể load data, split data,maptokenizer theo batch và chuẩn bị input choTrainer. - Biết khi nào dùng
Trainer API, khi nào cần custom training loop vớiaccelerate. - Biết đọc model card như review một third-party dependency trước khi đưa vào production.
- Viết được inference wrapper có model/tokenizer loading, device handling, batching, truncation, error handling và output schema rõ ràng.
TL;DR
Hugging Face là ecosystem giúp bạn dùng model AI giống cách Senior Software Engineer dùng package registry, artifact registry và SDK. transformers cung cấp model/tokenizer API, datasets xử lý data pipeline, tokenizers là lõi encode text thành token IDs, accelerate giúp chạy PyTorch code trên CPU/GPU/multi-GPU dễ hơn, Model Hub là nơi lưu model artifact, còn model card là tài liệu rủi ro và contract của model.
Trong production, không nên chỉ gọi from_pretrained() rồi deploy. Bạn cần pin model_id và revision, đọc license, kiểm tra intended use, benchmark latency/memory, kiểm soát tokenizer/model version, log model version, có fallback/rollback và không bật trust_remote_code=True nếu chưa audit.
1. Day 15 Nằm Ở Đâu Trong Phase 2
Day 14 đã giải thích Transformer architecture: encoder-only như BERT/PhoBERT, decoder-only như GPT/LLaMA/Qwen, encoder-decoder như T5. Day 16 sẽ fine-tune PhoBERT/BERT classifier.
Day 15 trả lời câu hỏi thực dụng ở giữa:
Đã hiểu Transformer rồi.
Làm sao lấy model thật, tokenizer thật, dataset thật, train/infer thật và deploy có kiểm soát?
Với góc nhìn Senior SE:
Transformer architecture = runtime engine concept
Hugging Face ecosystem = package registry + artifact registry + SDK + data pipeline + training/runtime tooling
2. Mental Model: Hugging Face Như Artifact Platform
| Hugging Face concept | SE equivalent | Ý nghĩa production |
|---|---|---|
| Model Hub | Docker Hub, npm, Maven registry | Nơi lấy model artifact, config, tokenizer, model card |
| Model checkpoint | Build artifact | Version có thể deploy, rollback, audit |
| Revision/commit SHA | Image digest, package lock | Pin để reproducible |
| Model card | README + risk note + API contract | Kiểm tra license, intended use, limitation, metrics |
transformers | SDK/client library | Load model, tokenizer, pipeline, Trainer |
datasets | Data pipeline/cache layer | Load, split, transform, cache dataset |
tokenizers | Parser/encoder runtime | Text contract trước khi vào model |
accelerate | Runtime launcher/device abstraction | Chạy cùng code trên CPU, GPU, multi-GPU, mixed precision |
Một AI feature production thường có dependency graph như sau:
business API
-> preprocessing
-> tokenizer version
-> model config
-> model weights revision
-> postprocessing label mapping
-> monitoring
-> rollback path
Nếu tokenizer đổi nhưng model không đổi, chất lượng có thể hỏng. Nếu model đổi nhưng label mapping không đổi đúng, API vẫn trả JSON hợp lệ nhưng business decision sai. Vì vậy model không chỉ là một file weights, mà là một bundle gồm weights, tokenizer, config, preprocessing, postprocessing và governance.
3. Model Hub Và Model Card
Model Hub là nơi bạn tìm model như bert-base-uncased, distilbert-base-uncased-finetuned-sst-2-english, vinai/phobert-base, embedding model, reranker model hoặc text generation model.
Trước khi dùng một model, cần đọc model card như review dependency bên ngoài.
Checklist đọc model card
| Mục cần kiểm tra | Câu hỏi cần trả lời | Production impact |
|---|---|---|
| License | Có được dùng commercial/internal không? Có điều kiện attribution không? | Legal/compliance |
| Intended use | Model được thiết kế cho task nào? Classification, embedding, generation, reranking? | Tránh dùng sai task |
| Limitations | Model yếu ở domain/ngôn ngữ/input nào? | Risk chất lượng |
| Language | Có hỗ trợ tiếng Việt không? Có cần word segmentation không? | Fit với user data |
| Dataset | Train/eval trên dataset nào? Có gần domain của mình không? | Generalization |
| Metrics | Metric nào, split nào, benchmark nào? | So sánh có cơ sở |
| Safety | Có bias, toxicity, privacy, misuse note không? | Risk vận hành |
| Inference requirements | Cần GPU không? VRAM bao nhiêu? Max sequence length? Có cần trust_remote_code không? | Cost/security/deployment |
Quy tắc ngắn: không deploy model nếu không rõ license, source, version, owner, intended use và rollback path.
4. tokenizers: Tokenizer Là Input Contract
Tokenizer biến text thành integer IDs để model xử lý:
"sản phẩm tốt" -> [0, 1234, 567, 89, 2]
Trong production, tokenizer giống parser ở API boundary:
- Parser đổi thì input semantic vào model đổi.
- Train dùng tokenizer A nhưng serve dùng tokenizer B thì quality có thể giảm mạnh.
max_lengthquá ngắn làm mất thông tin vì truncation.max_lengthquá dài làm latency và memory tăng, vì attention thường tăng theo độ dài sequence.- Padding strategy ảnh hưởng throughput khi batching.
Các tham số quan trọng khi dùng tokenizer:
encoded = tokenizer(
texts,
padding=True,
truncation=True,
max_length=128,
return_tensors="pt",
)
Ý nghĩa:
padding=True: pad các sample trong batch về cùng chiều dài để tensor hóa.truncation=True: cắt input vượt quámax_lengthhoặc giới hạn model.max_length=128: giới hạn token cho latency/memory predictable.return_tensors="pt": trả PyTorch tensors.
Với tiếng Việt, cần kiểm tra model yêu cầu preprocessing gì. Một số model như PhoBERT historically thường đi kèm giả định về word segmentation ở một số workflow. Nếu train preprocessing và serving preprocessing khác nhau, bug sẽ khó thấy bằng unit test thông thường nhưng metric production sẽ giảm.
5. transformers: Auto Classes, Pipeline Và Raw Model
transformers cung cấp API thống nhất cho nhiều architecture. Bạn thường bắt đầu bằng Auto Classes:
from transformers import AutoModelForSequenceClassification, AutoTokenizer
model_id = "distilbert-base-uncased-finetuned-sst-2-english"
revision = "main"
tokenizer = AutoTokenizer.from_pretrained(model_id, revision=revision, use_fast=True)
model = AutoModelForSequenceClassification.from_pretrained(model_id, revision=revision)
AutoTokenizer
AutoTokenizer đọc tokenizer config từ model repo và trả về tokenizer phù hợp. Đây là cách an toàn hơn việc đoán tokenizer class thủ công.
AutoModel
AutoModel load backbone model và thường trả hidden states, chưa có task head. Dùng khi bạn cần embedding, feature extraction hoặc build head riêng.
from transformers import AutoModel, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModel.from_pretrained("bert-base-uncased")
Task-specific model
Với classification, nên dùng task-specific class:
from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained(model_id)
Lý do: class này biết output schema cho classification, có logits, có thể có id2label/label2id trong config và tích hợp tốt với Trainer.
6. pipeline: Nhanh Cho Prototype
pipeline gom tokenizer, model, preprocessing và postprocessing vào một interface đơn giản:
from transformers import pipeline
classifier = pipeline(
"text-classification",
model="distilbert-base-uncased-finetuned-sst-2-english",
)
print(classifier(["This product is great.", "The delivery was terrible."]))
Nên dùng pipeline khi:
- Demo nhanh.
- Notebook exploration.
- Internal script nhỏ.
- Batch job đơn giản chưa cần latency SLA chặt.
Không nên xem pipeline là production architecture mặc định nếu bạn cần:
- Custom request/response schema.
- Batching theo traffic thật.
- Error handling rõ.
- Timeout/fallback.
- Observability theo model version/input length/latency.
- Kiểm soát device, dtype, quantization, warmup.
7. Raw Model Inference: Đường Production-Controlled
Raw model path cho bạn kiểm soát rõ từng bước:
validate input
-> batch texts
-> tokenize with truncation
-> move tensors to device
-> model forward under no_grad/inference_mode
-> softmax/postprocess
-> return stable JSON schema
-> log metrics without leaking PII
Ví dụ dưới đây là wrapper gần production cho text classification. Nó không thay thế full model server, nhưng có các điểm cốt lõi: load một lần, pin revision, device handling, batching, truncation, output schema, latency, token count và error handling.
from __future__ import annotations
import logging
import time
from dataclasses import dataclass
from typing import Iterable
import torch
from transformers import AutoModelForSequenceClassification, AutoTokenizer
logger = logging.getLogger(__name__)
class ModelLoadError(RuntimeError):
pass
class InferenceInputError(ValueError):
pass
@dataclass(frozen=True)
class ClassifierConfig:
model_id: str = "distilbert-base-uncased-finetuned-sst-2-english"
revision: str = "main"
max_length: int = 128
batch_size: int = 16
use_fast_tokenizer: bool = True
local_files_only: bool = False
@dataclass(frozen=True)
class Prediction:
label: str
confidence: float
token_count: int
@dataclass(frozen=True)
class BatchResult:
predictions: list[Prediction]
model_id: str
revision: str
device: str
latency_ms: float
def pick_device() -> torch.device:
if torch.cuda.is_available():
return torch.device("cuda")
if hasattr(torch.backends, "mps") and torch.backends.mps.is_available():
return torch.device("mps")
return torch.device("cpu")
def chunked(items: list[str], size: int) -> Iterable[list[str]]:
for start in range(0, len(items), size):
yield items[start : start + size]
class TextClassifier:
def __init__(self, config: ClassifierConfig):
self.config = config
self.device = pick_device()
try:
self.tokenizer = AutoTokenizer.from_pretrained(
config.model_id,
revision=config.revision,
use_fast=config.use_fast_tokenizer,
local_files_only=config.local_files_only,
)
self.model = AutoModelForSequenceClassification.from_pretrained(
config.model_id,
revision=config.revision,
local_files_only=config.local_files_only,
)
except Exception as exc:
raise ModelLoadError(f"Cannot load model/tokenizer for {config.model_id}") from exc
self.model.to(self.device)
self.model.eval()
def predict(self, texts: list[str]) -> BatchResult:
if not texts:
raise InferenceInputError("texts must not be empty")
if any(not isinstance(text, str) or not text.strip() for text in texts):
raise InferenceInputError("each text must be a non-empty string")
started = time.perf_counter()
predictions: list[Prediction] = []
try:
for batch in chunked(texts, self.config.batch_size):
encoded = self.tokenizer(
batch,
padding=True,
truncation=True,
max_length=self.config.max_length,
return_tensors="pt",
)
token_counts = encoded["attention_mask"].sum(dim=1).tolist()
encoded = {key: value.to(self.device) for key, value in encoded.items()}
with torch.inference_mode():
outputs = self.model(**encoded)
probs = torch.softmax(outputs.logits, dim=-1)
for row, token_count in zip(probs.detach().cpu(), token_counts):
label_id = int(torch.argmax(row).item())
label = self.model.config.id2label.get(label_id, str(label_id))
confidence = float(row[label_id].item())
predictions.append(
Prediction(
label=label,
confidence=round(confidence, 6),
token_count=int(token_count),
)
)
except RuntimeError:
logger.exception(
"model_inference_failed",
extra={"model_id": self.config.model_id, "revision": self.config.revision},
)
raise
latency_ms = (time.perf_counter() - started) * 1000
return BatchResult(
predictions=predictions,
model_id=self.config.model_id,
revision=self.config.revision,
device=str(self.device),
latency_ms=round(latency_ms, 2),
)
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
classifier = TextClassifier(ClassifierConfig(batch_size=2, max_length=128))
result = classifier.predict(
[
"This product is useful and reliable.",
"The delivery was late and support was terrible.",
]
)
print(result)
Production notes:
- Load model ở startup, không load trong từng request.
- Warm up bằng một request nhỏ trước khi nhận traffic thật.
- Log
model_id,revision, device, latency, token count, label, confidence; tránh log raw PII. - Pin
revisionbằng commit SHA khi cần reproducibility nghiêm túc. - Không dùng
trust_remote_code=Truetrừ khi đã audit repo model như audit dependency chạy code.
8. datasets: Data Pipeline Cho Training Và Evaluation
datasets giúp load dataset từ Hub hoặc local file, convert sang Arrow format/cache và apply transformation hiệu quả.
Ví dụ load CSV local cho Day 16:
from datasets import load_dataset
dataset = load_dataset(
"csv",
data_files={"train": "train.csv", "test": "test.csv"},
)
print(dataset)
print(dataset["train"][0])
Nếu chỉ có một file, tạo split:
from datasets import load_dataset
raw = load_dataset("csv", data_files="reviews.csv")["train"]
split = raw.train_test_split(test_size=0.2, seed=42)
Tokenize theo batch và convert label string sang labels dạng số cho Trainer:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-multilingual-cased")
labels = ["negative", "neutral", "positive"]
label2id = {label: idx for idx, label in enumerate(labels)}
def tokenize_batch(examples):
encoded = tokenizer(
examples["text"],
truncation=True,
max_length=128,
)
encoded["labels"] = [label2id[label] for label in examples["label"]]
return encoded
tokenized = split.map(
tokenize_batch,
batched=True,
remove_columns=["text", "label"],
)
Vì sao batched=True quan trọng:
- Ít overhead Python hơn.
- Tokenizer fast chạy hiệu quả hơn trên list text.
- Dễ giữ preprocessing giống nhau giữa train/eval.
Cache note:
- Datasets cache file đã download và data đã convert để tránh làm lại.
- Nếu đổi preprocessing nhưng thấy output không đổi, kiểm tra cache hoặc dùng tham số phù hợp để force recompute.
- Không commit cache lớn vào repo bài học.
9. Trainer API: Fine-tune Nhanh Cho Task Chuẩn
Trainer là training loop có sẵn cho Transformers model. Nó xử lý nhiều phần lặp lại: train/eval loop, checkpoint, logging, gradient accumulation, mixed precision, distributed training integration và metric callback.
Skeleton cho classification:
import numpy as np
from transformers import (
AutoModelForSequenceClassification,
AutoTokenizer,
DataCollatorWithPadding,
Trainer,
TrainingArguments,
)
model_id = "distilbert-base-multilingual-cased"
labels = ["negative", "neutral", "positive"]
label2id = {label: idx for idx, label in enumerate(labels)}
id2label = {idx: label for label, idx in label2id.items()}
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForSequenceClassification.from_pretrained(
model_id,
num_labels=len(labels),
label2id=label2id,
id2label=id2label,
)
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
def compute_metrics(eval_pred):
logits, label_ids = eval_pred
predictions = np.argmax(logits, axis=-1)
accuracy = (predictions == label_ids).mean()
return {"accuracy": float(accuracy)}
training_args = TrainingArguments(
output_dir="artifacts/day15-checkpoints",
learning_rate=2e-5,
per_device_train_batch_size=8,
per_device_eval_batch_size=16,
num_train_epochs=3,
weight_decay=0.01,
eval_strategy="epoch",
save_strategy="epoch",
logging_steps=20,
load_best_model_at_end=True,
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized["train"],
eval_dataset=tokenized["test"],
processing_class=tokenizer,
data_collator=data_collator,
compute_metrics=compute_metrics,
)
trainer.train()
trainer.save_model("artifacts/day15-final-model")
tokenizer.save_pretrained("artifacts/day15-final-model")
Dùng Trainer khi:
- Task là standard classification, token classification, question answering, language modeling.
- Loss không quá custom.
- Bạn muốn ship baseline fine-tune nhanh.
- Bạn muốn tận dụng logging/checkpoint/mixed precision mà không tự viết nhiều boilerplate.
Không dùng Trainer làm mặc định khi:
- Training loop có nhiều model hoặc nhiều loss đặc biệt.
- Cần RLHF/custom sampling/custom curriculum.
- Cần logic distributed rất riêng.
- Team đã có training framework nội bộ.
10. accelerate: Khi Cần Custom Loop Nhưng Vẫn Muốn Scale
accelerate giúp viết PyTorch loop gần như bình thường, nhưng chạy được trên CPU, một GPU, nhiều GPU hoặc mixed precision với ít thay đổi code.
Minimal pattern:
from accelerate import Accelerator
accelerator = Accelerator(mixed_precision="fp16")
model, optimizer, train_dataloader, scheduler = accelerator.prepare(
model,
optimizer,
train_dataloader,
scheduler,
)
for batch in train_dataloader:
outputs = model(**batch)
loss = outputs.loss
accelerator.backward(loss)
optimizer.step()
scheduler.step()
optimizer.zero_grad()
Điểm cần nhớ:
- Sau
accelerator.prepare(...), model/dataloader/optimizer đã được đặt đúng device/distributed setup. - Dùng
accelerator.backward(loss)thay vìloss.backward(). - Dùng
accelerator.print(...)để tránh nhiều process cùng print. - Dùng
Trainertrước nếu task chuẩn; chuyển sangacceleratekhi bạn cần custom loop nhưng vẫn muốn scale.
11. Trade-off Quan Trọng
| Lựa chọn | Nên dùng khi | Không nên dùng khi | Production note |
|---|---|---|---|
pipeline | Prototype, demo, notebook, batch nhỏ | API có SLA, cần schema/control/observability chặt | Nhanh để học, ít control |
| Raw model inference | Production API, custom batching, custom output | POC quá sớm, team chưa cần control | Cần tự viết postprocess/error handling |
Trainer | Standard fine-tune Transformer | Custom loss/loop phức tạp | Tốt cho v1 và Day 16 |
Custom loop + accelerate | Cần logic training riêng, multi-GPU control | Task chuẩn mà Trainer đã đủ | Tăng flexibility nhưng tăng code |
| Local self-host | Data sensitive, cần kiểm soát cost/latency lâu dài | Team thiếu ops, traffic thấp, GPU đắt | Cần serving, monitoring, scaling |
| Hosted inference | Muốn go-live nhanh, không muốn vận hành GPU | Data nhạy cảm, cost/request cao, cần SLA riêng | Kiểm tra data policy/SLA |
| CPU | Traffic thấp, model nhỏ, cost-sensitive | Realtime high throughput với model lớn | Dễ vận hành, latency cao hơn GPU |
| GPU | Throughput cao, batch tốt, model lớn | Traffic thấp, request rải rác | Cần batching/warmup để đáng tiền |
| Batch size lớn | Tăng throughput, tận dụng GPU | SLA per-request chặt | Tăng queueing latency và memory |
| Batch size nhỏ | Latency thấp, traffic realtime | GPU bị underutilized | Dễ predict latency hơn |
| Quantization | Giảm VRAM/cost, tăng khả năng chạy local | Chưa có regression eval, task quality-sensitive | INT8/INT4 cần benchmark chất lượng |
| Public model license thoáng | Prototype và một số production use | License mơ hồ hoặc hạn chế commercial | Luôn lưu bằng chứng review license |
trust_remote_code=True | Model bắt buộc custom code và đã audit | Chưa audit repo/model owner | Supply-chain risk như chạy code bên thứ ba |
12. Quantization Overview
Quantization là giảm precision của weights/activation, ví dụ từ FP32/FP16 xuống INT8 hoặc INT4, để giảm memory và đôi khi tăng tốc inference.
Tư duy thực tế:
- FP32: dễ tương thích, tốn RAM/VRAM.
- FP16/BF16: phổ biến trên GPU, giảm memory, thường ít giảm chất lượng.
- INT8: thường hợp lý cho CPU/GPU inference nếu có benchmark.
- INT4: tiết kiệm mạnh cho LLM lớn, nhưng cần kiểm tra quality regression kỹ hơn.
Không nên quantize chỉ vì thấy tiết kiệm. Cần đo:
- Accuracy/F1 hoặc metric business trước và sau quantization.
- p50/p95 latency.
- RAM/VRAM peak.
- Throughput theo batch size.
- Error cases có tăng không.
13. Model License Và Security
Model là dependency có thể kéo theo rủi ro:
- License không cho commercial use.
- Dataset train có dữ liệu nhạy cảm hoặc không rõ nguồn.
- Model card thiếu limitation và safety note.
- Model repo yêu cầu custom code.
- Artifact lớn làm cold start lâu.
- Label mapping không rõ.
- Model output có bias hoặc toxic behavior.
Production baseline:
- Pin
model_id,revision, package version. - Mirror artifact vào registry nội bộ nếu cần availability/compliance.
- Scan/audit custom code nếu dùng
trust_remote_code=True. - Có owner rõ cho model.
- Có model card nội bộ cho version đã deploy.
- Có golden test set và rollback plan.
14. Dùng Được Trong Production Không?
Có, Hugging Face ecosystem dùng được trong production, nhưng cần điều kiện rõ:
- Model card đã được review: license, intended use, limitations, language, dataset, metrics, safety, inference requirements.
- Model/tokenizer/config được pin version hoặc revision.
- Inference wrapper load model một lần ở startup, có warmup, batching, truncation và error handling.
- Có benchmark trên hardware thật: p50/p95 latency, throughput, RAM/VRAM, cold start.
- Có evaluation set hoặc golden set đại diện domain thật.
- Có monitoring: latency, error rate, confidence distribution, label distribution, token length, model version.
- Có data policy: không log raw PII, kiểm soát retention và access.
- Có fallback/rollback khi model lỗi hoặc quality regression.
- Có security review nếu model cần custom code hoặc lấy artifact từ nguồn public.
Nếu chỉ dùng notebook gọi pipeline() với model public chưa đọc license, chưa pin revision, chưa benchmark và chưa có monitoring, thì chưa đủ production.
15. Best Practices
- Bắt đầu bằng model nhỏ và baseline đơn giản trước khi chọn model lớn.
- Pin model revision như pin Docker image digest.
- Lưu
model_id,revision,max_length, tokenizer name, label mapping và package versions vào artifact. - Tách preprocessing/tokenization thành module dùng chung giữa train và serve.
- Benchmark với input length thật, không chỉ câu demo ngắn.
- Không log raw text nếu có PII hoặc nội dung khách hàng nhạy cảm.
- Viết model card nội bộ cho model đã fine-tune.
- Dùng
Trainercho v1 nếu task chuẩn; chỉ custom loop khi có lý do kỹ thuật thật. - Review license/security trước khi đưa model public vào hệ thống nội bộ.
- Chuẩn bị Day 16 bằng một sentiment dataset nhỏ, label mapping rõ và split reproducible.
16. Bài Tập Chuẩn Bị Cho Day 16
Trong 60-90 phút:
- Chọn một model classification từ Model Hub.
- Đọc model card theo checklist trong bài.
- Chạy
pipelinevới 5 câu. - Chạy raw model inference bằng wrapper trong bài với cùng 5 câu.
- So sánh output, latency, token count.
- Tạo một CSV nhỏ
text,labelcho sentiment tiếng Việt. - Load CSV bằng
datasets, split train/test và tokenize bằngmap(batched=True). - Ghi lại quyết định: model này có đủ điều kiện production chưa, thiếu gì.
Tự Kiểm Tra
AutoTokenizerkhácAutoModelở đâu?- Vì sao tokenizer là một phần của API contract?
- Khi nào dùng
pipeline, khi nào dùng raw model inference? - Vì sao cần pin
revision? Trainergiải quyết những phần nào của training loop?- Khi nào nên chuyển từ
Trainersang custom loop vớiaccelerate? - Model card cần kiểm tra những mục nào trước production?
- Batch size lớn giúp gì và gây rủi ro gì?
- Quantization nên được quyết định bằng metric nào?
- Điều kiện tối thiểu để dùng Hugging Face model trong production là gì?
Tài liệu
1. Model Card Review Template
Dùng template này trước khi đưa một model từ Model Hub vào thử nghiệm nghiêm túc hoặc production.
# Model Card Review
## Basic information
- Model ID:
- Revision/commit SHA:
- Model family:
- Task:
- Owner/team:
- Review date:
## License
- License:
- Commercial use allowed:
- Attribution requirements:
- Redistribution restrictions:
- Decision: approved / rejected / needs legal review
## Intended use
- Intended task:
- Intended users:
- Intended domain:
- Out-of-scope use:
## Language and locale
- Supported languages:
- Vietnamese support:
- Required preprocessing:
- Tokenizer notes:
## Training/evaluation data
- Training dataset:
- Evaluation dataset:
- Data source clarity:
- Domain match with our data:
- Known data risks:
## Metrics
- Reported metrics:
- Benchmark/split:
- Metric relevant to our use case:
- Missing metrics:
## Limitations
- Known weak domains:
- Max sequence length/context:
- Robustness concerns:
- Bias/toxicity/privacy notes:
## Safety and security
- Requires trust_remote_code:
- Custom code audited:
- Handles sensitive data:
- Output safety risks:
- Abuse/misuse concerns:
## Inference requirements
- Artifact size:
- CPU viable:
- GPU/VRAM requirement:
- Expected latency:
- Quantization available:
- Batch size tested:
## Production decision
- Can be used in production:
- Required conditions:
- Monitoring needed:
- Rollback plan:
- Final decision:
2. Dependency Pinning Template
model:
model_id: distilbert-base-uncased-finetuned-sst-2-english
revision: main
task: text-classification
max_length: 128
tokenizer:
use_fast: true
label_mapping:
"0": NEGATIVE
"1": POSITIVE
runtime:
python: "3.12"
torch: "pin-in-requirements"
transformers: "pin-in-requirements"
datasets: "pin-in-requirements"
accelerate: "pin-in-requirements"
serving:
device: auto
batch_size: 16
timeout_ms: 1000
log_raw_text: false
Trong production thật, nên thay revision: main bằng commit SHA cụ thể sau khi đã chọn version.
3. Pipeline Vs Raw Model Decision
| Câu hỏi | Nếu câu trả lời là có | Gợi ý |
|---|---|---|
| Cần demo nhanh trong notebook? | Có | Dùng pipeline |
| Cần stable response schema cho API? | Có | Dùng raw model wrapper |
| Cần custom batching theo traffic? | Có | Dùng raw model wrapper |
Cần benchmark nhiều max_length/batch size? | Có | Dùng raw model wrapper |
| Cần explain nhanh cho người mới học? | Có | Bắt đầu bằng pipeline, sau đó mở raw path |
| Cần timeout, fallback, metrics chi tiết? | Có | Dùng raw model wrapper |
4. Trainer Vs Custom Loop Decision
| Câu hỏi | Gợi ý |
|---|---|
| Task là sequence classification/token classification chuẩn? | Dùng Trainer trước |
| Cần metric callback, checkpoint, eval mỗi epoch? | Trainer đủ tốt cho v1 |
| Cần nhiều loss, nhiều model hoặc sampling custom? | Custom loop |
| Cần scale custom PyTorch loop lên GPU/multi-GPU? | Dùng accelerate |
| Team cần học nhanh trước Day 16? | Dùng Trainer |
5. Inference Wrapper Checklist
- Load model/tokenizer một lần ở startup.
- Pin
model_idvàrevision. - Chọn device rõ:
cuda,mpshoặccpu. - Gọi
model.eval(). - Dùng
torch.inference_mode()hoặctorch.no_grad()khi inference. - Tokenize theo batch.
- Bật
truncation=True. - Set
max_lengththeo domain và benchmark. - Dùng
padding=Truecho batch inference. - Move tensors sang đúng device.
- Convert output về CPU trước khi serialize.
- Trả stable JSON schema: label, confidence, model version, latency.
- Log latency, token count, model ID, revision; không log raw PII.
- Có exception rõ cho load error và input error.
- Có readiness check sau khi model warmup.
6. Dataset Preparation Checklist
- Dataset có schema rõ:
text,label. - Label mapping được lưu lại:
label2id,id2label. - Cột label string được convert thành cột
labelsdạng số trước khi dùngTrainer. - Split train/validation/test reproducible bằng seed.
- Không leak duplicate gần giống giữa train và test.
- Tokenization chạy qua
dataset.map(..., batched=True). - Giữ preprocessing giống nhau giữa train và serve.
- Không tune hyperparameter trên test set.
- Report macro F1 nếu class imbalance.
- Lưu confusion matrix và error examples.
7. CPU/GPU/Batch Size Notes
| Chủ đề | Ghi chú thực tế |
|---|---|
| CPU | Dễ vận hành, hợp model nhỏ/traffic thấp, latency có thể cao |
| GPU | Tốt cho throughput và model lớn, cần batching để tận dụng |
| Batch size | Tăng throughput nhưng tăng memory và queueing latency |
max_length | 128 thường hợp review/ticket ngắn; 512 tốn hơn nhiều |
| Quantization | Có thể giảm RAM/VRAM, phải đo quality regression |
| Warmup | Giảm latency spike đầu tiên sau deploy |
8. Hosted Vs Local
| Lựa chọn | Ưu điểm | Rủi ro |
|---|---|---|
| Hosted inference | Go-live nhanh, ít ops, không quản GPU | Cost/request, data policy, vendor SLA |
| Local self-host | Kiểm soát data, cost dài hạn, custom runtime | Ops phức tạp, GPU capacity, monitoring |
| Hybrid | Dùng hosted cho POC, local khi scale | Cần abstraction để đổi provider |
9. Tối Thiểu Cho Production
Hugging Face model dùng được trong production khi có đủ:
- Model card review được lưu lại.
- License được approve.
- Version/revision được pin.
- Evaluation set hoặc golden set đại diện domain.
- Inference wrapper có batching/truncation/error handling.
- Benchmark trên hardware thật.
- Monitoring và alert.
- Rollback/fallback.
- Data policy cho PII.
- Security review nếu dùng custom remote code.
10. Context7 Docs Đã Tham Chiếu Khi Viết Bài
/websites/huggingface_co_transformers_main:AutoTokenizer, tokenizer parameters,AutoModelForSequenceClassification,pipeline,Trainer./llmstxt/huggingface_co_datasets_main_en_llms_txt:load_dataset,map(batched=True), cache behavior./huggingface/accelerate:Accelerator,prepare,accelerator.backward, mixed precision và distributed pattern.
Bài tập
Mục tiêu thực hành
Hoàn thành bài này để bước sang Day 16 mà không bị mơ hồ về model loading, tokenizer, Model Hub, model card, datasets, Trainer và inference wrapper.
Yêu cầu môi trường
pip install -U torch transformers datasets accelerate scikit-learn numpy
Nếu máy không có GPU, vẫn làm được bài bằng model nhỏ và batch size thấp.
Exercise 1: Review Model Card
Chọn một model từ Model Hub, ví dụ:
distilbert-base-uncased-finetuned-sst-2-englishdistilbert-base-multilingual-casedvinai/phobert-base
Điền model card review:
| Mục | Câu trả lời |
|---|---|
| Model ID | |
| License | |
| Intended use | |
| Limitations | |
| Language | |
| Dataset | |
| Metrics | |
| Safety | |
| Inference requirements | |
| Có dùng production được không? | |
| Điều kiện còn thiếu |
Kết quả mong đợi: bạn phải nói được model này phù hợp task nào, không phù hợp task nào và có rủi ro gì.
Exercise 2: Pipeline Inference
Chạy inference bằng pipeline:
from transformers import pipeline
texts = [
"This product is useful and reliable.",
"The delivery was late and the support was terrible.",
"I need to test this model before using it in production.",
]
classifier = pipeline(
"text-classification",
model="distilbert-base-uncased-finetuned-sst-2-english",
)
print(classifier(texts))
Ghi lại:
- Model ID.
- Output label.
- Confidence.
- Thời gian chạy ước lượng.
- Bạn có kiểm soát được
max_length, batching, schema và logging đủ tốt chưa?
Exercise 3: Raw Model Inference
Viết lại inference bằng AutoTokenizer và AutoModelForSequenceClassification:
import torch
from transformers import AutoModelForSequenceClassification, AutoTokenizer
model_id = "distilbert-base-uncased-finetuned-sst-2-english"
texts = [
"This product is useful and reliable.",
"The delivery was late and the support was terrible.",
]
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForSequenceClassification.from_pretrained(model_id).to(device)
model.eval()
encoded = tokenizer(
texts,
padding=True,
truncation=True,
max_length=128,
return_tensors="pt",
)
encoded = {key: value.to(device) for key, value in encoded.items()}
with torch.inference_mode():
outputs = model(**encoded)
probs = torch.softmax(outputs.logits, dim=-1)
for row in probs.detach().cpu():
label_id = int(torch.argmax(row).item())
print(
{
"label": model.config.id2label[label_id],
"confidence": round(float(row[label_id].item()), 6),
}
)
So sánh với Exercise 2:
- Code nào nhanh để prototype hơn?
- Code nào dễ đưa vào API hơn?
- Bạn sẽ log thêm field nào?
- Bạn sẽ validate input thế nào?
Exercise 4: Batching Và Truncation
Chạy raw inference với các cấu hình:
| Run | max_length | batch_size | Ghi chú latency/token count |
|---|---|---|---|
| 1 | 64 | 1 | |
| 2 | 128 | 1 | |
| 3 | 128 | 8 | |
| 4 | 256 | 8 |
Kết luận:
max_lengthtăng ảnh hưởng thế nào?- Batch size tăng throughput hay latency ra sao?
- Với API realtime, bạn chọn cấu hình nào?
Exercise 5: Load Dataset Và Tokenize
Tạo file CSV nhỏ cho sentiment:
text,label
"sản phẩm tốt giao hàng nhanh",positive
"đóng gói kém hàng bị lỗi",negative
"tạm được chưa có gì đặc biệt",neutral
"shop hỗ trợ nhanh",positive
"giao hàng quá chậm",negative
"mới dùng nên chưa đánh giá",neutral
Load bằng datasets:
from datasets import load_dataset
from transformers import AutoTokenizer
model_id = "distilbert-base-multilingual-cased"
tokenizer = AutoTokenizer.from_pretrained(model_id)
labels = ["negative", "neutral", "positive"]
label2id = {label: idx for idx, label in enumerate(labels)}
raw = load_dataset("csv", data_files="reviews.csv")["train"]
split = raw.train_test_split(test_size=0.33, seed=42)
def tokenize_batch(examples):
encoded = tokenizer(
examples["text"],
truncation=True,
max_length=128,
)
encoded["labels"] = [label2id[label] for label in examples["label"]]
return encoded
tokenized = split.map(tokenize_batch, batched=True, remove_columns=["text", "label"])
print(tokenized)
print(tokenized["train"][0].keys())
Ghi lại:
- Dataset có những split nào?
- Sau tokenize có thêm field nào?
- Vì sao
Trainercần cộtlabelsdạng số thay vì label string? - Vì sao
map(batched=True)tốt hơn tokenize từng dòng bằng vòngforPython?
Exercise 6: Trainer Skeleton
Không cần train lâu. Mục tiêu là hiểu wiring giữa dataset, tokenizer, model và Trainer.
Viết skeleton:
import numpy as np
from transformers import (
AutoModelForSequenceClassification,
AutoTokenizer,
DataCollatorWithPadding,
Trainer,
TrainingArguments,
)
model_id = "distilbert-base-multilingual-cased"
labels = ["negative", "neutral", "positive"]
label2id = {label: idx for idx, label in enumerate(labels)}
id2label = {idx: label for label, idx in label2id.items()}
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForSequenceClassification.from_pretrained(
model_id,
num_labels=len(labels),
label2id=label2id,
id2label=id2label,
)
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
def compute_metrics(eval_pred):
logits, label_ids = eval_pred
predictions = np.argmax(logits, axis=-1)
return {"accuracy": float((predictions == label_ids).mean())}
training_args = TrainingArguments(
output_dir="artifacts/day15-smoke-test",
per_device_train_batch_size=2,
per_device_eval_batch_size=2,
num_train_epochs=1,
learning_rate=2e-5,
eval_strategy="epoch",
save_strategy="no",
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized["train"],
eval_dataset=tokenized["test"],
processing_class=tokenizer,
data_collator=data_collator,
compute_metrics=compute_metrics,
)
Câu hỏi:
DataCollatorWithPaddinggiải quyết vấn đề gì?label2idvàid2labelnên được lưu ở đâu?- Khi nào skeleton này chưa đủ production training?
Exercise 7: Production Decision
Trả lời ngắn, nhưng phải cụ thể:
Model đã chọn có dùng được trong production không?
Nếu có, cần điều kiện gì?
Nếu chưa, thiếu bằng chứng nào?
Rollback/fallback là gì?
Metric nào cần monitor?
Rủi ro license/security là gì?
Checklist hoàn thành:
- Đã đọc model card.
- Đã chạy
pipeline. - Đã chạy raw model inference.
- Đã đo hoặc ước lượng ảnh hưởng của
max_lengthvà batch size. - Đã load CSV bằng
datasets. - Đã tokenize bằng
map(batched=True). - Đã hiểu skeleton
Trainer. - Đã viết production decision rõ ràng.