Embedding và tìm kiếm ngữ nghĩa: từ word2vec tới Voyage
Tóm tắt
Embedding biến nghĩa của văn bản thành khoảng cách giữa các vector. Anthropic không có model embedding riêng và giới thiệu Voyage AI; chọn model bằng eval, đánh dấu đúng query/document và kết hợp với tìm theo từ khoá.
Người dùng gõ "cách đổi mật khẩu", còn tài liệu nội bộ viết "khôi phục thông tin đăng nhập". Tìm kiếm theo từ khoá trả về rỗng vì hai câu không chung từ nào. Embedding giải quyết đúng vấn đề này: biến văn bản thành vector số sao cho các câu cùng nghĩa nằm gần nhau trong không gian, bất kể dùng từ gì. Đây là nền móng của tìm kiếm ngữ nghĩa, RAG, gợi ý nội dung và phát hiện trùng lặp.
Từ word2vec tới embedding cả câu
- word2vec (Mikolov và cộng sự, 2013): học vector cho từng từ từ ngữ cảnh xung quanh; nổi tiếng với phép tính kiểu "vua − đàn ông + phụ nữ ≈ nữ hoàng". Nhược điểm: mỗi từ chỉ có một vector, không phân biệt nghĩa theo ngữ cảnh.
- Sentence-BERT (Reimers & Gurevych, 2019): tinh chỉnh BERT để sinh vector cho cả câu, giúp so sánh độ tương đồng giữa hàng nghìn câu nhanh hơn rất nhiều so với đưa từng cặp qua model.
- Embedding model hiện đại: mô hình chuyên dụng, đa ngôn ngữ, ngữ cảnh dài (hàng chục nghìn token), có loại riêng cho code, luật, tài chính.
Claude có embedding không?
Không. Tài liệu Anthropic nói rõ hãng không cung cấp model embedding riêng và giới thiệu Voyage AI (thuộc MongoDB) như một lựa chọn, đồng thời khuyên nên đánh giá nhiều nhà cung cấp. Theo tài liệu hiện tại:
| Nhu cầu | Model gợi ý |
|---|---|
| Chất lượng tốt nhất, đa ngôn ngữ | voyage-4-large |
| Cân bằng | voyage-4 |
| Rẻ, nhanh | voyage-4-lite |
| Code, agentic coding | voyage-code-4 |
| Chạy tại chỗ (open-weight) | voyage-4-nano |
Quy trình tìm kiếm ngữ nghĩa
import voyageai, numpy as np
vo = voyageai.Client() # đọc VOYAGE_API_KEY
docs = ["Khôi phục thông tin đăng nhập qua email…", "Chính sách hoàn tiền…"]
doc_vecs = vo.embed(docs, model="voyage-4", input_type="document").embeddings
q_vec = vo.embed(["cách đổi mật khẩu"], model="voyage-4", input_type="query").embeddings[0]
scores = np.dot(doc_vecs, q_vec) # vector đã chuẩn hoá: dot = cosine
print(docs[int(np.argmax(scores))])
Hai chi tiết hay bị bỏ qua:
input_type: đánh dấu đúng "query" hay "document"; tài liệu khuyên không bỏ trống tham số này cho tác vụ truy xuất.- Độ đo: vector của Voyage đã chuẩn hoá độ dài 1, nên cosine và dot product cho cùng kết quả (dot nhanh hơn).
Tối ưu lưu trữ
- Giảm số chiều (Matryoshka): một số model cho lấy vector ngắn hơn (256/512 chiều) mà vẫn giữ phần lớn chất lượng.
- Lượng tử hoá: lưu int8 hoặc binary thay float32 giúp giảm dung lượng 4 tới 32 lần, đổi lại giảm nhẹ độ chính xác.
Rủi ro và lưu ý
- Không trộn model: vector của hai model khác nhau không so sánh được. Đổi model = embed lại toàn bộ kho.
- Ngữ nghĩa không phải tất cả: mã sản phẩm, số hợp đồng, tên riêng hiếm thì tìm theo từ khoá (BM25) lại chính xác hơn. Kết hợp cả hai (hybrid search).
- "Gần nhau" ≠ "trả lời được": đoạn văn tương đồng chưa chắc chứa câu trả lời; thêm bước rerank cho kết quả quan trọng.
- Dữ liệu nhạy cảm: gửi văn bản đi embed là gửi dữ liệu ra ngoài; cân nhắc model chạy tại chỗ cho dữ liệu nội bộ.
Áp dụng thế nào?
- Dev: Bắt đầu với 50 câu hỏi thật của người dùng và đáp án mong đợi; đo tỷ lệ tìm đúng trong top-5 trước khi chọn model.
- Tech Lead: Lưu tên model và phiên bản cạnh mỗi vector; thiết kế sẵn quy trình embed lại khi nâng cấp.
- PM: Tính năng "tìm kiếm thông minh" cho FAQ, ticket, tài liệu nội bộ là ứng dụng embedding rẻ và thấy giá trị nhanh nhất.
Nguồn & tham khảo
- Embeddings — Claude Docs
- Efficient Estimation of Word Representations in Vector Space — Mikolov et al. (arXiv)
- Sentence-BERT — Reimers & Gurevych (arXiv)