Mục lục bài viết
Một người dùng nhập vào ô tìm kiếm:
“Làm thế nào để giảm thời gian phản hồi của API?”
Trong database lại không có document nào chứa chính xác câu đó. Thứ tồn tại là một tài liệu có tiêu đề:
“Các kỹ thuật tối ưu latency cho backend service”
Nếu hệ thống chỉ tìm kiếm bằng keyword, nó có thể bỏ qua tài liệu này vì "giảm thời gian phản hồi" và "tối ưu latency" không trùng nhau về mặt từ vựng.
Nhưng một developer đọc hai câu trên gần như ngay lập tức nhận ra chúng đang nói về cùng một vấn đề.
Đây chính là khoảng cách mà Semantic Similarity cố gắng thu hẹp: thay vì chỉ hỏi “hai đoạn text có bao nhiêu từ giống nhau?”, hệ thống muốn trả lời một câu hỏi khó hơn:
“Hai đoạn text này gần nhau đến mức nào về mặt ý nghĩa?”
Research nền của bài mô tả sự chuyển dịch này từ lexical matching sang việc biểu diễn văn bản thành các vector trong không gian nhiều chiều, nơi những văn bản gần nhau về ý nghĩa có xu hướng được đặt gần nhau về mặt hình học.
Nhưng câu chuyện không đơn giản là:
text
↓
embedding
↓
cosine similarity
↓
máy tính hiểu ý nghĩa
Để xây một hệ thống semantic search, recommendation hay RAG đáng tin cậy, chúng ta cần hiểu ít nhất ba lớp khác nhau:
Representation
Văn bản được biến thành vector như thế nào?
↓
Geometry
"Giống nhau" trong không gian vector được đo thế nào?
↓
Engineering
Điểm similarity có thực sự phản ánh điều ứng dụng cần tìm hay không?
Semantic Similarity nằm ở giao điểm của cả ba lớp đó.
1. Semantic Similarity thực chất đang đo cái gì?
Giả sử có ba câu:
A. Python được dùng nhiều trong backend development.
B. Python là một ngôn ngữ phổ biến để xây dựng server-side application.
C. JavaScript chạy trong trình duyệt.
Về mặt lexical matching, A và B không chia sẻ quá nhiều từ.
Nhưng về mặt ý nghĩa, chúng khá gần nhau.
Một hệ thống Semantic Similarity thường thực hiện hai bước:
Text A ──► Encoder ──► Vector A ──┐
│
├──► Similarity Function ──► Score
│
Text B ──► Encoder ──► Vector B ──┘
Encoder biến văn bản thành một dãy số:
A → [0.13, -0.42, 0.77, ..., 0.05]
B → [0.11, -0.39, 0.74, ..., 0.09]
Những con số riêng lẻ gần như không có ý nghĩa trực quan đối với con người. Điều quan trọng nằm ở cấu trúc tương đối của toàn bộ không gian embedding.
Nếu quá trình training hoạt động tốt, những text có quan hệ mà model được huấn luyện để nhận biết sẽ có representation gần nhau hơn.
Đây là một nuance rất quan trọng.
💡 Mental model: Embedding model không tạo ra một “tọa độ ý nghĩa tuyệt đối” của ngôn ngữ. Nó học một không gian biểu diễn mà trong đó khoảng cách phản ánh những quan hệ được hình thành bởi architecture, dữ liệu và training objective của model.
Vì vậy, một similarity score cao không nên được diễn giải đơn giản thành:
“Hai câu giống nhau 87% về ý nghĩa.”
Score 0.87 chỉ có ý nghĩa trong bối cảnh cụ thể của:
- embedding model đang dùng;
- similarity function;
- loại dữ liệu;
- task;
- cách model được train;
- distribution của corpus.
Đó cũng là lý do một embedding model rất mạnh trên Semantic Textual Similarity chưa chắc là model retrieval tốt nhất. Benchmark MTEB được xây dựng chính vì embedding cần được đánh giá trên nhiều task khác nhau như retrieval, clustering, classification, reranking và STS; nghiên cứu MTEB cũng cho thấy không có một phương pháp embedding duy nhất thống trị tất cả các loại tác vụ.
2. Vì sao ý nghĩa có thể biến thành vector?
Ý tưởng đứng phía sau embeddings hiện đại có nguồn gốc lâu hơn deep learning rất nhiều.
Một intuition quan trọng của ngôn ngữ học phân phối là:
Những từ xuất hiện trong những ngữ cảnh tương tự thường có quan hệ về mặt ngữ nghĩa.
Ví dụ:
The cat sat on the mat.
The dog sat on the mat.
Nếu "cat" và "dog" liên tục xuất hiện trong những cấu trúc tương tự trên một corpus rất lớn, hệ thống có thể học được rằng chúng có một số đặc tính ngữ nghĩa gần nhau dù không cần con người định nghĩa thủ công:
cat = động vật nhỏ, thú nuôi, ...
dog = động vật nhỏ, thú nuôi, ...
Máy không cần lưu những label này.
Nó chỉ cần học pattern thống kê đủ tốt.
Từ co-occurrence đến Word2Vec
Các phương pháp sớm có thể biểu diễn từ bằng ma trận đồng xuất hiện:
pet bark milk animal drive
cat 40 2 31 58 0
dog 37 42 3 61 0
car 0 0 0 1 49
cat và dog có distribution gần nhau hơn cat và car.
Vấn đề là vocabulary thực tế có thể chứa hàng trăm nghìn hoặc hàng triệu token, khiến representation kiểu này cực kỳ lớn và sparse.
Word2Vec đưa ra một hướng khác: thay vì trực tiếp lưu ma trận đồng xuất hiện khổng lồ, model học một dense vector có số chiều nhỏ hơn nhiều thông qua một prediction objective.
Paper Word2Vec năm 2013 giới thiệu hai kiến trúc để học continuous word representations hiệu quả trên corpus lớn.
Hai kiến trúc nổi tiếng là:
| Kiến trúc | Input | Model cố dự đoán |
|---|---|---|
| CBOW | Các từ xung quanh | Từ ở giữa |
| Skip-gram | Từ ở giữa | Các từ xung quanh |
Ví dụ với Skip-gram:
"The cat sits on the sofa"
target
│
▼
cat
│
┌────────┼─────────┐
▼ ▼ ▼
the sits on
Để thực hiện prediction tốt trên hàng triệu ví dụ, model phải tổ chức các word vectors theo cách giúp những từ có behavior tương tự chia sẻ representation tương tự.
Kết quả là chúng ta có một không gian hình học mang cấu trúc ngữ nghĩa.
Nhưng Word2Vec có một vấn đề lớn
Một từ chỉ có một vector.
bank → [ ... ]
Cho dù "bank" xuất hiện trong:
I deposited money at the bank.
hay:
We sat on the bank of the river.
representation vẫn giống nhau.
Đây được gọi là static embedding.
Trong ngôn ngữ thật, ý nghĩa của từ lại phụ thuộc mạnh vào context.
Đó là một trong những lý do contextual language models như BERT trở nên quan trọng.
3. Từ word embedding đến sentence embedding
BERT không tạo representation của "bank" một cách độc lập.
Representation của token được hình thành dựa trên các token xung quanh nó.
Vì vậy:
deposit → bank → money
và:
river → bank → water
có thể tạo ra những contextual representations khác nhau.
BERT được thiết kế để học deep bidirectional representations bằng cách conditioning trên cả context bên trái và bên phải của token.
Điều đó giải quyết một vấn đề quan trọng của static embedding.
Nhưng lại xuất hiện một vấn đề khác.
BERT giỏi hiểu một cặp text, nhưng không tự nhiên phù hợp để search hàng triệu text
Giả sử ta có:
Query:
"How can I reduce API latency?"
Document:
"Backend performance optimization techniques"
Một Cross-Encoder có thể ghép chúng thành một input:
[CLS]
How can I reduce API latency?
[SEP]
Backend performance optimization techniques
[SEP]
Sau đó Transformer cho phép token của query tương tác trực tiếp với token của document.
Điều này rất mạnh.
Model có thể reasoning ở mức token:
"reduce"
↕
"optimization"
"API"
↕
"backend"
"latency"
↕
"performance"
Nhưng có một hạn chế kiến trúc rất lớn:
Representation của document phụ thuộc vào query.
Vì vậy ta không thể đơn giản encode document một lần rồi reuse cho mọi query.
Nếu có một triệu documents:
query + document_1 → model
query + document_2 → model
query + document_3 → model
...
query + document_1_000_000 → model
Một triệu forward pass Transformer cho mỗi query là quá đắt đối với first-stage retrieval.
Sentence-BERT thay đổi bài toán
Sentence-BERT, hay SBERT, giới thiệu kiến trúc Siamese/Bi-Encoder để tạo sentence embeddings có thể so sánh trực tiếp bằng cosine similarity. Paper gốc báo cáo rằng bài toán tìm cặp giống nhau nhất trong 10.000 câu cần khoảng 50 triệu inference với BERT và mất khoảng 65 giờ trong setup của nghiên cứu, trong khi SBERT giảm tác vụ này xuống khoảng 5 giây.
Mental model của Bi-Encoder:
┌──────────────┐
Sentence A ──────►│ │──────► u
│ Encoder │
│ shared θ │
Sentence B ──────►│ │──────► v
└──────────────┘
│
▼
similarity(u, v)
Hai input được encode độc lập nhưng sử dụng cùng một model.
Đây chính là điểm mở khóa semantic retrieval.
Documents có thể được encode trước:
Document 1 → vector 1 ─┐
Document 2 → vector 2 │
Document 3 → vector 3 ├──► Vector Index
... │
Document N → vector N ─┘
Khi query xuất hiện:
Query
│
▼
Embedding Model
│
▼
Query Vector
│
▼
Nearest Neighbors
│
▼
Top-K Documents
Transformer chỉ cần encode query một lần.
Sau đó phần search chuyển thành bài toán hình học.
Đừng nhầm hai loại “quadratic complexity”
Đây là một lỗi technical khá phổ biến.
Transformer self-attention có complexity tăng gần bậc hai theo sequence length vì token tương tác với token.
Nhưng con số gần 50 triệu comparison trong ví dụ 10.000 câu của SBERT lại xuất phát từ số sentence pairs:
Đó là hai nguồn chi phí khác nhau:
Self-attention:
sequence length ↑
→ cost mỗi forward pass ↑
All-pairs comparison:
số sentence ↑
→ số forward pass ↑
Trong semantic search với một query và M documents, Cross-Encoder cần khoảng M pairwise forward passes chứ không phải M².
Tuy nhiên, khi M là hàng triệu, ngay cả O(M) Transformer inference cho mỗi query vẫn không thực tế.
Đó là lý do kiến trúc phổ biến là:
Bi-Encoder
│
│ fast retrieval
▼
Top 100–1000 candidates
│
│ expensive but accurate
▼
Cross-Encoder
│
▼
Top results
| Bi-Encoder | Cross-Encoder | |
|---|---|---|
| Encode query/document riêng | Có | Không |
| Precompute document embeddings | Có | Không |
| Token interaction giữa query và document | Không trực tiếp | Có |
| First-stage retrieval | Rất phù hợp | Quá đắt ở corpus lớn |
| Reranking Top-K | Có thể | Rất phù hợp |
| Latency | Thấp | Cao hơn |
| Precision trên candidate nhỏ | Tốt | Thường tốt hơn |
Sentence Transformers hiện cũng mô tả Bi-Encoder như bước đầu thường dùng trong pipeline hai tầng, sau đó Cross-Encoder rerank Top-K candidates.
4. Từ embedding đến hình học: Cosine Similarity thực sự làm gì?
Sau khi hai đoạn text đã trở thành vectors, neural network tạm thời rời khỏi trung tâm của bài toán.
Giả sử:
và:
Ta cần một function:
similarity(a, b) → score
Ba lựa chọn thường gặp là:
- Cosine Similarity;
- Dot Product;
- Euclidean Distance.
Euclidean Distance
Euclidean distance đo khoảng cách đường thẳng giữa hai điểm:
Trong hai chiều, intuition rất đơn giản:
y
│
│ ● B
│ /
│ / distance
│ /
│ ● A
│
└──────────── x
Khoảng cách càng nhỏ thì hai vector càng gần.
Nhưng Euclidean distance nhạy với cả:
- direction;
- magnitude.
Việc magnitude có mang ý nghĩa hay không lại phụ thuộc vào embedding model và cách nó được train. Vì vậy không nên mặc định rằng Euclidean luôn “sai” cho text embeddings; metric phải phù hợp với representation mà model được thiết kế để sử dụng.
Dot Product
Dot Product đơn giản hơn:
Dot Product bị ảnh hưởng bởi cả góc và magnitude:
Hai vector cùng hướng nhưng magnitude lớn hơn sẽ có dot product lớn hơn.
Điều này có thể là feature hoặc bug tùy model.
Cosine Similarity
Cosine Similarity loại magnitude khỏi phép so sánh bằng cách chia Dot Product cho độ dài của hai vector:
Thay vì hỏi:
Hai điểm cách nhau bao xa?
Cosine hỏi:
Hai vector đang chỉ về những hướng giống nhau đến mức nào?
B
↗
/ θ
/
/
O ─────────────► A
Nếu góc nhỏ, Cosine Similarity cao.
Sentence Transformers hiện sử dụng cosine làm similarity function mặc định cho SentenceTransformer.similarity, đồng thời hỗ trợ Dot Product, Euclidean và Manhattan.
Một misconception quan trọng: cosine âm không có nghĩa là “trái nghĩa”
Về toán học:
cos(0°) = 1
cos(90°) = 0
cos(180°) = -1
Nhưng embedding space không phải một từ điển antonym.
Hai câu:
I love cats.
I hate cats.
có thể vẫn nằm khá gần nhau vì cả hai nói về:
- cats;
- cảm xúc đối với cats;
- cùng grammatical structure;
- cùng semantic domain.
Semantic similarity và logical contradiction là hai bài toán khác nhau.
Một model được train cho entailment, contradiction hay reranking có thể phản ánh distinction này tốt hơn, nhưng không nên diễn giải giá trị cosine âm/dương như một logic rule phổ quát.
⚠️ Cẩn thận: Similarity không đồng nghĩa với entailment, correctness, relevance hay factual consistency.
5. Vì sao L2 normalization khiến Cosine và Dot Product trở nên gần như cùng một bài toán?
Đây là một trong những tính chất hữu ích nhất khi triển khai vector search.
Ta chuẩn hóa vector:
Sau normalization:
Với hai unit vectors u và v:
nên:
Tức là với embeddings đã được L2-normalized:
Cosine Similarity
=
Dot Product
Sentence Transformers cũng lưu ý rằng nếu embeddings đã normalized thì dùng dot metric có thể hợp lý hơn vì cosine sẽ phải normalize lại; dot product trên normalized embeddings tương đương cosine similarity.
Không chỉ vậy.
Euclidean distance giữa hai unit vectors cũng liên hệ trực tiếp với cosine.
Bắt đầu từ:
Khai triển:
Vì:
nên:
Và vì:
ta có:
Điều này dẫn đến một engineering implication rất hữu ích:
Với cùng tập L2-normalized vectors, ranking theo cosine similarity, dot product và Euclidean distance mang thông tin thứ tự tương đương nếu implementation sử dụng các convention tương ứng.
| Metric | Có quan tâm magnitude? | Với normalized vectors |
|---|---|---|
| Cosine Similarity | Không | Bằng Dot Product |
| Dot Product | Có nếu chưa normalize | Bằng Cosine |
| Euclidean Distance | Có nếu chưa normalize | Monotonic với Cosine |
Tuy nhiên, đừng vì đẳng thức toán học này mà tùy tiện đổi metric trong production.
Model card, training objective và vector database configuration vẫn phải thống nhất với nhau.
Nếu model được thiết kế cho Dot Product trên unnormalized embeddings, tự normalize có thể thay đổi behavior mà model đã học.
6. Một Semantic Similarity pipeline bằng Python trông như thế nào?
Với sentence-transformers, một ví dụ STS đơn giản hiện nay có thể viết rất ngắn:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer(
"sentence-transformers/all-MiniLM-L6-v2"
)
sentences = [
"How can I reduce API latency?",
"Techniques for improving backend response time.",
"How do I reset my database password?",
]
embeddings = model.encode(sentences)
scores = model.similarity(
embeddings,
embeddings,
)
print(scores)
model.similarity() trả về một similarity matrix giữa các embeddings. Đây cũng là pattern được tài liệu Sentence Transformers sử dụng cho Semantic Textual Similarity.
Conceptually:
Sentence 1 Sentence 2 Sentence 3
Sentence 1 1.00 0.7x 0.1x
Sentence 2 0.7x 1.00 0.1x
Sentence 3 0.1x 0.1x 1.00
Giá trị trên diagonal là similarity của sentence với chính nó.
Nhưng production search khác một chút.
Semantic Textual Similarity và Semantic Search không hoàn toàn giống nhau
STS thường là bài toán symmetric:
"That movie was fantastic."
"The film was really great."
Hai text có vai trò tương tự.
Search thường asymmetric:
Query:
"How to fix Redis memory issue?"
Document:
"Redis eviction policies, maxmemory configuration,
memory fragmentation and troubleshooting..."
Query ngắn, document dài và có vai trò khác nhau.
Với retrieval tasks, Sentence Transformers phiên bản hiện tại khuyến nghị dùng:
query_embedding = model.encode_query(query)
document_embeddings = model.encode_document(documents)
thay vì luôn dùng encode() cho cả hai, vì một số model sử dụng prompt hoặc routing khác nhau cho query và document.
Một pipeline retrieval đơn giản:
from sentence_transformers import SentenceTransformer
import torch
model = SentenceTransformer(
"sentence-transformers/all-MiniLM-L6-v2"
)
documents = [
"Redis maxmemory controls the memory limit.",
"PostgreSQL uses MVCC for concurrency control.",
"API latency can be reduced through caching and query optimization.",
]
document_embeddings = model.encode_document(
documents,
convert_to_tensor=True,
)
query = "How can I make my API respond faster?"
query_embedding = model.encode_query(
query,
convert_to_tensor=True,
)
scores = model.similarity(
query_embedding,
document_embeddings,
)[0]
top_score, top_index = torch.max(scores, dim=0)
print(documents[top_index])
Với vài nghìn hoặc vài chục nghìn documents, brute-force similarity có thể đủ.
Khi corpus tăng rất lớn, ta thường thay phần:
compare query với mọi document
bằng một ANN index.
Nhưng HNSW, IVF, PQ và vector database là những chủ đề đủ lớn để trở thành bài riêng. Điều cần giữ lại ở đây chỉ là:
Embedding model
│
▼
Vector representation
│
▼
Similarity geometry
│
▼
Nearest-neighbor retrieval
Vector database không tạo ra semantic similarity.
Nó chỉ giúp tìm những vectors gần nhau đủ nhanh ở quy mô lớn.
7. Similarity score không phải probability
Đây là một trong những lỗi phổ biến nhất khi developer mới dùng embeddings.
Giả sử:
cosine = 0.82
Ta rất dễ viết:
Hai câu giống nhau 82%.
Nhưng không có cơ sở tổng quát để kết luận như vậy.
Cosine similarity chỉ là một geometric score.
Distribution của nó có thể khác rất mạnh giữa các model.
Ví dụ, một model có thể cho:
unrelated ~ 0.10–0.30
related ~ 0.40–0.65
very related ~ 0.65–0.85
Trong khi model khác có thể tập trung phần lớn scores trong:
0.55–0.95
Ngay cả cùng một model, distribution cũng thay đổi theo domain.
Legal documents có thể behave khác source code.
Tiếng Việt có thể behave khác tiếng Anh.
Short queries có thể behave khác long passages.
Vì vậy hard-code:
if score > 0.8:
relevant = True
mà không đánh giá trên data thật là một anti-pattern.
Threshold nên được chọn từ evaluation data
Giả sử ta thu thập:
(query, document, relevant?)
từ application thực tế.
Sau đó chạy embedding model và quan sát:
Relevant pairs:
0.91
0.84
0.76
0.71
0.64
Irrelevant pairs:
0.69
0.55
0.42
0.31
0.12
Lúc này mới có thể phân tích threshold:
threshold = 0.60
sẽ ảnh hưởng:
- precision;
- recall;
- false positives;
- false negatives.
Và trong search, nhiều hệ thống thậm chí không cần absolute threshold.
Chúng chỉ cần:
Top-K nearest neighbors
rồi đưa candidates sang reranker.
🏗️ Production Note: Đừng thiết kế business logic dựa trên một similarity threshold chỉ vì score “trông có vẻ cao”. Calibration phải dựa trên distribution của chính dữ liệu và task của bạn.
8. Semantic Similarity thất bại ở đâu?
Embedding-based similarity rất mạnh, nhưng nó không phải một semantic oracle.
8.1. Cùng chủ đề không có nghĩa là cùng ý
Xét:
A. Redis improves application performance through caching.
B. Redis causes application performance problems when memory is exhausted.
Hai câu chia sẻ rất nhiều semantic features:
Redis
application
performance
memory/cache
Embedding có thể đặt chúng khá gần nhau.
Nhưng message của hai câu không giống nhau.
Nếu application cần phân biệt:
support
vs
contradiction
thì similarity alone có thể không đủ.
8.2. Named entities và identifiers có thể quan trọng hơn “ý nghĩa tổng thể”
Query:
ERR_CONNECTION_RESET 104
Document A:
Troubleshooting ERR_CONNECTION_RESET 104
Document B:
General guide to debugging network connection failures
Embedding model có thể thấy B rất relevant về mặt semantic.
Nhưng người dùng có thể muốn chính xác error code 104.
Đây là nơi lexical retrieval như BM25 vẫn cực kỳ hữu ích.
Semantic search không khiến keyword search lỗi thời.
Hai phương pháp giải quyết hai loại signal khác nhau:
| Signal | Lexical Search | Semantic Search |
|---|---|---|
| Exact keyword | Rất mạnh | Có thể yếu hơn |
| Error code / ID | Rất mạnh | Có thể yếu |
| Synonym | Yếu | Mạnh |
| Paraphrase | Yếu | Mạnh |
| Conceptual similarity | Hạn chế | Mạnh |
| Từ hiếm mới xuất hiện | Thường tốt | Phụ thuộc model |
Đó là lý do nhiều production retrieval systems kết hợp lexical và dense retrieval thay vì buộc phải chọn một bên.
8.3. Một vector phải nén quá nhiều thông tin
Giả sử document chứa:
- PostgreSQL indexing
- Redis caching
- Kubernetes networking
- AWS IAM
- Kafka consumer lag
Một single embedding phải nén toàn bộ document thành một vector có kích thước cố định.
Mental model có thể hình dung như:
5 chủ đề khác nhau
│
▼
┌──────────────────────┐
│ Fixed-size embedding │
└──────────────────────┘
│
▼
Một representation chung
Những detail nhỏ có thể bị “pha loãng”.
Đây là một lý do retrieval systems thường chunk documents trước khi embedding.
Nhưng chunk càng nhỏ cũng không phải càng tốt.
Chunk quá nhỏ có thể mất context.
Chunk quá lớn có thể làm representation không đủ tập trung.
Semantic Similarity vì thế không thể tách rời hoàn toàn khỏi đơn vị text mà ta lựa chọn để encode.
8.4. Model không hiểu domain của bạn đủ tốt
Một general-purpose embedding model có thể rất giỏi với:
movies
news
general questions
Wikipedia
nhưng chưa chắc hiểu tốt:
internal product codes
medical terminology
Japanese HR vocabulary
proprietary abbreviations
company-specific concepts
Nếu model chưa từng học được semantic distinction quan trọng đối với domain, similarity function không thể tự sửa vấn đề.
Cosine chỉ đo geometry.
Nếu geometry sai, cosine sẽ đo cái sai một cách rất chính xác.
9. Semantic Similarity không phải Semantic Search
Hai thuật ngữ này thường bị sử dụng thay thế cho nhau nhưng nên tách rõ.
Semantic Similarity
Bài toán:
text A + text B
│
▼
hai text giống nhau đến mức nào?
Output:
similarity score
Semantic Search
Bài toán:
query
│
▼
tìm những documents relevant nhất
trong một corpus lớn
Semantic Similarity là một component có thể được sử dụng bên trong Semantic Search.
Một semantic search system thực tế còn bao gồm:
Documents
│
▼
Chunking
│
▼
Embedding
│
▼
Indexing
│
▼
Query Embedding
│
▼
Candidate Retrieval
│
▼
Filtering / Fusion
│
▼
Optional Reranking
│
▼
Results
Nếu ứng dụng là RAG, còn thêm:
Results
│
▼
Context Construction
│
▼
LLM
│
▼
Answer
Vì vậy khi RAG retrieve sai document, nguyên nhân không nhất thiết là:
“Cosine similarity không tốt.”
Có thể lỗi nằm ở:
- chunking;
- embedding model;
- query formulation;
- metadata filtering;
- retrieval strategy;
- corpus quality;
- ANN configuration;
- reranking.
Đây là mental model quan trọng nhất khi chuyển từ một notebook demo sang production AI system.
10. Bi-Encoder và Cross-Encoder không phải đối thủ — chúng giải quyết hai stage khác nhau
Một hiểu nhầm phổ biến là hỏi:
Nên dùng Bi-Encoder hay Cross-Encoder?
Trong nhiều hệ thống, câu trả lời là:
Dùng cả hai, nhưng ở những vị trí khác nhau.
Hãy tưởng tượng có 10 triệu documents.
Cross-Encoder không thể đánh giá cả 10 triệu candidates với latency hợp lý.
Bi-Encoder lại đủ nhanh để tìm một candidate set nhỏ:
10,000,000 documents
│
│ Bi-Encoder + ANN
▼
Top 100
Sau đó Cross-Encoder có thể dành nhiều compute hơn để phân tích 100 candidates đó:
Top 100
│
│ Cross-Encoder
▼
Top 10
Đây là kiến trúc funnel:
┌──────────────────────────────┐
│ Full Corpus │
│ 10M documents │
└──────────────┬───────────────┘
│
│ fast + broad recall
▼
┌──────────────────────────────┐
│ Bi-Encoder Retrieval │
└──────────────┬───────────────┘
│
│ Top 100
▼
┌──────────────────────────────┐
│ Cross-Encoder Rerank │
└──────────────┬───────────────┘
│
│ precise ranking
▼
┌──────────────────────────────┐
│ Top 10 │
└──────────────────────────────┘
Bi-Encoder tối ưu cho:
candidate generation
Cross-Encoder tối ưu cho:
fine-grained comparison
Không phải mọi system đều cần reranking.
Nếu corpus nhỏ, query đơn giản hoặc latency requirement cực thấp, Bi-Encoder có thể đủ.
Ngược lại, trong search hay RAG nơi một vài vị trí đầu tiên có giá trị rất lớn, reranking thường đáng cân nhắc.
11. Năm lỗi dễ gặp khi triển khai Semantic Similarity
Lỗi 1: Chọn model chỉ dựa trên leaderboard
Một model đứng đầu một benchmark không có nghĩa nó tốt nhất cho application của bạn.
Latency, dimension, language, domain, context length và retrieval objective đều quan trọng.
MTEB tồn tại chính vì embedding quality cần được xem xét trên nhiều task thay vì một score duy nhất.
Lỗi 2: Nghĩ cosine score là probability
0.82 không có nghĩa "82% relevant".
Threshold phải được evaluate.
Lỗi 3: Dùng một giant document làm một embedding
Một embedding cố định có giới hạn về lượng information structure nó có thể giữ.
Chunking strategy ảnh hưởng trực tiếp tới retrieval quality.
Lỗi 4: Bỏ lexical search vì đã có embeddings
Semantic models mạnh ở paraphrase.
BM25 mạnh ở exact lexical evidence.
Product code, version number, tên riêng và error identifier có thể khiến lexical retrieval cực kỳ quan trọng.
Lỗi 5: Tập trung vào Vector Database trước Embedding Quality
Developer đôi khi dành rất nhiều thời gian tranh luận:
Pinecone?
Qdrant?
Weaviate?
pgvector?
Milvus?
trong khi vấn đề thực sự nằm ở embedding hoặc data.
Vector database giúp trả lời:
Làm sao tìm nearest neighbors nhanh?
Nó không tự trả lời:
Representation này có đặt đúng documents cạnh nhau hay không?
Nếu embedding space không phản ánh task của bạn, index nhanh hơn chỉ giúp trả về kết quả sai nhanh hơn.
12. Mental model cuối cùng: Semantic Similarity là learned geometry
Ban đầu chúng ta đặt câu hỏi:
Vì sao
"giảm thời gian phản hồi API"có thể tìm được tài liệu"tối ưu backend latency"dù hai câu không sử dụng cùng từ?
Bây giờ câu trả lời đã rõ hơn.
Không phải hệ thống đang tra một dictionary chứa:
"giảm thời gian phản hồi"
=
"tối ưu latency"
Thay vào đó:
- embedding model đã học statistical structure của language;
- mỗi text được ánh xạ thành một representation nhiều chiều;
- những patterns mà model đánh giá tương tự được đặt gần nhau trong embedding space;
- một similarity function đo relationship hình học giữa các representations;
- retrieval system sử dụng relationship đó để tìm candidates gần query.
Có thể rút gọn toàn bộ cơ chế thành:
Language
│
▼
Learned Representation
│
▼
Vector Space
│
▼
Geometry
│
▼
Similarity
│
▼
Retrieval / Ranking / Clustering / Matching
Nhưng điều quan trọng nhất là không thần thánh hóa bước "Vector Space".
Semantic Similarity không phải bằng chứng rằng model sở hữu một hệ thống hiểu ý nghĩa giống con người.
Nó là một learned geometric approximation cực kỳ hữu ích: model được train sao cho những relationship quan trọng đối với objective của nó xuất hiện dưới dạng structure trong vector space.
Và chính điểm này giải thích cả sức mạnh lẫn giới hạn của embeddings.
Khi representation phù hợp với task, một phép Dot Product đơn giản có thể giúp tìm đúng information giữa hàng triệu documents.
Khi representation không phù hợp, không có vector database, cosine formula hay ANN algorithm nào có thể biến geometry sai thành semantic understanding đúng.
Nếu cần giữ lại bốn ý sau khi đọc bài này, hãy nhớ:
- Embedding quyết định không gian; similarity function chỉ đo không gian đó.
- Cosine score không phải probability hay truth score.
- Bi-Encoder giúp retrieval scalable; Cross-Encoder giúp comparison sâu hơn.
- Semantic Similarity là nền tảng của semantic search, nhưng một production retrieval system còn nhiều stage khác ngoài similarity.
Khi nắm được mental model này, các chủ đề tiếp theo như Vector Database, Hybrid Search, Reranking hay RAG sẽ không còn là những công nghệ rời rạc. Chúng chỉ là những tầng engineering khác nhau được xây lên trên cùng một nền móng: biến thông tin thành representation có thể so sánh và tìm kiếm bằng toán học.
Nguồn tham khảo
- Mikolov et al. — Efficient Estimation of Word Representations in Vector Space.
- Devlin et al. — BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding.
- Reimers & Gurevych — Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks.
- Sentence Transformers — Semantic Textual Similarity Documentation.
- Sentence Transformers — Semantic Search Documentation.
- Sentence Transformers — Migration Guide: encode_query / encode_document.
- Muennighoff et al. — MTEB: Massive Text Embedding Benchmark.



