Tokenization — vì sao model không thấy ký tự
Model thấy token, không thấy chữ cái. Đó là gốc của lỗi đếm chữ, và lý do hoá đơn API tiếng Việt cao hơn tiếng Anh cho cùng nội dung.
TL;DR: LLM không đọc từng chữ cái — văn bản được tokenizer cắt thành token (mảnh sub-word), và model chỉ thấy dãy số ID của các mảnh đó. Vì thế model đếm ký tự sai hệ thống; cùng nội dung, tiếng Việt tốn token hơn tiếng Anh — tức trả tiền API nhiều hơn. Số token không phải thuộc tính của văn bản mà của cặp (văn bản, tokenizer): mỗi model đếm một kiểu, nên ước lượng chi phí phải đo bằng đúng tokenizer của model đang dùng, không dùng quy tắc nhẩm "4 ký tự = 1 token".
Team bạn ước lượng chi phí chatbot tra cứu policy nội bộ bằng quy tắc lan truyền: "1 token ≈ 4 ký tự". Hai triệu ký tự tài liệu tiếng Việt, nhân chia ra ngân sách gọn gàng. Cuối tháng đầu, hoá đơn API cao gần gấp đôi ước tính — dù lưu lượng đúng dự phóng. Cùng lúc, tester báo bug khó hiểu: hỏi bot "từ 'strawberry' có mấy chữ r?", bot dõng dạc trả lời sai.
Hai sự cố — một về tiền, một về đếm chữ — chung một gốc: model không nhìn thấy ký tự. Bài này giải thích tokenizer cắt văn bản thế nào, vì sao tiếng Việt bị "phạt" token, và cách đếm đúng.
1. Analogy — combo ở siêu thị
Siêu thị bán hàng theo combo: món hay được mua cùng nhau — mì gói + trứng + xúc xích — gói sẵn, quét một mã vạch là xong. Món lạ không có combo, phải quét từng món lẻ.
Tokenizer làm y hệt với văn bản: chuỗi ký tự hay đi cùng nhau trong kho huấn luyện (đa số tiếng Anh) — the, ing, tion — được "đóng combo" thành một token; "Hôm nay" với dấu tiếng Việt hiếm gặp thì không có combo, bị quét thành nhiều mảnh lẻ.
| Siêu thị | Tokenizer |
|---|---|
| Combo mì + trứng + xúc xích, quét 1 mã | Chuỗi ký tự phổ biến gộp thành 1 token |
| Món lạ không có combo, quét từng món | Từ hiếm/có dấu bị cắt thành nhiều token |
| Danh mục combo chốt sẵn, in trước | Vocabulary cố định sau khi train tokenizer |
| Hoá đơn tính theo số lần quét | API tính tiền theo số token |
Token = combo ký tự: văn bản "quen" thì ít lần quét, "lạ" thì nhiều — và hoá đơn tính theo lần quét.
2. Token là gì — và model thấy gì
Bài trước bạn đã thấy vòng lặp: model dự đoán mảnh kế tiếp dựa trên các mảnh đứng trước. Giờ gọi tên chính xác mảnh đó. Token là đơn vị nhỏ nhất model xử lý — thường là mảnh của từ, đôi khi trọn từ, đôi khi một ký tự. Tokenizer là chương trình tách văn bản thành token trước khi model thấy bất cứ thứ gì, dựa trên vocabulary (danh mục token) cố định vài chục tới vài trăm nghìn mục.
Điểm then chốt: sau bước tách, model chỉ nhận dãy số ID, không nhận văn bản.
2.1 Tách thật từ hai tokenizer
Đo bằng hai tokenizer của OpenAI (cl100k_base đời GPT-4, o200k_base đời GPT-4o), ngày 2026-07-23:
| Chuỗi | cl100k_base (đời GPT-4) | o200k_base (đời GPT-4o) |
|---|---|---|
strawberry | str · aw · berry — 3 token | st · raw · berry — 3 token |
Vietnam | Viet · nam — 2 token | Vietnam — 1 token |
Việt Nam | Vi · ệ · t · Nam — 4 token | Vi · ệt · Nam — 3 token |
Hôm nay | H · ôm · n · ay — 4 token | H · ôm · nay — 3 token |
500_000_000 | 500 · _ · 000 · _ · 000 — 5 token | 500 · _ · 000 · _ · 000 — 5 token |
Khoảng trắng được gộp vào token đứng sau (thực tế ␣Nam, ␣n).
Bốn điều lộ ra ngay:
"strawberry"với model là vài mảnh ID — trong dãy ID không tồn tại "chữ r". Hỏi model đếm chữ r là hỏi thứ nó chưa từng thấy; sai không phải bug, là hệ quả kiến trúc."Việt Nam"tốn token hơn"Vietnam"— dấu tiếng Việt hiếm trong kho huấn luyện tokenizer, không được "đóng combo".- Code và số cũng bị cắt vụn: hằng số 11 ký tự thành 5 token — đo kỹ hơn ở mục 4.
- Hai tokenizer cắt cùng một chuỗi ra kết quả khác nhau — bằng chứng đầu tiên cho luận điểm trung tâm: số token không nằm trong văn bản, nó nằm trong con mắt của tokenizer.
3. Cơ chế bên dưới — BPE đóng combo thế nào
Thuật toán tách token phổ biến nhất là BPE (Byte Pair Encoding) — Sennrich, Haddow và Birch đưa vào dịch máy năm 2016 (arXiv:1508.07909, ACL 2016) để xử lý từ hiếm — cắt từ chưa gặp thành các mảnh đã biết. Ý tưởng huấn luyện gọn trong một vòng lặp:
vocab <- tất cả ký tự đơn lẻ trong kho -- khởi đầu: toàn "món lẻ"
while vocab.size < mục tiêu (vd 100k):
(a, b) <- cặp token đứng cạnh nhau
XUẤT HIỆN NHIỀU NHẤT trong kho văn bản
vocab.add(merge(a, b)) -- đóng combo mới
thay mọi (a, b) trong kho bằng combo vừa tạo
-- Kết quả: chuỗi phổ biến = 1 token, chuỗi hiếm = nhiều mảnh
(Biến thể hiện đại byte-level khởi đầu từ 256 giá trị byte khả dĩ (2^8) thay vì ký tự — nhờ vậy mọi chuỗi đều mã hoá được, không còn "ký tự lạ" ngoài vocabulary.) Chạy trên kho đa số tiếng Anh, th merge sớm, rồi the, rồi the — tiếng Anh tích luỹ combo dài. Chuỗi có dấu như ệt xuất hiện ít hơn nhiều bậc, merge muộn hoặc không bao giờ. "Bất công token" là hệ quả thống kê của dữ liệu huấn luyện tokenizer, không ai cố tình thiết kế. Đo trên nhiều ngôn ngữ, cùng nội dung dịch ra các thứ tiếng chênh nhau tới 15 lần số token (Petrov et al., arXiv:2305.15425) — kể cả tokenizer mức ký tự/byte vẫn chênh trên 4 lần, tức bỏ BPE không xoá được vấn đề.
Toàn cảnh đường đi của văn bản:

