Embeddings & Vector Search

Vector Embeddings Là Gì? Từ Trực Giác Hình Học Đến Semantic Search Và RAG

Vector embeddings biến text thành các điểm trong không gian số để máy có thể tìm kiếm theo ý nghĩa thay vì chỉ dựa vào từ khóa. Bài viết đi từ trực giác hình học đến similarity, HNSW, hybrid retrieval và kiến trúc RAG thực tế.

Minh họa cho bài Vector Embeddings Là Gì? Từ Trực Giác Hình Học Đến Semantic Search Và RAG
Mục lục bài viết

Hãy tưởng tượng bạn đang xây một hệ thống tìm kiếm cho tài liệu nội bộ của công ty.

Trong database có một đoạn:

“Nhân viên có thể xin làm việc tại nhà tối đa hai ngày mỗi tuần nếu được quản lý trực tiếp phê duyệt.”

Người dùng lại tìm:

“Một tuần được remote mấy hôm?”

Nếu search theo keyword truyền thống, đây không phải một truy vấn dễ. Câu hỏi không chứa “làm việc tại nhà”, tài liệu không chứa “remote”, và cách diễn đạt giữa hai bên gần như không trùng nhau.

Nhưng về ý nghĩa, chúng đang nói về cùng một vấn đề.

Đây chính là khoảng trống mà vector embeddings cố gắng giải quyết.

Thay vì yêu cầu hai đoạn text phải chứa những từ giống nhau, embedding model biến chúng thành các vector số sao cho những nội dung có quan hệ ngữ nghĩa phù hợp có thể được đặt gần nhau trong một không gian toán học. Nhờ đó, search engine không còn chỉ hỏi:

“Hai đoạn có bao nhiêu từ giống nhau?”

mà có thể hỏi một câu hữu ích hơn:

“Hai đoạn này có đang nói về những thứ giống nhau không?”

Ý tưởng đó nghe khá đơn giản. Nhưng từ một vector vài trăm hoặc vài nghìn số đến một hệ thống semantic search chạy trên hàng triệu tài liệu là cả một chuỗi quyết định engineering: model học không gian đó bằng cách nào, “gần nhau” được đo ra sao, tại sao không thể quét toàn bộ database, HNSW giải quyết vấn đề gì, vì sao embedding retrieval vẫn có thể trả sai, và tại sao production RAG thường cần thêm keyword search hoặc reranking.

Bài viết này sẽ đi từ trực giác đó đến kiến trúc retrieval thực tế, nhưng giữ một trọng tâm duy nhất:

Vector embedding không phải một database feature hay một chuỗi số thần bí. Nó là một learned representation giúp biến bài toán so sánh ý nghĩa thành bài toán tìm kiếm hình học.


1. Vector embedding thực chất là gì?

Một vector embedding có thể trông như thế này:

Text
[
   0.021,
  -0.184,
   0.733,
   0.091,
  ...
]

Trong thực tế vector có thể chứa hàng trăm hoặc hàng nghìn phần tử.

Ví dụ đơn giản:

Text
"mèo"       → [ 0.17, -0.31, 0.82, ... ]
"mèo con"   → [ 0.20, -0.28, 0.79, ... ]
"máy bay"   → [-0.61,  0.43, 0.05, ... ]

Con người gần như không thể nhìn ba vector này rồi đọc ra ý nghĩa của từng con số. Điều quan trọng không nằm ở một dimension riêng lẻ, mà nằm ở cấu trúc hình học của toàn bộ không gian.

Nếu model được huấn luyện tốt cho semantic similarity hoặc retrieval, các dữ liệu có quan hệ mà model cần học sẽ tạo ra những cấu trúc khoảng cách hữu ích trong không gian đó. Đây cũng là trực giác cốt lõi của research ban đầu: embeddings chuyển dữ liệu phi cấu trúc thành các điểm trong không gian vector để similarity có thể được xử lý bằng toán học.

Một cách hình dung đơn giản là:

Text
                    "database replication"
                             ●
                            /
                           /
        "PostgreSQL" ●────● "database"




   "mèo con" ●
              \
               ● "mèo"
                \
                 ● "con mèo nhỏ"

Hình vẽ hai chiều này chỉ là minh họa. Embedding thật có thể nằm trong không gian 768, 1.024, 3.072 hoặc nhiều dimension hơn.

Điểm quan trọng hơn là:

Embedding model không lưu một dictionary kiểu remote = work from home.

Nó học một hàm:

Text
f(input) → vector

sao cho geometry của vector hữu ích đối với objective mà model đã được huấn luyện.

Ví dụ:

Text
f("Một tuần được remote mấy hôm?")
        ↓
query vector

f("Nhân viên có thể làm việc tại nhà tối đa hai ngày mỗi tuần...")
        ↓
document vector

Nếu hai vector có similarity cao, hệ thống có lý do để xem tài liệu đó là một candidate tốt.

Embedding là representation, không phải “ý nghĩa được lưu trong từng dimension”

Một misconception dễ gặp là tưởng rằng:

