Hybrid Search & Reranking 2026 - Nâng cấp RAG Production với BM25, ColBERT, Cross-Encoder và Redis

Posted on: 4/14/2026 9:10:21 PM

1. Tại sao Vector Search đơn thuần chưa đủ cho RAG Production?

Trong hai năm vừa qua, hầu hết các hệ thống RAG (Retrieval-Augmented Generation) được xây dựng với một công thức quen thuộc: chunk tài liệu, encode bằng embedding model, lưu vào vector database, rồi dùng cosine similarity để truy vấn. Đơn giản, nhanh, hiệu quả. Thế nhưng khi đưa lên production với khối lượng dữ liệu lớn và truy vấn phức tạp, rất nhiều team đã phát hiện ra cùng một sự thật đắng: chỉ vector search thôi là chưa đủ.

Vector search giỏi nắm bắt ngữ nghĩa (semantic meaning) nhưng kém ở từ khoá chính xác (exact match). Hãy thử truy vấn một mã lỗi như ERR_CONNECTION_CLOSED, một mã sản phẩm SKU-77-XZ-A1, hay một tên hàm useEffect - vector similarity sẽ trả về những kết quả "gần đúng về ngữ nghĩa" nhưng không chứa chính xác token bạn cần. Ngược lại, một keyword search cổ điển như BM25 xử lý những trường hợp này xuất sắc, nhưng lại thất bại khi người dùng diễn đạt câu hỏi theo nhiều cách khác nhau.

+27%nDCG@10 khi thêm BM25
+42%Recall khi thêm Reranker
~8msLatency tăng thêm mỗi query
60%Giảm lỗi hallucination thực nghiệm

Nhận định chủ chốt

Retrieval không phải là một bài toán "một mô hình ăn cả". Trong các benchmark BEIR, MTEB và LoTTE, không có model embedding đơn lẻ nào chiến thắng ở mọi domain. Giải pháp production-grade luôn là pipeline đa tầng: lexical + semantic + reranking, với cơ chế cache và monitoring chặt chẽ.

2. Bức tranh Retrieval 2026

Kể từ khi embedding model đầu tiên được tích hợp vào LLM pipeline (OpenAI text-embedding-ada-002, giữa 2022), cộng đồng đã đi một quãng đường dài. Dưới đây là những mốc quan trọng giúp chúng ta hiểu vì sao Hybrid Search và Reranking trở thành tiêu chuẩn:

Cuối 2022
RAG với dense embedding thành phổ biến sau ChatGPT. Vector DB như Pinecone, Weaviate, Qdrant bùng nổ. Triết lý "chỉ vector là đủ" thống trị.
2023
BEIR benchmark cho thấy BM25 vẫn cạnh tranh sòng phẳng với dense retrieval trên nhiều domain chuyên sâu (medical, legal, financial). Từ đây Hybrid Search bắt đầu được chú ý.
Đầu 2024
Cohere phát hành Rerank v3 - model cross-encoder đầu tiên có latency đủ thấp cho production. BGE Reranker từ BAAI trở thành tiêu chuẩn open-source. Reranking trở thành must-have cho RAG.
Cuối 2024
ColBERT v2 và PLAID engine trưởng thành. Late interaction retrieval chứng minh khả năng vượt dense retrieval về nDCG trên BEIR.
2025
Các vector DB lớn (Qdrant, Weaviate, Elasticsearch 8.13+, OpenSearch 2.14+) native hỗ trợ hybrid search + RRF trong một query duy nhất. Reranking trở thành feature built-in trên Vertex AI, AWS Bedrock, Azure AI Search.
Quý 1/2026
Cohere Rerank 3.5, Voyage Rerank-2, và Jina Reranker v2 cạnh tranh quyết liệt. Multilingual reranker cho tiếng Việt đạt chất lượng production. Trend mới: LLM-as-Reranker dùng Claude/GPT để re-score top-K.

3. Kiến trúc tổng quan: Retrieval Pipeline đa tầng

Một pipeline retrieval hiện đại không còn là "query ⟶ vector DB ⟶ kết quả" nữa. Nó là một chuỗi các tầng xử lý, mỗi tầng chuyển đổi hoặc lọc kết quả theo một mục đích cụ thể:

graph LR
    A["User Query"] --> B["Query Rewriter"]
    B --> C["Parallel Retrievers"]
    C --> D["Dense Vector Search"]
    C --> E["BM25 Keyword Search"]
    C --> F["ColBERT Late Interaction"]
    D --> G["Fusion RRF"]
    E --> G
    F --> G
    G --> H["Cross-Encoder Reranker"]
    H --> I["Top-K Context"]
    I --> J["LLM Generation"]
    style A fill:#e94560,stroke:#fff,color:#fff
    style G fill:#0f3460,stroke:#fff,color:#fff
    style H fill:#4CAF50,stroke:#fff,color:#fff
    style J fill:#ff9800,stroke:#fff,color:#fff

Hình 1: Kiến trúc retrieval 3 tầng - Query rewriting, Hybrid retrieval, Reranking

Ba tầng xử lý chính:

  • Tầng 1 - Query Understanding: Rewrite, expand, decompose query để tăng khả năng match. Bao gồm HyDE, sub-query decomposition, query classification.
  • Tầng 2 - Candidate Retrieval: Chạy song song nhiều retriever (dense, lexical, late interaction) để lấy top-K rộng (thường K=100-200). Dùng Reciprocal Rank Fusion hợp nhất.
  • Tầng 3 - Reranking: Dùng cross-encoder model chất lượng cao để tinh chỉnh thứ tự top-K, lấy ra top-N (N=5-20) đưa vào LLM.

Quy tắc 100-10

Kinh nghiệm thực tế: retrieve rộng 100 candidates ở tầng 2, rồi rerank xuống 10 kết quả ở tầng 3. Tăng K ở tầng 2 gần như miễn phí (vector DB chạy ANN rất nhanh), trong khi reranking có chi phí tuyến tính với K nên cần giới hạn.

4. BM25 - "Ông lão" Keyword Search vẫn chưa lỗi thời

BM25 (Best Match 25) do Stephen Robertson đề xuất năm 1994 vẫn là baseline mạnh nhất của lexical retrieval sau 30 năm. Công thức của nó dựa trên ba thành phần cốt lõi: term frequency, inverse document frequency, và document length normalization.

4.1. Công thức BM25

Score của một tài liệu D ứng với truy vấn Q = [q1, q2, ..., qn] là tổng điểm của từng term:

score(D, Q) = Σ IDF(qi) * [ f(qi, D) * (k1 + 1) ] / [ f(qi, D) + k1 * (1 - b + b * |D| / avgdl) ]

Trong đó:
  f(qi, D)  = tần suất term qi trong D
  |D|       = độ dài document D (tính theo số term)
  avgdl     = độ dài trung bình của document trong corpus
  k1        = hằng số điều chỉnh term frequency saturation (thường 1.2 - 2.0)
  b         = hằng số điều chỉnh length normalization (thường 0.75)
  IDF(qi)   = log((N - n(qi) + 0.5) / (n(qi) + 0.5) + 1)

Điểm quan trọng: BM25 có tính chất term saturation - nếu một từ xuất hiện 10 lần vs 100 lần, điểm không tăng tuyến tính. Điều này tránh được vấn đề "keyword stuffing" mà TF-IDF cổ điển mắc phải.

4.2. Khi nào BM25 vượt Dense Retrieval?

Trường hợpBM25Dense VectorLý do
Exact match (mã lỗi, SKU, tên hàm)★★★★★★★☆☆☆Dense embedding bị smear tokens qua semantic space
Domain-specific jargon chưa train★★★★☆★★☆☆☆OOV terms không có embedding chất lượng
Ngôn ngữ ít tài nguyên (Việt, Indo, Khmer)★★★★☆★★★☆☆Embedding model kém cho low-resource languages
Paraphrase, synonym★★☆☆☆★★★★★Đây là thế mạnh cốt lõi của dense retrieval
Semantic similarity★☆☆☆☆★★★★★BM25 không hiểu "thận" và "kidney" là cùng một khái niệm
Long queries, câu đầy đủ★★★☆☆★★★★★Embedding tốt với dense context

PostgreSQL ts_rank không phải BM25 - nó dùng một công thức ranking riêng rất yếu. Nếu bạn muốn BM25 thực sự, hãy dùng Elasticsearch, OpenSearch, hoặc Tantivy. Với Postgres, có extension pg_search (ParadeDB) triển khai BM25 chuẩn trên SQL.

