Top-P và Top-K là các tham số lấy mẫu (sampling parameters) dùng để kiểm soát cách mô hình ngôn ngữ lớn (LLM) chọn token tiếp theo từ phân phối xác suất. Về bản chất, đây là các bộ lọc quyết định tập hợp ứng viên nào được giữ lại trước khi mô hình thực hiện bước lựa chọn cuối cùng.
Nếu không có các tham số này, mô hình thường rơi vào hiện tượng lặp từ vô tận (degenerate output) khi dùng giải mã tham lam (greedy decoding), hoặc sinh ra nội dung hỗn loạn khi lấy mẫu ngẫu nhiên trên toàn bộ từ vựng. Việc tinh chỉnh Top-P và Top-K cho phép bạn cân bằng giữa tính xác định (determinism) và tính biến hóa (variance) của hệ thống.
Cả hai đều không dạy mô hình điều gì mới. Chúng chỉ quyết định mô hình được phép với tay tới đâu trong những gì nó đã biết.

Từ logits đến xác suất: chuyện xảy ra trước khi mô hình chọn token
Trước khi một token được hiển thị, dữ liệu phải đi qua lớp tuyến tính cuối cùng (final linear layer) của Transformer để tạo ra các điểm số thô gọi là logits. Logits có thể mang giá trị âm hoặc dương, không giới hạn, và không có ý nghĩa xác suất trực tiếp. Để biến chúng thành một phân phối dùng được, mô hình áp dụng hàm Softmax.

Công thức xác suất P cho một token x_i được biểu diễn như sau:
P(x_i) = exp(l_i) / Σ(j=1..V) exp(l_j)Trong đó V là kích thước bộ từ vựng và l_i là logit của token thứ i. Hàm này đảm bảo tổng xác suất của tất cả các token luôn bằng 1. Nếu bạn chỉ đơn giản chọn token có xác suất cao nhất ở mỗi bước, tức greedy decoding, mô hình sẽ hoạt động kém hơn nhiều người tưởng. Nghiên cứu của Holtzman và cộng sự chỉ ra rằng ngôn ngữ tự nhiên không luôn chọn từ có xác suất cao nhất; văn bản của con người cần cả những chỗ bất ngờ.
Nhưng lấy mẫu tự do trên toàn bộ phân phối cũng không phải lời giải. Phần "đuôi dài" (long tail) chứa hàng chục nghìn token xác suất cực thấp; từng token một thì không đáng kể, nhưng cộng lại chúng chiếm một khối xác suất đủ lớn để thỉnh thoảng được chọn trúng. Một lần chọn trúng là đủ để câu văn trật khỏi mạch. Top-P và Top-K sinh ra để cắt cái đuôi đó đi.
Top-K là gì, và nó cắt ở đâu?
Top-K (Fan và cộng sự, 2018) thực hiện lọc cứng dựa trên số lượng. Hệ thống sắp xếp các token theo xác suất giảm dần, chỉ giữ lại K ứng viên đứng đầu, và gán xác suất bằng 0 cho toàn bộ phần còn lại. Sau nhát cắt đó, các xác suất còn lại được chuẩn hóa lại để tổng bằng 1.