Text
dimension 17 = chủ đề tài chính
dimension 51 = mức độ tích cực
dimension 82 = địa điểm

Đó không phải mental model nên dùng cho dense embeddings hiện đại.

Các đặc trưng thường được phân tán qua nhiều dimension. Một dimension riêng lẻ hiếm khi có interpretation ổn định đủ để developer dùng như một feature thủ công.

Cách hiểu tốt hơn là:

Model đã học một hệ tọa độ mà trong đó các phép so sánh hình học trở nên hữu ích cho downstream task.

🌱 Cách hiểu đơn giản

Một embedding không cố “dịch câu thành một danh sách thuộc tính mà con người đọc được”.

Nó cố dịch câu thành một vị trí toán học mà máy có thể so sánh nhanh với hàng triệu vị trí khác.


2. Vì sao model có thể biến “ý nghĩa” thành geometry?

Embedding sẽ không hữu ích nếu model chỉ tạo vector ngẫu nhiên.

Điều làm nên embedding space chính là training objective.

Giả sử chúng ta có ba câu:

Text
A: "Làm thế nào reset mật khẩu?"
B: "Tôi quên password, đổi lại bằng cách nào?"
C: "Cách tạo Kubernetes cluster?"

Ta muốn:

Text
similarity(A, B) → cao
similarity(A, C) → thấp

Trong quá trình training, model được tối ưu sao cho representation của các positive pair tiến lại gần nhau và các negative pair bị tách ra.

Một cách biểu diễn khái niệm:

Text
Before training

A ●                    ● B

             ● C


After training

A ●──● B



                         ● C

Các mô hình khác nhau sử dụng objective và training data khác nhau, nhưng nguyên lý chung vẫn là:

Text
input
  │
  ▼
Transformer / encoder
  │
  ▼
hidden representations
  │
  ▼
pooling / projection
  │
  ▼
embedding
  │
  ▼
training loss điều chỉnh geometry

Từ token representation đến sentence embedding

Transformer không nhất thiết ngay lập tức tạo ra một vector duy nhất cho cả câu.

Sau khi xử lý:

Text
"Vector search rất hữu ích"

model có thể tạo representation cho từng token:

Text
Vector   → v1
search   → v2
rất      → v3
hữu ích  → v4

Để phục vụ semantic search theo kiểu single-vector retrieval, hệ thống cần chuyển các token representations này thành một vector đại diện cho toàn bộ input.

Một số kiến trúc sử dụng pooling, special token hoặc projection được huấn luyện riêng cho mục đích này.

Đây là một khác biệt quan trọng giữa việc đơn giản lấy hidden state từ một language model và việc sử dụng một model được huấn luyện thực sự cho embeddings.

Sentence-BERT là một cột mốc quan trọng trong hướng này. Thay vì phải đưa từng cặp câu qua BERT để so sánh, SBERT tạo sentence embeddings có thể được tính trước và sau đó so sánh bằng cosine similarity, khiến semantic similarity search trở nên khả thi ở quy mô lớn hơn rất nhiều.

Symmetric similarity và asymmetric retrieval không hoàn toàn giống nhau

Hãy xem hai task:

Text
Task A:
"Cách reset password?"
vs
"Làm sao đổi mật khẩu?"

Task B:
Query:
"Cách reset password?"

Document:
"Để đặt lại mật khẩu, mở Settings → Security..."

Task A hỏi:

Hai câu có giống nghĩa với nhau không?

Task B hỏi:

Document này có phải tài liệu phù hợp để trả lời query không?

Đó không hoàn toàn là cùng một relationship.

Vì vậy embedding model hiện đại có thể phân biệt vai trò:

Text
query
document
classification input
clustering input
semantic similarity input

Ví dụ, tài liệu Gemini Embeddings hiện tại phân biệt rõ các trường hợp retrieval query, retrieval document, semantic similarity, classification và clustering; với model mới hơn, task có thể được truyền như instruction cho embedding model.

🏗️ Production Note

Đừng mặc định rằng:

Text
embed(query)

và:

Text
embed(document)

luôn phải sử dụng chính xác cùng một preprocessing hoặc instruction.

Hãy làm theo contract của model bạn sử dụng. Nếu model được huấn luyện theo asymmetric retrieval nhưng application bỏ qua query/document instruction, chất lượng retrieval có thể giảm ngay cả khi code vẫn chạy hoàn toàn bình thường.


3. Khi đã có vector, “gần nhau” được tính như thế nào?

Embedding chỉ giải quyết bước:

Text
data → vector

Search engine vẫn phải trả lời:

Vector nào gần query vector nhất?

Ba metric phổ biến nhất là:

  • Cosine similarity
  • Dot product
  • Euclidean distance

Cosine similarity: so hướng của hai vector

Với hai vector (A) và (B):

cosine(A,B)=A⋅B∥A∥∥B∥\text{cosine}(A,B) = \frac{A \cdot B}{\lVert A \rVert \lVert B \rVert}

Cosine similarity tập trung vào góc giữa hai vector.

Hai vector cùng hướng:

