localaiforum
Đăng nhập
Hướng dẫn › Kiến thức nền tảng

Token & tokenizer

Mô hình không bao giờ thấy từ hay chữ cái. Chúng thấy các ID token — những số nguyên đánh chỉ mục vào một từ vựng cố định gồm các mảnh subword, được dựng bằng mã hóa cặp byte (BPE) hoặc một biến thể gần giống. Token hóa là cửa khẩu cho mọi thứ: prompt của bạn, câu trả lời, cửa sổ ngữ cảnh, đồng hồ token-mỗi-giây, hóa đơn API. Một khi bạn tư duy bằng token, một nửa truyền thuyết về hành vi LLM tan biến.

Từ vựng được xây dựng thế nào

BPE khởi đầu từ byte thô và lặp đi lặp lại việc ghép cặp liền kề thường gặp nhất cho đến khi từ vựng chạm ngân sách. Kết quả: từ phổ biến thành một token duy nhất, từ hiếm thành 2–5 mảnh, và không có gì là không thể biểu diễn — cơ chế fallback byte che mọi chuỗi, kể cả lỗi chính tả và emoji. Từ vựng dao động từ ~30k mục (mô hình cũ) đến ~250k (đa ngôn ngữ hiện đại):

Tokenizer Kích thước từ vựng Ghi chú
GPT-2 ~50k nặng tiếng Anh/web
Llama 2 ~32k tiếng Hàn bị xẻ đau đớn
Llama 3 ~128k bước nâng cấp đa ngôn ngữ lớn
Qwen 2 / 2.5 / 3 ~151k phép ghép CJK mạnh
Gemma ~256k từ vựng phổ biến lớn nhất

Một tokenizer được huấn luyện chủ yếu trên tiếng Anh sẽ ghép các mảnh tiếng Anh rất hăng; các cặp âm tiết tiếng Hàn nhận được ít phép ghép hữu ích hơn hẳn. Từ vựng quyết định "thuế tiếng Hàn" của bạn từ trước khi bản thân mô hình giỏi hay dốt tiếng Hàn.

Ví dụ minh họa: tiếng Anh

"Tokenization turns text into pieces."

→ ["Token", "ization", " turns", " text", " into", " pieces", "."]
→ 37 characters → 7 tokens ≈ 5.3 chars/token

Chú ý các chi tiết: từ phổ biến "Token" là một mảnh; hậu tố có mảnh riêng; và khoảng trắng đầu tiên thuộc về token theo sau (" turns", chứ không phải "turns"). Đó là lý do "hello", " hello" và "Hello" là ba token khác nhau — hai prompt khác nhau một khoảng trắng hay một chữ in hoa sẽ token hóa khác nhau.

Ví dụ minh họa: tiếng Hàn

Cùng một câu, kinh tế tồi tệ hơn. Hangul được viết theo khối âm tiết, và các phép ghép tiếng Hàn hiếm hơn hẳn trong những từ vựng nặng tiếng Anh (cách tách dưới đây là hợp lý, không chính xác tuyệt đối):

"안녕하세요, 만나서 반가워요."        # 17 ký tự

từ vựng đa ngôn ngữ mạnh (~150k mục):
["안녕", "하세요", ",", " 만나", "서", " 반", "가", "워", "요", "."]
→ ~10 tokens ≈ 1.7 chars/token

từ vựng yếu (~32k mục, tách ở mức jamo):
["안", "녕", "하", "세", "요", ",", " 만", "나", "서", ...]
→ 15+ tokens ≈ 1.1 chars/token

Tiếng Anh trung bình ~4 ký tự/token. Tiếng Hàn thường rơi vào 1–1.5. Cùng ý nghĩa, gấp 3–4 lần token. Vì vậy:

  • Prompt CJK ngốn cửa sổ ngữ cảnh với tốc độ đáng báo động — một cửa sổ 8k token chứa được nhiều tiếng Anh hơn tiếng Hàn khoảng 3–4 lần.
  • Sinh văn bản tiếng Hàn "cảm giác" chậm hơn với cùng tok/s: nhiều token hơn mỗi câu, ít văn bản hơn mỗi token.
  • Tiếng Hàn tốn kém hơn trên các API tính phí theo token, và các vết suy luận viết bằng tiếng Hàn đốt ngân sách theo đúng cách đó.

