Tầng 1 — Embeddings: cơ chế thật
Đây là tầng bị hiểu sai nhiều nhất, nên đi chậm.
1.1 Kiến trúc tối giản mà vẫn là embedding model thật
Phần tiêu đề “1.1 Kiến trúc tối giản mà vẫn là embedding model thật”tokens → tra bảng vector → mean pooling → chuẩn hoá L2 → z E[t] u = mean(E[t]) z = u/‖u‖Chỉ một tham số học được: bảng E (V × d) — mỗi từ một vector. Không attention,
không transformer. Nhưng cơ chế HỌC thì y hệt các model thật. Model thật thay
mean pooling bằng transformer (để vector của một từ phụ thuộc ngữ cảnh xung quanh),
nhưng hàm loss và cách sinh dữ liệu thì giống.
Vì sao phải chuẩn hoá L2? Ba lý do, đều thật:
- Sau chuẩn hoá, dot product chính là cosine. Đây là lý do vector DB yêu cầu vector đã normalize — dùng phép dot nhanh hơn mà vẫn ra cosine.
- Nó tách hướng khỏi độ dài. Độ dài vector tương quan với tần suất từ, không phải với ý nghĩa. Bỏ độ dài là bỏ một nhiễu.
- Gradient qua chuẩn hoá chỉ còn thành phần tiếp tuyến với mặt cầu:
dL/du = (dL/dz − (dL/dz · z)z)/‖u‖. Số hạng trừ đi là thành phần dọc theo z — kéo z dài/ngắn không đổi gì (sẽ bị chuẩn hoá lại), nên gradient hướng đó = 0. Chuẩn hoá khiến gradient chỉ có thể QUAY vector, không thể phóng to nó.
1.2 Bi-encoder vs cross-encoder — bất đối xứng chi phí
Phần tiêu đề “1.2 Bi-encoder vs cross-encoder — bất đối xứng chi phí”Đây là kiến thức nền cho toàn bộ Tầng 4 (reranking).
| Bi-encoder | Cross-encoder | |
|---|---|---|
| Cách chạy | encode(q) và encode(d) độc lập | encode(q ⊕ d) cùng nhau |
| Attention | q không bao giờ “thấy” d | mọi token của q thấy mọi token của d |
| Index trước được? | ✅ toàn bộ corpus encode offline | ❌ phải chạy tại query time |
| Chi phí query | 1 lần encode + tìm vector | N lần forward pass |
| Chất lượng | thấp hơn | cao hơn rõ rệt |
Toàn bộ ngành retrieval hiện đại là hệ quả của bảng này: dùng bi-encoder để lấy top-100 (rẻ), dùng cross-encoder để xếp lại top-100 (đắt nhưng chỉ 100 lần). Đó là two-stage pipeline, và là kỹ thuật có ROI cao nhất trong toàn bộ tài liệu này.
1.3 Contrastive learning — vì sao model “biết” nghĩa
Phần tiêu đề “1.3 Contrastive learning — vì sao model “biết” nghĩa”Hàm loss là InfoNCE. Cho batch B cặp khớp nhau (a_i, b_i):
In-batch negatives — ý tưởng cốt lõi. Trong ma trận S, S[i,i] là cặp đúng.
Toàn bộ B−1 phần tử còn lại trên hàng i là cặp sai, và chúng miễn phí — không
cần gán nhãn negative, chỉ cần lấy mẫu khác trong cùng batch.
→ Đây là lý do embedding model train được ở quy mô hàng tỷ cặp. → Và là lý do mọi bài báo về embedding đều khoe batch size: batch càng lớn, càng nhiều negative mỗi bước, tín hiệu học càng mạnh.
Vì sao chỉ dùng cặp ĐÚNG mà model lại biết nghĩa? Vì để giảm loss, cách duy nhất là đặt các từ hay xuất hiện trong cùng ngữ cảnh vào cùng vùng không gian. Ngữ nghĩa là sản phẩm phụ của bài toán phân biệt “cặp nào đi với cặp nào.” Không ai dạy model định nghĩa từ.
Gradient của softmax + cross-entropy gọn đến mức đáng ngờ nhưng đúng:
dL/dS = (P − I)/B. Đã kiểm chứng bằng sai phân hữu hạn, sai số 8e-8.
Dữ liệu train ở đâu ra khi không có nhãn? Khai thác cấu trúc sẵn có: tiêu đề ↔ nội dung, câu ↔ câu cùng đoạn, câu hỏi ↔ câu trả lời trong forum, anchor text ↔ trang đích. Đây là self-supervised, và là lý do pre-train được ở quy mô web.
1.4 Temperature τ — và bài học “loss thấp ≠ retrieval tốt”
Phần tiêu đề “1.4 Temperature τ — và bài học “loss thấp ≠ retrieval tốt””Chia cho τ trước softmax = phóng đại khoảng cách giữa các điểm.
- τ nhỏ (0.01): softmax rất nhọn → phạt cực nặng nếu một negative lọt gần positive. Học “khắt khe”, tách khái niệm gần nhau rất mạnh, dễ bất ổn.
- τ lớn (1.0): phân bố mềm → mọi negative bị đẩy ra nhẹ như nhau. Êm hơn, ranh giới mờ hơn.
Model thật thường dùng 0.01–0.05, và τ hay là tham số học được.
Đo thực tế (60 epoch, cùng seed, cùng dữ liệu):
| loss cuối | title→doc acc | nDCG@5 | cosine TB giữa 2 doc | |
|---|---|---|---|---|
| τ=0.01 | 0.354 | 1.000 | 0.723 | +0.409 |
| τ=0.05 | 0.350 | 1.000 | 0.753 | +0.212 |
| τ=0.2 | 0.484 | 1.000 | 0.751 | −0.019 |
| τ=1.0 | 2.502 | 1.000 | 0.782 | −0.018 |
Hai điều quan trọng ở đây:
(a) τ=1.0 có loss cao gấp 7 lần nhưng nDCG tốt nhất. τ nhỏ khớp rất giỏi mục tiêu huấn luyện (tách các cặp train) nhưng làm méo không gian với truy vấn chưa từng thấy. → Đừng bao giờ chọn siêu tham số embedding bằng training loss. Phải chọn bằng retrieval metric trên held-out set.
(b) τ nhỏ gây anisotropy. cosine trung bình giữa hai tài liệu bất kỳ: +0.409 ở τ=0.01 so với −0.018 ở τ=1.0. Đây là liên hệ đo được giữa temperature và hiện tượng hình nón — xem mục sau.
1.5 Anisotropy (cone effect) — và cách sửa gần như miễn phí
Phần tiêu đề “1.5 Anisotropy (cone effect) — và cách sửa gần như miễn phí”Nếu không gian đẳng hướng, hai vector ngẫu nhiên gần như vuông góc → cosine trung bình ≈ 0. Thực tế mọi embedding model đều cho con số này dương và lớn: mọi vector chen chúc trong một hình nón hẹp. Hệ quả: cosine 0.8 nghe như “rất giống” nhưng thực ra có thể là mức nền.
Đo thực tế:
| không gian | cosine TB giữa 2 doc bất kỳ | nDCG@5 |
|---|---|---|
| ngẫu nhiên (chưa train) | +0.106 | 0.644 |
| đã train | +0.212 | 0.753 |
| đã train + trừ tâm | −0.019 | 0.799 |
Hai phát hiện:
- Train làm anisotropy TỆ HƠN (+0.106 → +0.212). Hình nón siết lại chứ không mở ra. Đây là hệ quả tự nhiên của contrastive loss trên dữ liệu hữu hạn.
- Trừ vector trung bình của corpus khỏi mọi embedding: +6.1% nDCG, chi phí ~0. Một phép trừ vector. Không train lại, không đổi model.
→ Nên áp dụng vào AI Agent: thử centering (và whitening — ZCA/PCA trên ma trận hiệp phương sai) trên embedding hiện tại. Đây là thay đổi 5 dòng code, và ở đây nó cho +6%.
Lưu ý sản xuất: tâm phải tính trên corpus, và phải lưu lại để áp dụng cho cả truy vấn mới. Nếu corpus thay đổi nhiều thì tính lại định kỳ.
1.6 Matryoshka (MRL) — chiều vector là thứ mua được
Phần tiêu đề “1.6 Matryoshka (MRL) — chiều vector là thứ mua được”Ý tưởng: tính loss riêng cho từng tiền tố chiều rồi cộng lại.
Hệ quả: 48 chiều đầu buộc phải tự mình làm được việc, 192 chiều đầu cũng vậy. Kết quả là cắt vector còn 1/8 chiều mà chất lượng giảm rất ít — tiết kiệm bộ nhớ và tăng tốc ANN gần như miễn phí.
Đo thực tế (nDCG@5, % so với 128 chiều):
| d=128 | d=64 | d=32 | d=16 | d=8 | |
|---|---|---|---|---|---|
| train thường | 0.753 | 0.748 (−1%) | 0.701 (−7%) | 0.663 (−12%) | 0.603 (−20%) |
| train Matryoshka | 0.768 | 0.772 (+1%) | 0.709 (−8%) | 0.665 (−13%) | 0.624 (−19%) |
Ngược lại lý thuyết: lợi ích MRL ở đây rất nhỏ (−19% vs −20% ở d=8). Vì sao? Vì 128 chiều cho từ vựng 637 từ và 50 tài liệu là quá thừa — thông tin vốn đã nằm trong không gian chiều thấp, nên train thường cũng tự trải đều. MRL chỉ tỏ ra giá trị khi chiều đầy đủ thực sự cần thiết, tức ở quy mô thật.
→ Bài học phương pháp: kết luận từ toy corpus không tự động chuyển sang production. Cái toy chứng minh được là cơ chế; còn độ lớn hiệu ứng phải đo trên dữ liệu thật.
1.7 Hard negatives — khi in-batch không còn đủ
Phần tiêu đề “1.7 Hard negatives — khi in-batch không còn đủ”In-batch negatives là các mẫu ngẫu nhiên khác trong batch. Sau một thời gian train, chúng trở nên quá dễ — model đã tách được “gói dịch vụ” khỏi “mã lỗi API” từ lâu, gradient gần như bằng 0, việc học chững lại.
Hard negative = tài liệu trông rất giống positive nhưng sai. Cách khai thác:
- Dùng BM25 hoặc chính model hiện tại lấy top-k cho query.
- Loại bỏ positive đã biết.
- Phần còn lại là hard negatives — nạp vào loss như negative tường minh.
Cạm bẫy: false negative. Trong top-k đó rất có thể có tài liệu thật sự liên quan mà golden set chưa gán nhãn. Dạy model đẩy nó ra là dạy sai. Cách giảm thiểu: bỏ qua các mẫu có điểm quá cao (nghi là positive chưa gán nhãn), hoặc dùng cross-encoder lọc trước.
1.8 Phát hiện lớn nhất của tầng này
Phần tiêu đề “1.8 Phát hiện lớn nhất của tầng này”| Hệ thống | nDCG@5 | A | B (paraphrase) | C | D |
|---|---|---|---|---|---|
| BM25 | 0.787 | 0.971 | 0.456 | 0.834 | 0.888 |
| Dense chưa train | 0.644 | 0.809 | 0.293 | 0.677 | 0.798 |
| Dense đã train | 0.753 | 0.971 | 0.354 | 0.835 | 0.850 |
Tôi đã dự đoán trong lộ trình rằng dense sẽ thắng BM25 ở lớp B. Sai. Dense tự train được 0.354, còn kém BM25 (0.456) đúng ở lớp mà nó được kỳ vọng mạnh nhất — dù nó đạt 100% chính xác trên nhiệm vụ được huấn luyện (title→doc).
Cơ chế thật: model chỉ thấy 50 tài liệu. Nó không thể học được rằng “miễn phí” ≈ “không cần nhập thẻ”, vì hai cách nói đó chưa bao giờ xuất hiện cùng nhau trong dữ liệu nó thấy. Kiến thức đó là kiến thức về thế giới, và nó chỉ đến từ pre-training ở quy mô lớn.
Sức mạnh của dense retrieval không nằm ở kiến trúc. Nó nằm ở quy mô pre-training. Một bi-encoder tự train trên dữ liệu nội bộ của bạn sẽ tệ hơn BM25. Đây là lý do lựa chọn đúng gần như luôn là: lấy model pre-trained mạnh, rồi fine-tune nếu cần — chứ không phải train từ đầu.
Ghi chú thú vị thứ hai: dense đạt 0.971 ở lớp A, ngang BM25. Bag-of-embeddings
xử lý tốt truy vấn từ khoá vì token hiếm (E2003) nhận được vector rất đặc trưng.
Nhưng điều này sẽ không đúng với model pre-trained dùng subword tokenizer — ở đó
E2003 bị cắt thành E/200/3 và mất tính đặc trưng. Đó chính là điểm mù kinh
điển của dense mà hybrid phải lấp.
1.9 Chọn embedding model cho tiếng Việt — các trục cần cân
Phần tiêu đề “1.9 Chọn embedding model cho tiếng Việt — các trục cần cân”| Trục | Câu hỏi |
|---|---|
| Chất lượng tiếng Việt | Model có tiếng Việt trong pre-train đủ nhiều? Benchmark trên golden set của bạn, không tin leaderboard tiếng Anh. |
| Số chiều | 1536 chiều × 1M chunk × 4 byte = 6 GB RAM. MRL cho phép hạ xuống 384 → 1.5 GB. |
| Độ dài context | Model cắt ở 512 token thì chunk dài hơn bị mất đuôi âm thầm. |
| Đối xứng hay không | Nhiều model cần prefix khác nhau cho query và document (query: / passage:). Quên prefix = mất 5–15% chất lượng, không có cảnh báo. |
| Pooling | CLS vs mean pooling — phải dùng đúng cách model được train. |
| Quyền riêng tư | Gửi dữ liệu khách hàng ra API nước ngoài có vi phạm chính sách của bạn? |