Text
     B
    ↗
   ↗
  ↗
 ↗ A

sẽ có cosine similarity cao.

Hai vector gần vuông góc:

Text
B
↑
│
│
└────→ A

sẽ ít aligned hơn.

Điều này đặc biệt hữu ích khi độ dài vector không phải tín hiệu quan trọng mà ta muốn retrieval dựa chủ yếu trên orientation trong embedding space.

Dot product

Dot product là:

A⋅B=∑iAiBiA \cdot B = \sum_i A_iB_i

Nó liên quan trực tiếp đến cosine:

A⋅B=∥A∥∥B∥cos⁡(θ)A \cdot B = \lVert A \rVert \lVert B \rVert \cos(\theta)

Điều đó có nghĩa dot product chịu ảnh hưởng cả bởi:

  • góc giữa hai vector;
  • magnitude của chúng.

Nếu embedding model đã normalize output về unit length:

∥A∥=∥B∥=1\lVert A \rVert = \lVert B \rVert = 1

thì:

A⋅B=cos⁡(θ)A \cdot B = \cos(\theta)

và ranking bằng dot product hoặc cosine sẽ tương đương.

Euclidean distance

Euclidean distance đo khoảng cách đường thẳng:

d(A,B)=∑i(Ai−Bi)2d(A,B) = \sqrt{\sum_i(A_i-B_i)^2}

Giá trị càng nhỏ, hai điểm càng gần.

Với unit-normalized vectors, có một quan hệ đẹp:

∥A−B∥2=2−2cos⁡(θ)\lVert A-B \rVert^2 = 2-2\cos(\theta)

Do đó, nếu tất cả vector đều có norm bằng 1, cosine similarity cao hơn cũng đồng nghĩa Euclidean distance nhỏ hơn. Hai metric sẽ cho cùng ordering nearest-neighbor.

Metric Tốt hơn khi Direction
Cosine similarity Direction là tín hiệu chính Cao hơn tốt hơn
Dot product Model được optimize cho inner product hoặc magnitude có ý nghĩa Cao hơn tốt hơn
Euclidean / L2 Khoảng cách hình học tuyệt đối phù hợp với embedding space Thấp hơn tốt hơn

Điều cần nhớ không phải là:

“Text thì luôn phải dùng cosine.”

Mà là:

Similarity function phải phù hợp với cách embedding model được training và với vector index bạn đang sử dụng.

Nhiều vector database hỗ trợ đồng thời cosine, inner product và L2. Chẳng hạn pgvector cung cấp operator/index class riêng cho từng distance function.

Một ví dụ nhỏ

Giả sử query có embedding:

Text
q = [0.8, 0.6]

và hai document:

Text
d1 = [0.75, 0.65]
d2 = [-0.2, 0.9]

Ta có thể tính:

Python
import numpy as np

def cosine(a, b):
    a = np.array(a)
    b = np.array(b)
    return np.dot(a, b) / (
        np.linalg.norm(a) * np.linalg.norm(b)
    )

q = [0.8, 0.6]

docs = {
    "doc_1": [0.75, 0.65],
    "doc_2": [-0.2, 0.9],
}

for name, vector in docs.items():
    print(name, cosine(q, vector))

Ở production, bạn hiếm khi tự loop qua hàng triệu vectors như vậy. Nhưng về mặt conceptual, semantic retrieval vẫn bắt đầu từ chính phép toán này:

Text
query embedding
      │
      ├── similarity → document 1
      ├── similarity → document 2
      ├── similarity → document 3
      │
      ...
      ▼
  nearest vectors

Vấn đề tiếp theo chính là dấu ....

Nếu database có 100 triệu vectors, chúng ta có thật sự muốn tính 100 triệu similarities cho mỗi query?


4. Từ embedding đến semantic search: chuyện gì thực sự xảy ra?

Một semantic search system tối giản có hai phase khác nhau.

Phase 1 — Indexing

Document được xử lý trước:

Text
Documents
    │
    ▼
Chunking
    │
    ▼
Embedding model
    │
    ▼
Document vectors
    │
    ▼
Vector index

Ví dụ:

Text
Document A
"Chính sách làm việc từ xa..."

Document B
"Cách đăng ký nghỉ phép..."

Document C
"Quy định reimbursement..."

sẽ trở thành:

Text
A → [0.18, -0.41, ...]
B → [0.72,  0.11, ...]
C → [0.05, -0.82, ...]

Các vector này có thể được tính trước vì document không thay đổi theo từng user query.

Đây là yếu tố khiến embedding retrieval có thể scale.

Phase 2 — Query time

Khi người dùng hỏi:

Text
"Một tuần được remote bao nhiêu ngày?"

pipeline trở thành:

Text
User query
    │
    ▼
Embedding model
    │
    ▼
Query vector
    │
    ▼
Vector index
    │
    ▼
Top-K nearest documents

Chúng ta chỉ cần encode query mới.

Document embeddings đã tồn tại.

Đó chính là đặc tính quan trọng của bi-encoder retrieval: query và document được encode độc lập, sau đó interaction xảy ra qua similarity function.