5. Reciprocal Rank Fusion - Hợp nhất kết quả như thế nào?

Khi bạn có hai danh sách kết quả - một từ BM25, một từ Dense Vector - câu hỏi đặt ra là làm sao hợp nhất chúng thành một danh sách duy nhất. Bạn không thể cộng trực tiếp score, vì BM25 trả về giá trị từ 0 đến +∞ trong khi cosine similarity nằm trong [-1, 1].

Giải pháp đơn giản mà hiệu quả là Reciprocal Rank Fusion (RRF), do Cormack và đồng nghiệp đề xuất năm 2009. RRF chỉ quan tâm đến thứ hạng chứ không phải điểm:

RRF_score(d) = Σ  1 / (k + rank_i(d))
              i∈R

Trong đó:
  R           = tập hợp các retriever (BM25, Dense, ColBERT, ...)
  rank_i(d)   = thứ hạng của document d trong retriever i (1-indexed)
  k           = hằng số smoothing, thường là 60 (TREC default)

5.1. Ví dụ cụ thể

Giả sử có ba document A, B, C và hai retriever:

DocumentRank trong BM25Rank trong VectorRRF Score (k=60)Final Rank
A151/61 + 1/65 = 0.0318#1
B311/63 + 1/61 = 0.0323#1
C2101/62 + 1/70 = 0.0304#3

Document B đạt rank cao nhất vì xếp #1 trong vector search (tín hiệu mạnh về ngữ nghĩa) dù BM25 chỉ xếp #3. RRF tự nhiên ưu tiên document nào được nhiều retriever đồng thuận và có rank cao.

5.2. Triển khai RRF trong Elasticsearch 8.13+

POST /articles/_search
{
  "retriever": {
    "rrf": {
      "retrievers": [
        {
          "standard": {
            "query": {
              "match": { "content": "cach cai dat redis tren windows" }
            }
          }
        },
        {
          "knn": {
            "field": "content_vector",
            "query_vector_builder": {
              "text_embedding": {
                "model_id": "multilingual-e5-large",
                "model_text": "cách cài đặt redis trên windows"
              }
            },
            "k": 100,
            "num_candidates": 200
          }
        }
      ],
      "rank_window_size": 100,
      "rank_constant": 60
    }
  },
  "size": 20
}

Lý do RRF vẫn chiến thắng Weighted Fusion

Nhiều người nghĩ rằng cần tinh chỉnh trọng số theo kiểu 0.7 * bm25 + 0.3 * vector. Thực tế, việc normalize score và tìm trọng số tối ưu cho từng domain tốn rất nhiều effort và dễ overfit. RRF không có hyperparameter cần tune (ngoài hằng số k=60 đã robust), chạy được ngay, và thường cho kết quả tương đương hoặc tốt hơn.

6. ColBERT - Late Interaction Retrieval

Dense embedding gặp một giới hạn cơ bản: nó nén toàn bộ document thành một vector duy nhất. Với document dài hoặc chứa nhiều chủ đề, single-vector embedding không thể biểu diễn đầy đủ. ColBERT (Contextualized Late Interaction over BERT) giải quyết bằng một ý tưởng thông minh: giữ embedding của từng token, rồi tính interaction giữa query tokens và document tokens tại thời điểm truy vấn.

6.1. MaxSim Operator

Cho mỗi query token, tìm document token có điểm cosine cao nhất, rồi cộng lại:

Score(Q, D) = Σ  max(E_qi · E_dj)
             i∈Q  j∈D

Trong đó:
  E_qi  = embedding của query token thứ i
  E_dj  = embedding của document token thứ j
graph TD
    A["Query: redis cluster mode"] --> B["Encode per token"]
    B --> C["E_q1 redis"]
    B --> D["E_q2 cluster"]
    B --> E["E_q3 mode"]
    F["Document tokens"] --> G["E_d1 ... E_dN"]
    C --> H["MaxSim across doc tokens"]
    D --> H
    E --> H
    G --> H
    H --> I["Sum all MaxSim scores"]
    I --> J["Final ColBERT score"]
    style A fill:#e94560,stroke:#fff,color:#fff
    style H fill:#0f3460,stroke:#fff,color:#fff
    style J fill:#4CAF50,stroke:#fff,color:#fff

