Bỏ qua để đến nội dung
Search & RAG

5.6 Late interaction: mua tương tác bằng dung lượng index

5.2 đặt ra một trục: tương tác giữa truy vấn và tài liệu bị đẩy sớm (bi-encoder, một vector cho cả tài liệu) hay muộn (cross-encoder, không có vector nào). Late interaction là điểm ở giữa, và nó là một điểm được thiết kế cẩn thận chứ không phải một sự thoả hiệp cẩu thả.

Bi-encoder: tài liệu ──► [một vector 768 chiều]
Late interaction: tài liệu ──► [v₁][v₂][v₃]…[v₂₀₀] ← một vector cho MỖI token
Cross-encoder: tài liệu ──► không vector nào, phải có truy vấn mới tính được

Các vector token tính trước được (không cần biết truy vấn), nên vẫn index được như bi-encoder. Nhưng lúc truy vấn, thay vì một phép nhân vô hướng, bạn cho các token gặp nhau bằng MaxSim:

điểm(q,d)=itoken(q)  maxjtoken(d)  cos(vqi,vdj)\text{điểm}(q, d) = \sum_{i \in \mathrm{token}(q)} \; \max_{j \in \mathrm{token}(d)} \; \cos\bigl(v_{q_i},\, v_{d_j}\bigr)

Đọc bằng lời: với mỗi token của câu hỏi, tìm token khớp nhất trong tài liệu, rồi cộng lại. Mỗi token của truy vấn được “khớp mềm” vào chỗ tốt nhất của nó trong tài liệu.

Đó là thứ mà một vector duy nhất không làm được. Với câu hỏi “tiền đã bị trừ mà đơn không thành công”, token trừ tìm được hoàn, token thất bại tìm được không thành công — mỗi từ tự tìm chỗ neo của nó, thay vì cả câu bị nén thành một điểm.

Đây là chỗ phải nhìn số. ColBERT bản gốc, trên MS MARCO (8,8 triệu đoạn):

Cấu hìnhDung lượng index
128 chiều × 4 byte/chiều286 GiB
24 chiều × 2 byte/chiều27 GiB — mất khoảng 1% chất lượng

Hai dòng đó nói hai điều. Thứ nhất: mặc định thì late interaction rất tốn — 286 GiB cho một corpus mà bi-encoder xử lý trong vài chục GB. Thứ hai: phần lớn chi phí đó mua lại được bằng giảm chiều và quantize, với tổn thất nhỏ. Toàn bộ dòng nghiên cứu sau ColBERT là về việc đó.

ColBERTv2 (2021) — nén dư (residual compression) quanh các centroid: giảm dung lượng của late interaction 6–10× so với bản gốc.

PLAID (2022) — engine phục vụ, cắt tỉa theo centroid trước khi chấm điểm đầy đủ. MS MARCO v1, k = 1000:

Phần cứngColBERTv2+ PLAID
GPU259,6 ms38,4 ms
CPU 8 luồng4568,5 ms101,3 ms
CPU 1 luồng3485,1 ms352,3 ms

Nhìn dòng giữa: 4,5 giây → 0,1 giây trên CPU, không mất chất lượng. Đó là khác biệt giữa “không dùng được ngoài GPU” và “dùng được”. Dung lượng index cùng lúc đó: 21,6 GiB (PLAID) so với 24,6 GiB.

ConstBERT (ECIR 2025) — bỏ luôn ràng buộc một vector mỗi token, học một số vector cố định cho mỗi tài liệu. MS MARCO:

ModelIndexMRR@10
ColBERT22 G39,99
ConstBERT (32 vector/doc)11 G39,04
ConstBERT (16 vector/doc)5 G37,84
ConstBERT (128 vector/doc)40 G39,53

Một nửa dung lượng cho gần một điểm MRR@10. Và đường cong này là thứ bạn nên nhớ về late interaction nói chung: có một núm đánh đổi liên tục giữa dung lượng và chất lượng, và nó khá phẳng ở giữa.

MUVERA (NeurIPS 2024) — tấn công từ phía phục vụ: mã hoá đa vector thành một vector chiều cố định sao cho inner product xấp xỉ độ tương đồng đa vector, để dùng lại được hạ tầng MIPS/ANN một-vector có sẵn. Báo cáo: cùng recall với các heuristic trước đó nhưng lấy về ít ứng viên hơn 2–5×, và đo đầu-cuối là recall cao hơn 10% với độ trễ thấp hơn 90%.

Late interaction có còn đắt không? Hai số nói ngược lại

Phần tiêu đề “Late interaction có còn đắt không? Hai số nói ngược lại”

Hai dữ kiện làm suy yếu ấn tượng “ColBERT là thứ xa xỉ”:

  • answerai-colbert-small-v1: một ColBERT 33 triệu tham số vượt ColBERTv2 gốc (110M) trên toàn bộ benchmark được thử, kể cả các tập chưa từng thấy như LoTTe.
  • Jina-ColBERT-v2: late interaction đa ngữ 14 thứ tiếng, huấn luyện với loss kiểu Matryoshka nên cắt chiều token sau khi huấn luyện được: giảm 128 → 64 chiều (một nửa dung lượng) chỉ mất 0,01 nDCG@10 (1,59% tương đối). BEIR trung bình 53,1 so với ColBERTv2 49,6; MIRACL 19 thứ tiếng 62,3.