Text
Query ──► Encoder ──► q vector ───┐
                                  │ similarity
Doc   ──► Encoder ──► d vector ───┘

Nhờ separation này:

Text
document embedding

có thể được precompute một lần rồi sử dụng cho rất nhiều queries.

Nhưng nén cả document thành một vector có cái giá của nó

Hãy tưởng tượng một chunk dài chứa:

Text
- remote work policy
- exceptions
- contractor rules
- approval process
- security requirements

Single-vector embedding phải nén toàn bộ những thông tin đó thành:

Text
[0.13, -0.88, 0.27, ...]

Đó là một representation rất compact.

Compactness đem lại tốc độ.

Nhưng nó cũng tạo bottleneck:

Nhiều chi tiết khác nhau phải cạnh tranh để tồn tại trong cùng một vector.

Một query có thể liên quan tới một chi tiết nhỏ của document nhưng global representation của document chưa chắc nhấn mạnh chi tiết đó đủ mạnh.

Đây là một trong những lý do semantic retrieval không nên được hiểu là:

Text
embedding = hiểu hoàn hảo nội dung

Embedding chỉ là một compressed representation được optimize cho một objective nhất định.


5. Vì sao vector database cần ANN và HNSW?

Giả sử chúng ta có:

Text
10 documents

Brute-force search hoàn toàn ổn.

Ta tính:

Text
similarity(query, doc_1)
similarity(query, doc_2)
...
similarity(query, doc_10)

Nhưng với:

Text
100,000,000 vectors

mỗi query phải thực hiện một lượng khổng lồ distance calculations.

Đó là exact nearest-neighbor search:

Text
Query
  │
  ▼
Compare với tất cả N vectors
  │
  ▼
Sort / select nearest K

Search cost tăng trực tiếp theo kích thước corpus.

Ở quy mô lớn, hệ thống thường chuyển sang:

Approximate Nearest Neighbor — ANN

Từ khóa quan trọng là approximate.

ANN không cam kết luôn kiểm tra mọi vector.

Nó cố tìm những hàng xóm rất tốt mà chỉ cần khám phá một phần nhỏ không gian search.

Trade-off trở thành:

Text
higher recall  ←────────────→ lower latency
more work                       less work

Mental model của HNSW

Một trong những ANN index phổ biến nhất là HNSW — Hierarchical Navigable Small World.

Hãy tưởng tượng tìm một cửa hàng trong thành phố.

Nếu phải kiểm tra từng căn nhà:

Text
house 1
house 2
house 3
...
house 5,000,000

thì rất chậm.

Thay vào đó, bạn có nhiều cấp đường:

Text
Highway
   ↓
Main road
   ↓
Street
   ↓
Exact neighborhood

HNSW tạo một cấu trúc graph nhiều layer có trực giác tương tự.

Text
Layer 2        ●──────────────●
               │
               ▼

Layer 1     ●────●──────●────●────●
             \          /
              \        /
               ▼      ▼

Layer 0  ●─●─●─●─●─●─●─●─●─●─●─●─●
          dense graph containing all points

Upper layers chứa ít nodes hơn, cho phép search thực hiện những bước nhảy dài.

Khi đã tới vùng tương đối gần query, search đi xuống layer thấp hơn và refinement dần kết quả.

Original HNSW work mô tả chính kiến trúc proximity graph phân tầng này, trong đó các layer phía trên chứa các subset ngày càng thưa của data và hỗ trợ navigation hiệu quả hơn so với việc duyệt toàn bộ collection.

Ba knob mà engineer thường phải hiểu

Tên parameter có thể thay đổi đôi chút giữa implementations, nhưng ba concept quan trọng thường là:

Text
M
efConstruction
efSearch

M: graph dày đến đâu?

M kiểm soát số connection mà node có thể duy trì.

Tăng M:

Text
more edges
   ↓
more possible search paths
   ↓
potentially better recall

nhưng:

Text
more edges
   ↓
more memory

efConstruction: đầu tư bao nhiêu lúc build index?

Khi thêm một point mới, index phải chọn các neighbors phù hợp.

efConstruction lớn hơn cho phép index xem xét nhiều candidates hơn trong lúc xây graph.

Thông thường:

Text
higher efConstruction
    ↓
better graph quality
    ↓
slower index build / inserts

efSearch: tìm kỹ đến mức nào ở query time?

efSearch kiểm soát lượng candidates được explore khi query.

Text
low efSearch
→ nhanh hơn
→ dễ bỏ lỡ neighbor tốt

high efSearch
→ explore nhiều hơn
→ recall tốt hơn
→ latency/CPU cao hơn

Đây không chỉ là lý thuyết. pgvector, chẳng hạn, expose m, ef_construction và hnsw.ef_search, đồng thời mô tả HNSW là lựa chọn có speed–recall trade-off tốt hơn IVFFlat nhưng tốn memory và build time hơn.

Qdrant cũng expose các knob tương tự và ghi nhận trực tiếp trade-off giữa m, ef_construct, accuracy, memory và index-building cost.

