Khi bạn gõ một prompt cho AI, từ lúc AI nhận prompt - xử lí - trả ra kết quả thì điều gì đã xảy ra. Trong bài viết này mình sẽ trả lời câu hỏi đó, nội dung này mình học và tìm hiểu thông qua cuốn sách "Hand's on Large Language Model" của tác giả Jay Alammar và Maarten Grootendorst.
Trước tiên ta cần hiểu Tokenizer là gì ? Tokenizer là công cụ chia văn bản thành những đơn vị nhỏ gọi là token. Các token này sau đó được ánh xạ thành chỉ số số hóa, giúp Transformer xử lý dễ dàng.
I. Tokenizers chuẩn bị đầu vào cho Language Model thế nào ?
Language Model (LM) được hiểu cơ bản như là một mô hình ngôn ngữ, được chia nhỏ làm 2 loại Representation Model (BERT) và Generative Model (GPT). Trước khi prompt của người dùng được hiển thị cho LM, nó phải được token hoá thành nhiều mảnh. Ngoài các token từ prompt sinh ra, mỗi mô hình còn có các special-token riêng, được huấn luyện sẵn. Ví dụ [CLS], [MASK], <|assistant|>

Ảnh minh hoạ - Nguồn: Medium
Bên trong một Tokenizer tồn tại một bảng, là mapping những ID tới những từ. Trong ảnh minh hoạ ta có thể hiểu như Tokenizer[Learn] = 29387.
Để xem minh hoạ cho quá trình này, input - output, bạn có thể khởi tạo một Notebook và chạy đoạn các đoạn code dưới đây:
- Load model và tokenizer
from transformers import AutoModelForCausalLM, AutoTokenizer
# Load model and tokenizer
model = AutoModelForCausalLM.from_pretrained("microsoft/Phi-3-mini-4k-instruct", device_map="cuda", torch_dtype="auto", trust_remote_code=True, ) tokenizer = AutoTokenizer.from_pretrained("microsoft/Phi-3-mini4k-instruct")- Nhập prompt và in kết quả
prompt = "Write an email apologizing to Sarah for the tragic gardening mishap. Explain how it happened.<|assistant|>"
# Tokenize the input prompt
input_ids = tokenizer(prompt, return_tensors="pt").input_ids.to("cuda")
# Generate the text
generation_output = model.generate( input_ids=input_ids, max_new_tokens=20 )
#Print the output
print(tokenizer.decode(generation_output[0]))Nếu bạn đang cần một nền tảng để chạy đoạn code này, hãy tham khảo nội dung trong bài viết này: Các nền tảng cung cấp GPU cho người mới
II. Cách Tokenizer chia nhỏ văn bản
Có ba yếu tố chính quyết định việc chia nhỏ văn bản đầu vào thành các token:
- Model design time: Tuỳ người thiết kế chọn phương pháp token-hoá, mỗi thời điểm sẽ có một phương pháp mới, chẳng hạn như ChatGPT ban đầu sử dụng BPE, BERT sử dụng WordPiece
- Chọn các tham số cho Tokenizer: Bao gồm kích cỡ từ điển, token đặc biệt, xử lí in hoa,...
- Dataset: Với mỗi ngôn ngữ, ta cần huấn luyện mô hình trên các bộ data riêng biệt, khác nhau. Không thể sử dụng Tokenizer được huấn luyện bằng tiếng Anh để token-hoá tiếng Việt được. Điều này cũng tương tự các trường hợp mình từng gặp phải khi làm các project Machine Learning. Mình từng huấn luyện một mô hình ML với train loss rất thấp, nhưng khi mình test thực tế thì độ chính xác không cao, điều đáng nói là valid loss cũng rất thấp. Sau một thời gian tìm hiểu mình hiểu ra là vì bộ data mình huấn luyện mô hình ML và bộ mình dùng để kiểm tra được lấy ở 2 khu vực khác nhau (Mĩ và Việt Nam). Vì vậy đây cũng là điều mình rút kinh nghiệm khi bắt đầu tiến hành huấn luyện và thử nghiệm các mô hình.
III. Các phương pháp Token hoá
Có 4 phương pháp được chú ý khi tiến hành token hoá:
- Word Tokens: Lưu theo từng từ, mỗi từ là một token. Cách này đã được giới thiệu từ rất lâu, không phổ biến và không hữu ích với các mô hình hiện đại.
- Subword Tokens: Được chia thành full words và partial words. Có thể dễ dàng biểu diễn các từ mới bằng cách chia nhỏ nó thành các kí tự nhỏ. Ví dụ như từ have qua phương pháp này vẫn giữ nguyên 1 token là từ have, còn từ bards khi áp dụng phương pháp này sẽ thành "bard" + "s"
- Character Tokens: Phương pháp giải quyết tốt các từ mới vì nó chứa các kí tự thô để sử dụng. Dễ dàng token hoá nhưng phức tạp cho mô hình. Tốn context hơn Subword rất nhiều
- Byte Tokens: Phương pháp này được hiểu đơn giản là đối với mỗi kí tự trong Prompt đều sẽ chuyển thành các byte
Note: 1 số subword-tokenizer sử dụng character token ở block cuối như 1 cơ chế fallback khi gặp những kí tự không thể biểu diễn
IV. Kết luận
Tokenizer có thể chỉ là bước đầu tiên trước khi dữ liệu đi vào Language Model, nhưng nó ảnh hưởng trực tiếp đến cách mô hình tiếp nhận và biểu diễn văn bản.
Từ một câu prompt mà con người có thể đọc được, Tokenizer sẽ chia nhỏ nó thành các token, ánh xạ chúng thành ID và chuẩn bị dữ liệu để mô hình tiếp tục xử lý. Cách chia token không hoàn toàn giống nhau giữa các mô hình mà phụ thuộc vào phương pháp token hoá, vocabulary, dataset huấn luyện và cách thiết kế Tokenizer.
Trong các mô hình ngôn ngữ hiện đại, Subword Tokenization được sử dụng rất phổ biến vì tạo được sự cân bằng giữa kích thước vocabulary và số lượng token cần thiết để biểu diễn văn bản. Tuy nhiên, những phương pháp dựa trên character hay byte cũng có những ưu điểm riêng, đặc biệt khi cần xử lý những ký tự hoặc từ chưa từng xuất hiện trong vocabulary.
Như vậy, khi chúng ta gửi một prompt cho AI, mô hình thực tế không nhìn thấy nguyên câu chữ giống như con người. Thứ đầu tiên mà nó tiếp nhận là một chuỗi các token đã được số hoá.
Ở bài viết tiếp theo, mình sẽ đi sâu hơn vào bước xảy ra sau Tokenization: các token được biến thành Embedding và được Transformer xử lý như thế nào.

Thảo luận bài viết
Câu hỏi, ghi chú và góc nhìn của bạn về nội dung này.