Layer nào trong model "thảy" ra mấy câu AI SLOP ?

Mình cực kỳ khó chịu với mấy chữ "sặc mùi AI" và với thói quen là trước khi chửi cái gì đó mình phải hiểu nó. Và đây là thí nghiệm vui của mình

Layer nào trong model "thảy" ra mấy câu AI SLOP ?

Đọc tài liệu AI viết, mình khó chịu vì mấy khuôn cứ lặp đi lặp lại: heading cho một ý chỉ đáng một câu, chữ đậm ở đầu mỗi gạch đầu dòng, "không phải A, mà là B", ba vế xếp hàng. Bản nháp agent viết cho omelet.tech cũng có. Ngày 21/08/2026, sau một lượt dọn giọng máy, bài về DeepSeek-V4 vẫn còn câu "Cơ chế của nó đơn giản tới mức khó chịu", một câu đánh giá hộ người đọc trước khi kể cơ chế.

Tháng 10/2026, Erik Markus Kannike đăng hai bài blog lần theo loại giọng này vào trong model [1] [2]. Kannike lấy hiệu activation giữa bản viết cường điệu và bản viết thường của cùng một câu, được một hướng trong residual stream, rồi đo xem hướng đó có từ bước huấn luyện nào.

Ảnh chụp phần TL;DR trong bài "Where AI slop comes from" của Kannike, tô vàng hai cụm. Cụm thứ nhất nói model base chỉ học văn web đã có hướng slop nhưng viết gần như không slop. Cụm thứ hai nói ở OLMo 2, SFT đưa các khuôn tu từ vào, còn preference tuning làm điểm slop tăng gấp đôi.

Đọc xong, mình tò mò mấy chuyện bài đó để ngỏ. OLMo 2 công bố checkpoint của từng bước huấn luyện, vậy đếm khuôn ở từng checkpoint thì bước nào cài khuôn nào? Kannike thấy câu "tốt hơn" trong dữ liệu preference sloppy hơn ở 57% số cặp, nhưng bộ dữ liệu đó ghép câu trả lời của hơn 20 model khác nhau, nên con số ấy có thể chỉ phản ánh chuyện model mạnh hay được chọn. Và với câu tiếng Việt thì sao?

Mình đo năm checkpoint của OLMo-2-0425-1B (base, SFT, DPO, RLVR1, Instruct) [3], chấm lại bộ preference đi kèm, và thêm Qwen3-4B cho phần tiếng Việt. Model chạy trên một máy DGX của lab trong hai ngày 17 và 18/10/2026.

Model base đã có sẵn hướng markdown nhưng viết văn xuôi. SFT và DPO giữ gần nguyên hướng đó và dạy model đi theo nó ngay trước dòng markdown đầu tiên. DPO thêm markdown và độ dài, hai thứ nhãn chosen vẫn thưởng khi đã tính tới model nào viết câu trả lời.

Câu hỏi về Git commit

Prompt là "Explain to a new developer what a Git commit is.", seed 0, temperature 0,7, tối đa 1024 token. Model base không có chat template, nên nhận prompt dạng Question: ...\nAnswer:.

Ba câu trả lời cho cùng prompt về Git commit, xếp từ trên xuống. Base viết 68 từ văn xuôi, SFT viết 82 từ văn xuôi, không có dấu markdown nào. DPO viết 413 từ với 5 heading ba dấu thăng, 3 dòng đánh số, 6 gạch đầu dòng và 7 cụm chữ đậm, tất cả tô vàng. Chữ Essentially và một em dash ở câu thứ hai tô cam. Dòng chú thích trong khối code bắt đầu bằng dấu thăng cũng bị tô vàng.

Base và SFT trả lời bằng một đoạn văn xuôi, 68 và 82 từ. DPO mở đầu gần như cùng câu với SFT ("A Git commit is a unique snapshot of your..."), rồi viết tiếp tới 413 từ, có heading, danh sách đánh số, gạch đầu dòng in đậm ở đầu, "Essentially" và một em dash. Bộ đếm tính được 22 dấu markdown, trong đó dòng # feature/newfeature.js nằm trong khối code bị tính là heading vì regex chỉ khớp hình dạng dòng.

Một câu trả lời thì nhiễu, nên các kết luận lấy từ số gộp trên 300 câu mỗi checkpoint; câu Git chỉ để minh hoạ.

Đếm khuôn bằng regex

Bộ đếm có năm lớp: em dash; "not X, but Y" và các biến thể như "it's not X, it's Y"; liệt kê ba vế; một danh sách từ trang trọng ("delve", "crucial", "landscape"...); và dấu markdown, gồm heading, gạch đầu dòng, chữ đậm. Mỗi lớp tính trên 1.000 từ. Để có mốc, mình chạy cùng bộ đếm trên văn người viết: 3.000 câu trả lời trong Dolly 15k [4] và tập test của WikiText-103 [5].