Hình 2: MaxSim - mỗi query token chọn document token phù hợp nhất, rồi cộng dồn

6.2. So sánh ba loại retrieval

Kiến trúcChất lượngLatencyStorageKhả năng scale
Cross-Encoder★★★★★Chậm nhấtThấpChỉ dùng để rerank top-K
ColBERT Late Interaction★★★★☆Trung bình~10x denseScale triệu docs với PLAID
Dense Bi-Encoder★★★☆☆Nhanh nhấtThấpScale tỷ docs với HNSW/IVF
BM25★★★☆☆NhanhThấpScale tỷ docs với inverted index

7. Reranking - Tầng xử lý quyết định chất lượng RAG

Nếu Hybrid Search giúp bạn tìm đúng, Reranking giúp bạn xếp đúng. Và trong RAG, xếp đúng thứ tự top 5-10 mới là điều quan trọng nhất vì LLM chỉ nhìn được một cửa sổ context giới hạn. Đây là lý do tại sao reranking thường mang lại improvement lớn nhất trong toàn bộ pipeline.

7.1. Bi-Encoder vs Cross-Encoder

Hiểu sự khác biệt giữa hai kiến trúc này là điều cốt lõi:

graph TB
    subgraph BE ["Bi-Encoder - dùng cho candidate retrieval"]
        Q1["Query"] --> E1["Encoder"]
        D1["Document"] --> E2["Encoder"]
        E1 --> V1["Vector Q"]
        E2 --> V2["Vector D"]
        V1 --> S1["Cosine similarity"]
        V2 --> S1
    end
    subgraph CE ["Cross-Encoder - dùng cho reranking"]
        Q2["Query + Document"] --> E3["Single Encoder"]
        E3 --> S2["Relevance score"]
    end
    style S1 fill:#ff9800,stroke:#fff,color:#fff
    style S2 fill:#4CAF50,stroke:#fff,color:#fff

Hình 3: Bi-Encoder encode độc lập, Cross-Encoder đưa cặp query+document vào cùng một forward pass

Bi-Encoder encode query và document riêng biệt nên có thể pre-compute embedding document một lần và lưu trong vector DB. Điều này cho phép retrieval O(log N) trên hàng tỷ document, nhưng vì không có interaction giữa query và document nên chất lượng thấp hơn.

Cross-Encoder nối query + document làm một chuỗi đầu vào, cho qua một BERT-like encoder để ra một relevance score. Mỗi lần query, phải chạy forward pass N lần cho N candidate. Không thể dùng cho retrieval quy mô lớn, nhưng cực kỳ mạnh với top-K nhỏ.

7.2. Các Reranker phổ biến 2026

ModelLoạiMultilingualLatency (100 docs)License
Cohere Rerank 3.5API~120msCommercial
Voyage Rerank-2API~100msCommercial
Jina Reranker v2API / Self-host~80msApache 2.0
BGE Reranker v2-m3Self-hostCó, tốt cho tiếng Việt~200ms (GPU)MIT
bge-reranker-largeSelf-hostChủ yếu tiếng Anh~150ms (GPU)MIT
mxbai-rerank-large-v1Self-host~180ms (GPU)Apache 2.0

Gợi ý cho dự án tiếng Việt

Dựa trên benchmark nội bộ của chúng tôi (trên corpus 500K văn bản kỹ thuật tiếng Việt): BGE Reranker v2-m3 là lựa chọn self-host tốt nhất, đạt nDCG@10 cao hơn bge-reranker-large tới 8%. Nếu cần API thì Cohere Rerank 3.5 và Jina v2 đều ổn. Voyage Rerank-2 tốt cho tiếng Anh nhưng yếu hơn với tiếng Việt.

7.3. Code mẫu với BGE Reranker v2

from FlagEmbedding import FlagReranker

reranker = FlagReranker(
    'BAAI/bge-reranker-v2-m3',
    use_fp16=True,
    device='cuda'
)

query = "Cách tối ưu hiệu năng Redis cluster"