Nếu K = 1, bạn đang dùng greedy decoding. Nếu K = 50, mô hình chọn trong 50 ứng viên tốt nhất. Logic này có thể minh họa bằng mã giả:
# Lọc Top-K rồi chuẩn hóa lại
probs = softmax(logits)
top_k_indices = np.argsort(probs)[-K:]
filtered_probs = np.zeros_like(probs)
filtered_probs[top_k_indices] = probs[top_k_indices]
# Bước quan trọng: chuẩn hóa lại để tổng bằng 1
normalized_probs = filtered_probs / np.sum(filtered_probs)Nhược điểm cốt lõi của Top-K là vấn đề K tĩnh. Trong ngữ cảnh có độ tin cậy cao, ví dụ "Thủ đô của Pháp là...", xác suất hội tụ gần như trọn vẹn vào một hai token. Ép mô hình cân nhắc đủ 50 ứng viên lúc này chỉ mở cửa cho token rác. Ngược lại, trong ngữ cảnh mở như "Tương lai của công ty này là...", có thể có hàng trăm ứng viên hợp lý, và K = 50 lại cắt mất những lựa chọn tốt. Cùng một con số K không thể đúng cho cả hai tình huống, vì nó không biết mô hình đang tự tin hay đang phân vân.
Top-P (nucleus sampling) là gì, và vì sao nó tự co giãn?
Để giải quyết sự cứng nhắc đó, Holtzman và cộng sự (2020) giới thiệu Top-P, còn gọi là nucleus sampling. Thay vì chọn một số lượng token cố định, Top-P sắp xếp token theo xác suất giảm dần rồi gom dần vào "nhân" (nucleus) cho đến khi tổng xác suất tích lũy đạt ngưỡng p, ví dụ 0.95. Phần còn lại bị loại, và các xác suất giữ lại được chuẩn hóa lại.

Điểm mấu chốt là tập ứng viên này tự co giãn theo ngữ cảnh. Khi mô hình tự tin, nhân co lại: nếu token dẫn đầu đã chiếm 96% và ngưỡng là 0.95, chỉ đúng một token được giữ. Khi mô hình phân vân, nhân nở ra, có thể tới hàng trăm token, cho đến khi gom đủ 95% khối xác suất. Đây chính là thứ Top-K không làm được, bởi Top-P đo độ tin cậy, còn Top-K chỉ đếm số lượng.
Chính vì vậy Top-P là mặc định phổ biến ở phần lớn API thương mại. Nó cho mô hình quyền sáng tạo khi có nhiều phương án hợp lý, và tự siết lại khi token tiếp theo là hiển nhiên. Tuy nhiên nó vẫn có điểm yếu riêng, và điểm yếu đó lộ ra đúng lúc bạn cần nó nhất, như phần dưới sẽ nói kỹ.
Temperature khác Top-P và Top-K ở điểm nào?
Temperature (T) không phải là bộ lọc cắt bỏ; nó là tham số tái cấu trúc phân phối, bằng cách chia logits cho T trước khi đưa vào Softmax. Bài Temperature trong LLM là gì đi sâu vào công thức đó và vào việc nên đặt bao nhiêu cho từng loại công việc; ở đây ta chỉ cần thấy nó khác hai bộ cắt ở chỗ nào.
Bạn có thể coi Temperature như nút chỉnh độ tương phản. Khi T < 1, khoảng cách giữa các xác suất bị phóng đại, token mạnh càng mạnh hơn, và mô hình trở nên gần như xác định. Khi T > 1, phân phối bị làm phẳng, các token yếu có thêm cơ hội, đổi lại là rủi ro mất mạch. Con số dưới đây cho thấy mức độ:
| Token | Logit | P (T = 1.0) | P (T = 0.2) | P (T = 2.0) |
|---|---|---|---|---|
| Bún chả | 3.0 | 68.6% | 99.3% | 50.6% |
| Phở | 2.0 | 25.3% | 0.7% | 30.7% |
| Cơm | 0.5 | 5.6% | ~0.0% | 14.5% |
| Xe đạp | -2.0 | 0.5% | ~0.0% | 4.2% |

