Bỏ qua để đến nội dung

🧮 Embedding

Embedding là cách biến đổi text (hoặc image, audio) thành các vector số trong không gian nhiều chiều, giúp máy tính “hiểu” và so sánh ngữ nghĩa.

📚 Bài viết liên quan:


Máy tính không hiểu text như con người. Nó cần biểu diễn text dưới dạng số.

# Vocabulary: ["apple", "banana", "orange"]
# One-hot encoding:
apple = [1, 0, 0]
banana = [0, 1, 0]
orange = [0, 0, 1]
# Vấn đề:
# - Không thể hiện được "apple" và "orange" đều là trái cây
# - Vector rất thưa (sparse) với vocabulary lớn
# Embedding vectors (ví dụ 3 chiều, thực tế có 768-4096 chiều)
apple = [0.82, 0.15, 0.73] # Trái cây, màu đỏ
banana = [0.79, 0.21, 0.12] # Trái cây, màu vàng
orange = [0.85, 0.18, 0.68] # Trái cây, màu cam
car = [0.12, 0.95, 0.08] # Xe cộ
# Kết quả:
# - apple ≈ orange (gần nhau trong không gian vector)
# - apple ≠ car (xa nhau)

graph LR
A["📝 Text<br/>'Python is great'"] --> B["🔤 Tokenizer<br/>Chia thành tokens"]
B --> C["🧠 Embedding Model<br/>Text-embedding-3-small"]
C --> D["📊 Vector<br/>[0.12, -0.34, ...]"]

Hai text có nghĩa tương tự sẽ có vector gần nhau.

from sklearn.metrics.pairwise import cosine_similarity
text1 = "Python is a programming language"
text2 = "Python là ngôn ngữ lập trình"
text3 = "The weather is nice today"
embedding1 = get_embedding(text1) # [0.12, 0.45, ...]
embedding2 = get_embedding(text2) # [0.11, 0.47, ...]
embedding3 = get_embedding(text3) # [0.89, -0.32, ...]
cosine_similarity(embedding1, embedding2) # 0.92 (rất giống)
cosine_similarity(embedding1, embedding3) # 0.15 (rất khác)

Cosine Similarity:

  • 1.0 = Hoàn toàn giống nhau
  • 0.0 = Không liên quan
  • -1.0 = Hoàn toàn trái ngược

Model Dimensions Max Tokens Price (per 1M tokens)
text-embedding-3-large 3072 8191 $0.13
text-embedding-3-small 1536 8191 $0.02
text-embedding-ada-002 1536 8191 $0.10
from openai import OpenAI
client = OpenAI()
response = client.embeddings.create(
model="text-embedding-3-small",
input="Python is a great programming language"
)
embedding = response.data[0].embedding
print(f"Dimensions: {len(embedding)}") # 1536
Model Dimensions Max Tokens
text-embedding-004 768 2048
textembedding-gecko@001 768 3072
import google.generativeai as genai
genai.configure(api_key="YOUR_API_KEY")
result = genai.embed_content(
model="models/text-embedding-004",
content="Python is a great programming language"
)
embedding = result['embedding']
print(f"Dimensions: {len(embedding)}") # 768
Model Dimensions Đặc điểm
all-MiniLM-L6-v2 384 Nhẹ, nhanh
all-mpnet-base-v2 768 Cân bằng chất lượng/tốc độ
bge-large-en 1024 Chất lượng cao
multilingual-e5-large 1024 Hỗ trợ đa ngôn ngữ
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
sentences = [
"Python is a programming language",
"Java is also a programming language",
"The weather is nice today"
]
embeddings = model.encode(sentences)
print(f"Shape: {embeddings.shape}") # (3, 384)

Tìm kiếm dựa trên ý nghĩa, không chỉ từ khóa.

# Query: "cách học lập trình hiệu quả"
# Kết quả trả về:
# ✅ "Phương pháp tự học code nhanh" (semantic match)
# ✅ "Tips học programming cho người mới"
# ❌ "Lập trình viên cần gì?" (không liên quan)

Sử dụng embedding để tìm documents liên quan trước khi hỏi LLM.

flowchart TD
Q["❓ User Query<br/>Chính sách nghỉ phép?"] --> EMB["🔢 Embedding Query → Vector"]
EMB --> SEARCH["🔎 Tìm trong Vector DB"]
SEARCH --> DOC["📄 HR Policy Document"]
DOC --> LLM["🤖 Gửi document + query → LLM"]
LLM --> ANS["✅ Response chính xác<br/>dựa trên data riêng"]
style Q fill:#e3f2fd,stroke:#2196f3
style DOC fill:#fff3e0,stroke:#ff9800
style LLM fill:#f3e5f5,stroke:#9c27b0
style ANS fill:#e8f5e9,stroke:#4caf50

