🧮 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:
- Generative AI - Token là gì, cách AI xử lý text
- RAG - Ứng dụng embedding trong retrieval
- Prompt Engineering - Viết prompt hiệu quả
Tại sao cần Embedding?
Phần tiêu đề “Tại sao cần Embedding?”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ố.
Cách cũ: One-Hot Encoding
Phần tiêu đề “Cách cũ: One-Hot Encoding”# 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ớnCách mới: Embedding
Phần tiêu đề “Cách mới: Embedding”# 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àngorange = [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)Embedding hoạt động như thế nào?
Phần tiêu đề “Embedding hoạt động như thế nào?”Quá trình tạo Embedding
Phần tiêu đề “Quá trình tạo Embedding”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, ...]"]Similarity: Đo độ giống nhau
Phần tiêu đề “Similarity: Đo độ giống nhau”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
Các Embedding Model phổ biến
Phần tiêu đề “Các Embedding Model phổ biến”OpenAI Embeddings
Phần tiêu đề “OpenAI Embeddings”| 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].embeddingprint(f"Dimensions: {len(embedding)}") # 1536Google Embeddings
Phần tiêu đề “Google Embeddings”| 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)}") # 768Open Source Models
Phần tiêu đề “Open Source Models”| 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)Ứng dụng của Embedding
Phần tiêu đề “Ứng dụng của Embedding”1. Semantic Search
Phần tiêu đề “1. Semantic Search”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)2. RAG (Retrieval-Augmented Generation)
Phần tiêu đề “2. RAG (Retrieval-Augmented Generation)”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:#4caf50Xem thêm: RAG System
3. Recommendation System
Phần tiêu đề “3. Recommendation 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", ...]4. Clustering / Classification
Phần tiêu đề “4. Clustering / Classification”# Phân nhóm emails tự độngemail_embeddings = [get_embedding(email) for email in emails]
from sklearn.cluster import KMeansclusters = KMeans(n_clusters=5).fit(email_embeddings)
# Cluster 0: Support tickets# Cluster 1: Sales inquiries# Cluster 2: Spam# ...5. Duplicate Detection
Phần tiêu đề “5. Duplicate Detection”# Tìm câu hỏi trùng lặp trên forumdef 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ớiVector Database
Phần tiêu đề “Vector Database”Để lưu trữ và tìm kiếm nhanh với triệu vectors, cần dùng Vector Database.
Các Vector DB phổ biến
Phần tiêu đề “Các Vector DB phổ biến”| 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 |
Ví dụ với Chroma
Phần tiêu đề “Ví dụ với Chroma”import chromadbfrom chromadb.utils import embedding_functions
# Tạo clientclient = chromadb.Client()
# Sử dụng OpenAI embeddingopenai_ef = embedding_functions.OpenAIEmbeddingFunction( api_key="YOUR_API_KEY", model_name="text-embedding-3-small")
# Tạo collectioncollection = client.create_collection( name="documents", embedding_function=openai_ef)
# Thêm documentscollection.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ếmresults = collection.query( query_texts=["Ngôn ngữ lập trình nào dễ học?"], n_results=2)# → ["doc1", "doc2"]Best Practices
Phần tiêu đề “Best Practices”1. Chọn Model phù hợp
Phần tiêu đề “1. Chọn Model phù hợp”| 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 |
2. Normalize vectors
Phần tiêu đề “2. Normalize vectors”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)3. Chunking cho documents dài
Phần tiêu đề “3. Chunking cho documents dài”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 chunkschunks = chunk_text(long_document)embeddings = [get_embedding(chunk) for chunk in chunks]4. Cache embeddings
Phần tiêu đề “4. Cache embeddings”import hashlibimport 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]Bài tập thực hành 🧪
Phần tiêu đề “Bài tập thực hành 🧪”Bài 1: Semantic Search đơn giản
Phần tiêu đề “Bài 1: Semantic Search đơn giản”- Cài đặt:
pip install sentence-transformers - Tạo embeddings cho 10 câu
- 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ấtBài 2: Visualize Embeddings
Phần tiêu đề “Bài 2: Visualize Embeddings”Sử dụng t-SNE hoặc UMAP để visualize embeddings trong 2D.
from sklearn.manifold import TSNEimport 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()Tóm tắt
Phần tiêu đề “Tóm tắt”| 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.