Khác biệt quan trọng nhất: Temperature không loại bỏ token nào. Ngay cả ở mức rất thấp, mọi token trong từ vựng về lý thuyết vẫn giữ một xác suất khác 0. Và vì phép chia l_i / T áp dụng đồng đều cho mọi logit, thứ tự xếp hạng giữa các token không bao giờ thay đổi, tức token mạnh nhất ở T = 0.2 vẫn là token mạnh nhất ở T = 2.0. Temperature điều chỉnh khoảng cách, Top-P và Top-K mới thực sự gạch tên. Đây cũng là lý do câu "tăng temperature cho mô hình sáng tạo hơn" gây hiểu nhầm: nó không thêm ý tưởng mới nào, nó chỉ nới rộng mức độ sẵn sàng chọn những gì vốn đã nằm trên bàn.
Thứ tự áp dụng: vì sao cùng tham số vẫn ra kết quả khác nhau
Thứ tự xử lý trong chuỗi sampler, tức các bộ lọc chạy nối tiếp nhau để chọn ra token cuối cùng, là nguyên nhân khiến cùng một bộ tham số cho ra kết quả khác nhau giữa các framework. Một chuỗi tiêu chuẩn chạy như sau:
- Penalties (repetition, frequency, presence) chạy đầu tiên.
- Truncation (Top-K, Top-P, Min-P) loại bỏ các ứng viên xấu.
- Temperature tái cấu trúc xác suất của những ứng viên còn lại.
- Sampling rút token cuối cùng.

Vấn đề nằm ở chỗ không phải framework nào cũng chạy đúng thứ tự này. llama.cpp áp dụng Temperature ở bước cuối, còn HuggingFace Transformers thường áp dụng Temperature trước khi cắt. Khác biệt đó không hề vô hại: vì Temperature làm thay đổi độ lớn các xác suất, chạy nó trước sẽ thay đổi luôn việc token nào lọt vào nhân Top-P. Cùng top_p = 0.95 trên hai framework có thể cho ra hai tập ứng viên khác nhau, và đây là một nguồn lỗi khó truy khi bạn chuyển một cấu hình từ môi trường này sang môi trường khác.
Tài liệu của Google mô tả chuỗi này rõ ràng cho Gemini: các token Top-K có xác suất cao nhất được lấy trước, sau đó lọc tiếp theo Top-P, và token cuối cùng được chọn bằng lấy mẫu theo temperature. Nếu bạn dựa vào một mặc định mà không biết framework của mình xếp thứ tự ra sao, bạn đang chỉnh một tham số mà không thực sự biết nó tác động lên cái gì.
Khi nào Top-P hỏng, và min-p sinh ra để làm gì?
Top-P hỏng đúng lúc mô hình bối rối nhất. Khi phân phối trở nên phẳng, tức không token nào nổi trội, việc gom cho đủ 95% khối xác suất có thể phải nạp vào hàng trăm, thậm chí hàng nghìn token chất lượng thấp. Nghịch lý là mô hình càng không chắc chắn, Top-P càng thả nhiều rác vào tập ứng viên, trong khi lẽ ra nó nên thận trọng hơn.

Min-P (Nguyen và cộng sự, 2025) sửa đúng chỗ đó bằng cách đặt ngưỡng tương đối thay vì tích lũy. Ngưỡng được tính từ chính token mạnh nhất:
threshold = min_p × P(token mạnh nhất)Nếu token dẫn đầu đạt 90% và min_p = 0.1, ngưỡng là 0.09, rất khắt khe. Nếu token dẫn đầu chỉ đạt 5%, ngưỡng tụt xuống 0.005, nới lỏng theo. Cơ chế này khắt khe khi mô hình tự tin và dễ dãi khi mô hình phân vân, tức là ngược hoàn toàn với hành vi của Top-P trên phân phối phẳng.
Một hướng khác là Top-n-sigma (Tang và cộng sự, 2025), cắt dựa trên độ lệch chuẩn của logits: threshold = max(l) - n × σ(l). Vì phép tính này chạy trên logits thô chứ không phải xác suất sau Softmax, ranh giới cắt không phụ thuộc temperature. Bạn có thể chỉnh độ ngẫu nhiên mà không vô tình làm tập ứng viên phình ra, điều mà cả Top-P lẫn Top-K đều không đảm bảo được.
Mỗi nhà cung cấp một kiểu: Anthropic khai tử, Google vẫn giữ
Hai nhà cung cấp lớn đang đi theo hai hướng ngược nhau, và điều này quan trọng hơn phần lớn hướng dẫn tinh chỉnh bạn đọc được trên mạng.

