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

7.11 Query API và prefetch

Từ v1.10, Qdrant gộp năm endpoint tìm kiếm cũ (search, recommend, discover, search_groups, …) vào một API duy nhất: query. Đây không chỉ là dọn dẹp API — nó mở ra thứ mà trước đó phải làm ở tầng ứng dụng: một cascade nhiều tầng chạy trọn vẹn bên trong database.

Quy tắc chỉ có một câu:

Nếu một truy vấn có prefetch, Qdrant chạy prefetch trước, rồi áp truy vấn chính lên kết quả của prefetch thay vì lên toàn bộ collection.

prefetch lồng nhau được. Từ đó ra toàn bộ sức mạnh của API này.

{
"prefetch": {
"prefetch": { "query": <vector rẻ>, "limit": 1000 }, ← tầng 1: quét rộng, rẻ
"query": <vector đầy đủ>, "limit": 100 ← tầng 2: thu hẹp
},
"query": <multivector ColBERT>, "limit": 10 ← tầng 3: xếp lại, đắt
}

Đây chính là kiến trúc hai (ba) giai đoạn của 5.1dùng cái rẻ để thu hẹp, dùng cái đắt để quyết định — nhưng chạy trong một request, không phải ba vòng qua mạng.

KiểuTầng 1Tầng cuốiĐược gì
Nén → gốcvector đã quantizationvector float đầy đủĐây chính là rescore của 7.10, viết tường minh
Ngắn → dài256 chiều đầu (Matryoshka)vector đầy đủTầng 1 rẻ hơn nhiều lần
Dense → ColBERTdense 1 vectormultivector max_simLate interaction mà không cần dịch vụ rerank riêng
Dense + sparse → fusionhai prefetch song songfusionHybrid — xem 7.12

Ba kiểu đầu là rescoring: một prefetch, một truy vấn chính chấm điểm lại. Kiểu thứ tư là fusion: nhiều prefetch song song, fusion thứ hạng.

Mẹo RAM đi kèm. Vector chỉ dùng ở tầng cuối (ColBERT, vector float gốc khi tầng 1 là bản nén) không cần đồ thị HNSW — rescore không đi qua HNSW. Đặt m: 0 cho named vector đó. Xem 7.37.7.

offset chỉ áp lên truy vấn chính, không áp lên prefetch. Nghĩa là:

Mỗi prefetch phải có limit ít nhất bằng limit + offset của truy vấn chính. Nếu không, bạn có thể nhận về kết quả rỗng.

Đây là bug điển hình khi làm phân trang trên hybrid search: trang 1 ổn, trang 5 trống rỗng.

2. limit của tầng 1 trần recall của cả truy vấn

Phần tiêu đề “2. limit của tầng 1 là trần recall của cả truy vấn”

Đây không phải chuyện riêng của Qdrant — nó là 5.4 phát biểu lại bằng cú pháp Query API:

Tầng cuối không tìm được thứ mà tầng 1 chưa đưa cho nó. Nếu prefetch lấy 100 và đáp án đúng đứng hạng 137, thì ColBERT có giỏi đến mấy cũng vô ích.

Cách chọn limit cho tầng 1 vẫn là cách của 5.4: đo recall@k của riêng tầng 1 với nhiều giá trị k, tìm điểm mà đường cong bắt đầu phẳng, lấy giá trị đó.

Chúng dễ bị bỏ quên nhưng rất hay dùng trong vận hành:

scroll — duyệt tuần tự theo filter, không cần vector. Kết quả sắp theo ID, và phân trang bằng next_page_offset (khi nó null là hết). Dùng để: kiểm dữ liệu, xoá hàng loạt theo điều kiện, tái xử lý.

Từ v1.19 có điều kiện slice cho phép chia collection thành các phần rời nhau xác định, nên nhiều worker có thể duyệt song song mà không giẫm chân nhau — cách này tốt hơn hẳn phân trang tuần tự khi cần quét lại toàn bộ.

count — mặc định là ước lượng, vì đếm chính xác đòi quét. Đặt exact: true khi bạn thật sự cần con số đúng.

⚠️ points_count trả về trong thông tin collection cũng là con số xấp xỉ. Đừng dùng nó để đối chiếu số lượng bản ghi với hệ nguồn rồi kết luận là mất dữ liệu.

Bạn cầnDùng
Tìm giống nhấtquery với một vector
Tìm giống nhất theo từ khoáquery với sparse vector
Cả haiquery + hai prefetch + fusion (7.12)
Tìm rẻ rồi chấm lại đắtquery + prefetch lồng nhau
Lấy dữ liệu theo điều kiện, không cần vectorscroll
Đếmcount (nhớ exact)
Gom nhóm, đếm theo giá trị7.14
Phần 7 — Qdrant