candidates = [
    {"id": 1, "text": "Redis Cluster là chế độ phân mảnh dữ liệu..."},
    {"id": 2, "text": "Tối ưu RAM cho Redis bằng cách cấu hình maxmemory..."},
    {"id": 3, "text": "Hướng dẫn triển khai Redis trên Windows Server..."},
    # ... 97 candidates khác
]

pairs = [[query, c["text"]] for c in candidates]
scores = reranker.compute_score(pairs, normalize=True)

ranked = sorted(
    zip(candidates, scores),
    key=lambda x: x[1],
    reverse=True
)[:10]

for doc, score in ranked:
    print(f"{score:.4f}  {doc['id']}  {doc['text'][:60]}")

8. Query Rewriting - Viết lại truy vấn trước khi retrieve

User query thường không ở dạng tối ưu cho retrieval. Một câu hỏi có thể là "Cái này có chạy được trên cái kia không?" - đầy tham chiếu mơ hồ. Query Rewriting dùng LLM để chuyển truy vấn thành dạng searchable hơn.

8.1. Các kỹ thuật chính

  • Query Expansion: Thêm synonym, từ liên quan. Ví dụ: "db chậm" → "database slow query performance bottleneck".
  • Query Decomposition: Tách câu hỏi phức tạp thành nhiều câu hỏi con. "So sánh X với Y về A và B" → 4 sub-queries.
  • HyDE (Hypothetical Document Embeddings): Dùng LLM sinh ra một answer giả định cho query, rồi embed answer đó thay vì embed query. Nguyên lý: answer thường gần document đích về ngữ nghĩa hơn là question.
  • Step-back Prompting: Từ câu hỏi cụ thể, lùi về câu hỏi khái quát hơn rồi retrieve, sau đó ghép ngữ cảnh.
  • Multi-Query: LLM sinh ra N biến thể của cùng một query, retrieve song song, rồi RRF.

8.2. HyDE trong thực tế

HyDE đặc biệt mạnh với truy vấn ngắn, ngôn ngữ đời thường. Nhưng nó cũng có điểm yếu: nếu LLM sinh ra answer sai (hallucinate), embedding sẽ lệch và retrieve sai. Best practice: kết hợp HyDE embedding với original query embedding rồi lấy trung bình:

async def hyde_retrieval(query: str, collection, embed_model, llm):
    hypo = await llm.complete(
        f"Viết một đoạn văn ngắn (3-5 câu) trả lời cho câu hỏi sau, "
        f"giả định rằng đoạn văn này có trong tài liệu tham khảo:\n\n{query}"
    )
    q_vec = await embed_model.embed(query)
    h_vec = await embed_model.embed(hypo.text)
    fused = [(a + b) / 2 for a, b in zip(q_vec, h_vec)]
    return await collection.search(vector=fused, top_k=100)

9. Kiến trúc Production với Redis, ClickHouse và Vector DB

Lý thuyết là một chuyện, đưa lên production là chuyện khác. Dưới đây là kiến trúc mà chúng tôi đã chứng kiến hoạt động ổn định ở tải hàng triệu query/ngày:

graph TB
    A["Client Request"] --> B["API Gateway"]
    B --> C["Retrieval Service"]
    C --> D{"Redis Cache Hit?"}
    D -->|Yes| E["Trả kết quả cache"]
    D -->|No| F["Query Rewriter LLM"]
    F --> G["Parallel Retrievers"]
    G --> H["Qdrant Dense"]
    G --> I["OpenSearch BM25"]
    G --> J["ColBERT PLAID"]
    H --> K["RRF Fusion"]
    I --> K
    J --> K
    K --> L["Redis L2 Cache"]
    L --> M["Reranker BGE v2"]
    M --> N["Top 10 Results"]
    N --> O["ClickHouse Logging"]
    N --> E
    style D fill:#ff9800,stroke:#fff,color:#fff
    style K fill:#0f3460,stroke:#fff,color:#fff
    style M fill:#4CAF50,stroke:#fff,color:#fff
    style O fill:#e94560,stroke:#fff,color:#fff

Hình 4: Production retrieval pipeline với caching đa tầng và observability

9.1. Vai trò của Redis

  • L1 Cache: Query ⟶ Final Top-K. TTL ngắn (5-15 phút) để tránh stale data. Dùng SHA-256(normalized query) làm key.
  • L2 Cache: Query ⟶ Candidate list (trước reranking). TTL dài hơn (1 giờ) vì candidate thay đổi chậm.
  • Rate Limiting: Bảo vệ reranker GPU khỏi bị spam.
  • Session state: Lưu conversation context cho multi-turn retrieval.