🔬 Deep Dive — ANN recall thực sự có nghĩa gì?

Giả sử exact nearest-neighbor search cho biết Top 10 thật sự là:

Text
A B C D E F G H I J

ANN trả:

Text
A B C D E F G H I X

Nó tìm đúng 9 trong 10.

Có thể nói đơn giản:

Text
Recall@10 = 9 / 10 = 0.9

Tăng search effort có thể khiến ANN tìm lại J.

Nhưng nếu application chỉ cần một relevant document và A đã hoàn toàn đủ để trả lời, việc theo đuổi 100% nearest-neighbor recall có thể không tạo thêm giá trị đáng kể cho end user.

Đây là lý do production tuning phải dựa vào end-to-end retrieval quality, không chỉ index benchmark.


Giả sử user tìm:

Text
ERR_CONN_RESET_0x8FA19

Document chính xác chứa:

Text
ERR_CONN_RESET_0x8FA19

Đây là trường hợp keyword search cực kỳ mạnh.

Bạn không cần “hiểu ngữ nghĩa sâu”.

Bạn cần:

Text
exact token match

Một số query khác cũng có đặc tính tương tự:

Text
invoice ID
product SKU
class name
error code
rare surname
acronym nội bộ
version number

Dense embedding có thể xử lý một phần trong số đó, nhưng không nên mặc định rằng semantic vector search sẽ luôn vượt lexical retrieval.

Ngược lại:

Text
Query:
"Ứng dụng bị đăng xuất sau vài phút không thao tác"

Document:
"Session expires after ten minutes of inactivity"

semantic search có lợi thế rất lớn dù lexical overlap khá thấp.

Hai failure mode gần như đối lập:

Text
Keyword search
  mạnh với exact lexical signals
  yếu với paraphrase

Dense embeddings
  mạnh với semantic similarity
  có thể yếu với rare/exact identifiers

Đây là lý do hybrid search xuất hiện.

Text
                    ┌──► Lexical search ───┐
User query ─────────┤                      ├──► Fusion ─► Candidates
                    └──► Dense retrieval ──┘

Hai retriever nhìn dữ liệu qua hai “ống kính” khác nhau.

Dense retrieval hỏi:

“Nội dung nào có ý nghĩa gần query?”

Lexical retrieval hỏi:

“Nội dung nào có tín hiệu từ vựng phù hợp?”

Một hệ thống tốt không nhất thiết phải lựa chọn một trong hai.

Nó có thể dùng cả hai rồi hợp nhất ranking.

Hybrid search không có nghĩa cộng hai raw scores

Giả sử:

Text
Dense score:
0.82
0.75
0.69

BM25 score:

Text
17.3
12.8
8.2

Hai score không cùng scale.

Cộng trực tiếp:

Text
0.82 + 17.3

thường không mang ý nghĩa toán học đáng tin cậy.

Một hướng phổ biến là rank fusion.

Ví dụ Reciprocal Rank Fusion quan tâm tới vị trí ranking hơn raw score:

RRF(d)=∑r1k+rankr(d)RRF(d) = \sum_r \frac{1}{k + rank_r(d)}

Nếu document đứng cao ở nhiều retriever, nó nhận tổng score cao hơn.

Điều này giúp hệ thống kết hợp:

Text
semantic rank
keyword rank

mà không cần giả định raw scores của chúng tương thích trực tiếp.


7. Retrieval và reranking giải quyết hai bài toán khác nhau

Đây là một trong những distinction quan trọng nhất khi thiết kế search system.

Retriever hỏi:

Trong một triệu documents, 50–200 documents nào đáng xem tiếp?

Reranker hỏi:

Trong 100 candidates này, thứ tự nào thực sự tốt nhất cho query cụ thể?

Embedding bi-encoder rất phù hợp với bước đầu vì document vectors có thể precompute.

Nhưng khi query và document được encode riêng:

Text
query ─► vector

document ─► vector

chúng chỉ thực sự “gặp nhau” ở similarity function.

Model không có cơ hội quan sát chi tiết kiểu:

Text
query token 1 ↔ document token 5
query token 2 ↔ document token 9
...

Cross-encoder giải quyết vấn đề đó bằng cách đưa query và document vào model cùng lúc:

Text
[ query | document ]
        │
        ▼
   Transformer
        │
        ▼
 relevance score

Self-attention cho phép các token từ hai phía tương tác trực tiếp trong model.

Điều này thường giúp ranking tinh tế hơn.

Nhưng nó phá vỡ lợi thế quan trọng của bi-encoder:

Document representation không còn độc lập với query.

Ta không thể đơn giản precompute một score cho document.

Với:

Text
1,000,000 documents

chạy cross-encoder cho cả triệu pairs ở mỗi request sẽ cực kỳ đắt.

Do đó architecture phổ biến là:

Text
                    millions of documents
                            │
                            ▼
                     Bi-Encoder / ANN
                            │
                      Top 50–200
                            │
                            ▼
                       Reranker
                            │
                         Top 5–20
                            │
                            ▼
                        Consumer

