Sau khi thu được 24.216 item thô, bước tiếp theo là gán nhãn. Dùng deepseek-v4.1-flash qua gateway, taxonomy cố định 22 nhãn vấn đề và 15 nhãn cách làm tạm, mỗi item trả về: một nhãn vấn đề, tối đa ba nhãn cách làm tạm, tên tool, vai trò người nói, mức nặng 1–5, và một trích dẫn nguyên văn tối đa 180 ký tự. Gọi theo batch 15 item, temperature 0,1.
Số thật từng bước
- Lọc trước khi tốn token: bỏ item dưới 110 ký tự (riêng tiêu đề Stack Exchange 40 ký tự), review 1–2 sao luôn giữ, các item khác phải khớp một danh sách từ khoá tín hiệu. 24.216 → 11.922 ứng viên, và sau khi khử theo 160 ký tự đầu còn 9.318.
- 11.922 ứng viên chia batch 15 là 795 lần gọi, cộng thêm 172 lần phải chia đôi batch vì JSON hỏng và 72 lần retry vì lỗi mạng. Log ghi được 13 lần chạy, mỗi lần khoảng 4.700 ứng viên, nhưng chỉ 18.529 dòng được ghi lại.
- 18.529 dòng kết quả, trong đó 7.450 dòng có nhãn nằm trong taxonomy (40,2%). Phần còn lại: model trả về null (không phải than phiền về công việc) hoặc trả về một nhãn không tồn tại.
- 1.903 dòng trùng khít từng byte với một dòng khác. Sau khi khử trùng theo (nguồn, 130 ký tự đầu của trích dẫn): 6.672 dòng.
- 778 dòng trong số đó thuộc 534 nhóm cùng (nguồn, trích dẫn) — trong đó 118 nhóm có nhãn vấn đề khác nhau giữa các lần phân loại, không có nhãn nào chiếm đa số rõ ràng để chọn.
- Ghi chú quan trọng: cơ chế resume dựa vào việc bỏ qua những dòng có trích dẫn đã thấy, mà tỷ lệ model trả về trích dẫn rỗng là khoảng 1/4 (4.745 trên 18.529). Nghĩa là ngưỡng khử lặp phụ thuộc vào việc model có trích dẫn hay không, chứ không phải vào dữ liệu.
Bốn lỗi im lặng, không có exception nào
- Trường ways bị model trả về dạng object thay vì chuỗi: 29 lần trên toàn corpus. Trong đó 26 object không có mã nào, 1 lần mã nằm sai chỗ (mã vấn đề lọt vào nhãn cách làm tạm). Code đọc dữ liệu có xử lý cả hai dạng, nên không crash, chỉ âm thầm mất dữ liệu.
- Nhãn cách làm tạm không nằm trong danh mục: 5 dòng, gồm một nhãn còn dính dấu “>” phía trước.
- Câu trả lời hợp lệ: 22 nhãn vấn đề đều được dùng ít nhất 27 lần, nhãn nhiều nhất 1.162 lần. Không có dấu hiệu model bị kẹt ở một nhãn — thang đo dùng được.
- Mức nặng phân bố hợp lý: trung bình 3,31, độ lệch chuẩn 0,89, dải 1–5, không có giá trị ngoài khoảng.
Cái đáng giá nhất hoá ra không phải nhãn
59,7% item không được gán nhãn vấn đề nào. Nhìn qua thì đó là lãng phí: đã trả tiền cho 11.922 ứng viên mà chỉ 7.450 cái có nhãn. Nhưng phần lớn số null là thật — câu hỏi cách dùng hàm, khoe thành tích, quảng cáo, hoặc review 5 sao. Bộ lọc theo từ khoá chỉ lọc theo hình thức, và LLM là bước duy nhất trả lời được câu “cái này có phải than phiền không”. Nếu thay bằng bộ lọc chặt hơn, ta mất nhiều item thật hơn là tiết kiệm token.
Cảnh báo đi kèm: không đo được token tiêu thụ. Script đếm ký tự của phần đã lưu, nhưng phần gửi đi (SYS + payload, mỗi item cắt 1.100 ký tự) dài hơn nhiều, và gateway được dùng cũng không log usage — nên con số “1,5 nghìn vào + 800 ra cho mỗi lần gọi” là ước lượng gián tiếp, không phải số đo.
Quy trình đầy đủ, kèm cách tự kiểm tra các lỗi trên ở bài Checklist 8 điểm; các bài học chỉ nhìn thấy khi tổng hợp cả corpus ở bài Bốn điều chỉ thấy khi đã có corpus 2 vạn item.