Regex chỉ đếm hình dạng câu. "Not X, but Y" có lúc dùng đúng chỗ, và một danh sách gạch đầu dòng có lúc giúp người đọc. Điểm này chỉ dùng để so các checkpoint với nhau và với mốc người viết. Mình cũng chưa đọc tay mẫu nào để đo bộ đếm bắt đúng bao nhiêu phần trăm.

Bước nào cài khuôn nào

Mỗi checkpoint trả lời 100 prompt tiếng Anh cố định (giải thích khái niệm cho người mới, viết email, so sánh hai công cụ, tóm tắt), mỗi prompt 3 seed, tổng 300 câu.

Biểu đồ cột chồng điểm slop trên 1.000 từ cho năm checkpoint và hai tập văn người viết. Base 3,9, SFT 27,9, DPO 52,8, RLVR1 52,7, Instruct 52,7. Phần xanh dương là markdown, chiếm phần lớn cột ở SFT và gần như toàn bộ phần tăng thêm ở DPO. Dolly 15k ở mức 15,5 và WikiText ở 4,6, vẽ mờ bên phải.

Tổng điểm đi từ 3,9 ở base lên 27,9 ở SFT, 52,8 ở DPO, rồi đứng yên ở RLVR1 và Instruct. Ở 95 trên 100 prompt, DPO có điểm cao hơn SFT. Error bar là khoảng tin cậy 95% bootstrap theo prompt; tổng của DPO tính riêng từng seed nằm trong 50,2 tới 54,4, hẹp hơn nhiều so với khoảng cách giữa SFT và DPO.

Markdown gánh 22,8 trong 24,9 điểm DPO thêm vào. Bỏ markdown ra, tổng của năm checkpoint còn 2,9, 11,4, 13,5, 14,0 và 14,5, và bước nhảy lớn khi đó nằm ở SFT. Liệt kê ba vế tăng hơn ba lần ở SFT, từ 2,1 lên 7,1. Hai chỗ này khớp với Kannike: SFT cài khuôn tu từ, DPO nhân đôi tổng điểm.

"Not X, but Y" thì không khớp. Kannike thấy khuôn này tăng khoảng ba lần ở SFT. Ở đây nó là 0,2 ở base và 0,3 ở SFT, hai khoảng tin cậy chồng nhau. Sau DPO nó lên 0,6, tức 71 lần trong cả 300 câu.

DPO viết dài gần gấp đôi SFT, 411 so với 212 từ mỗi câu. Chấm lại chỉ trên 150 từ đầu của mỗi câu để bỏ khác biệt độ dài, SFT ra 24,1 còn DPO 48,7: phần tăng vẫn còn nguyên.

Em dash gần như chưa có trước DPO. Trong 300 câu, base có 0 câu dùng em dash, SFT có 3, DPO có 45. Dù vậy, mức 0,6 trên 1.000 từ sau DPO vẫn thấp hơn WikiText (1,1), nên ở model này em dash không đủ để nhận ra văn máy.

Base trả lời ngắn kiểu văn web, trung vị khoảng 60 token, và prompt dạng hỏi đáp không gợi markdown, nên mức markdown thấp của base có một phần do cách hỏi.

Câu "tốt hơn" có sloppy hơn không

DPO học từ các cặp câu trả lời gắn nhãn chosen và rejected. Kannike chấm 3.000 cặp của OLMo 2 và thấy câu chosen sloppy hơn ở 57% số cặp.

Ảnh chụp đoạn trong bài của Kannike, tô vàng câu nói trên 3.000 cặp, câu được gắn nhãn tốt hơn là câu sloppy hơn ở 57% số lần. Bên dưới là biểu đồ trong bài so câu preferred với câu rejected theo từng loại khuôn, markdown lines 38,1 so với 28,8.

Mình lấy 3.000 cặp cố định (seed 0) từ allenai/olmo-2-0425-1b-preference-mix [6] và chấm lượt trả lời cuối bằng bộ đếm của mình. Bỏ cặp hoà, câu chosen có điểm cao hơn ở 58,3% số cặp. Chấm cả 378.301 cặp ra 57,8%.

Thẻ dataset ghi pipeline tương tự Tulu 3, và paper Tulu 3 mô tả bước gán nhãn: GPT-4o chấm mỗi câu từ 1 tới 5 trên bốn tiêu chí, câu có điểm trung bình cao nhất thành chosen, câu rejected lấy ngẫu nhiên trong các câu điểm thấp hơn [7].

Ảnh chụp mục 5.2.1 paper Tulu 3, tô vàng hai cụm. Cụm đầu nói họ dùng GPT-4o-2024-0806 làm giám khảo chấm mỗi câu từ 1 tới 5 trên bốn khía cạnh. Cụm sau nói câu có điểm cao nhất được lấy làm chosen, còn rejected lấy ngẫu nhiên trong các câu có điểm trung bình thấp hơn.