Vì sao câu hỏi đếm chữ cái thất bại

Hỏi "trong strawberry có bao nhiêu chữ r" và ngay cả mô hình lớn cũng lúng túng. Lý do: mô hình không bao giờ thấy chữ cái. "strawberry" đến dưới dạng đại khái ["straw", "berry"] — hai số nguyên. Không có số đếm chữ cái bên trong một số nguyên, cũng như số trang không cho bạn biết chính tả của trang đó. Mô hình có thể đọc thuộc chính tả đã ghi nhớ hoặc suy luận từng bước, và cả hai đều không đáng tin. Nếu cần việc này làm đúng: buộc mô hình đánh vần từ đó trước, mỗi dòng một chữ, rồi đếm số dòng.

Từ vựng đi kèm mô hình

  • Các tệp tokenizer (vocab, merges) là một phần của bản phát hành; GGUF nhúng chúng, các repo safetensors mang chúng cạnh trọng số.
  • Các engine (llama.cpp, LM Studio, vLLM, ...) tự nạp đúng tokenizer. Bạn không bao giờ phải chọn.
  • Số token mang tính tương đối theo mô hình: cùng một văn bản có thể là 1,000 token dưới từ vựng của họ này và 1,150 dưới họ khác. Đừng bao giờ hardcode ngân sách token chéo các mô hình.
  • Chất lượng từ vựng và chất lượng mô hình là hai trục riêng: một mô hình từ vựng 32k vẫn xử lý được tiếng Hàn (nó hiểu các token của mình); nó chỉ tốn nhiều token hơn mỗi câu.

Mọi thứ đều được định giá bằng token

Điều bạn quan tâm Đo bằng đơn vị
Cửa sổ ngữ cảnh (4k → 128k+) token vào + token ra gộp chung
Tốc độ sinh văn bản token mỗi giây
Bộ nhớ KV cache tăng theo mỗi token trong ngữ cảnh (KV cache)
Giá API mỗi triệu token
Giới hạn độ dài đầu ra số token đầu ra tối đa
Ngân sách suy luận/thinking số token mô hình được phép tiêu trước khi trả lời
Embedding tài liệu cho RAG chia đoạn và tính theo triệu token

Token đặc biệt và chat template

Bên cạnh các mảnh văn bản, từ vựng dành sẵn các ID điều khiển: bắt đầu chuỗi, kết thúc chuỗi, và các dấu vai trò. Khi giao diện chat của bạn gửi một tin nhắn, nó không gửi văn bản thô — nó điền vào một chat template chen các token đặc biệt như <|im_start|>user ... <|im_end|> xung quanh lời của bạn. Chính lớp bọc này là lý do số token mà engine báo cáo luôn nhỉnh hơn một chút so với phần chữ trong tin nhắn của bạn, và là lý do trộn lẫn template của các họ khác nhau làm mô hình rối trí.

Quy tắc ước lượng: ký tự tiếng Anh ÷ 4. Ký tự tiếng Hàn ÷ 1.0–1.5 — hãy cứ tính theo kịch bản xấu nhất. Mô phỏng dùng xấp xỉ ~4 ký tự/token và được hiệu chuẩn cho tiếng Anh; hãy tự nhân thêm trong đầu cho tiếng Hàn.

Tự đếm token

pip install tiktoken
python -c "import tiktoken as t; e = t.get_encoding('o200k_base'); print(len(e.encode('hello world')))"
  • tiktoken (https://github.com/openai/tiktoken) bao các bộ mã của họ OpenAI; các họ khác khác biệt nhưng chênh lệch chừng ±15% cho tiếng Anh.
  • Trang mô hình trên Hugging Face có trình xem tokenizer; các tokenizer playground cho phép bạn dán văn bản và xem cách tách diễn ra trực tiếp.
  • Các engine cục bản in số token prompt trong log — đối chiếu một lần với prompt thật của bạn, rồi ước lượng theo tỉ lệ.

Liên quan: bên trong transformer · prefill vs decode · KV cache