Trong RAG, consumer cuối có thể là LLM.

Text
User question
     │
     ▼
Hybrid / Dense Retrieval
     │
     ▼
Candidate chunks
     │
     ▼
Cross-Encoder / Reranker
     │
     ▼
Best context
     │
     ▼
LLM
     │
     ▼
Answer

Điều đáng chú ý là architecture này không sử dụng hai model vì “AI càng nhiều càng tốt”.

Hai stage tồn tại vì chúng optimize cho hai mục tiêu khác nhau:

Stage Mục tiêu chính Corpus size
Retrieval Recall + scalability rất lớn
Reranking Precision nhỏ
Generation Tổng hợp câu trả lời rất nhỏ

Sentence-BERT chính là một ví dụ lịch sử quan trọng cho lợi thế của precomputed sentence embeddings so với pairwise BERT scoring ở large-scale similarity search.

Late interaction nằm ở đâu?

Có một khoảng trống giữa:

Text
single-vector bi-encoder

và:

Text
full cross-encoder

Các architecture như ColBERT cố giữ nhiều representation ở token level rồi thực hiện interaction muộn hơn.

Thay vì:

Text
document → ONE vector

ta có thể có:

Text
document
  ├─ token vector 1
  ├─ token vector 2
  ├─ token vector 3
  └─ ...

Nhờ đó matching có thể tinh tế hơn single-vector retrieval trong khi document representations vẫn có khả năng được tính trước. ColBERT được thiết kế chính để giữ fine-grained interaction nhưng tránh chi phí pairwise inference của cross-encoder trên toàn corpus.

Đổi lại, multi-vector representation có storage và indexing cost lớn hơn đáng kể; những hệ thống hỗ trợ late interaction vì thế phải giải quyết một trade-off mới giữa retrieval quality và footprint.

Đây là một chủ đề đủ lớn cho một bài riêng. Điều cần giữ lại ở đây chỉ là:

Một vector duy nhất là một lựa chọn kiến trúc để đổi compression và scalability lấy một phần fine-grained interaction — không phải cách duy nhất để biểu diễn document.


8. Embeddings đi vào RAG như thế nào?

RAG thường được minh họa quá đơn giản:

Text
Question
   ↓
Vector DB
   ↓
LLM

Sơ đồ này đúng về ý tưởng, nhưng che mất hầu hết những failure points quan trọng.

Một pipeline thực tế hơn là:

Text
                    INDEXING

Raw documents
     │
     ▼
Parsing / cleaning
     │
     ▼
Chunking
     │
     ▼
Metadata
     │
     ▼
Embedding
     │
     ▼
Vector + lexical indexes


                     QUERY

User question
     │
     ▼
Query transformation
     │
     ├───────────────┐
     ▼               ▼
Dense retrieval   Lexical retrieval
     │               │
     └───────┬───────┘
             ▼
          Fusion
             │
             ▼
         Reranking
             │
             ▼
      Context selection
             │
             ▼
            LLM

Embedding chỉ trực tiếp chịu trách nhiệm cho một vài bước trong pipeline.

Điều này rất quan trọng vì khi RAG trả lời sai, developer thường đổ lỗi:

Text
"embedding model không đủ tốt"

trong khi nguyên nhân có thể là:

Text
document parse sai
chunk boundary tệ
metadata filter sai
query transformation làm mất entity
ANN recall thấp
keyword candidate bị bỏ
reranker xếp sai
context bị cắt
LLM bỏ qua evidence

Giả sử document dài 20 trang.

Nếu embed nguyên toàn bộ:

Text
20 pages
   ↓
one vector

representation phải nén quá nhiều topics.

Nếu chia quá nhỏ:

Text
sentence 1 → vector
sentence 2 → vector
sentence 3 → vector
...

mỗi chunk có thể mất context cần thiết để hiểu ý nghĩa.

Chunking vì vậy tạo ra một optimization problem:

Text
smaller chunks
    ↓
more focused representation
    ↓
but less context

larger chunks
    ↓
more context
    ↓
but more semantic dilution

Không tồn tại một chunk size “chuẩn cho mọi RAG”.

Con số như 256, 512 hay 1.024 tokens chỉ nên được xem như starting point.

Chunking phải được evaluate trên chính corpus và query distribution của application.

Metadata không phải thứ phụ

Giả sử user hỏi:

Text
"Chính sách nghỉ phép của nhân viên Nhật Bản"

Semantic similarity có thể tìm được hàng loạt leave policies.

Nhưng nếu application biết:

Text
country = JP
document_status = active
effective_year = 2026

thì retrieval có thể áp dụng metadata filtering trước hoặc trong quá trình vector search.

Text
semantic relevance
        +
structured constraints

thường mạnh hơn việc bắt embedding tự suy ra tất cả mọi constraint.

Migration embedding model thường đồng nghĩa re-index

Embedding space chỉ có ý nghĩa nội tại đối với model đã tạo ra nó.

Nếu:

Text
documents → model A
query     → model B

hai vector không nhất thiết nằm trong cùng một coordinate system.