Nhãn "tốt hơn" vì vậy là nhãn của GPT-4o. Còn câu trả lời đến từ hơn 20 model, từ Falcon 7B, MPT-30B tới Qwen2.5-32B và GPT-4. Ngay dòng đầu của bộ dữ liệu, câu chosen do Qwen2.5-14B-Instruct viết, câu rejected do MPT-30B-Chat viết.

Ảnh chụp trình xem dữ liệu trên Hugging Face của bộ olmo-2-0425-1b-preference-mix, dòng đầu tiên. Cột chosen_model tô vàng ghi Qwen/Qwen2.5-14B-Instruct, cột rejected_model tô vàng ghi mosaicml/mpt-30b-chat.

Với cặp kiểu này, nếu GPT-4o hay chọn model mạnh và model mạnh viết nhiều markdown hơn, câu chosen sẽ sloppy hơn kể cả khi GPT-4o chẳng để ý gì tới khuôn câu.

Hai biểu đồ. Bên trái, mỗi chấm là một model sinh câu trả lời, trục ngang là điểm slop trung bình theo thang log, trục dọc là phần trăm số lần được chọn. Các chấm đi lên từ Falcon 7B ở góc dưới trái tới GPT-4, Qwen2.5 32B và Gemma 2 27B ở góc trên phải. Bên phải là bốn cột hệ số Bradley-Terry của điểm slop, giảm từ 0,331 khi chỉ có điểm slop xuống 0,124 khi cố định model, 0,098 khi thêm độ dài, 0,055 khi bỏ markdown khỏi điểm slop.

Trên 21 model trong biểu đồ trái, mức slop trung bình và tỉ lệ được chọn tương quan Spearman 0,63. GPT-4 trung bình 164 trên 1.000 từ và được chọn 72% số lần xuất hiện. Falcon 7B 15 trên 1.000 từ và 14%. OLMo 2 1B SFT, cũng có câu trong bộ dữ liệu, 74 trên 1.000 từ và 31%. Mình bỏ GPT-4o và các câu không ghi tên model khỏi biểu đồ, vì cả hai đến từ cùng một tập con: câu chosen để trống tên model, câu rejected luôn ghi gpt-4o.

Để tách hai thứ ra, mình fit Bradley-Terry trên 378.255 cặp do hai model khác nhau viết. Chỉ có điểm slop thì hệ số là +0,331 trên một độ lệch chuẩn. Thêm hiệu ứng cố định cho từng model sinh câu, hệ số còn +0,124: khoảng hai phần ba hiệu ứng thô đến từ chuyện model nào viết câu trả lời. Thêm độ dài, còn +0,098. Bỏ markdown khỏi điểm slop, còn +0,055.

Trong cùng một cặp model, câu sloppy hơn vẫn được chọn nhỉnh hơn. Hệ số lớn nhất là độ dài (+0,110), rồi tới markdown (+0,077). "Not X, but Y" chỉ +0,018, còn em dash bị phạt nhẹ (-0,037). Markdown và độ dài cũng là hai thứ DPO đẩy lên ở OLMo 1B.

Hướng markdown có sẵn từ base

Muốn lấy hướng markdown, mình cần cặp câu chỉ khác nhau ở markdown. Mỗi cặp là một câu trả lời có markdown, đặt cạnh chính câu đó đã gỡ heading, gạch đầu dòng và chữ đậm. Đưa cả hai qua model, lấy residual stream ở đầu ra mỗi layer, trung bình theo token, rồi lấy hiệu. Trung bình hiệu trên 30 cặp là hướng markdown của layer đó; 34 cặp còn lại, từ những prompt khác, để kiểm. Hướng "not X, but Y" lấy giống vậy trên 64 cặp agent soạn, kiểu "The bug was not in the parser, but in the cache layer." đặt cạnh "The bug was in the cache layer."

Cách lấy hướng này là difference-in-means, quen thuộc trong các nghiên cứu steering [8]. Một hướng tách được dữ liệu mới chỉ cho thấy tương quan.

Model card của SFT ghi base là allenai/OLMo-2-0425-1B [9].

Ảnh chụp mục Model tree trên trang Hugging Face của OLMo-2-0425-1B-SFT. Dòng Base model trỏ tới allenai/OLMo-2-0425-1B, phần này được tô vàng.

Lấy hướng trên nhánh main của repo đó, cosine với hướng của SFT ra gần 0 ở mọi layer. Các ma trận trọng số cũng trực giao: q_proj ở layer 8 cho cosine 0,001, lm_head cho -0,007, trong khi SFT với DPO cho 1,00. Repo base có 268 nhánh checkpoint pretraining. Mình đọc hàng 1000 tới 2999 của ma trận embedding ở từng nhánh bằng HTTP range, khỏi tải cả model, rồi so với SFT.

