1 điểm bởi GN⁺ 2025-08-13 | Chưa có bình luận nào. | Chia sẻ qua WhatsApp
  • Tác giả chia sẻ trải nghiệm phát triển công cụ tìm kiếm web dựa trên 300 triệu embedding trong 2 tháng, xuất phát từ vấn đề chất lượng công cụ tìm kiếm suy giảm và sự tiến bộ của các mô hình embedding dựa trên Transformer
  • Thông qua hạ tầng và thuật toán hiệu năng cao như 200 cụm GPU, crawler phân tán quy mô lớn, RocksDB, HNSW, hệ thống hiện thực hóa tìm kiếm hiểu ngôn ngữ tự nhiên theo thời gian thực
  • Mục tiêu là hỏi đáp theo ý định thay vì khớp từ khóa, áp dụng nhiều kỹ thuật NLP/ML như chuẩn hóa, chunking, nối câu để phân tích tài liệu và giữ ngữ cảnh
  • Bài viết giới thiệu cách thiết kế hệ thống phân tán quy mô lớn theo từng lớp như pipeline, storage, service mesh, vector index, cùng các phương án tối ưu nút thắt và chi phí
  • Cuối cùng mô tả việc tạo ra một công cụ tìm kiếm cá nhân hóa có độ trễ cực thấp, phân tán ở quy mô lớn và độ chính xác cao

Tổng quan và động lực

  • Tác giả gần đây nhận thấy vấn đề chất lượng công cụ tìm kiếm suy giảm, SEO spam và sự gia tăng của nội dung không liên quan, đồng thời trong bối cảnh các mô hình embedding dựa trên Transformer đã nâng cao mạnh năng lực hiểu ngôn ngữ tự nhiên, nên quyết định tự xây dựng một công cụ tìm kiếm từ đầu
  • Giới hạn của các công cụ tìm kiếm hiện có bắt nguồn từ việc thiếu khả năng hiểu câu hỏi ở mức con người và chỉ dựa vào khớp từ khóa đơn giản
  • Mục tiêu là xếp hạng theo ý định truy vấn, để nội dung chất lượng tốt luôn xuất hiện ở trên cao và vẫn khám phá đều cả phần long tail
  • Quá trình xây dựng công cụ tìm kiếm web bao trùm nhiều lĩnh vực như khoa học máy tính, ngôn ngữ học, ontology, NLP, ML, hệ thống phân tán và kỹ thuật hiệu năng
  • Dự án lần này là một thử thách: trong 2 tháng, bắt đầu hoàn toàn một mình, không có sẵn hạ tầng hay kinh nghiệm trước đó, để hiện thực một công cụ tìm kiếm hoàn toàn mới

Cấu trúc tổng thể của hệ thống

  • Tạo 300 triệu text embedding dựa trên SBERT bằng 200 cụm GPU
  • Hàng trăm crawler chạy đồng thời thu thập 50.000 trang mỗi giây, xây dựng tổng cộng 280 triệu mục chỉ mục
  • Lưu trữ và lập chỉ mục bằng cách sharding RocksDB và HNSW trên hạ tầng 200 core CPU, 4TB RAM, 82TB SSD
  • Tổng độ trễ phản hồi truy vấn được đặt ở mức khoảng 500ms
  • Kiến trúc tổng thể và luồng xử lý được tách thành crawler, pipeline, storage, vector index embedding, service mesh và phần frontend/backend

Thử nghiệm và cải tiến tìm kiếm dựa trên embedding

Neural Embedding Playground

  • Thử nghiệm xác nhận rằng tìm kiếm sử dụng các mô hình embedding như SBERT có khả năng hiểu truy vấn tự nhiên và độ chính xác cao hơn so với tìm kiếm truyền thống dựa trên từ khóa
  • Có thể nắm bắt ý định của truy vấn đầu vào theo ngữ cảnh và cấp độ câu, rồi trích xuất đáp án thực sự liên quan

Ví dụ: tìm kiếm truyền thống vs. tìm kiếm neural

  • Tìm kiếm truyền thống: kết quả mang tính ngẫu nhiên, chủ yếu dựa vào khớp từ khóa
  • Tìm kiếm embedding: hiểu ngữ cảnh và ý định của câu hỏi, trả về kết quả tập trung vào câu hoặc khái niệm cốt lõi chính xác
  • Với các truy vấn kết hợp khái niệm phức tạp, câu hỏi hàm ý/tổng hợp, hoặc truy vấn chứa tín hiệu chất lượng, có thể tìm ra đáp án dựa trên ngữ nghĩa

