AI & GenAI

[Tech Blog #07 | AI & GenAI] Giải Mã Embeddings & Vector Search: Bí Quyết Giúp Máy Tính "Hiểu Ngữ Nghĩa" Và Nền Tảng Của RAG

1 views
[Tech Blog #07 | AI & GenAI] Giải Mã Embeddings & Vector Search: Bí Quyết Giúp Máy Tính "Hiểu Ngữ Nghĩa" Và Nền Tảng Của RAG

1. Đặt vấn đề: Sự bất lực của tìm kiếm từ khóa truyền thống (Keyword Search)

Giả sử bạn xây dựng một chatbot hỏi đáp y tế. Người dùng gõ câu hỏi:

"Tôi bị đau bao tử thì nên uống thuốc gì?"

Trong cơ sở dữ liệu của bạn có một tài liệu chuyên môn với tiêu đề:

"Cẩm nang điều trị viêm loét dạ dày tá tràng."

Nếu bạn dùng câu lệnh SQL truyền thống như WHERE content LIKE '%đau bao tử%', hệ thống sẽ trả về 0 kết quả. Lý do: hai từ "bao tử" và "dạ dày" về mặt ký tự (Lexical) không hề trùng khớp nhau một chữ nào.

Tìm kiếm từ khóa cổ điển (Lexical Match) chỉ so sánh mặt chữ cái đơn thuần. Nó hoàn toàn "mù ngữ nghĩa", không hiểu được từ đồng nghĩa, tiếng lóng, hay ngữ cảnh bài viết.

Để máy tính có thể hiểu được: "Đau bao tử" và "Viêm loét dạ dày" thực chất nói về cùng một căn bệnh, chúng ta cần một cầu nối kỳ diệu có tên là Vector Embeddings.


2. Bản chất của Embeddings: Tọa độ hóa tri thức

Máy tính không thể hiểu ý nghĩa của từ ngữ, nhưng nó cực kỳ giỏi tính toán các con số.

Embedding là quá trình chuyển đổi một đoạn văn bản (từ, câu hoặc cả tài liệu) thành một mảng số thực cố định, được gọi là một Vector (thường có kích thước 768, 1536 hoặc 3072 chiều tùy theo mô hình).

"Vua"       --->  [0.25, -0.41, 0.88, ..., 0.12]
"Hoàng hậu" --->  [0.24, -0.39, 0.85, ..., 0.15]  (Nằm rất gần vector "Vua")
"Quả táo"   --->  [-0.85, 0.11, -0.32, ..., 0.90] (Nằm rất xa)

Khi được ánh xạ vào một không gian đa chiều (Embedding Space):

  • Những khái niệm có ý nghĩa tương đồng sẽ được gom lại nằm rất gần nhau.
  • Những khái niệm khác biệt sẽ bị đẩy ra xa nhau.

Phép toán kinh điển minh họa cho không gian này: King⃗−Man⃗+Woman⃗≈Queen⃗\vec{\text{King}} - \vec{\text{Man}} + \vec{\text{Woman}} \approx \vec{\text{Queen}} (Lấy vector "Vua", trừ đi yếu tố "Đàn ông", cộng thêm yếu tố "Phụ nữ", kết quả thu được sẽ có tọa độ gần sát nhất với vector "Hoàng hậu".)


3. Đo lường sự tương đồng: Cosine Similarity

Sau khi biến câu hỏi của người dùng và các tài liệu thành các vector số học, làm sao để tìm ra tài liệu phù hợp nhất? Chúng ta đo góc giữa các vector bằng Cosine Similarity.

Cosine Similarity=cos⁡(θ)=A⃗⋅B⃗∥A⃗∥∥B⃗∥\text{Cosine Similarity} = \cos(\theta) = \frac{\vec{A} \cdot \vec{B}}{\Vert{}\vec{A}\Vert{} \Vert{}\vec{B}\Vert{}}

  • cos⁡(θ)=1\cos(\theta) = 1 (θ=0∘\theta = 0^\circ): Hai vector chỉ cùng một hướng →\rightarrow Hai câu có ngữ nghĩa tương đồng hoàn toàn.
  • cos⁡(θ)=0\cos(\theta) = 0 (θ=90∘\theta = 90^\circ): Hai vector vuông góc →\rightarrow Hai câu hoàn toàn không liên quan đến nhau.
  • cos⁡(θ)=−1\cos(\theta) = -1 (θ=180∘\theta = 180^\circ): Hai vector đối nghịch hướng →\rightarrow Ý nghĩa trái ngược nhau.

Tại sao không dùng khoảng cách Euclid thông thường?
Khoảng cách Euclid đo độ dài thực tế giữa hai điểm. Một đoạn văn ngắn 5 từ và một bài luận 500 từ dù cùng bàn về một chủ đề thì vector của chúng có thể có độ dài lệch nhau rất nhiều. Cosine Similarity chỉ quan tâm đến góc lệch hướng, giúp đánh giá chuẩn xác ngữ nghĩa bất chấp độ dài ngắn của văn bản.


4. So sánh: Keyword Search vs. Vector Semantic Search

Tiêu chíKeyword Search (SQL LIKE, BM25)Vector Semantic Search (Embeddings)
Cơ chếSo khớp chính xác chuỗi ký tự (Lexical Matching).So khớp khoảng cách trong không gian vector (Semantic Matching).
Từ đồng nghĩa & Ngữ cảnh❌ Kém, phải tự khai báo từ điển từ đồng nghĩa thủ công.✅ Tự động hiểu từ đồng nghĩa, ngữ cảnh đa nghĩa (ví dụ: Apple công ty vs quả táo).
Đa ngôn ngữ (Cross-lingual)❌ Không thể tìm bài tiếng Việt bằng từ khóa tiếng Anh.✅ Các mô hình Multilingual Embedding có thể tìm được văn bản tiếng Việt từ câu hỏi tiếng Anh.
Độ chính xác với từ khóa đặc thù✅ Rất mạnh với mã lỗi kỹ thuật (vd: ERR_404), số CCCD, mã SKU sản phẩm.⚠️ Có thể bị nhầm lẫn với các chuỗi ký tự số hoặc tên riêng quá hiếm gặp.
Ứng dụng tiêu biểuTìm kiếm mã đơn hàng, tra cứu catalog sản phẩm chính xác.Chatbot hỏi đáp thông minh (RAG), gợi ý bài viết, hệ thống khuyến nghị (Recommender System).

5. Thực hành thực chiến: Xây dựng công cụ Semantic Search mini bằng Python

Dưới đây là một script Python hoàn chỉnh mô phỏng cách hệ thống RAG (Retrieval-Augmented Generation) tìm kiếm câu trả lời dựa trên ngữ nghĩa mà không cần khớp từ khóa:

import numpy as np

# Giả lập một hàm sinh embedding đơn giản (Trong thực tế bạn sẽ gọi OpenAI, Gemini API hoặc Sentence-Transformers)
# Để code chạy được ngay lập tức trên mọi máy mà không cần cài thêm thư viện nặng,
# ta dùng thư viện sentence-transformers nếu có, hoặc dùng mock vectors minh họa cơ chế.

try:
    from sentence_transformers import SentenceTransformer
    # Sử dụng mô hình embedding mini siêu nhẹ, đa ngôn ngữ
    embed_model = SentenceTransformer("paraphrase-multilingual-MiniLM-L12-v2")
    
    def get_embedding(text: str) -> np.ndarray:
        return embed_model.encode(text)
    USE_REAL_MODEL = True
    print("Đã tải thành công mô hình SentenceTransformer thực tế!")
except ImportError:
    # Nếu môi trường chưa cài sentence-transformers, mô phỏng vector 4 chiều trực quan
    USE_REAL_MODEL = False
    print("Chưa cài sentence-transformers, sử dụng cơ chế vector minh họa.")
    # Định nghĩa vector giả lập: [y_tế, công_nghệ, du_lịch, ẩm_thực]
    mock_dict = {
        "doc1": np.array([0.9, 0.1, 0.0, 0.2]), # Y tế
        "doc2": np.array([0.1, 0.8, 0.3, 0.0]), # Công nghệ
        "doc3": np.array([0.0, 0.1, 0.9, 0.7]), # Du lịch
        "query": np.array([0.85, 0.15, 0.0, 0.1])# Hỏi về sức khỏe
    }

def cosine_similarity(vec_a: np.ndarray, vec_b: np.ndarray) -> float:
    """Hàm tính Cosine Similarity giữa 2 vector số học."""
    dot_product = np.dot(vec_a, vec_b)
    norm_a = np.linalg.norm(vec_a)
    norm_b = np.linalg.norm(vec_b)
    
    if norm_a == 0 or norm_b == 0:
        return 0.0
    return float(dot_product / (norm_a * norm_b))

# 1. Khởi tạo Cơ sở tri thức (Knowledge Base)
knowledge_base = [
    {"id": 1, "text": "Bệnh nhân bị viêm loét dạ dày cần hạn chế ăn đồ cay nóng và rượu bia."},
    {"id": 2, "text": "Hướng dẫn cấu hình mạng riêng ảo VPN và giao thức Tailscale trên hệ điều hành Linux."},
    {"id": 3, "text": "Top 10 địa điểm du lịch biển đảo đẹp nhất tại Phú Quốc vào mùa hè."},
    {"id": 4, "text": "Cách viết câu lệnh SQL tối ưu với chỉ mục Index để tăng tốc độ truy vấn."}
]

# 2. Câu hỏi của người dùng (Không chứa từ 'dạ dày' hay 'viêm loét')
user_query = "Tôi bị đau tức bao tử và ợ chua thì cần kiêng cữ những món gì?"

print(f"\n--- CÂU HỎI TÌM KIẾM ---: '{user_query}'")

# 3. Tính toán độ tương đồng ngữ nghĩa
if USE_REAL_MODEL:
    query_vec = get_embedding(user_query)
    results = []
    for doc in knowledge_base:
        doc_vec = get_embedding(doc["text"])
        score = cosine_similarity(query_vec, doc_vec)
        results.append((doc["id"], doc["text"], score))
else:
    # Chạy trên dữ liệu mô phỏng
    query_vec = mock_dict["query"]
    results = [
        (1, knowledge_base[0]["text"], cosine_similarity(query_vec, mock_dict["doc1"])),
        (2, knowledge_base[1]["text"], cosine_similarity(query_vec, mock_dict["doc2"])),
        (3, knowledge_base[2]["text"], cosine_similarity(query_vec, mock_dict["doc3"])),
    ]

# 4. Sắp xếp tài liệu có điểm tương đồng cao nhất lên đầu
results.sort(key=lambda x: x[2], reverse=True)

print("\n--- KẾT QUẢ TÌM KIẾM NGỮ NGHĨA (RANKING) ---")
for rank, (doc_id, text, score) in enumerate(results, start=1):
    print(f"Top {rank} [Điểm: {score:.4f}]: {text}")

6. Câu hỏi phỏng vấn thực tế (Interview Q&A)

Câu 1 (Mức độ: Junior / Entry-level)

Câu hỏi: "Embeddings đóng vai trò gì trong kiến trúc RAG (Retrieval-Augmented Generation)?"

Gợi ý trả lời:
*"Trong hệ thống RAG, Embeddings đóng vai trò là 'chiếc la bàn ngữ nghĩa' ở bước Retrieval (Truy xuất):

  1. Đầu tiên, toàn bộ tài liệu nội bộ của công ty được cắt nhỏ (chunking) và chuyển đổi thành các Embedding Vectors để lưu trữ trong Vector Database (như Milvus, Qdrant, Chroma).
  2. Khi người dùng đặt câu hỏi, hệ thống chuyển câu hỏi đó thành một Vector truy vấn.
  3. Hệ thống so sánh vector câu hỏi với kho tài liệu qua Cosine Similarity để tìm ra Top 3-5 đoạn văn bản liên quan nhất.
  4. Cuối cùng, các đoạn văn bản liên quan này được đính kèm vào Context của Prompt để gửi cho LLM tổng hợp câu trả lời chính xác, giúp loại bỏ hoàn toàn hiện tượng ảo giác (Hallucination)."*

Câu 2 (Mức độ: Junior / Mid-level)

Câu hỏi: "Khi nào Vector Search thuần túy thất bại và giải pháp khắc phục trong thực tế là gì?"

Gợi ý trả lời:
*"Vector Search thuần túy thường gặp khó khăn trong hai tình huống:

  1. Tìm kiếm từ khóa đặc thù (Exact Keyword/Identifier): Ví dụ người dùng gõ tìm mã đơn hàng DH_982734 hoặc mã lỗi phần mềm ORA-00942. Vector Search có xu hướng khái quát hóa ngữ nghĩa nên thường trả về kết quả mờ nhạt thay vì khớp chính xác chuỗi.
  2. Tên riêng hoặc thuật ngữ hiếm gặp (Out-of-vocabulary).
    Giải pháp tối ưu: Các hệ sinh thái tìm kiếm hiện đại đều triển khai Hybrid Search (Tìm kiếm lai), kết hợp cả hai phương pháp: dùng thuật toán BM25 (cho từ khóa chính xác) song song với Vector Embeddings (cho ngữ nghĩa), sau đó hợp nhất kết quả thông qua thuật toán RRF (Reciprocal Rank Fusion)."*

7. Key Takeaways (Ghi nhớ nhanh)

  1. Embedding là chiếc cầu nối biến văn bản tự nhiên thành tọa độ vector đa chiều mà máy tính có thể tính toán được.
  2. Ngữ nghĩa tương đồng →\rightarrow Vector nằm gần nhau: Giúp giải quyết triệt để bài toán từ đồng nghĩa, viết tắt và đa ngôn ngữ.
  3. Cosine Similarity là thước đo vàng để so khớp văn bản vì nó đo góc lệch hướng thay vì chiều dài câu chữ.
  4. Trái tim của RAG: Không có Embeddings và Vector Search thì không thể có các chatbot thông minh tra cứu tài liệu nội bộ doanh nghiệp.
0Claps