Biểu đồ thanh ngang, cosine theo hàng của ma trận embedding so với SFT. Nhánh main 0,010 và checkpoint khởi tạo 0,015, gần bằng 0. Checkpoint cuối stage 1 đạt 0,9991, ba checkpoint stage 2 ingredient 1, 2, 3 đạt 0,9995, 0,9995 và 0,9999. Ingredient 3 tô xanh lá, main tô đỏ.

Nhánh main là một lần huấn luyện khác, xa SFT như một model khởi tạo ngẫu nhiên. Nhánh gần SFT nhất là stage2-ingredient3-step23852-tokens51B, cosine theo hàng 0,9999 và khoảng cách L2 tương đối 0,013. Hành vi của hai nhánh thì gần như nhau (tổng slop 4,3 trên main, 3,9 trên ingredient 3), nên ai chỉ đo hành vi sẽ không thấy gì lạ. Mình không biết Kannike so với nhánh nào. "Base" ở mọi số đo của mình là ingredient 3.

Hai biểu đồ đường theo layer từ 0 tới 16. Bên trái là hướng markdown, cosine giữa hướng của SFT, DPO, Instruct với hướng của base thật đi từ 1 ở embedding xuống khoảng 0,7 ở các layer giữa rồi lên 0,76 tới 0,87 ở layer 16. Bên phải là hướng not X, but Y, ba đường nằm ngang quanh 0,94. Ở cả hai bên, đường đứt nét đỏ của nhánh main nằm sát 0.

Với base đúng, ở bốn layer 4, 8, 12, 16, hướng markdown của SFT, DPO và Instruct có cosine 0,73 tới 0,87 với hướng của base; hướng "not X, but Y" 0,88 tới 0,95. Cả hai hướng đã có ở base và đổi rất ít qua SFT, DPO, Instruct. Ở mọi checkpoint, kể cả base, hai hướng tách đúng 100% cặp để kiểm ở mọi layer.

Logit lens [10] cho biết hướng đó đẩy token nào: nhân hướng với trọng số của final norm rồi đưa qua lm_head. Hướng markdown ở layer 16 đẩy các biến thể của ** (" **", "**:", ":**") ở cả base lẫn DPO. Đầu kia, ở DPO, là "\n\n" và "...\n\n".

Base có hướng markdown mà vẫn viết văn xuôi, nên mình đo xem model đi theo hướng từ lúc nào. Mình so trạng thái ở dấu xuống dòng ngay trước dòng markdown đầu tiên của mỗi câu trả lời với trạng thái ở các dấu xuống dòng trước một dòng văn xuôi, trong phần câu trả lời trước chỗ markdown đầu tiên. Cả hai nhóm đều là token \n, nên khác biệt không đến từ bản thân token.

Biểu đồ đường theo layer 1 tới 16, độ lệch về phía markdown ở dấu xuống dòng trước dòng markdown đầu tiên, tính bằng độ lệch chuẩn của nhóm văn xuôi. Bốn đường SFT, DPO, RLVR1, Instruct âm ở các layer đầu, quanh 0 ở các layer giữa, rồi leo dần từ layer 11 và đạt khoảng 2 ở layer 16 với DPO, RLVR1, Instruct, 1,7 với SFT.

Ở layer 16, dấu xuống dòng trước dòng markdown đầu tiên đã lệch về phía markdown 2,1 độ lệch chuẩn ở DPO và 1,7 ở SFT. Ở các layer giữa hiệu gần 0. Phép so này dùng 150 câu mỗi checkpoint (50 prompt chưa dùng để lấy hướng, mỗi prompt 3 seed), và base chỉ có 9 vị trí như vậy, quá ít để so. Độ chiếu ở token cuối của prompt chỉ tương quan yếu với tỉ lệ markdown của câu trả lời (Spearman -0,14 tới 0,28 trên 50 prompt), nên mình chưa thấy dấu hiệu model chọn markdown từ trước chữ đầu tiên.

Với "not X, but Y" thì không thấy gì trước chữ "not". Kannike báo tín hiệu tăng khoảng 1 độ lệch chuẩn ở từ đứng trước "not" trên Qwen3-4B; ở OLMo DPO, hiệu ở bốn layer đó nằm trong -0,48 tới -0,04.

Trừ hướng markdown

Nếu hướng markdown thật sự lái model, trừ nó đi trong lúc sinh thì markdown phải giảm. Trên DPO, mình sửa đầu ra của block 12 tới 16 ở mọi vị trí theo \(h \leftarrow h - \alpha \lVert h \rVert d\), với \(d\) là hướng markdown đơn vị của từng layer và α từ 0,01 tới 0,6. Đối chứng là một vector ngẫu nhiên mỗi layer, trừ với cùng các mức α. Mỗi điều kiện sinh 100 câu: 50 prompt chưa dùng để lấy hướng, mỗi prompt 2 mẫu, cùng seed giữa các điều kiện.