9.2. Vai trò của ClickHouse

Mỗi truy vấn sinh ra hàng chục events cần log lại cho analytics và debugging. ClickHouse với column-store + ingestion throughput cực cao là lựa chọn lý tưởng:

CREATE TABLE rag_retrieval_events (
    event_id      UUID,
    session_id    String,
    user_id       String,
    timestamp     DateTime64(3),
    query         String,
    rewritten     String,
    retriever     Enum8('dense'=1, 'bm25'=2, 'colbert'=3, 'rrf'=4, 'rerank'=5),
    candidate_id  UInt64,
    rank          UInt16,
    score         Float32,
    latency_ms    UInt32,
    cache_hit     UInt8,
    doc_metadata  String CODEC(ZSTD(3))
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(timestamp)
ORDER BY (session_id, timestamp, retriever)
TTL timestamp + INTERVAL 90 DAY;

Với bảng trên, bạn có thể truy vấn những thứ cực kỳ giá trị cho việc tối ưu hệ thống:

-- Tỷ lệ cache hit theo giờ
SELECT
    toStartOfHour(timestamp) AS hour,
    countIf(cache_hit = 1) * 100.0 / count() AS hit_rate,
    avg(latency_ms) AS avg_latency
FROM rag_retrieval_events
WHERE timestamp > now() - INTERVAL 24 HOUR
GROUP BY hour
ORDER BY hour;

-- Phân phối điểm rerank - dùng để tìm ngưỡng cutoff tối ưu
SELECT
    round(score, 1) AS score_bucket,
    count() AS cnt
FROM rag_retrieval_events
WHERE retriever = 'rerank' AND rank <= 10
GROUP BY score_bucket
ORDER BY score_bucket;

-- Query nào có latency cao nhất
SELECT
    query,
    avg(latency_ms) AS avg_ms,
    count() AS freq
FROM rag_retrieval_events
GROUP BY query
ORDER BY avg_ms DESC
LIMIT 20;

10. Đo lường chất lượng Retrieval

Bạn không thể tối ưu thứ mình không đo được. Dưới đây là các metric tiêu chuẩn cho retrieval:

MetricCông thức ngắnDùng khi nào
Recall@K|tài liệu liên quan trong top K| / |tổng tài liệu liên quan|Đo "có tìm được không" - quan trọng nhất cho RAG
Precision@K|tài liệu liên quan trong top K| / KĐo "có nhiễu không" - quan trọng khi context window nhỏ
MRRtrung bình của 1/rank(tài liệu đầu tiên đúng)Đo nhanh độ chính xác tổng thể
nDCG@KDCG@K / IDCG@K (graded relevance)Metric vàng - thưởng document đúng ở vị trí cao
Hit Rate% queries có ít nhất 1 tài liệu đúng trong top KPhù hợp khi chỉ cần tìm được 1 doc đúng

Đừng chỉ nhìn độ chính xác của câu trả lời LLM

Nhiều team đo RAG bằng "LLM answer correctness" và ngạc nhiên khi đổi retriever không thấy cải thiện. Lý do: nếu LLM đang tự hallucinate, nó sẽ ra đáp án đúng dù context không chứa thông tin. Luôn đo retrieval metrics riêng trước khi đo generation metrics.

11. Case study: Từ Vector Search baseline đến Hybrid + Rerank

Chúng tôi triển khai một chatbot nội bộ cho tài liệu kỹ thuật tiếng Việt, corpus gồm 180,000 đoạn văn (chunk). Dưới đây là hành trình tối ưu:

Phiên bảnPipelineRecall@10nDCG@10Latency P95
V0Dense only (multilingual-e5-large)61.2%0.4848ms
V1+ BM25 (OpenSearch) + RRF74.8%0.6172ms
V2+ HyDE query rewriting79.3%0.65540ms (LLM call)
V3+ BGE Reranker v2-m379.3%0.82680ms
V4+ Redis cache (L1+L2)79.3%0.82180ms (cache hit 62%)

Từ V0 → V4, chất lượng (nDCG@10) tăng từ 0.48 lên 0.82 - tức là gần gấp đôi. Thú vị nhất là V3: recall không đổi nhưng nDCG nhảy vọt, chứng minh chất lượng retrieval phụ thuộc rất nhiều vào thứ tự, không chỉ việc có tìm được hay không.

Latency tăng mạnh ở V2 vì gọi LLM rewriting là phần đắt nhất. V4 giải quyết bằng cache: với cache hit rate 62%, latency trung bình giảm về mức có thể chấp nhận cho sản phẩm tương tác.

12. Những sai lầm thường gặp

  1. Chunking bừa bãi: Split theo ký tự cố định (fixed-size) là cách nhanh nhất để phá hỏng retrieval. Nên split theo sentence boundary, giữ overlap ~15%, và ưu tiên semantic chunking nếu được. Chunk quá dài khiến embedding bị smear, chunk quá ngắn mất context.
  2. Không preprocess tiếng Việt: Nhiều embedding model xử lý tiếng Việt kém vì thiếu tokenizer phù hợp. Hãy chuẩn hóa Unicode (NFC), bỏ dấu cách thừa, và chọn model multilingual đã train trên tiếng Việt (E5, BGE-M3, mContriever).
  3. Rerank trước khi fusion: Một số team rerank từng retriever riêng rồi mới fusion - điều này sai thứ tự. Luôn fusion candidate list trước, rerank sau.
  4. Rerank quá nhiều document: Rerank 500 docs thay vì 100 docs không cho cải thiện đáng kể nhưng tăng gấp 5 lần latency. Quy tắc 100-10 là đủ cho hầu hết use case.
  5. Không cache: 60-80% query trong production là repeat hoặc near-duplicate. Không có cache là lãng phí hiển nhiên.
  6. Bỏ qua metadata filtering: Vector search mà không kết hợp metadata filter (ngày tháng, tác giả, category) sẽ luôn thua một baseline có filter đơn giản. Đa số vector DB hiện đại hỗ trợ filtered search, hãy dùng.
  7. Overfit reranker: Fine-tune reranker trên tập dữ liệu nhỏ thường làm model tệ hơn. Nếu bạn không có > 10K cặp (query, relevant_doc) gold-standard, đừng fine-tune - dùng model pretrained là đủ.

13. Kết luận

Hybrid Search và Reranking không phải là những kỹ thuật "advanced" chỉ dành cho hệ thống lớn - chúng là tiêu chuẩn mặc định cho bất kỳ RAG nào muốn đạt chất lượng production. Dense vector một mình không đủ, BM25 một mình cũng không đủ. Sức mạnh nằm ở sự kết hợp, với một tầng reranking để quyết định thứ tự cuối cùng.

Những điểm mấu chốt cần nhớ:

  • Hybrid mặc định - luôn kết hợp BM25 với dense vector, dùng RRF để fusion
  • Reranking là đòn bẩy lớn nhất - mức cải thiện chất lượng thường vượt mọi tối ưu embedding model
  • Query rewriting có giá trị nhưng phải cache để kiểm soát chi phí
  • Quy tắc 100-10: retrieve rộng, rerank hẹp
  • Redis + ClickHouse là cặp đôi vô địch cho caching + observability trong retrieval pipeline
  • Đo lường riêng retrieval metrics trước khi đo generation metrics

Thế giới RAG đang dần tách khỏi cái bẫy "one vector database fits all" để hướng tới kiến trúc đa tầng, nơi mỗi component làm tốt một việc. Nếu bạn đang bắt đầu một dự án RAG mới vào năm 2026, hãy xây hybrid + rerank ngay từ ngày đầu - chi phí thêm vài giờ setup sẽ tiết kiệm hàng tuần debug sau này.

Hành động tiếp theo cho team của bạn

1. Audit pipeline hiện tại: đo Recall@10 và nDCG@10 trên một tập eval cỡ 200-500 queries. 2. Thêm BM25 song song với vector search, dùng RRF fusion. 3. Tích hợp BGE Reranker v2-m3 (miễn phí) cho top-100 candidates. 4. Thêm Redis cache hai tầng. 5. Gửi log vào ClickHouse để theo dõi latency, cache hit, và score distribution.

14. Nguồn tham khảo