Ngay cả khi cả hai đều có:

Text
768 dimensions

chúng không tự động tương thích.

Google hiện ghi rõ rằng embedding spaces của gemini-embedding-001 và gemini-embedding-2 không tương thích trực tiếp; migration yêu cầu re-embed dữ liệu hiện có.

Đây là một production implication rất lớn:

Đổi embedding model không giống đổi một stateless API endpoint. Nó có thể là một data migration.

🏗️ Production Note

Hãy version embedding trong schema:

Text
embedding_model
embedding_version
embedding_dimension
indexed_at

thay vì chỉ lưu:

Text
embedding

Khi model thay đổi, bạn sẽ biết vector nào cần re-index và có thể chạy migration song song thay vì ghi đè một cách mù quáng.


9. Đừng chọn embedding model chỉ bằng một leaderboard score

Một model có thể mạnh ở:

Text
semantic textual similarity

nhưng không phải lựa chọn tốt nhất cho:

Text
document retrieval

Hoặc rất tốt với English nhưng không tốt bằng một model khác với Vietnamese, Japanese hoặc domain terminology của công ty.

Đó là lý do benchmark embeddings cần nhiều loại tasks.

MTEB được xây dựng chính từ nhận xét rằng đánh giá embedding chỉ trên một task không đủ; benchmark ban đầu bao phủ retrieval, clustering, classification, pair classification, reranking, semantic textual similarity, summarization và bitext mining, và nghiên cứu cũng chỉ ra không có một phương pháp embedding duy nhất thống trị mọi loại task.

Với một RAG system, average leaderboard score vì vậy chỉ là screening signal.

Evaluation hữu ích hơn thường có ba tầng:

Text
Model benchmark
      ↓
Retrieval benchmark trên corpus của bạn
      ↓
End-to-end application evaluation

Tầng 1 — Public benchmark

Dùng để loại bỏ các model rõ ràng không phù hợp và hiểu capability tổng quát.

Tầng 2 — Retrieval evaluation

Tạo dataset:

Text
query
→ relevant documents

rồi đo các metric như:

Text
Recall@K
MRR
NDCG

Ví dụ:

Text
Query:
"Làm sao đổi mật khẩu khi mất điện thoại?"

Expected relevant chunk:
security_policy_42

Nếu chunk đó không xuất hiện trong Top 20, generation model gần như không có cơ hội sử dụng nó.

Tầng 3 — End-to-end RAG

Ngay cả retrieval tốt cũng chưa đảm bảo answer tốt.

Ta còn phải kiểm tra:

Text
retrieved evidence
      ↓
context construction
      ↓
LLM reasoning
      ↓
final answer

Đây là distinction cực kỳ quan trọng:

Embedding quality không đồng nghĩa RAG quality.

Embedding chỉ là một component trong retrieval system.


10. Những sai lầm phổ biến khi bắt đầu với vector embeddings

Không.

Dense search và lexical search giải quyết những failure modes khác nhau.

Nếu domain chứa nhiều:

Text
IDs
product codes
error messages
proper nouns
versions
technical identifiers

lexical retrieval vẫn rất giá trị.

Cách nghĩ tốt hơn:

Hãy xem dense retrieval và lexical retrieval như hai nguồn evidence bổ sung cho nhau.


Sai lầm 2: “Vector database hiểu document”

Vector database thường không phải component tạo ra semantic understanding.

Nó nhận:

Text
vectors

và thực hiện:

Text
storage
indexing
filtering
nearest-neighbor search

Embedding model mới là component tạo learned representation.

Một database có HNSW cực nhanh không cứu được embedding space tệ.

Ngược lại, embedding model rất tốt cũng không cứu được search architecture cấu hình sai.


Sai lầm 3: “Cosine score 0.8 nghĩa là 80% giống nhau”

Cosine similarity không phải probability.

Text
0.8

không có nghĩa:

Text
80% relevant

Ngưỡng phù hợp phụ thuộc vào:

Text
embedding model
domain
query distribution
chunking
task

Một threshold chỉ có ý nghĩa sau khi calibration trên dữ liệu thật.


Sai lầm 4: “Dimension càng lớn thì embedding càng tốt”

Vector nhiều dimension hơn có thể chứa representation phong phú hơn, nhưng nó cũng làm tăng:

Text
storage
memory bandwidth
distance computation
index size
network transfer

Và thêm dimensions không tự động tạo ra retrieval quality.

Một số model hiện đại thậm chí được thiết kế để hỗ trợ dimension reduction. Matryoshka Representation Learning là một ví dụ nghiên cứu về cách tổ chức representation coarse-to-fine để model có thể sử dụng các prefix dimension nhỏ hơn khi downstream system cần trade quality lấy efficiency.

Câu hỏi đúng không phải:

“Vector lớn nhất là bao nhiêu?”

mà là:

“Dimension nào đạt quality target với chi phí phù hợp trên workload của tôi?”


Sai lầm 5: “ANN trả sai nghĩa là embedding model tệ”