Hai biểu đồ theo alpha. Bên trái là markdown còn lại trên 1.000 từ. Đường trừ hướng markdown giảm từ 41,4 xuống 24,3 ở alpha 0,05 và về 0 từ alpha 0,2. Đường trừ hướng ngẫu nhiên giảm chậm, còn 30,2 ở alpha 0,2, rồi mới tụt từ alpha 0,3. Một điểm hình thoi cam ở mức 17,9 là kiểu gỡ hẳn thành phần. Bên phải là phần trăm câu vỡ, đường hướng markdown nằm sát 0 tới alpha 0,05, lên 29% ở 0,1 và 100% từ 0,2, đường ngẫu nhiên chỉ vọt lên từ 0,4.

Ở α 0,05, markdown giảm từ 41,4 xuống 24,3 trên 1.000 từ, tức 41%, và khoảng tin cậy không chồng với lúc không can thiệp. Chỉ 1% câu vỡ, perplexity của model trên văn người viết (Dolly và WikiText) không đổi. Hướng ngẫu nhiên cùng α giảm 7%. Nó phải tới α 0,3 mới giảm được 50%, và khi đó perplexity trên văn người viết đã tăng 36 tới 50%. Trừ hướng markdown ở 0,05 còn kéo các lớp khác xuống theo: tổng slop không tính markdown từ 16,0 còn 10,6, từ trang trọng từ 5,5 còn 3,2.

Ở α 0,1, 29% câu vỡ; từ 0,2 là 100%.

Câu trả lời Git của DPO ở năm mức can thiệp. Không can thiệp, 519 từ và 40 dấu markdown, có heading và chữ đậm. Alpha 0,05, 332 từ và 12 dấu, vẫn là danh sách đánh số có chữ đậm. Alpha 0,1, 416 từ và 10 dấu, danh sách còn số nhưng mất chữ đậm. Alpha 0,2 chỉ còn A và ba chấm. Alpha 0,3 là những dòng ba chấm cách nhau bởi dòng trống.

Câu Git ở đây sinh lại bằng code steering, nên bản không can thiệp là một mẫu khác với câu ở đầu bài: 519 từ, 40 dấu markdown. Ở 0,05 câu trả lời vẫn là danh sách đánh số có chữ đậm ("1. The state of your project..."), heading đã mất. Ở 0,1 danh sách còn số nhưng hết chữ đậm. Từ 0,2 câu trả lời chỉ còn "A..." hoặc hàng loạt dòng "...".

Khi vỡ, model vẫn xuống dòng như sắp mở một danh sách, rồi kẹt trong dòng trống và dấu ba chấm. Đó là đầu văn xuôi của hướng markdown trong logit lens ("...\n\n"). Không có mức α nào xoá hết markdown mà văn bản còn đọc được.

Gỡ hẳn thành phần dọc theo hướng, \(h \leftarrow h - (h \cdot d)\, d\), giảm markdown 57% mà độ dài và các lớp slop khác giữ nguyên (16,8 so với 16,0). Kannike báo chiều ngược lại trên Qwen3-4B: gỡ hướng đó làm slop tăng tới 89%. Hướng của Kannike gộp nhiều khuôn, lại khác model và cách chấm, nên mình chưa biết hai kết quả này có mâu thuẫn thật hay không.

Ở α 0,1, model đôi khi viết "1: Know your audience" thay cho "1. ", và bộ đếm không bắt dạng đó, nên con số markdown giảm ở α 0,1 hơi lớn hơn thay đổi thật.

Câu tiếng Việt trên Qwen3-4B

OLMo 1B gần như không học tiếng Việt, nên mình chạy thêm Qwen3-4B, model chính của Kannike. So embedding cho thấy Qwen3-4B-Instruct-2507 đúng là đi từ Qwen3-4B-Base [11], cosine theo hàng có trung vị 0,982. Post-training của Qwen sửa trọng số nhiều hơn của OLMo: khoảng cách L2 tương đối của embedding là 0,21, so với 0,013 ở OLMo.

Cặp câu tiếng Việt lấy theo blacklist stop-slop của mình, bộ 117 pattern gom từ những lần sửa bài omelet.tech. Có 48 cặp theo khuôn tương phản, đặt câu có khuôn cạnh câu nói thẳng vế sau, ví dụ "Lỗi không nằm ở bộ phân tích cú pháp, mà nằm ở lớp cache." với "Lỗi nằm ở lớp cache.". Thêm hai bộ đối chứng, một tiếng Anh một tiếng Việt, mỗi bộ 24 cặp kiểu "Hôm nay trời không mưa." với "Hôm nay trời mưa.". Câu có khuôn nào cũng chứa chữ "không" hay "not", nên hướng lấy được có thể chỉ là hướng "câu này phủ định". Bộ đối chứng đo xem phần đó lớn cỡ nào.

