AI Core cho lập trình viên/Tokenization — vì sao model không thấy ký tự
21/54
Bài 21 / 54~13 phútCỗ máy LLMMiễn phí lượt xem

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ónTừ hiếm/có dấu bị cắt thành nhiều token
Danh mục combo chốt sẵn, in trướcVocabulary cố định sau khi train tokenizer
Hoá đơn tính theo số lần quétAPI tính tiền theo số token
💡 Cách nhớ

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ỗicl100k_base (đời GPT-4)o200k_base (đời GPT-4o)
strawberrystr · aw · berry — 3 tokenst · raw · berry — 3 token
VietnamViet · nam — 2 tokenVietnam — 1 token
Việt NamVi · ệ · t · Nam — 4 tokenVi · ệt · Nam — 3 token
Hôm nayH · ôm · n · ay — 4 tokenH · ôm · nay — 3 token
500_000_000500 · _ · 000 · _ · 000 — 5 token500 · _ · 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:

Chữ vào qua tokenizer encode thành chuỗi ID; trong khung, model chỉ thấy ID và dự đoán ID kế tiếp; tokenizer decode trả lại thành chữ

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 đã.

Thử đoán

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_baseo200k_base
Token bản tiếng Việt13684
Token bản tiếng Anh5755
Tỉ lệ Việt/Anh2.39×1.53×
Token mỗi từ — Việt2.131.31
Token mỗi từ — Anh1.191.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ưởngVì saoHệ quả với tiếng Việt
Chi phí APITính tiền theo token vào + raCùng nội dung, trả nhiều hơn theo đúng tỉ lệ token
Context windowGiớ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 độ sinhModel sinh từng token mộtCâ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

📚 Nguồn gốc — đọc khi muốn xuống tầng sâu hơn

Paper & tài liệu chính chủ:

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

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

Tự kiểm tra
Q1
Vì 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.

Q2
Cùng nội dung, vì sao "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ữ.

Q3
Team 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 — 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.

Q4
Bạ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.

Q5
Bot 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

Đặt 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

Bài tiếp theo

Context window — bộ nhớ làm việc hữu hạn