Có hai loại lỗi hoàn toàn khác nhau.

Representation error

Relevant document không đủ gần query trong embedding space.

Text
embedding/model problem

Search error

Relevant vector thật sự gần query, nhưng ANN index không tìm thấy nó.

Text
index/search problem

Muốn phân biệt, hãy benchmark ANN với exact search trên một subset đủ đại diện.

Nếu exact retrieval tốt nhưng HNSW retrieval giảm mạnh:

Text
model có thể ổn
index tuning có vấn đề

Nếu cả exact search cũng không tìm được relevant document:

Text
tăng efSearch sẽ không cứu được

Đây là reasoning rất quan trọng khi debug retrieval.


11. Một mental model hoàn chỉnh cho vector retrieval

Sau tất cả các chi tiết phía trên, có thể gom hệ thống lại thành năm layer.

Text
┌─────────────────────────────────────┐
│ 1. REPRESENTATION                   │
│ text → embedding                    │
└──────────────────┬──────────────────┘
                   │
                   ▼
┌─────────────────────────────────────┐
│ 2. GEOMETRY                         │
│ cosine / dot product / L2           │
└──────────────────┬──────────────────┘
                   │
                   ▼
┌─────────────────────────────────────┐
│ 3. INDEX                            │
│ exact search / HNSW / other ANN     │
└──────────────────┬──────────────────┘
                   │
                   ▼
┌─────────────────────────────────────┐
│ 4. RETRIEVAL STRATEGY               │
│ dense + lexical + filters + fusion  │
└──────────────────┬──────────────────┘
                   │
                   ▼
┌─────────────────────────────────────┐
│ 5. RELEVANCE REFINEMENT             │
│ reranker / late interaction         │
└─────────────────────────────────────┘

Mỗi layer có một responsibility khác nhau.

Nếu kết quả search không tốt, hỏi lần lượt:

Text
Representation:
Model có đặt relevant content gần query không?

Geometry:
Metric có phù hợp với model không?

Index:
ANN có tìm được nearest neighbors không?

Retrieval:
Có cần lexical signal hoặc metadata filter không?

Refinement:
Top candidates có cần reranking không?

Cách debug này hiệu quả hơn nhiều so với phản ứng:

Text
"Thử đổi vector database."

hoặc:

Text
"Thử embedding model lớn hơn."

bởi vì bạn đang xác định đúng layer gây lỗi trước khi thay technology.


Kết luận

Quay lại câu hỏi ban đầu:

Text
Query:
"Một tuần được remote mấy hôm?"

Document:
"Nhân viên có thể làm việc tại nhà tối đa hai ngày mỗi tuần..."

Keyword search nhìn thấy hai chuỗi text khá khác nhau.

Vector retrieval cố nhìn chúng dưới một representation khác:

Text
meaning
  ↓
embedding
  ↓
geometry
  ↓
nearest-neighbor search

Đó là bước chuyển quan trọng nhất mà embeddings mang lại.

Nhưng khi đi từ demo sang production, ta cũng thấy rõ rằng “tạo embedding rồi lưu vào vector database” mới chỉ là phần đầu của câu chuyện.

Một semantic retrieval system đáng tin cậy phải giải quyết đồng thời:

  • representation quality — model có học đúng relationship mà application cần hay không;
  • similarity geometry — distance function có phù hợp với embedding space không;
  • search scalability — exact search hay ANN, HNSW phải trade recall lấy latency như thế nào;
  • retrieval coverage — khi nào semantic signal cần kết hợp lexical search và metadata;
  • ranking precision — khi nào candidates cần reranker hoặc interaction giàu thông tin hơn.

Mental model quan trọng nhất có thể giữ lại là:

Embedding biến dữ liệu thành một không gian mà relevance có thể được tìm bằng geometry. Vector index giúp chúng ta khám phá không gian đó ở quy mô lớn. Nhưng retrieval quality cuối cùng vẫn là kết quả của toàn bộ pipeline, không phải của riêng vector.

Khi hiểu được distinction đó, vector database không còn là một “hộp đen AI”.

Nó trở thành một component rất cụ thể trong kiến trúc search:

Text
Representation
      ↓
Similarity
      ↓
Indexing
      ↓
Retrieval
      ↓
Reranking
      ↓
Application

Và đó cũng là nền tảng cần có trước khi đi sâu hơn vào hybrid search, RAG retrieval, HNSW tuning, embedding model evaluation hay multi-vector architectures.

Nguồn tham khảo

  • Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks — Reimers & Gurevych, EMNLP 2019.
  • Efficient and Robust Approximate Nearest Neighbor Search Using Hierarchical Navigable Small World Graphs — Malkov & Yashunin.
  • MTEB: Massive Text Embedding Benchmark — Muennighoff et al.
  • Matryoshka Representation Learning — Kusupati et al.
  • ColBERT: Efficient and Effective Passage Search via Contextualized Late Interaction over BERT — Khattab & Zaharia.
  • pgvector — Vector Similarity Search and HNSW/IVFFlat Documentation.
  • Gemini API — Embeddings Documentation.