Lần chạy đầu cho mọi hướng giống hệt nhau, cosine giữa hướng tiếng Anh và hướng tiếng Việt ra 1,00. Ở layer 9 tới 27 của Qwen, riêng chiều số 4 của residual stream chiếm 86 tới 93% bình phương độ dài của mọi hướng, kể cả hướng phủ định. Đây là massive activation, hiện tượng vài chiều mang giá trị lớn hơn phần còn lại hàng nghìn lần [12]. Mình bỏ các chiều có trung bình trị tuyệt đối lớn hơn 10 lần trung vị của layer rồi đo lại. Số của OLMo gần như không đổi giữa hai lần chạy.

Hai biểu đồ. Bên trái là các cột phần trăm hiệu ứng mà cặp phủ định thường đi được dọc hướng not X, but Y, so với cặp có khuôn. Qwen layer 18 là 66 với tiếng Anh và 51 với tiếng Việt, layer 27 là 63 và 57, OLMo DPO layer 12 là 50 và 41, layer 16 là 54 và 48. Bên phải là logit lens của Qwen3-4B Instruct theo thang log, chấm đỏ của chữ Trung nghĩa là mà là nằm ở hạng 1 ở cả sáu dòng, chấm tím sondern ở hạng 2 tới 7, chấm cam chữ mà và chấm xám chữ but nằm ở hạng hàng nghìn tới hàng trăm nghìn.

Sau khi bỏ các chiều đó, hướng "not X, but Y" học từ câu tiếng Anh tách đúng mọi cặp tiếng Việt, ở cả Qwen lẫn OLMo 1B. Cosine giữa hướng tiếng Anh và hướng tiếng Việt là 0,71 tới 0,77 ở Qwen, 0,52 tới 0,54 ở OLMo DPO.

Khoảng một nửa hướng là phủ định thường: cặp phủ định đi dọc hướng được 37 tới 74% quãng đường của cặp có khuôn, tuỳ model, tiếng và layer. Trừ phần phủ định khỏi hướng, phần còn lại vẫn tách đúng 100% cặp để kiểm ở cả hai thứ tiếng, nghĩa là trong hướng có một phần riêng cho cấu trúc "mà là", tách được khỏi chữ "không".

Ở Qwen, hướng này không đẩy chữ "mà" lên.

Trích file kết quả qwen_instruct_masked.json, mục logit lens của hướng tiếng Việt ở layer 27. Danh sách token được đẩy lên mở đầu bằng chữ Trung nghĩa là mà là, tô vàng, rồi tới sondern, necessarily, merely, nor. Phần hạng của các token dò cho chữ Trung hạng 1, sondern hạng 2, but hạng 9.495, và chữ mà hạng 4.979, tô cam.

Cả hướng tiếng Anh lẫn hướng tiếng Việt đều đẩy "而是", chữ Trung nghĩa là "mà là", lên hạng 1 trên 151.936 token ở layer 18, 27 và 36. " sondern" của tiếng Đức đứng hạng 2 tới 7. " mà" là một token nguyên trong tokenizer của Qwen nhưng chỉ đứng hạng 2.070 tới 45.650 với hướng tiếng Việt. Bỏ phần phủ định ra, "而是" vẫn hạng 1 ở layer 27, cả hai thứ tiếng. Ở Qwen Base, "而是" cũng ở hạng 1 tới 5, và hướng của Base với hướng của Instruct có cosine 0,90 tới 0,94: như hướng markdown ở OLMo, hướng này có sẵn trước post-training.

Bản nháp agent viết cho omelet.tech

Repo blog có 10 commit với message nói việc dọn giọng máy, trên 8 bài, từ 12/08 tới 27/09/2026. Bản trước là bài ở commit cha, bản sau là bài ở commit đó. Mình chỉ chấm phần văn, bỏ code, công thức, đường link; đơn vị là hit blacklist trên 1.000 chữ.

Biểu đồ dạng quả tạ cho tám bài, chấm đỏ là bản nháp đầu, chấm xanh là bản sau lượt dọn cuối trong 10 lượt đếm, tính bằng hit blacklist trên 1.000 chữ. Bài Amazon đi từ khoảng 12,7 về 0. Bài DeepSeek-V4 từ khoảng 10,5 về 6,2. Bài Phép toán ứng dụng thực tế từ 3,4 về 2,1. Năm bài còn lại thay đổi rất ít, đều dưới 2.

Tính cả 10 lượt, số hit đi từ 131 xuống 62, tức 3,92 xuống 1,88 trên 1.000 chữ. Hai lượt gánh gần hết: bài DeepSeek ngày 21/08 bỏ 37 hit, bài Amazon ngày 20/09 bỏ 32 hit. Năm lượt sớm trên loạt livestream và bài "Trọng số chưa bao giờ là sản phẩm" thay đổi rất ít, một phần vì bản nháp của chúng vốn ít hit.