Phân tích và chuẩn hóa trang web

  • Mục tiêu chuẩn hóa là chỉ trích xuất các thành phần văn bản có ý nghĩa từ HTML, đồng thời loại bỏ nhiễu như bố cục và phần tử điều khiển

  • Tuân theo các tiêu chuẩn như WHATWG, MDN để giữ nguyên cấu trúc bảng của các phần tử như p, table, pre, blockquote, ul, ol, dl

  • Loại bỏ hoàn toàn các thành phần chrome như menu, điều hướng, bình luận, giao diện

  • Áp dụng quy tắc đặc thù theo từng site (ví dụ: en.wikipedia.org) để xử lý tình trạng trích xuất quá mức hoặc thiếu hụt

  • Cũng có thể tận dụng dữ liệu có cấu trúc dựa trên ngữ nghĩa (meta, OpenGraph, schema.org, v.v.) để xây dựng knowledge graph và cải thiện xếp hạng

Chunking và bảo toàn ngữ cảnh

Chunking theo đơn vị câu

  • Để vượt qua giới hạn của mô hình embedding, hệ thống áp dụng chunking theo câu thay vì dùng toàn bộ trang
  • Khi chunking, sử dụng spaCy sentencizer để phân tách chính xác nhiều trường hợp như ranh giới câu tự nhiên, ngữ pháp, từ viết tắt, URL và cách diễn đạt không chính thức

Bảo toàn ngữ cảnh và liên kết

  • Hệ thống nắm bắt quan hệ phụ thuộc giữa các câu, heading, đoạn văn, bảng biểu rồi gộp cả thông tin ngữ cảnh đó vào embedding
  • Ví dụ, với cấu trúc bảng, hệ thống nối chuỗi heading/điều khoản cấp trên để vẫn giữ được ý nghĩa của từng hàng khi nhúng

Chuỗi câu (Statement Chaining)

  • Dùng bộ phân loại DistilBERT để phân tích đồng thời một câu và câu trước đó, tự động hóa việc xác định phụ thuộc ngữ cảnh và trích xuất chuỗi
  • Khi embedding, hệ thống đưa vào toàn bộ các câu phụ thuộc cấp trên để tăng khả năng giữ ngữ cảnh

Kết quả từ nguyên mẫu

  • Thử nghiệm nhiều truy vấn thực tế trong môi trường sandbox cho thấy hệ thống đạt khả năng hỏi đáp chính xác hơn rất nhiều, phù hợp ngữ cảnh so với cách truyền thống
  • Ngay cả khi từ khóa không khớp, có lược bỏ, ẩn dụ hoặc câu hỏi phức hợp, ứng dụng vẫn nhận ra ý định và ghép đúng câu theo ngữ cảnh, đồng thời khai phá hiệu quả tri thức ẩn và các quan hệ

Web crawler quy mô lớn (dựa trên node)

  • Xem xét nhiều yếu tố ổn định và hiệu quả như work stealing để phân phối tải, kiểm soát đồng thời/lưu lượng theo domain, xác thực DNS/URL/header
  • Crawler áp dụng Promise dựa trên asynchronous I/O, cơ chế chống DDoS, quản lý tài nguyên (bộ nhớ, độ trễ, backoff), phát hiện domain nhiễu
  • Tăng cường lọc URL trùng lặp/bất thường thông qua chuẩn hóa URL, giới hạn giao thức, cổng/thông tin người dùng và canonicalization

Pipeline (distributed task queue)

  • Trạng thái của từng trang ban đầu được quản lý trong PostgreSQL, giai đoạn đầu dùng trực tiếp polling/transaction
  • Trong môi trường phân tán quy mô lớn (hàng nghìn crawler), phát sinh vấn đề scale và nghẽn ở queue/lock → chuyển sang coordinator in-memory viết bằng Rust để quản lý trạng thái hàng đợi
  • Cấu trúc task gồm nhiều cách lập chỉ mục như hash map, binary heap, nhóm domain, random poll, hoán đổi vị trí (swap_remove)
  • Mỗi task chỉ chiếm khoảng 100B bộ nhớ, nên trên server 128GB có thể xử lý cả 1B task
  • Sau đó tác giả còn phát triển hàng đợi mã nguồn mở dựa trên RocksDB để thay thế SQS, hỗ trợ 300.000 ops/giây trên một node

