Các ví dụ Thiết kế ML¶
Cách tốt nhất để học thiết kế hệ thống ML là qua các ví dụ đã làm trọn vẹn. File này đi qua bảy thiết kế hoàn chỉnh: hệ thống gợi ý, xếp hạng tìm kiếm, dự đoán click quảng cáo, phát hiện gian lận, kiểm duyệt nội dung, AI hội thoại và tìm kiếm ảnh quy mô lớn.
-
Mỗi ví dụ tuân theo một khung nhất quán:
- Xác định bài toán (problem framing): chúng ta đang xây dựng cái gì, người dùng là ai, các ràng buộc là gì?
- Dữ liệu: chúng ta có dữ liệu gì, nó được thu thập thế nào, được gán nhãn ra sao?
- Đặc trưng: mô hình cần những đặc trưng nào?
- Mô hình: kiến trúc và cách tiếp cận huấn luyện nào?
- Phục vụ (serving): mô hình được triển khai và phục vụ thế nào?
- Đánh giá: chúng ta đo lường thành công ra sao?
- Cải tiến (iteration): chúng ta sẽ cải thiện gì theo thời gian?
1. Hệ thống Gợi ý (Ví dụ: YouTube, Netflix, Spotify)¶
Xác định bài toán¶
- Mục tiêu: hiển thị cho người dùng nội dung họ sẽ thích, tối đa hóa mức độ tương tác (thời gian xem, lượt nghe, lượt click).
- Quy mô: 1 tỷ+ người dùng, 100 triệu+ món hàng, 10 nghìn+ gợi ý mỗi giây.
- Độ trễ: <200ms cho toàn bộ pipeline gợi ý.
- Thách thức chính: không gian ứng viên khổng lồ (100 triệu món). Không thể chấm điểm tất cả món cho tất cả người dùng theo thời gian thực.
Kiến trúc: Pipeline hai giai đoạn¶
100 triệu món → Sinh ứng viên (nhanh, thô) → 1000 ứng viên
→ Xếp hạng (chậm, chính xác) → 100 món đã xếp hạng
→ Xếp hạng lại (luật kinh doanh) → 20 món hiển thị cho người dùng
Sinh ứng viên (Candidate Generation)¶
- Mục tiêu: thu hẹp 100 triệu món còn ~1000 ứng viên. Phải nhanh (<50ms).
- Mô hình hai tòa tháp (two-tower model): mã hóa (encode) người dùng và món hàng vào cùng một không gian embedding. Embedding người dùng nắm bắt sở thích; embedding món hàng nắm bắt đặc điểm nội dung. Điểm = tích vô hướng của embedding người dùng và món hàng.
- Huấn luyện: học đối chiếu (contrastive learning) trên các bộ ba (user, positive_item, negative_items). Dương = các món người dùng đã tương tác. Âm = các món ngẫu nhiên + các âm khó (các món phổ biến mà người dùng không tương tác).
- Phục vụ: tính trước tất cả embedding món hàng. Tại thời điểm yêu cầu: tính embedding người dùng, tìm kiếm ANN (HNSW trong một vector database) để tìm 1000 embedding món hàng gần nhất.
Xếp hạng (Ranking)¶
- Mục tiêu: chấm điểm chính xác 1000 ứng viên. Có thể chấp nhận ~100ms.
- Mô hình: một mạng nơ-ron sâu (MLP hoặc transformer) nhận các đặc trưng phong phú: đặc trưng người dùng (nhân khẩu học, lịch sử, ngữ cảnh), đặc trưng món hàng (nội dung, độ phổ biến, độ tươi mới), và đặc trưng chéo (lịch sử tương tác user-item, độ liên quan theo ngữ cảnh).
- Đầu ra: xác suất tương tác dự đoán (click, xem 50%+ , thích, chia sẻ). Nhiều mục tiêu có thể kết hợp: \(\text{score} = w_1 \cdot P(\text{click}) + w_2 \cdot P(\text{watch}) + w_3 \cdot P(\text{like})\).
Xếp hạng lại (Re-ranking)¶
- Áp dụng các luật kinh doanh: đa dạng (không hiển thị 5 video từ cùng một người sáng tạo), độ tươi mới (đẩy mạnh nội dung mới), an toàn (lọc nội dung bị cờ), và khám phá cá nhân hóa (hiển thị một số món xếp hạng thấp mà người dùng có thể khám phá).
Các con số ước lượng (Back-of-Envelope)¶
- Chỉ mục embedding món hàng: 100 triệu món × 256 chiều × float16 = 50 GB. Chỉ mục HNSW thêm ~2x overhead → ~100 GB. Vừa với một máy đơn có 128 GB RAM, hoặc chia mảnh qua 4 × 32 GB máy.
- Tính embedding người dùng: ~5ms mỗi người dùng (MLP nhỏ trên đặc trưng người dùng). Tại 10K QPS, cần ~50 bản sao mô hình (replicas) để gánh tải.
- Tìm kiếm ANN: ~2ms cho top-1000 từ 100 triệu vector với HNSW. Tại 10K QPS, mỗi bản sao chỉ mục gánh ~500 QPS → cần 20 bản sao.
- Mô hình xếp hạng: 1000 ứng viên × ~0,1ms mỗi ứng viên = 100ms mỗi yêu cầu. Tại 10K QPS, cần 1000 GPU-giây mỗi giây → ~10 GPU A10G chỉ cho xếp hạng.
- Tổng hạ tầng: ~20 bản sao chỉ mục embedding + ~50 server embedding người dùng + ~10 GPU xếp hạng + bộ nhớ đệm + cân bằng tải. Chi phí: ~\(50K-\)100K/tháng theo giá cloud.
Khởi động nguội (Cold Start)¶
- Người dùng mới (chưa có lịch sử): dùng đặc trưng nhân khẩu học, ngữ cảnh thiết bị/vị trí và các gợi ý dựa trên độ phổ biến. Sau 5-10 lượt tương tác, chuyển sang mô hình cá nhân hóa.
- Món hàng mới (chưa có dữ liệu tương tác): dùng đặc trưng dựa trên nội dung (tiêu đề, mô tả, embedding ảnh thumbnail). Phân bổ ngân sách khám phá: hiển thị món mới cho một phần người dùng để thu thập dữ liệu tương tác nhanh. Các món không có tương tác sau giai đoạn đẩy mạnh sẽ bị hạ hạng.
- Khởi động nguội là một bài toán hệ thống: kho đặc trưng phải xử lý duyên dáng các đặc trưng bị thiếu (trả về giá trị mặc định, không phải lỗi). Mô hình phải được huấn luyện với các đặc trưng thiếu (dropout trên các đặc trưng lịch sử người dùng trong huấn luyện mô phỏng người dùng mới).
Đánh giá¶
- Ngoại tuyến: NDCG (Normalized Discounted Cumulative Gain - Lợi ích Tích lũy Giảm dần Chuẩn hóa), recall@K, precision@K trên một tập giữ riêng.
- Trực tuyến: A/B test đo thời gian xem, DAU, tỷ lệ giữ chân. Các A/B test dài hạn (nhiều tuần) để bắt được các hiệu ứng lên tỷ lệ giữ chân mà các test ngắn bỏ sót.
2. Xếp hạng Tìm kiếm (Ví dụ: Google, Bing)¶
Xác định bài toán¶
- Mục tiêu: với một truy vấn người dùng, trả về các kết quả liên quan nhất từ một kho tài liệu hàng tỷ bản.
- Độ trễ: <500ms tổng cộng (100ms truy xuất + 200ms xếp hạng + 100ms dựng trang + overhead).
Kiến trúc: Hiểu truy vấn → Truy xuất → Xếp hạng¶
Hiểu truy vấn (Query Understanding)¶
-
Trước khi truy xuất, xử lý truy vấn thô để cải thiện kết quả:
-
Sửa lỗi chính tả (spell correction): "reccomendation systm" → "recommendation system." Dùng một mô hình khoảng cách chỉnh sửa (edit-distance) hoặc mô hình sequence-to-sequence được huấn luyện trên các cặp (viết sai, đã sửa) từ log tìm kiếm.
- Mở rộng truy vấn (query expansion): thêm các thuật ngữ liên quan để cải thiện recall. "Python ML" → "Python machine learning scikit-learn pytorch." Dùng từ điển đồng nghĩa, embedding từ, hoặc một LLM để sinh các mở rộng.
- Phân loại ý định (intent classification): xác định người dùng muốn gì. "mua giày Nike" là giao dịch (hiển thị trang sản phẩm). "backpropagation hoạt động thế nào" là thông tin (hiển thị bài viết). "facebook.com" là điều hướng (đi thẳng đến trang web). Các ý định khác nhau nên kích hoạt các chiến lược truy xuất và bố cục kết quả khác nhau.
- Nhận diện thực thể (entity recognition): trích xuất các thực thể từ truy vấn. "nhà hàng ngon gần Times Square" → vị trí: "Times Square", loại thực thể: "nhà hàng." Định tuyến đến một pipeline tìm kiếm có nhận thức vị trí.
Truy xuất (Retrieval)¶
- BM25 (truyền thống): truy xuất khớp từ dùng một chỉ mục đảo (inverted index). Nhanh, hiệu quả cho các truy vấn từ khóa. Không có hiểu ngữ nghĩa ("thức ăn cho chó" không khớp "dinh dưỡng thú cưng").
- Truy xuất dày đặc (dense retrieval): mã hóa các truy vấn và tài liệu thành embedding (dùng một bi-encoder như DPR hoặc ColBERT). Truy xuất bằng tìm kiếm ANN. Nắm bắt sự tương đồng ngữ nghĩa ("thức ăn cho chó" khớp "dinh dưỡng thú cưng"). Chậm hơn BM25 nhưng tốt hơn cho các truy vấn ngôn ngữ tự nhiên.
- Truy xuất lai (hybrid retrieval): kết hợp BM25 và truy xuất dày đặc. BM25 tìm các khớp từ khóa chính xác; truy xuất dày đặc tìm các khớp ngữ nghĩa. Trộn và loại bỏ trùng lặp. Tốt nhất của cả hai thế giới.
Xếp hạng (Ranking)¶
-
Học để xếp hạng (learning to rank): một mô hình chấm điểm mỗi cặp (truy vấn, tài liệu). Ba cách tiếp cận:
- Pointwise: dự đoán một điểm liên quan cho mỗi tài liệu độc lập. Đơn giản nhưng bỏ qua thứ tự tương đối.
- Pairwise: dự đoán tài liệu nào trong hai tài liệu liên quan hơn. LambdaMART (cây được tăng cường gradient - gradient-boosted trees) là cách tiếp cận kinh điển.
- Listwise: tối ưu toàn bộ danh sách đã xếp hạng trực tiếp cho một chỉ số cấp danh sách (NDCG). Phức tạp hơn nhưng cho kết quả tốt nhất.
-
Cross-encoder: một transformer nhận
[truy vấn, tài liệu]làm đầu vào và xuất ra một điểm liên quan. Chính xác hơn các bi-encoder (mã hóa truy vấn và tài liệu độc lập) vì nó nắm bắt các tương tác chi tiết. Nhưng quá chậm cho toàn bộ kho — chỉ dùng để xếp hạng lại top 100-1000 ứng viên từ truy xuất.
Đặc trưng¶
- Đặc trưng truy vấn: độ dài truy vấn, ngôn ngữ, phân loại ý định (điều hướng, thông tin, giao dịch).
- Đặc trưng tài liệu: PageRank, độ tươi mới, điểm chất lượng nội dung, thẩm quyền tên miền (domain authority).
- Đặc trưng truy vấn-tài liệu: điểm BM25, độ tương đồng embedding, số lượng khớp chính xác, tỷ lệ click-through cho cặp (truy vấn, tài liệu) này trong log lịch sử.
3. Dự đoán Click Quảng cáo (Ads Click Prediction)¶
Xác định bài toán¶
- Mục tiêu: dự đoán xác suất người dùng sẽ click vào một quảng cáo. Điều này xác định mức giá thầu (bid) trong các phiên đấu giá thời gian thực.
- Quy mô: 100 nghìn+ phiên đấu giá mỗi giây, mỗi cái đòi hỏi một dự đoán trong 10ms.
- Tác động doanh thu: cải thiện 0,1% độ chính xác dự đoán click chuyển thành hàng triệu đô doanh thu thêm.
Kiến trúc¶
-
Đặc trưng kỹ thuật là cốt lõi của các hệ thống quảng cáo. Các đặc trưng bao gồm:
- Đặc trưng người dùng: nhân khẩu học, lịch sử duyệt web, lịch sử mua hàng, thiết bị, vị trí, thời gian trong ngày.
- Đặc trưng quảng cáo: nội dung sáng tạo (hình ảnh/văn bản), nhà quảng cáo, danh mục, CTR lịch sử, mức giá thầu.
- Đặc trưng ngữ cảnh: nội dung trang, vị trí quảng cáo, loại thiết bị, tốc độ kết nối.
- Đặc trưng chéo: tương tác user_category × ad_category, tương tác user_region × ad_campaign.
-
Mô hình: lịch sử là hồi quy logistic (đơn giản, nhanh, có thể giải thích). Các hệ thống hiện đại dùng học sâu: một DLRM (Deep Learning Recommendation Model - Mô hình Gợi ý Học sâu) với các bảng embedding cho các đặc trưng phân loại và một MLP cho các đặc trưng dày đặc.
- Hiệu chuẩn (calibration): xác suất dự đoán phải chính xác (nếu mô hình nói P(click) = 0,05, thì 5% các impression như vậy thực sự phải được click). Hiệu chuẩn rất quan trọng vì xác suất dự đoán trực tiếp quyết định các mức giá thầu.
- Khám phá-khai thác (exploration-exploitation): luôn hiển thị quảng cáo tốt nhất dự đoán được là phi tối ưu dài hạn (bạn không bao giờ khám phá ra một quảng cáo mới có thể tốt hơn). Thompson sampling hoặc khai thác \(\epsilon\)-greedy đảm bảo một phần các impression đi đến các quảng cáo kém chắc chắn hơn để thu thập dữ liệu.
Đấu giá Thời gian thực (Real-Time Bidding)¶
-
Khi một người dùng tải một trang, một phiên đấu giá quảng cáo chạy trong <100ms:
- Nhà xuất bản gửi một yêu cầu giá thầu (thông tin người dùng, ngữ cảnh trang) đến nhiều sàn giao dịch quảng cáo (ad exchanges).
- Máy chủ giá thầu của mỗi nhà quảng cáo dự đoán CTR cho quảng cáo của họ.
- Giá thầu = CTR × giá_trị_mỗi_click. Các giá thầu cao hơn thắng phiên đấu giá.
- Quảng cáo thắng được hiển thị; nếu được click, nhà quảng cáo trả tiền.
4. Phát hiện Gian lận (Fraud Detection)¶
Xác định bài toán¶
- Mục tiêu: phát hiện các giao dịch gian lận theo thời gian thực (gian lận thẻ tín dụng, chiếm đoạt tài khoản, đánh giá giả).
- Độ trễ: <100ms (giao dịch phải được chấp thuận hoặc cờ trước khi thanh toán được xử lý).
- Thách thức chính: mất cân bằng lớp cực độ (tỷ lệ gian lận 0,1%). Dương tính giả chặn người dùng hợp pháp; âm tính giả làm mất tiền.
Kiến trúc¶
Đặc trưng¶
- Đặc trưng giao dịch: số tiền, loại tiền tệ, danh mục người bán, giờ trong ngày, is_international.
- Đặc trưng người dùng: tuổi tài khoản, số tiền giao dịch trung bình, số lượng giao dịch gần đây, vân tay thiết bị (device fingerprint).
- Đặc trưng vận tốc (velocity features) (thời gian thực, từ một pipeline luồng): số giao dịch trong 5 phút qua, số lượng người bán khác nhau trong 1 giờ qua, khoảng cách địa lý từ giao dịch trước.
- Đặc trưng đồ thị (graph features): liệu người bán này có kết nối với các băng nhóm gian lận đã biết không? Thiết bị này có được chia sẻ với các tài khoản bị cờ không?
Mô hình¶
- Các cây được tăng cường gradient (gradient-boosted trees) (XGBoost, LightGBM) là chuẩn cho phát hiện gian lận dạng bảng (tabular). Chúng xử lý các loại đặc trưng hỗn hợp, có thể giải thích (tầm quan trọng đặc trưng - feature importance), và huấn luyện nhanh.
- Xử lý mất cân bằng: under-sampling lớp đa số, over-sampling lớp thiểu số (SMOTE), hoặc dùng trọng số lớp trong hàm mất mát. Focal loss (chương 8) giảm trọng số các âm dễ.
- Ma trận chi phí (cost matrix): một dương tính giả (chặn một giao dịch hợp pháp) có một chi phí (người dùng bực bội, mất doanh số). Một âm tính giả (lỡ gian lận) có một chi phí khác (tổn thất tài chính). Ngưỡng quyết định nên tối thiểu hóa tổng chi phí kỳ vọng, không phải tối đa hóa độ chính xác.
Con người trong vòng lặp (Human-in-the-Loop)¶
- Các dự đoán không chắc chắn (độ tự tin mô hình từ 0,3 đến 0,7) được gửi đến những người xem xét (reviewers). Quyết định của người xem xét trở thành nhãn cho huấn luyện lại. Điều này tạo ra một vòng lặp phản hồi: mô hình cải thiện theo thời gian khi nó thấy nhiều ca gian lận có nhãn hơn.
5. Kiểm duyệt Nội dung (Content Moderation)¶
Xác định bài toán¶
- Mục tiêu: tự động phát hiện và gỡ bỏ nội dung có hại (bài phát ngôn thù ghét, bạo lực, thông tin sai lệch, CSAM) khỏi một nền tảng.
- Quy mô: hàng tỷ bài đăng mỗi ngày (văn bản, hình ảnh, video).
- Thách thức: phụ thuộc ngữ cảnh (mỉa mai, châm biếm, sắc thái văn hóa). Phải cân bằng tự do ngôn luận với an toàn.
Kiến trúc¶
- Phân loại đa phương thức (multi-modal classification): các mô hình riêng biệt cho văn bản, hình ảnh và video, với một lớp hợp nhất (fusion) kết hợp các tín hiệu của chúng.
- Kiểm duyệt văn bản: mô hình ngôn ngữ được tinh chỉnh phân loại văn bản vào các danh mục (quấy rối, phát ngôn thù ghét, thông tin sai lệch, spam). Các mô hình đa ngôn ngữ xử lý 100+ ngôn ngữ.
- Kiểm duyệt hình ảnh: mô hình thị giác phát hiện: nội dung rõ ràng (khỏa thân, bạo lực), văn bản trong ảnh (OCR + bộ phân loại văn bản), và nội dung có hại đã biết (khớp mã băm với các cơ sở dữ liệu CSAM đã biết).
- Kiểm duyệt video: lấy mẫu các khung hình (frames) ở các khoảng đều đặn, chạy bộ phân loại hình ảnh trên mỗi khung, kết hợp với bản chép lời âm thanh (ASR → bộ phân loại văn bản).
- Chính sách như mã (policy-as-code): các chính sách kiểm duyệt được định nghĩa trong các luật có cấu trúc ánh xạ đầu ra mô hình thành hành động:
if text_model.hate_speech_score > 0.9:
action = "remove"
elif text_model.hate_speech_score > 0.7:
action = "human_review"
else:
action = "allow"
- Các chính sách thay đổi thường xuyên (quy định mới, chuẩn mực đang tiến hóa). Tách chính sách khỏi mô hình đảm bảo các thay đổi có thể triển khai mà không cần huấn luyện lại.
Kiểm duyệt Chủ động so với Phản ứng (Proactive vs Reactive)¶
- Chủ động (proactive - trước xuất bản): chạy các bộ phân loại trên nội dung trước khi nó lên sóng. Các vi phạm tự tin cao bị chặn tự động. Cách này ngăn nội dung có hại từng được nhìn thấy nhưng thêm độ trễ cho việc xuất bản và rủi ro dương tính giả (chặn nội dung hợp pháp).
- Phản ứng (reactive - sau xuất bản): nội dung lên sóng ngay lập tức. Người dùng có thể báo cáo vi phạm. Các báo cáo kích hoạt bộ phân loại + xem xét con người. Độ trễ thấp hơn cho người xuất bản nhưng nội dung có hại hiển thị cho đến khi bị phát hiện.
- Hầu hết các nền tảng dùng cả hai: chủ động cho các danh mục mức độ nghiêm trọng cao (CSAM: không khoan nhượng, chặn trước xuất bản) và phản ứng cho các danh mục tinh tế (thông tin sai lệch: cần phán đoán con người, xem xét sau báo cáo).
Khớp mã băm (Hash Matching)¶
- Với nội dung có hại đã biết (CSAM, tuyên truyền khủng bố), dùng hashing nhận thức (perceptual hashing): tính một mã băm của hình ảnh/video mà bền vững trước các sửa đổi nhỏ (cắt xén, thay đổi kích thước, nén). So sánh với các cơ sở dữ liệu nội dung có hại đã biết (cơ sở dữ liệu mã băm của NCMEC, cơ sở dữ liệu mã băm chia sẻ GIFCT). Khớp → gỡ bỏ ngay lập tức mà không cần bộ phân loại.
- PhotoDNA (Microsoft) là mã băm nhận thức chuẩn cho phát hiện CSAM. Đó là một nghĩa vụ pháp lý ở nhiều khu vực tài phán, không chỉ là một lựa chọn kỹ thuật.
Các con số ước lượng¶
- Quy mô: 1 tỷ bài đăng/ngày = ~12 nghìn bài/giây. Mỗi bài cần: phân loại văn bản (~5ms), phân loại hình ảnh (~20ms), khớp mã băm (~1ms). Tại 12K QPS: cần ~60 bộ phân loại văn bản, ~240 bộ phân loại hình ảnh, và ~12 bộ khớp mã băm (cộng thêm dự phòng).
- Xem xét con người: nếu 2% bài đăng bị cờ để xem xét = 20 triệu/ngày. Tại 100 lần xem xét/người xem xét/ngày, cần 200 nghìn người xem xét (đây là lý do độ chính xác tự động quan trọng: mỗi sự giảm 0,1% dương tính giả tiết kiệm 1 triệu lần xem xét/ngày).
- Ngân sách độ trễ: kiểm duyệt chủ động phải hoàn thành trong pipeline xuất bản (~500ms). Văn bản (5ms) + hình ảnh (20ms) + mã băm (1ms) + overhead = nằm gọn trong ngân sách. Video là ngoại lệ: ngay cả lấy mẫu 1 khung/giây từ một video 10 phút cũng đòi hỏi 600 lệnh gọi bộ phân loại → xử lý bất đồng bộ.
Quy trình Leo thang (Escalation Workflow)¶
- Gỡ bỏ tự động → xem xét con người với các kháng nghị → xem xét chuyên gia (pháp lý, chuyên gia văn hóa) → đội chính sách cho các ca mơ hồ. Mỗi cấp độ xử lý ít ca hơn với nhiều sắc thái hơn.
- Phản hồi cho mô hình: quyết định xem xét con người là nhãn chất lượng cao nhất cho huấn luyện lại. Những bất đồng giữa mô hình và người xem xét được ưu tiên cho học chủ động — chúng đại diện cho các ca mô hình xử lý tệ nhất.
6. AI Hội thoại (Chatbot dựa trên RAG)¶
Xác định bài toán¶
- Mục tiêu: một chatbot trả lời các câu hỏi về sản phẩm của một công ty dùng tài liệu của nó.
- Yêu cầu: chính xác (không bịa đặt - hallucinate), trích dẫn nguồn, xử lý các câu hỏi theo sau, và nằm trong phạm vi sản phẩm.
Kiến trúc: Tạo sinh có Truy hồi tăng cường (Retrieval-Augmented Generation - RAG)¶
Truy vấn người dùng → Embedding Truy vấn → Tìm kiếm Vector (tài liệu) → Top-K đoạn
↓
Truy vấn người dùng + Các đoạn truy xuất → LLM → Phản hồi (có trích dẫn)
Các thành phần¶
-
Thu nạp tài liệu (document ingestion): chia nhỏ (chunk) tài liệu và embed chúng. Chiến lược chia nhỏ (chunking strategy) rất quan trọng:
- Chia nhỏ kích thước cố định (fixed-size chunking): chia mỗi N token (ví dụ 500) với M token chồng lấp (ví dụ 50). Kích thước chunk đơn giản, dự đoán được, nhưng có thể chia cắt giữa câu hoặc giữa đoạn, làm mất ngữ cảnh.
- Chia nhỏ ngữ nghĩa (semantic chunking): chia tại các ranh giới đoạn văn hoặc phần. Mỗi chunk là một đơn vị thông tin mạch lạc. Kích thước biến thiên (một số chunk 100 token, một số 800), đòi hỏi hệ thống truy xuất xử lý các độ dài biến thiên.
- Chia nhỏ đệ quy (recursive chunking): cố gắng chia tại các ranh giới đoạn văn. Nếu một đoạn quá dài, chia tại ranh giới câu. Nếu một câu quá dài, chia tại kích thước cố định. Sự cân bằng tốt nhất giữa tính mạch lạc và tính nhất quán kích thước.
- Embedding: embed mỗi chunk với một bộ mã hóa văn bản (ví dụ E5, BGE, Cohere embed). Lưu trong một vector database.
-
Truy xuất (retrieval): embed truy vấn người dùng, tìm kiếm vector database cho \(k\) chunk tương đồng nhất (thường \(k = 5\)-\(10\)). Tùy chọn xếp hạng lại với một cross-encoder để độ chính xác cao hơn.
- Tạo sinh (generation): xây dựng một prompt với các chunk truy xuất làm ngữ cảnh:
System: Bạn là một trợ lý hữu ích. Chỉ trả lời dựa trên ngữ cảnh được cung cấp.
Nếu câu trả lời không có trong ngữ cảnh, hãy nói "Tôi không biết."
Context:
[chunk 1]
[chunk 2]
...
User: {question}
- Chắn (guardrails): ngăn LLM trả lời các câu hỏi ngoài phạm vi sản phẩm, sinh nội dung có hại, hoặc mâu thuẫn với ngữ cảnh truy xuất. Thực hiện qua: lọc đầu vào (từ chối các truy vấn ngoài chủ đề), lọc đầu ra (kiểm tra phản hồi so với ngữ cảnh truy xuất), và prompting theo hiến pháp (constitutional prompting - hướng dẫn mô hình từ chối một số yêu cầu).
- Bộ nhớ hội thoại (conversation memory): duy trì \(n\) lượt hội thoại gần nhất. Đưa chúng vào prompt để mô hình hiểu các câu hỏi theo sau ("Còn về giá cả thì sao?" → cần ngữ cảnh trước về sản phẩm nào).
Viết lại Truy vấn (Query Rewriting)¶
-
Người dùng thường hỏi các câu hỏi theo sau mơ hồ: "Còn về giá cả thì sao?" (giá của cái gì?). Viết lại truy vấn (query rewriting) dùng lịch sử hội thoại để sinh ra một truy vấn độc lập:
- Đầu vào: lịch sử hội thoại + "Còn về giá cả thì sao?"
- Viết lại: "Giá của gói doanh nghiệp của Sản phẩm X là bao nhiêu?"
-
Truy vấn được viết lại này là thứ được embed và tìm kiếm trong vector database. Nếu không viết lại, truy xuất sẽ tìm "giá cả" mà không có ngữ cảnh và trả về các chunk không liên quan.
- Việc viết lại truy vấn có thể thực hiện bằng một lệnh gọi LLM nhỏ (~50ms) hoặc bằng một mô hình sequence-to-sequence được tinh chỉnh (~5ms).
Các con số ước lượng¶
- Kho tài liệu: 10K trang, trung bình 2000 token mỗi trang = 20 triệu token. Tại 500 token/chunk với 50 chồng lấp = ~44K chunk.
- Chỉ mục embedding: 44K chunk × 768 chiều × float16 = ~65 MB. Vừa trong bộ nhớ một cách tầm thường. Ngay cả 10 triệu chunk cũng chỉ ~15 GB.
- Phân tích độ trễ: embed truy vấn (5ms) + tìm kiếm vector (2ms) + xếp hạng lại cross-encoder (20ms cho top-50) + tạo sinh LLM (500-2000ms) = ~600-2100ms tổng cộng. LLM chiếm ưu thế. Dùng streaming để giảm độ trễ cảm nhận.
- Chi phí: tại \(3/1 triệu token (API Claude/GPT-4), 1000 truy vấn/ngày với ~2K token mỗi truy vấn = ~\)6/ngày. Quy mô lớn (1 triệu truy vấn/ngày), tự host một mô hình 7B trên 2 GPU A10G (~$50/ngày) cho sự giảm chi phí 100x.
Đánh giá¶
- Chất lượng truy xuất: Recall@K (các top-K chunk có chứa câu trả lời không?), MRR (Mean Reciprocal Rank - Hạng Nghịch đảo Trung bình).
- Chất lượng tạo sinh: độ chính xác thực tế (phản hồi có khớp ngữ cảnh truy xuất không?), tính có căn cứ (groundedness - phản hồi có trích dẫn các chunk đúng không?), độ liên quan của câu trả lời.
- End-to-end: mức độ hài lòng người dùng (thumbs up/down), tỷ lệ leo thang lên tác tử con người.
7. Tìm kiếm Ảnh Quy mô lớn (Large-Scale Image Search)¶
Xác định bài toán¶
- Mục tiêu: với một hình ảnh, tìm các hình ảnh trực quan tương tự từ một kho 1 tỷ+ hình ảnh.
- Ứng dụng: tìm kiếm ảnh đảo (reverse image search), tìm kiếm sản phẩm (ảnh → các sản phẩm khớp), phát hiện trùng lặp.
- Độ trễ: <500ms bao gồm cả khứ hồi mạng.
Kiến trúc¶
Trích xuất Embedding¶
- Mô hình: một bộ mã hóa thị giác tiền huấn luyện (ViT, bộ mã hóa ảnh của CLIP, DINOv2). Tinh chỉnh trên miền cụ thể nếu cần (thời trang, thương mại điện tử, hình ảnh y tế).
- Huấn luyện: học đối chiếu (contrastive learning - chương 10). Cặp dương = các góc nhìn khác nhau của cùng một ảnh (hoặc ảnh + văn bản khớp). Cặp âm = các ảnh ngẫu nhiên. Mô hình học cách sinh embedding tương tự cho các ảnh tương tự và embedding khác biệt cho các ảnh khác nhau.
Lập chỉ mục (Indexing)¶
- Ngoại tuyến: embed tất cả 1 tỷ ảnh và xây dựng một chỉ mục ANN. Với HNSW (file 03), việc xây dựng chỉ mục mất vài giờ và chỉ mục được lưu trong bộ nhớ (~128 GB cho 1 tỷ × 512 chiều × float16 + overhead đồ thị).
- Chia mảnh (sharding): chia chỉ mục qua nhiều máy. Mỗi máy giữ một shard. Tại thời điểm truy vấn, tìm kiếm tất cả các shard song song và hợp nhất các kết quả top-K.
- Cập nhật tăng dần (incremental updates): các ảnh mới (tải lên, sản phẩm mới) phải được thêm vào chỉ mục. HNSW hỗ trợ chèn tăng dần mà không cần xây dựng lại. Các vector database (Milvus, Pinecone) xử lý việc này một cách native (natively).
Phục vụ (Serving)¶
- Dịch vụ embedding (embedding service): một server GPU chạy mô hình ViT. Độ trễ: ~20ms mỗi ảnh. Gộp batch nhiều truy vấn để tăng thông lượng.
- Dịch vụ tìm kiếm (search service): server chỉ mục ANN. Độ trễ: ~10ms cho top-100 tìm kiếm trên 1 tỷ vector (với HNSW).
- Bộ nhớ đệm (caching): cache kết quả cho các truy vấn phổ biến. Với phát hiện trùng lặp, cache embedding của các ảnh vừa tải lên và so sánh các tải lên mới với cache trước khi tìm kiếm toàn bộ chỉ mục.
Đánh giá¶
- Precision@K: các kết quả top-K có thực sự tương tự không?
- Recall@K: trong tất cả các ảnh thực sự tương tự trong kho, có bao nhiêu nằm trong top-K?
- Mean Average Precision (mAP - Độ chính xác trung bình trung bình): diện tích dưới đường cong precision-recall.
- Đánh giá con người: với sự tương đồng chủ quan, những người chấm điểm (raters) con người phán đoán xem các ảnh truy xuất có liên quan không.
Khung Phỏng vấn (The Interview Framework)¶
-
Khi bạn gặp một câu hỏi thiết kế hệ thống, hãy tuân theo khung này:
-
Làm rõ yêu cầu (2-3 phút): hỏi về quy mô, độ trễ, yêu cầu nhất quán, và các ca biên (edge cases). "Bao nhiêu người dùng? Độ trễ nào có thể chấp nhận? Điều gì xảy ra khi có lỗi?"
- Thiết kế cấp cao (5-7 phút): vẽ các thành phần chính và sự tương tác của chúng. Bắt đầu với đường hạnh phúc (happy path). Dùng các mẫu từ file 01-03.
- Đi sâu (deep dive) (15-20 phút): chọn thành phần thú vị/thách thức nhất và thiết kế nó chi tiết. Đây là nơi bạn thể hiện chiều sâu. Với một hệ thống ML, deep dive thường là: kiến trúc mô hình, pipeline đặc trưng, hoặc kiến trúc phục vụ.
- Đánh giá và giám sát (3-5 phút): bạn đo lường thành công ra sao? Điều gì có thể sai? Bạn phát hiện và phản ứng với các vấn đề thế nào?
- Cải tiến (iteration) (2-3 phút): bạn sẽ cải thiện gì với nhiều thời gian/tài nguyên hơn? Điều này cho thấy bạn hiểu các đánh đổi (tradeoffs) và có thể ưu tiên.
- Điều các nhà phỏng vấn tìm kiếm: tư duy có cấu trúc (không nhảy vọt đến giải pháp), nhận thức đánh đổi (mọi lựa chọn đều có chi phí), kiến thức thực tế (bạn đã thực sự xây dựng hệ thống), và khả năng giao tiếp (bạn có thể giải thích thiết kế của mình rõ ràng không?).