Lượt dọn cũng chèn 10 hit mà bản trước không có. Lượt dọn bài Amazon ngày 20/09 chèn ba câu kể chuyện đi lấy tư liệu, lượt 27/09 bỏ chúng, và blacklist có thêm nhóm "kể lể hậu trường lấy tư liệu". Nhóm sót nhiều nhất sau 10 lượt là dịch thuật ngữ quá tay, 43 hit trước và 42 sau, hầu hết ở bài DeepSeek: sau lượt dọn ngày 21/08, bài đó vẫn còn 7 lần "sổ ghi nhớ" cho KV cache và 5 lần "cú ngắt". Ba commit tiếp theo trong vòng 41 phút, message không nói chuyện dọn giọng nên nằm ngoài 10 lượt mình đếm, mới gỡ hai cụm đó cùng câu "đơn giản tới mức khó chịu". Bài DeepSeek trên blog hiện còn 2 hit.

Blacklist gom từ chính những lượt sửa này, và skill stop-slop còn dẫn nguyên văn câu trong bài DeepSeek làm ví dụ, nên bản "trước" đương nhiên bị đếm cao.

Hai khung. Khung trên trích dòng 83 tới 91 của file blacklist, dòng 89 tô vàng là không phải A, mà, ngoặc là, dấu hỏi, B. Khung dưới chạy grep với pattern đó, câu thật về slop và thói quen của model không khớp, mã thoát 1, còn câu mẫu không phải A, mà là B thì khớp.

Khuôn tương phản thì blacklist không đo được. Dòng 89 là nguyên văn không phải A, mà (là )?B, với A và B là chữ cái thật, nên nó chỉ khớp đúng câu mẫu. Cả 48 câu có khuôn trong bộ cặp tiếng Việt đều lọt qua.

Đào sâu: Mấy chỗ suýt đo sai

Image NGC nvcr.io/nvidia/vllm:26.06-py3 bật sẵn TF32 cho phép nhân ma trận. Sai số làm tròn tạo khác biệt giả giữa các vị trí của cùng một token, nên phép so dấu xuống dòng trước markdown với dấu xuống dòng trước văn xuôi ra hiệu khác 0 ngay ở layer 0, nơi hai token giống hệt nhau phải có embedding giống hệt nhau. Tắt bằng TORCH_ALLOW_TF32_CUBLAS_OVERRIDE=0 thì mọi vị trí của cùng một token cho đúng một vector ở layer 0.

Chọn layer có d' cao nhất thì hướng "not X, but Y" rơi vào layer 1, tức chỉ là tín hiệu từ vựng: chữ "not" và "but" có mặt hay không. Mọi số liệu đọc ở layer cố định (4, 8, 12, 16 với OLMo; 9, 18, 27, 36 với Qwen).

Ở layer 16 của DPO, norm residual trung bình là 43,6 và độ lệch chuẩn của độ chiếu lên hướng markdown là 4,0. α 0,05 vì vậy dịch khoảng 0,55 độ lệch chuẩn ở layer 16, khoảng 0,6 ở layer 12, và cộng dồn qua năm layer.

Thước đo độ vỡ đầu tiên là perplexity của DPO không can thiệp trên câu sinh ra khi steering. Nó gắn cờ cả văn xuôi trôi chảy, vì DPO quen markdown nên thấy văn xuôi "lạ"; tính cả tiêu chí đó thì α 0,1 có 76% câu vỡ, trong khi đọc tay các câu bị gắn cờ đều đọc được. Nó cũng bỏ sót rác kiểu "mermermermer..." ở hướng ngẫu nhiên α 0,6, vì chuỗi lặp ký tự dễ đoán nên perplexity thấp. Thước đo cuối cùng gọi một câu là vỡ cứng khi nó dưới 20 từ, hoặc tỉ lệ nén zlib thấp hơn phân vị 1% của câu không can thiệp, hoặc tỉ lệ từ nằm ngoài từ vựng của các câu đã đếm khuôn cao hơn phân vị 99%, hoặc tỉ lệ lặp 4-gram cao hơn phân vị 99%.

Ngưỡng 10 lần trung vị để bỏ chiều massive là mình chọn tay. Ở layer 18 của Qwen nó bỏ 8 chiều (0, 3, 4, 19, 24, 55, 100, 396), ở OLMo DPO chỉ 2 tới 4 chiều mỗi layer. Sau khi bỏ, chiều lớn nhất chỉ còn chiếm khoảng 5% bình phương độ dài của hướng. Hướng markdown của OLMo dùng cho phần steering chưa bao giờ bị một chiều chi phối (tối đa 18%), nên phần đó không dính lỗi này.