Xem thêm: RAG System

# User đã đọc: "Python Tutorial for Beginners"
user_embedding = get_embedding("Python Tutorial for Beginners")
# Tìm bài viết tương tự
similar_articles = find_similar(
user_embedding,
all_article_embeddings,
top_k=5
)
# → ["Python List Comprehension", "Python Functions", ...]
# Phân nhóm emails tự động
email_embeddings = [get_embedding(email) for email in emails]
from sklearn.cluster import KMeans
clusters = KMeans(n_clusters=5).fit(email_embeddings)
# Cluster 0: Support tickets
# Cluster 1: Sales inquiries
# Cluster 2: Spam
# ...
# Tìm câu hỏi trùng lặp trên forum
def find_duplicates(new_question, existing_questions, threshold=0.9):
new_embedding = get_embedding(new_question)
for q in existing_questions:
similarity = cosine_similarity(new_embedding, q.embedding)
if similarity > threshold:
return q # Đã có câu hỏi tương tự
return None # Câu hỏi mới

Để lưu trữ và tìm kiếm nhanh với triệu vectors, cần dùng Vector Database.

Database Loại Đặc điểm
Pinecone Cloud Dễ dùng, serverless
Weaviate Self-hosted/Cloud Full-text + vector search
Chroma Self-hosted Nhẹ, tốt cho prototyping
Qdrant Self-hosted/Cloud Rust, hiệu năng cao
pgvector PostgreSQL extension Dùng chung với PostgreSQL
import chromadb
from chromadb.utils import embedding_functions
# Tạo client
client = chromadb.Client()
# Sử dụng OpenAI embedding
openai_ef = embedding_functions.OpenAIEmbeddingFunction(
api_key="YOUR_API_KEY",
model_name="text-embedding-3-small"
)
# Tạo collection
collection = client.create_collection(
name="documents",
embedding_function=openai_ef
)
# Thêm documents
collection.add(
documents=[
"Python là ngôn ngữ lập trình phổ biến",
"JavaScript dùng cho web development",
"Machine Learning là nhánh của AI"
],
ids=["doc1", "doc2", "doc3"]
)
# Tìm kiếm
results = collection.query(
query_texts=["Ngôn ngữ lập trình nào dễ học?"],
n_results=2
)
# → ["doc1", "doc2"]

Use case Khuyến nghị
Prototyping all-MiniLM-L6-v2 (miễn phí)
Production tiếng Anh text-embedding-3-small
Đa ngôn ngữ (có tiếng Việt) multilingual-e5-large
Chất lượng cao nhất text-embedding-3-large

Một số database yêu cầu vectors đã được normalize.

import numpy as np
def normalize(vector):
return vector / np.linalg.norm(vector)
normalized = normalize(embedding)
def chunk_text(text, chunk_size=500, overlap=50):
"""Chia text dài thành các chunks nhỏ hơn."""
words = text.split()
chunks = []
for i in range(0, len(words), chunk_size - overlap):
chunk = ' '.join(words[i:i + chunk_size])
chunks.append(chunk)
return chunks
# Document 10000 từ → 20-25 chunks
chunks = chunk_text(long_document)
embeddings = [get_embedding(chunk) for chunk in chunks]
import hashlib
import json
def get_embedding_cached(text, cache={}):
"""Cache embedding để tránh gọi API lặp lại."""
key = hashlib.md5(text.encode()).hexdigest()
if key not in cache:
cache[key] = get_embedding(text)
return cache[key]

  1. Cài đặt: pip install sentence-transformers
  2. Tạo embeddings cho 10 câu
  3. Tìm câu tương tự nhất với query
from sentence_transformers import SentenceTransformer, util
model = SentenceTransformer('all-MiniLM-L6-v2')
documents = [
"Python is great for beginners",
"JavaScript runs in browsers",
"Machine learning needs data",
# ... thêm câu
]
query = "Ngôn ngữ nào tốt cho người mới?"
# Tìm document tương tự nhất

Sử dụng t-SNE hoặc UMAP để visualize embeddings trong 2D.

from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
# Giảm từ 384 chiều xuống 2 chiều để vẽ
tsne = TSNE(n_components=2)
reduced = tsne.fit_transform(embeddings)
plt.scatter(reduced[:, 0], reduced[:, 1])
plt.show()

Khái niệm Ý nghĩa
Embedding Biến text → vector số
Dimensions Số chiều của vector (384, 768, 1536…)
Cosine Similarity Đo độ giống nhau (0-1)
Vector Database DB chuyên lưu/tìm kiếm vectors
Chunking Chia document dài thành phần nhỏ

Bài tiếp theo: Fine-tuning - Tinh chỉnh model cho use case riêng.