Thiết kế storage (Oracle → PostgreSQL → RocksDB)

  • Ban đầu dùng Oracle Cloud (egress/storage chi phí thấp), sau đó đến PostgreSQL (TOAST), nhưng gặp giới hạn về mở rộng ghi và hiệu năng
  • Do đặc tính của PostgreSQL như MVCC, write amplification, WAL, việc INSERT song song quy mô lớn bị nghẽn, cuối cùng chuyển sang RocksDB là KV store
  • Với lưu blob riêng biệt của RocksDB (BlobDB), file SST, đa luồng, hash indexing, hệ thống tận dụng tối đa hiệu năng của NVMe SSD
  • Mở rộng thành 64 shard RocksDB — mỗi shard được route dựa trên xxHash(key), dùng Serde + MessagePack để tuần tự hóa
  • Cuối cùng hệ thống xử lý 200.000 ops/giây từ hàng nghìn client (crawler/parser/vectorizer), với metadata và blob được tách riêng rồi nén để lưu trữ

Service mesh và mạng

  • Khi mở rộng hạ tầng, hệ thống được thiết kế dựa trên mTLS + HTTP2 để tự động khám phá service instance và bảo mật giao tiếp
  • Mỗi node áp dụng chứng chỉ dựa trên root CA, dùng trực tiếp tuần tự hóa MessagePack, đồng thời phát triển DNS nội bộ, CoreDNS và custom client SDK
  • Tác giả từng dùng VPN như ZeroTier, Tailscale, nhưng do vấn đề mạng, hiệu năng và vận hành nên chọn tự xây dựng bằng HTTP + mTLS
  • Việc quản lý được thống nhất thông qua điều khiển system service (systemd + cgroup + journald), giúp tinh gọn và chuẩn hóa

Pipeline tạo embedding GPU quy mô lớn

  • Ban đầu sử dụng OpenAI API, sau đó chuyển sang môi trường GPU hiệu năng cao như Runpod vì chi phí
  • Pipeline tách bất đồng bộ từng stage, đạt hiệu suất GPU trên 90%, và với 250 GPU có thể tạo 100.000 embeddings mỗi giây
  • Pipeline viết bằng Rust, phần inference bằng Python → IPC qua named pipe, với backpressure có cấu trúc để tự động tinh chỉnh tài nguyên

Lập chỉ mục vector (HNSW/sharding)

  • Dùng thuật toán HNSW cho vector search trong bộ nhớ, cung cấp ANN (Approximate Nearest Neighbor) với độ trễ cực thấp
  • Khi chạm giới hạn RAM, hệ thống áp dụng sharding đồng đều theo node (64 node), mỗi shard là một chỉ mục HNSW riêng và được tìm kiếm song song
  • Do HNSW cần rất nhiều RAM và có giới hạn với cập nhật trực tiếp, cuối cùng hệ thống chuyển sang CoreNN, một vector DB mã nguồn mở chạy trên đĩa
  • CoreNN có thể truy vấn chính xác cao trên 3B embedding ngay cả với 128GB RAM và một node đơn

UX công cụ tìm kiếm và tối ưu độ trễ

  • UX của công cụ tìm kiếm lấy phản hồi tức thì làm cốt lõi (không có load indicator, SSR truyền thống)
  • Dùng Cloudflare Argo để đến gần edge PoP và áp dụng HTTP/3 nhằm giảm tối đa độ trễ truyền tải
  • Chuẩn bị toàn bộ dữ liệu ở cấp app server, giảm tối thiểu round trip API riêng lẻ, phản hồi ngay trang đã minify và nén

Bản tóm tắt này hướng dẫn cụ thể các quyết định thiết kế và tối ưu hóa chính trên toàn bộ hệ thống, thuật toán và hạ tầng, cho thấy một công cụ tìm kiếm web quy mô lớn ứng dụng công nghệ NLP/ML hiện đại có thể được xây dựng end-to-end như thế nào chỉ trong 2 tháng.

Chưa có bình luận nào.

Chưa có bình luận nào.