Những gì chưa kiểm

Mình chỉ đo model 1B và 4B, không đo model đóng, nên không suy được gì về GPT hay Claude. Các cặp câu tiếng Anh lẫn tiếng Việt do agent viết, chưa có người đọc lại.

Thẻ dataset ghi bộ preference dùng cho DPO của OLMo-2-0325-32B-SFT, trong khi model card của bản 1B DPO liệt kê chính bộ đó [13]. Mình chưa xác nhận được bản 1B dùng đúng bộ này.

Mình mới thử steering trên một bộ layer (12 tới 16) với hai kiểu can thiệp. Một cách khác đáng thử là kẹp độ chiếu về mức của văn xuôi, để model không bị đẩy sang cực ba chấm. Tới ngày 18/10/2026, Kannike chưa công bố code hay paper, nên mình chưa so được cách đếm của hai bên.

Mình chưa hiểu phần tiếng Việt. Ở OLMo 1B, "not X, but Y" hiếm và gần như không được nhãn preference thưởng, vậy mà khuôn tương phản đứng đầu phần tiếng Việt của stop-slop. Agent viết các bản nháp cho blog chạy trên model đóng, và mình không có checkpoint của nó để lần ngược từng bước.

Bình

Phụ lục: Citations (13)
  1. Erik Markus Kannike. Where AI slop comes from, and how to turn it down inside the model. 100toolkit.com. 2026-10. Blog cá nhân, chưa bình duyệt; code và prompt hẹn ra cùng paper. Kết quả: base đã có hướng slop nhưng viết gần như không slop; SFT cài khuôn tu từ, DPO nhân đôi điểm; 57% cặp preference có câu chosen sloppy hơn; gỡ hướng làm slop tăng tới 89%; tín hiệu tăng khoảng 1 SD trước chữ not trên Qwen3-4B.
  2. Erik Markus Kannike. Slop, neuron by neuron: the two neurons behind "not X, but Y". 100toolkit.com. 2026-10. Bài thứ hai, chỉ làm trên Qwen3-4B, lần khuôn "not X, but Y" tới hai neuron.
  3. allenai/OLMo-2-0425-1B. Hugging Face, Ai2. Repo base, 268 nhánh checkpoint pretraining. Nhánh main (a1847dff) là một lần huấn luyện khác; cha của SFT là nhánh stage2-ingredient3-step23852-tokens51B (f83cd641).
  4. databricks/databricks-dolly-15k. Hugging Face, Databricks. Hỏi đáp do nhân viên Databricks viết.
  5. Stephen Merity, Caiming Xiong, James Bradbury, Richard Socher. Pointer Sentinel Mixture Models. 2016-09-26. Paper giới thiệu WikiText-103.
  6. allenai/olmo-2-0425-1b-preference-mix. Hugging Face, Ai2. 378.301 cặp, ODC-BY, revision c6454f3d. Thẻ dataset ghi pipeline tương tự Tulu 3 và ghi bộ này dùng cho DPO của OLMo-2-0325-32B-SFT.
  7. Nathan Lambert và cộng sự. Tulu 3: Pushing Frontiers in Open Language Model Post-Training. 2024-11-22. Mục 5.2.1: GPT-4o-2024-0806 chấm mỗi câu 1 tới 5 trên helpfulness, instruction-following, honesty, truthfulness; câu điểm trung bình cao nhất là chosen, rejected lấy ngẫu nhiên trong các câu điểm thấp hơn.
  8. Nina Panickssery (Rimsky), Nick Gabrieli, Julian Schulz, Meg Tong, Evan Hubinger, Alexander Matt Turner. Steering Llama 2 via Contrastive Activation Addition. 2023-12-09. Lấy hướng bằng trung bình hiệu activation trên cặp câu tương phản rồi cộng hoặc trừ vào residual stream.
  9. allenai/OLMo-2-0425-1B-SFT. Hugging Face, Ai2. Model card ghi base_model allenai/OLMo-2-0425-1B. Revision 0d85a3d0.
  10. nostalgebraist. interpreting GPT: the logit lens. LessWrong. 2020-08-31. Đọc trạng thái giữa chừng qua lớp unembedding.
  11. Qwen/Qwen3-4B-Instruct-2507. Hugging Face, Qwen. Revision cdbee75f; base là Qwen/Qwen3-4B-Base revision 906bfd4b.
  12. Mingjie Sun, Xinlei Chen, J. Zico Kolter, Zhuang Liu. Massive Activations in Large Language Models. 2024-02-27. Vài chiều của hidden state mang giá trị lớn hơn phần còn lại nhiều bậc độ lớn.
  13. allenai/OLMo-2-0425-1B-DPO. Hugging Face, Ai2. Model card liệt kê allenai/olmo-2-0425-1b-preference-mix. Revision c4b04859.