Dòng thứ hai đáng chú ý với người làm tiếng Việt: đây là một trong ít model late interaction công khai được huấn luyện đa ngữ tử tế.

Và lĩnh vực này vẫn đang chạy: ECIR 2026 có workshop riêng cho late interaction và multi-vector retrieval.

Chỗ dễ lẫn nhất về ColBERT, nên nói thẳng: cả hai, và bạn phải chọn.

Cách dùngNghĩa làĐánh đổi
Stage 1 (end-to-end retrieval)Index toàn corpus dưới dạng đa vector, tìm trực tiếp trên đóRecall tốt hơn bi-encoder. Trả bằng dung lượng index + engine riêng (PLAID)
Stage 2 (reranker)Chấm điểm MaxSim cho k ứng viên đã cóKhông đổi stage 1. Nhưng vector token phải từ đâu ra: lưu sẵn (phồng index) hay tính lúc truy vấn (mất phần lớn cái lợi tốc độ) — xem ba cách cắm dưới đây

Bản stage 2 tính vector lúc truy vấn nghe hấp dẫn nhưng thường không hợp lý: nếu dù sao cũng phải chạy model trên k tài liệu lúc truy vấn, thì chạy hẳn một cross-encoder — nó chất lượng cao hơn. Late interaction chỉ thật sự thắng khi các vector token được tính trước: hoặc index cả corpus (stage 1), hoặc lưu sẵn rồi chỉ MaxSim trên k ứng viên (mục dưới).

Con số so sánh trực tiếp, từ bài báo ColBERT gốc: MS MARCO dev MRR@10 34,9 (ColBERT) so với 36,0 (reranker BERT-base của cùng nhóm) — thấp hơn một chút về chất lượng, nhưng “nhanh hơn hơn 170×” và “ít FLOPs hơn 14.000 lần mỗi truy vấn”. Đó chính là mệnh giá của việc tính trước vector token.

Đây là câu hỏi kiến trúc thật, và cái bẫy nằm ở chỗ hai phương án không cùng một tầng:

hybrid + rerank: BM25 ─┐
├─ RRF ─► top-k ─► cross-encoder ─► top-5
dense ─┘
→ đổi stage 2, index cũ giữ nguyên
late interaction: index đa vector ─► MaxSim trên toàn corpus ─► top-k
→ đổi chính stage 1

Nói gọn: rerank chữa bệnh “lấy đúng, xếp sai”; late interaction chữa bệnh “không lấy được về” (5.4). Chọn sai bệnh thì tiêu tiền không ra kết quả.

Phần lớn so sánh trên mạng ghép số từ hai bài báo khác nhau. BEIR (2021) chạy cả hai trong cùng một harness — 18 tập dữ liệu, nDCG@10 trung bình, so với BM25:

Kiến trúcChất lượng so với BM25Index (DBPedia 1M)Latency (DBPedia 1M)
ColBERT (late interaction, end-to-end)+2,5%20 GB350 ms GPU — bảng không có số CPU
BM25 + cross-encoder rerank top-100+11%0,4 GB450 ms GPU · 6100 ms CPU

Ba cột phải đọc cùng nhau. Rerank mua gấp hơn bốn lần phần chất lượng, với index nhỏ hơn 50× — nhưng trả bằng CPU: 6,1 giây một truy vấn nếu không có GPU. Late interaction đắt index mà rẻ latency GPU. Cùng bài báo đó: index ColBERT cho BioASQ (~15 triệu tài liệu) là ~900 GB, so với 18 GB của BM25.

Đây là số 2021, và phải nói rõ, vì cả hai bên đều đã tiến từ đó: phía late interaction có ColBERTv2 → PLAID → ConstBERT → MUVERA (các mục trên); phía rerank có listwise reranker đạt BEIR nDCG@10 63,20 (5.8). Dùng bảng này để hiểu hình dạng của đánh đổi, không phải để chốt điểm số hôm nay.

Chỗ late interaction thắng mà rerank không tranh được

Phần tiêu đề “Chỗ late interaction thắng mà rerank không tranh được”

Bảng 2 của bài ColBERT gốc, MS MARCO 8,8 triệu đoạn — cùng một model, chỉ khác chỗ cắm:

Cách cắm ColBERTMRR@10Recall@1000
Rerank top-1000 của BM2534,881,4 ← đúng bằng trần của BM25
Tìm end-to-end trên index đa vector36,096,8

+15 điểm recall@1000 chỉ vì stage 1 không còn là BM25. Đây là 5.4 viết dưới dạng số: recall@1000 của nhánh “rerank BM25” bằng chính xác recall của BM25 — rerank không bao giờ đổi được recall@k, chỉ đổi thứ tự trong k. Không reranker nào đưa 81,4 lên 96,8.

