Embedding Models
Mô hình nhúng văn bản
Máy tính chỉ hiểu số. Làm sao để nó biết 'vua' và 'hoàng đế' có nghĩa GIỐNG nhau, trong khi 'vua' và 'mèo' thì KHÁC nhau?
Hình minh họa
Không gian embedding 2D — 20 từ tiếng Việt
Mỗi chấm là một từ được chiếu xuống 2D bằng t-SNE. Các từ cùng chủ đề (quyền lực, động vật, màu sắc, công nghệ, cảm xúc) tự động tụ lại thành cụm. Di chuột để xem chi tiết. Nhấn vào một từ để đặt nó làm query.
Chú ý: "vua" và "hoàng đế" nằm sát nhau, "mèo" và "chó" cũng sát nhau. Đây không phải là "tô màu" thủ công — embedding model học vị trí này từ hàng tỷ câu văn trên Internet.
Hình minh họa
Nearest neighbor — 5 từ gần nhất với query
Gõ một từ bất kỳ trong danh sách để xem 5 từ gần nghĩa nhất trong không gian embedding.
5 từ gần nhất với "vua":
Các từ cùng cụm với "vua" sẽ có similarity cao (> 0.7). Các từ khác cụm sẽ có similarity thấp (< 0.3). Đây chính là cơ sở của semantic search.
Hình minh họa
Heatmap cosine similarity — hai embedding model
Cùng 6 từ tiếng Việt, hai model cho ra ma trận similarity hơi khác nhau. Chuyển qua lại để thấy model đa ngôn ngữ (Sentence Transformers) bắt liên kết ngữ nghĩa mạnh hơn một chút so với OpenAI text-embedding-3-small (chủ yếu train trên tiếng Anh).
Nhận xét: Cả hai model đều bắt đúng các cặp gần nghĩa (vua–hoàng đế, mèo–chó, xanh–đỏ). Model đa ngôn ngữ (Sentence-Transformers) có similarity cao hơn một chút ở các cặp đồng nghĩa vì được train đặc biệt trên dữ liệu đa ngôn ngữ. Trong thực tế, benchmark MTEB (Massive Text Embedding Benchmark) là nơi so sánh các model công bằng trên nhiều task.
'Phở bò Hà Nội' và 'Beef pho from Hanoi' — cosine similarity sẽ như thế nào với một embedding model đa ngôn ngữ?
Bạn có 1 triệu document và muốn tìm document gần nhất với mỗi query. So sánh cosine với TẤT CẢ 1 triệu mỗi lần query thì quá chậm. Giải pháp đúng là gì?
v / np.linalg.norm(v) trước.Giải thích
Embedding model chuyển đổi text (từ, câu, đoạn văn) thành vector số trong không gian nhiều chiều (thường 384– 3072 chiều). Mỗi chiều đại diện một khía cạnh ý nghĩa mà model đã học từ hàng tỷ câu văn trên Internet.
Bản chất toán học: embedding là một hàm , với là số chiều (384, 768, 1024, 1536, 3072 tuỳ model). Hàm được học sao cho text giống nghĩa → vector gần nhau theo metric cosine.
Đo góc giữa hai vector. Góc nhỏ (cùng hướng) = giống nghĩa. Góc vuông = không liên quan. Góc 180° = đối nghĩa (hiếm trong thực tế).
Giá trị: -1 (đối nghĩa) → 0 (không liên quan) → 1 (đồng nghĩa). Với vector đã normalize (norm = 1), cosine = — tính cực nhanh.
Các embedding model phổ biến năm 2025:
| Model | Nhà cung cấp | Chiều | Đặc điểm |
|---|---|---|---|
| text-embedding-3-large | OpenAI | 3072 | Chất lượng cao, Matryoshka (truncate xuống 256/512/1024) |
| text-embedding-3-small | OpenAI | 1536 | Rẻ hơn 5x so với -large, đủ tốt cho hầu hết use case |
| BGE-M3 | BAAI (open-source) | 1024 | Đa ngôn ngữ, dense + sparse + multi-vector, hỗ trợ tiếng Việt tốt |
| voyage-3-large | Voyage AI | 1024 | Tối ưu cho RAG, top MTEB |
| Cohere embed-v3 | Cohere | 1024 | 100+ ngôn ngữ, tốt cho tiếng Việt |
| all-MiniLM-L6-v2 | Sentence-Transformers (OSS) | 384 | Nhẹ, chạy local trên CPU, tiếng Anh |
| E5-mistral-7b | Microsoft (OSS) | 4096 | SOTA open-source, dùng Mistral làm backbone |
"""
Ví dụ: gọi API OpenAI để tạo embedding cho nhiều câu,
sau đó tính cosine similarity giữa các cặp.
Cài đặt:
pip install openai numpy
Cần OPENAI_API_KEY trong biến môi trường.
"""
from openai import OpenAI
import numpy as np
client = OpenAI()
# 1) Chuẩn bị danh sách câu (nhiều ngôn ngữ để test multilingual)
texts = [
"Phở bò Hà Nội rất ngon", # 0
"Bún chả là đặc sản Hà Nội", # 1
"Beef pho from Hanoi is delicious",# 2 — tiếng Anh
"Python là ngôn ngữ lập trình", # 3
"JavaScript dùng để lập trình web",# 4
"Mèo thích ngủ trên sofa", # 5
"Chó là bạn thân của con người", # 6
]
# 2) Gọi API batch — tạo tất cả embedding trong 1 request (rẻ & nhanh)
response = client.embeddings.create(
model="text-embedding-3-small", # 1536 chiều
input=texts,
encoding_format="float", # mặc định
)
# response.data[i].embedding là list[float] có 1536 phần tử
vectors = np.array([d.embedding for d in response.data])
print("Shape của ma trận embedding:", vectors.shape)
# → (7, 1536)
# 3) Cosine similarity giữa hai vector
def cosine(a: np.ndarray, b: np.ndarray) -> float:
return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)))
# 4) In ma trận similarity 7x7
print("\n=== Cosine Similarity Matrix ===")
print(" " * 32 + " ".join(f"{i:4d}" for i in range(len(texts))))
for i, ti in enumerate(texts):
row = []
for j, tj in enumerate(texts):
row.append(f"{cosine(vectors[i], vectors[j]):.2f}")
short = (ti[:28] + "..") if len(ti) > 28 else ti.ljust(30)
print(f"{i} {short} " + " ".join(row))
# Kết quả kỳ vọng:
# - (0, 1) cao (~0.65): 2 câu ẩm thực Hà Nội
# - (0, 2) cao (~0.80): cùng nghĩa dù khác ngôn ngữ (đa ngôn ngữ!)
# - (3, 4) cao (~0.70): 2 câu về lập trình
# - (5, 6) cao (~0.70): 2 câu về vật nuôi
# - (0, 3) thấp (~0.10): ẩm thực vs lập trình
# 5) Tìm nearest neighbor cho query
query = "Tôi muốn ăn món Hà Nội"
query_vec = np.array(
client.embeddings.create(
model="text-embedding-3-small",
input=[query],
).data[0].embedding
)
sims = [cosine(query_vec, v) for v in vectors]
ranked = sorted(enumerate(sims), key=lambda x: -x[1])
print(f"\nTop-3 gần nhất với: '{query}'")
for rank, (idx, sim) in enumerate(ranked[:3], 1):
print(f" {rank}. [{sim:.3f}] {texts[idx]}")
# Dự kiến top-1 là "Phở bò Hà Nội rất ngon" hoặc "Bún chả là đặc sản Hà Nội"
# → đây chính là cơ sở cho semantic search."""
Chạy embedding hoàn toàn local bằng sentence-transformers.
Không tốn tiền API, không phụ thuộc Internet, dùng được cho
dữ liệu nhạy cảm (y tế, nội bộ doanh nghiệp).
Cài đặt:
pip install sentence-transformers
Model nhỏ (all-MiniLM-L6-v2) chỉ ~80 MB, chạy được trên CPU.
"""
from sentence_transformers import SentenceTransformer
import numpy as np
# Model đa ngôn ngữ, hỗ trợ tiếng Việt tốt
model = SentenceTransformer("sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2")
# 1) Encode corpus — 1 lần, lưu ra disk, sau đó dùng lại
corpus = [
"Phở bò Hà Nội rất ngon",
"Bún chả là đặc sản Hà Nội",
"Beef pho from Hanoi is delicious",
"Python là ngôn ngữ lập trình",
"JavaScript dùng để lập trình web",
"Mèo thích ngủ trên sofa",
"Chó là bạn thân của con người",
]
corpus_embeddings = model.encode(
corpus,
normalize_embeddings=True, # QUAN TRỌNG: normalize để cosine = dot product
batch_size=32,
show_progress_bar=True,
)
# Shape: (7, 384)
# 2) Query → encode → tìm top-K gần nhất
query = "Tôi muốn ăn món Hà Nội"
query_embedding = model.encode([query], normalize_embeddings=True)[0]
# Dot product (vì đã normalize)
similarities = corpus_embeddings @ query_embedding # shape (7,)
top_k_idx = np.argsort(-similarities)[:3]
print(f"Query: '{query}'")
for rank, idx in enumerate(top_k_idx, 1):
print(f" #{rank} [{similarities[idx]:.3f}] {corpus[idx]}")
# 3) Lưu corpus embeddings ra disk — reload nhanh cho lần sau
np.save("corpus_embeddings.npy", corpus_embeddings)
# Lần sau:
# corpus_embeddings = np.load("corpus_embeddings.npy")
# 4) Semantic similarity giữa 2 câu bất kỳ
from sentence_transformers.util import cos_sim
sim = cos_sim(corpus_embeddings[0], corpus_embeddings[2])
print(f"\n'{corpus[0]}' vs '{corpus[2]}' → {sim.item():.3f}")
# → ~0.82: cùng nghĩa dù khác ngôn ngữ (Việt vs Anh)
# 5) Benchmark tốc độ (trên CPU M1 MacBook):
# - OpenAI API: ~200ms/request + chi phí
# - sentence-transformers local: ~20ms/câu, miễn phí
# → Production thường dùng LOCAL cho throughput cao.Ứng dụng thực tế của embedding model:
- Semantic search:thay keyword search bằng tìm theo nghĩa. Người dùng gõ "cách nấu phở" → tìm được document "recipe for Vietnamese soup".
- RAG: Retrieval Augmented Generation — LLM lấy context từ vector DB để trả lời câu hỏi chính xác.
- Recommendation: embed user behavior và item → tìm item gần nhất trong không gian vector.
- Clustering: gom document thành chủ đề tự động bằng K-means trên embedding.
- Classification: embedding làm feature extractor cho classifier cổ điển (logistic regression, SVM).
- Anomaly detection: document có embedding xa cụm chính → bất thường.
- Zero-shot classification:so sánh document với embedding của nhãn ("tích cực", "tiêu cực") → chọn nhãn gần nhất.
Đọc thêm:
- Vector Databases — cách lưu và query hàng triệu vector với ANN.
- Semantic Search — xây search engine dựa trên embedding.
- Word Embeddings — tiền thân: Word2Vec, GloVe, FastText.
- Self-Attention — cơ chế cốt lõi giúp Transformer tạo ra embedding tốt.
- RAG — ứng dụng số 1 của embedding trong kỷ nguyên LLM.
- Embedding model chuyển text → vector số trong không gian nhiều chiều (384–3072 chiều).
- Câu/từ giống nghĩa → vector gần nhau → cosine similarity cao (gần 1).
- Model đa ngôn ngữ (BGE-M3, Cohere, multilingual sentence-transformers) hiểu ngữ nghĩa xuyên ngôn ngữ.
- Cosine similarity là metric chuẩn; với vector đã normalize, cosine = dot product (rất nhanh).
- Nền tảng cho semantic search, RAG, classification, clustering, recommendation.
- Với 1M+ vector, dùng vector database với ANN (HNSW, IVF) thay vì so sánh brute-force.
Kiểm tra hiểu biết
Embedding chuyển 'Phở ngon' thành vector [0.82, 0.15, 0.03, ...]. Các số này đại diện cho gì?