Phía Anthropic, cả ba tham số đều đã bị đánh dấu deprecated trong tài liệu API chính thức. Các mô hình phát hành sau Claude Opus 4.6 không còn hỗ trợ đặt temperature (chỉ chấp nhận giá trị 1.0 để tương thích ngược), không hỗ trợ top_p (chỉ chấp nhận giá trị từ 0.99 trở lên), và từ chối mọi giá trị top_k. Đặt sai sẽ nhận lỗi 400. Ngay cả với các mô hình đời cũ hơn, khuyến nghị của tài liệu vốn đã dè dặt: thường bạn chỉ cần temperature, top_k chỉ dành cho trường hợp nâng cao, và không nên chỉnh temperature cùng top_p một lúc.
Phía Google thì ngược lại. Gemini vẫn giữ đầy đủ topK, topP và temperature trong generationConfig, và tài liệu còn mô tả rõ thứ tự áp dụng của chúng. Đáng chú ý là mặc định thay đổi theo từng mô hình, và một số mô hình chạy nucleus-only sẽ không cho phép đặt topK, nên "mặc định của Gemini" không phải một con số duy nhất mà bạn có thể ghi nhớ.
Tôi thấy hướng của Anthropic khó chịu lúc đầu, vì nó lấy đi thứ mình đã quen tay, nhưng nó thành thật hơn: nếu nhà cung cấp biết rõ vùng tham số nào cho ra kết quả tốt, để người dùng tự dò trong vùng đó chỉ tạo ra ảo giác kiểm soát. Bức tranh rút ra khá thẳng thắn: các knob này đang mất dần vị trí ở tầng mô hình biên giới, nơi nhà cung cấp muốn tự kiểm soát hành vi lấy mẫu, nhưng vẫn sống khỏe ở tầng hạ tầng mở như llama.cpp và vLLM, nơi bạn tự vận hành mô hình và tự chịu trách nhiệm. Trước khi dành thời gian dò tìm bộ tham số hoàn hảo, hãy kiểm tra xem mô hình bạn đang gọi có còn nhận chúng hay không.
Vậy nên chỉnh gì cho công việc của bạn?
Nếu bạn gọi API của một mô hình biên giới đời mới, câu trả lời có thể đơn giản đến bất ngờ: không chỉnh gì cả, vì API đã không còn nhận. Việc cần làm là dẫn dắt bằng prompt thay vì bằng tham số lấy mẫu.
Nếu bạn tự vận hành mô hình và thực sự có quyền chỉnh, hãy giữ mọi thứ tối giản. Với code và toán, để temperature thấp (0.0 đến 0.2) và top_p cao (0.95). Với chatbot hay viết lách, cặp temperature 0.7 đến 1.0 kèm min_p 0.05 đến 0.1 là lựa chọn mà phần lớn người dùng llama.cpp và vLLM đã hội tụ về. Điều nên tránh nhất là bật cả bốn bộ lọc cùng lúc rồi tự hỏi vì sao đầu ra kỳ lạ: mỗi bộ lọc đều cắt vào cùng một phân phối, và chồng chúng lên nhau khiến bạn không còn biết cái nào đang thực sự quyết định.
Tài liệu tham khảo
- The Curious Case of Neural Text Degeneration
- How to generate text: using different decoding methods for language generation with Transformers
- Generation strategies (Hugging Face Transformers)
- How do temperature, top-k, and top-p sampling differ? (Sebastian Raschka)
- Messages (Claude API Reference)
- Experiment with parameter values (Google Cloud)
- LLM Sampling Parameters Explained: Intuition to Math
- Temperature doesn't make your model creative