Token là gì? BPE và vì sao tiếng Việt tốn token hơn
Tóm tắt
LLM không đọc chữ mà đọc token do thuật toán như BPE cắt ra. Điều này giải thích vì sao tiếng Việt tốn token hơn và vì sao model đếm ký tự kém; hãy đo token trên dữ liệu thật và để code làm việc mức ký tự.
Vì sao cùng một đoạn nội dung mà bản tiếng Việt "ăn" nhiều token hơn bản tiếng Anh? Vì sao model đếm sai số chữ "r" trong một từ, hay lúng túng khi đảo ngược chuỗi ký tự? Câu trả lời nằm ở bước đầu tiên của mọi LLM: tokenization, tức cắt văn bản thành các mảnh (token) trước khi model nhìn thấy. Model không đọc chữ cái, nó đọc dãy số ID của token. Hiểu bước này giúp bạn ước lượng chi phí đúng và tránh giao cho model những việc nó "mù" từ gốc.
Token là gì?
Token là đơn vị nhỏ nhất model xử lý. Nó có thể là cả một từ phổ biến ("the"), một phần của từ ("ing"), một dấu cách kèm từ, hoặc thậm chí một byte lẻ. Mỗi model có một bộ từ vựng (vocabulary) cố định gồm hàng chục nghìn đến vài trăm nghìn token; mọi văn bản đều được biểu diễn bằng tổ hợp các token trong bộ này.
BPE hoạt động thế nào?
Thuật toán phổ biến nhất là Byte Pair Encoding (BPE), được Sennrich và cộng sự đưa vào dịch máy năm 2015 để xử lý từ hiếm. Ý tưởng rất đơn giản:
- Bắt đầu với từ vựng gồm các ký tự (hoặc 256 byte).
- Đếm cặp ký hiệu đứng cạnh nhau xuất hiện nhiều nhất trong dữ liệu huấn luyện.
- Gộp cặp đó thành một token mới, thêm vào từ vựng.
- Lặp lại cho tới khi đạt kích thước từ vựng mong muốn.
# Minh hoạ: "low lower lowest"
l o w → gộp (l,o) → lo w → gộp (lo,w) → low
low e r → gộp (e,r) → low er
Kết quả: chuỗi hay gặp thành một token, chuỗi hiếm bị cắt thành nhiều mảnh nhỏ. Repo karpathy/minbpe cài đặt BPE mức byte trong vài trăm dòng Python, đọc rất dễ hiểu; còn openai/tiktoken là tokenizer BPE nhanh dùng cho các model của OpenAI.
Hệ quả thực tế
| Hiện tượng | Nguyên nhân từ tokenization |
|---|---|
| Tiếng Việt tốn token hơn | Dữ liệu huấn luyện tokenizer thiên về tiếng Anh; chữ có dấu thường bị cắt thành nhiều byte/mảnh |
| Đếm ký tự, đảo chuỗi hay sai | Model thấy "strawberry" là 2–3 token, không thấy từng chữ cái |
| Số học với số dài kém ổn định | Số bị chia thành các nhóm chữ số không đều |
| Dấu cách thừa đổi kết quả | " hello" và "hello" là hai token khác nhau |
| Cùng nội dung, model khác giá khác | Mỗi họ model có tokenizer riêng, số token khác nhau |
Đếm token đúng cách
Đừng ước lượng "1 token ≈ 4 ký tự" cho tiếng Việt, sai số rất lớn. Với Claude, dùng endpoint đếm token của API trước khi gửi:
count = client.messages.count_tokens(
model="claude-sonnet-5-5",
messages=[{"role": "user", "content": "Xin chào, bạn khỏe không?"}],
)
print(count.input_tokens)
Kết quả đếm của tokenizer OpenAI (tiktoken) không áp dụng cho Claude và ngược lại, vì mỗi bên có từ vựng riêng.
Rủi ro và lưu ý
- Ước lượng chi phí sai: báo giá dự án theo số từ tiếng Anh rồi chạy trên dữ liệu tiếng Việt có thể lệch đáng kể. Đo trên mẫu dữ liệu thật.
- Giao việc mức ký tự cho model: đếm chữ, kiểm tra độ dài chính xác, cắt chuỗi theo vị trí… nên làm bằng code, model chỉ gọi tool.
- Token "lạ" trong input: chuỗi ngẫu nhiên (hash, base64) rất tốn token và dễ làm model sao chép sai. Đừng nhồi chúng vào prompt nếu không cần.
Áp dụng thế nào?
- Dev: Gọi API đếm token cho mẫu dữ liệu thật trước khi chọn model và kích thước context; xử lý tác vụ mức ký tự bằng code.
- Tech Lead: Đưa "token/tài liệu trung bình" theo ngôn ngữ vào tài liệu thiết kế; dùng số này để tính chi phí và giới hạn chunk khi làm RAG.
- PM: Khi so sánh giá giữa các nhà cung cấp, so trên cùng một bộ văn bản tiếng Việt, không so đơn giá/1M token một cách máy móc.
Nguồn & tham khảo
- Neural Machine Translation of Rare Words with Subword Units — Sennrich, Haddow, Birch (arXiv)
- minbpe — Andrej Karpathy (GitHub)
- tiktoken — OpenAI (GitHub)
- Token counting — Claude Docs