Hai hộp Tokenizer — encode và decode — là biên giới duy nhất giữa thế giới ký tự và thế giới ID. Mọi thứ model "biết" về chính tả hay số chữ cái đều là kiến thức gián tiếp từ dữ liệu, không phải quan sát trực tiếp.
4. Đo thật: tiếng Việt "đắt" hơn bao nhiêu?
Đừng chỉ tin con số in sẵn — đoán trước đã.
Cùng nội dung viết bằng tiếng Việt và tiếng Anh — bạn đoán bản Việt tốn gấp mấy lần token? Viết ra con số trước khi cuộn tiếp.
Chúng tôi đo 5 cặp câu song ngữ cùng nội dung bằng cả hai tokenizer (thư viện gpt-tokenizer, đo 2026-07-23):
| Phép đo (tổng 5 cặp câu) | cl100k_base | o200k_base |
|---|---|---|
| Token bản tiếng Việt | 136 | 84 |
| Token bản tiếng Anh | 57 | 55 |
| Tỉ lệ Việt/Anh | 2.39× | 1.53× |
| Token mỗi từ — Việt | 2.13 | 1.31 |
| Token mỗi từ — Anh | 1.19 | 1.15 |
Đọc kết quả:
- Tiếng Việt tốn từ gấp rưỡi (1.53×, o200k) tới hơn gấp đôi (2.39×, cl100k) so với tiếng Anh cùng nội dung — khớp bậc độ lớn nghiên cứu đa ngôn ngữ. Nhớ bậc, đừng nhớ số lẻ.
- o200k (vocabulary lớn hơn) cắt tiếng Việt tốt hơn hẳn — tokenizer tiến hoá bớt bất công, nhưng chưa xoá khoảng cách.
- Đổi model có thể kèm đổi tokenizer — model cùng họ thường chung thước (GPT-3.5 và GPT-4 chung
cl100k), nhưng khi tokenizer đổi thật, mức lệch đáng kể: migration guide của Anthropic ghi tokenizer mới của một đời Opus dùng "roughly 1x to 1.35x as many tokens" — nâng cấp model là phải đo lại ngân sách token.
Cùng phép đo cho trục code: dòng if dài 53 ký tự tốn 17 token trên cả hai tokenizer — ~3.1 ký tự/token, so với ~5.5 của văn xuôi tiếng Anh cùng bộ đo. Ký hiệu, số, dấu chấm là chuỗi hiếm bị cắt lẻ — code/JSON "đặc" token gần gấp đôi văn xuôi Anh.
Hệ quả dây chuyền — token là đơn vị của cả ba thứ bạn trả giá:
| Thứ bị ảnh hưởng | Vì sao | Hệ quả với tiếng Việt |
|---|---|---|
| Chi phí API | Tính tiền theo token vào + ra | Cùng nội dung, trả nhiều hơn theo đúng tỉ lệ token |
| Context window | Giới hạn đo bằng token (bài sau) | "Bộ nhớ làm việc" chứa được ít nội dung tiếng Việt hơn |
| Tốc độ sinh | Model sinh từng token một | Câu trả lời tiếng Việt cần nhiều bước sinh hơn |
5. Pitfall tổng hợp
❌ Nhầm 1 — nhờ model đếm ký tự, đảo chữ, tách vần:
✅ Model không thấy ký tự — tác vụ mức ký tự (đếm, đảo chuỗi, soát chính tả từng chữ) là điểm mù kiến trúc. Cần đếm thì để code đếm: kết quả xác định, model chỉ đoán. (Kể cả code cũng phải chọn đúng đơn vị — text.length của JS đếm code unit UTF-16, một emoji có thể tính thành nhiều.) Việc máy tính xác định được thì đừng giao cho máy dự đoán.
❌ Nhầm 2 — ước lượng chi phí bằng "1 token ≈ 4 ký tự":
✅ Quy tắc đó là rough rule of thumb của OpenAI cho tiếng Anh — với tiếng Việt, sai số đủ vỡ ngân sách như scenario mở bài. Cách đúng: chạy vài mẫu tài liệu thật qua đúng tokenizer của model định dùng, lấy tỉ lệ đo được làm hệ số.
❌ Nhầm 3 — dùng tiktoken đếm token cho mọi model:
✅ tiktoken là tokenizer của OpenAI — đếm cho Claude bằng nó là đếm bằng thước của hãng khác: lệch hệ thống, thiếu hay thừa tuỳ cặp tokenizer và không biết trước được. Claude có endpoint count_tokens chính chủ; model khác có tokenizer riêng của họ. Nguyên tắc: model nào, thước đó.
6. 📚 Deep Dive
Paper & tài liệu chính chủ:
- Sennrich, Haddow & Birch — Neural Machine Translation of Rare Words with Subword Units (ACL 2016) — paper khai sinh BPE cho NLP; đọc motivation để hiểu vì sao sub-word thắng word-level lẫn character-level.
- Petrov et al. — Language Model Tokenizers Introduce Unfairness Between Languages (NeurIPS 2023) — nguồn của con số chênh tới 15 lần giữa các ngôn ngữ.
- tiktoken (OpenAI) — tokenizer thật, chạy offline; tự tách thử mọi chuỗi bạn tò mò.
- Hugging Face NLP Course — chương Tokenizers — so sánh BPE / WordPiece / Unigram.
Ghi chú: hai paper là nền lý thuyết (chỉ con số 15 lần lấy từ Petrov et al.); các số đo tiếng Việt trong bài là đo độc lập bằng gpt-tokenizer, 2026-07-23.
7. Liên hệ các bài khác
- Bài 01 — Dự đoán token kế tiếp — vòng lặp sinh văn bản: mỗi bước sinh đúng một token, đơn vị bài này vừa gọi tên.
- Bài 03 — Context window — "bộ nhớ làm việc" của model đo bằng token, nên hệ quả tiếng-Việt-tốn-token lặp lại ở đó.
- Bài 06 — Hallucination — lỗi đếm chữ r là ca nhỏ nhất của hiện tượng lớn hơn: model tự tin về thứ nó không quan sát được.
- Mini-challenge — đọc log ba sự cố — sự cố số một cần đúng bài này để chẩn đoán.
8. Tóm tắt
- BPE đóng combo các chuỗi ký tự phổ biến — phổ biến thì ít token, hiếm thì nhiều; ký tự có dấu tiếng Việt hiếm trong kho huấn luyện nên bị cắt vụn.
- Tiếng Việt tốn gấp rưỡi tới hơn gấp đôi token so với tiếng Anh cùng nội dung (đo 1.53×–2.39× tuỳ tokenizer); chênh lệch giữa các ngôn ngữ nói chung tới 15 lần.
- Chi phí API, sức chứa context và tốc độ sinh đều tính bằng token — tiếng Việt bị ảnh hưởng cả ba.
- Tác vụ mức ký tự (đếm, đảo, chính tả) là điểm mù của model — giao cho code, đừng giao cho model.
9. Tự kiểm tra
Q1Vì sao model trả lời sai câu 'strawberry có mấy chữ r' — và vì sao đây không phải bug sửa được bằng prompt hay hơn?▸
Trước khi vào model, strawberry đã bị cắt thành vài mảnh ID — thông tin "từ này gồm những ký tự nào" không tồn tại trong dữ liệu model nhận. Model đoán từ hiểu biết gián tiếp, không đếm.
Prompt hay hơn không cứu được, vì thông tin ký tự đã mất từ bước encode. Cách sửa thật là đổi công cụ: để code đếm.
Q2Cùng nội dung, vì sao "Việt Nam" tốn nhiều token hơn "Vietnam"?▸
"Việt Nam" tốn nhiều token hơn "Vietnam"?BPE chỉ "đóng combo" cho chuỗi xuất hiện thường xuyên trong kho huấn luyện tokenizer — kho đó đa số tiếng Anh, nên Vietnam đủ phổ biến để thành ít mảnh.
Ký tự có dấu như ệ hiếm hơn nhiều bậc, không tích luỹ được merge — bị cắt vụn. Đây là hệ quả thống kê của dữ liệu, không phải quy tắc ngôn ngữ.
Q3Team bạn nâng cấp model lên đời mới hơn của cùng một hãng. Vì sao ngân sách token và ngưỡng cắt context phải đo lại từ đầu?▸
Mỗi đời model có thể kèm tokenizer mới — cùng văn bản cắt ra số token khác; thực tế từng có ca đổi tokenizer làm cùng nội dung tốn tới ~1.35 lần token.
Chi phí dự phóng, max_tokens, ngưỡng chunk đều tính bằng thước cũ — phải đo lại bằng thước mới. Số token là thuộc tính của cặp (văn bản, tokenizer): đổi một vế là con số hết hiệu lực.
Q4Bạn cần ước lượng chi phí cho chatbot nội bộ xử lý tài liệu tiếng Việt. Mô tả cách làm đúng trong khoảng mười phút, và giải thích vì sao quy tắc '1 token xấp xỉ 4 ký tự' cho ra ngân sách sai.▸
Chạy 5–10 mẫu tài liệu thật qua đúng tokenizer của model định dùng, lấy tỉ lệ token/ký tự đo được nhân khối lượng dự phóng. Ghi ngày đo + tên tokenizer.
Quy tắc 4-ký-tự là bình quân cho tiếng Anh — tiếng Việt bị cắt vụn hơn nên ngân sách hụt gấp rưỡi tới gấp đôi.
Q5Bot của bạn trả kết quả qua API dạng JSON có cấu trúc. Từ số đo mật độ trong bài, giải thích vì sao hoá đơn output cao hơn dự tính dù phần chữ ít, và cách kiểm chứng.▸
Bài đo được code chỉ đạt ~3.1 ký tự/token so với ~5.5 của văn xuôi Anh: ký hiệu, nháy, số, gạch dưới là chuỗi hiếm không được "đóng combo" (hằng số 11 ký tự thành 5 token). Phần "khung" JSON vì thế trả giá không kém phần nội dung.
Mỗi token output là một vòng sinh (bài 01) và được tính tiền. Kiểm chứng: đo vài response JSON mẫu bằng đúng tokenizer của model, so với bản văn xuôi cùng nội dung.
Bài tiếp theo: Context window — bộ nhớ làm việc hữu hạn
Bài này đáng gửi cho bạn học cùng?
Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.
Bài này có giúp bạn hiểu bản chất không?
Hỏi đáp về bài này
Chưa có câu hỏi
Có gì chưa rõ trong bài? Đặt câu hỏi đầu tiên — câu trả lời từ cộng đồng giúp bạn (và người sau).
Đặt câu hỏi đầu tiên