Mục trên chia “stage 1 hay stage 2”. Thực tế có ba, và cái ở giữa hay bị bỏ sót:

CáchIndexLúc truy vấnĐánh giá
1. Stage 1 đa vectorphồng, cần engine riêng (PLAID/MUVERA)MaxSim trên toàn corpusChữa recall. Hạ tầng nặng nhất
2. Rerank bằng vector token lưu sẵnphồng, nhưng không cần index ANN cho nóMaxSim trên k ứng viênRẻ latency, không đổi stage 1
3. Rerank bằng vector token tính lúc truy vấnkhông phồngencode k tài liệu rồi MaxSimĐừng. Đã encode k tài liệu thì chạy cross-encoder cho chất lượng cao hơn

Cách 2 là thứ các vendor đang bán. Qdrant lưu multivector ColBERT với hnsw_config(m=0)“các embedding này dùng để rerank, không dùng để retrieval ANN, nên không cần index HNSW” — và OpenSearch (12/2025) khuyến nghị đúng hình đó: bi-encoder lấy ứng viên, late interaction chấm điểm lại.

Cách 2 làm bảng đánh đổi mềm hơn hẳn: trả dung lượng, nhưng không phải dựng engine đa vector, và latency rerank thấp hơn cross-encoder rõ rệt — 61 ms so với 10.700 ms trong Bảng 1 của bài ColBERT (7 tỉ FLOPs so với 97 nghìn tỉ). Cái mất là chất lượng đỉnh: 34,9 so với 36,0 MRR@10 ở cùng bảng đó.

“Index phồng 10–100×” đúng đến mức nào

Phần tiêu đề ““Index phồng 10–100×” đúng đến mức nào”

Con số hay được nhắc (OpenSearch, 12/2025) là 10–100×, và nó đúng cho tài liệu dài với vector chưa nén. Nhưng hệ số phụ thuộc mạnh vào độ dài tài liệusố chiều của vector đơn mà bạn đang so: bảng của Weaviate (4/2025) cho 10.000 tài liệu × 100 token ra 20,48 MB (một vector 1024 chiều) so với 27,07 MB (ColBERTv2 128 chiều) — khoảng 1,3×, không phải 10×. Đo trên chunk thật của bạn trước khi tin bất kỳ hệ số nào.

Với hệ tiếng Việt: giấy phép cắt trước benchmark

Phần tiêu đề “Với hệ tiếng Việt: giấy phép cắt trước benchmark”

Cửa số 1 của Bảng 3 ở 5.15 loại bỏ phần lớn lựa chọn: jina-colbert-v2 — late interaction đa ngữ tốt nhất công khai, có tiếng Việt tường minh, 8192 token, ba mức chiều 128/96/64 — phát hành dưới CC-BY-NC-4.0, tức không dùng thương mại được. Thay thế công khai gần nhất, answerai-colbert-small-v1, mạnh nhưng tiếng Anh.

Nghĩa là với một sản phẩm thương mại tiếng Việt, “hybrid + rerank” không chỉ nhẹ hơn về hạ tầng — nó còn là con đường có nhiều model dùng được hơn.

Nên áp dụng vào AI Agent: mặc định là hybrid + rerank. Chỉ đổi sang late interaction khi đã đo và thấy recall@k của stage 1 là chỗ nghẽn — sau khi đã sửa tokenizer, đã bật hybrid, đã sửa chunking, theo đúng thứ tự ở 5.4. Muốn thử late interaction với chi phí thấp nhất thì thử cách 2 trước, đừng dựng engine đa vector ngay.

Tình huốngNên
Corpus vừa (≲ 1M đoạn), đã có ANN, muốn chất lượng cao ở topCross-encoder rerank. Đơn giản nhất, không đổi index
Recall@k của stage 1 là chỗ nghẽn, và bạn kiểm soát được hạ tầng indexLate interaction làm stage 1 — nó chữa đúng bệnh recall (5.4)
Đa ngữ, có tiếng Việt, cần chất lượng stage 1 tốt hơn bi-encoderKiểm tra giấy phép trước: jina-colbert-v2 là CC-BY-NC. Nếu là sản phẩm thương mại → bi-encoder đa ngữ + cross-encoder rerank
Dung lượng lưu trữ là ràng buộc cứngBi-encoder + cross-encoder rerank. Đừng chạm vào đa vector
Đang chạy tốt với bi-encoder + cross-encoderĐừng đổi. Late interaction là một hạ tầng nữa phải vận hành

Nên áp dụng vào AI Agent: trong đa số trường hợp, câu trả lời là chưa. Late interaction là công cụ đúng cho bài toán recall ở quy mô lớn, không phải cho bài toán “top-5 xếp chưa tốt” — cái đó cross-encoder giải rẻ hơn nhiều. Đọc mục này để biết nó tồn tại và biết khi nào cần, đừng đọc nó như một việc phải làm.

Phần 5 — Reranker