37 điểm bởi GN⁺ 2026-01-16 | 3 bình luận | Chia sẻ qua WhatsApp
  • Một người dùng trên Hacker News đặt câu hỏi mọi người đang triển khai Retrieval-Augmented Generation (RAG) trong môi trường cục bộ như thế nào
  • Có xu hướng khá rõ rằng với RAG cục bộ, ngay cả khi không có vector DB, vẫn có thể vận hành tốt chỉ bằng các cách tìm kiếm văn bản như SQLite FTS5, BM25, grep
  • Với tìm kiếm mã nguồn, có nhiều chia sẻ kinh nghiệm rằng embedding chậm và nhiều nhiễu, và cũng có nhiều ý kiến cho rằng cách dựa trên từ khóa như BM25 + trigram tốt hơn
  • Ngay cả khi cần tìm kiếm vector, vẫn có nhiều trường hợp giải quyết bằng cấu hình gọn nhẹ như Postgres + pgvector, lưu vector BLOB trong SQLite, hoặc nạp FAISS vào bộ nhớ
  • Có thể cải thiện chất lượng tìm kiếm bằng các tổ hợp như tìm kiếm lai kết hợp BM25 + vector, RRF (Reciprocal Rank Fusion), reranking, mở rộng multi-query
  • Thay vì cố định theo kiểu “RAG = vector DB”, xu hướng là chọn theo tìm kiếm đơn giản → lai → kiểu agent tùy loại tài liệu, quy mô và gánh nặng vận hành

Kết luận chung ở bước tìm kiếm

  • Thay vì mặc định vector DB hay graph là bắt buộc, nhiều người chọn cách bắt đầu đơn giản theo hạ tầng sẵn có, loại tệp và yêu cầu hiệu năng
  • Cũng có ý kiến cho rằng cách để agent truy vấn trực tiếp filesystem hoặc API thì dễ thiết lập và bảo trì hơn, nhưng có thể hơi chậm
  • Nhận thức rằng “thứ RAG đưa cho LLM là những mẩu văn bản ngắn từ kết quả tìm kiếm” đã khiến trọng tâm tối ưu hiệu năng chuyển sang chất lượng truy xuất
  • Về “định nghĩa RAG”, có cả ý kiến cho rằng chỉ cần retrieval + generation là đã là RAG dù không có vector DB, và cũng có ý kiến rằng thông thường người ta vẫn dùng từ này với giả định có vector DB

Mô hình embedding và tìm kiếm vector

  • Mô hình embedding mdbr-leaf-ir do MongoDB phát triển chạy hoàn toàn trên CPU và đứng đầu nhiều bảng xếp hạng trong nhóm mô hình cùng kích thước
    • Trên máy chủ tiêu chuẩn 2vCPU có thể xử lý khoảng 22 tài liệu/giây và 120 truy vấn/giây
    • Đạt 53.55 điểm trên benchmark BEIR (all-MiniLM-L12-v2 đạt 42.69 điểm)
  • Các embedding từ tĩnh như model2vec/minish có tốc độ suy luận nhanh hơn nhưng độ chính xác truy xuất thấp hơn
    • Vì chỉ thực hiện tokenization + lookup table + trung bình nên nhanh hơn mô hình dựa trên transformer
  • Cũng có cách tạo vector cho từng đoạn văn bản bằng Meta-Llama-3-8B rồi lưu vào cột SQLite BLOB, sau đó dùng FAISS để tìm kiếm
    • Với 5 triệu chunk thì dùng khoảng 40GB bộ nhớ
    • faiss-gpu trên A6000 rất nhanh, còn faiss-cpu trên M1 Ultra chậm hơn nhưng vẫn đủ dùng nếu chỉ truy vấn vài lần mỗi ngày

Khuyến nghị cho tìm kiếm mã nguồn

  • Với mã nguồn, nên tránh dùng cơ sở dữ liệu vector và ưu tiên kết hợp BM25 + trigram
    • Embedding chậm và không phù hợp với code
    • Nếu không có reranker thì nhiễu lớn, và việc re-index file cũng tốn công
    • Tốc độ phản hồi tìm kiếm nhanh và chất lượng kết quả cũng tốt
  • Có thể triển khai tìm kiếm BM25 trong PostgreSQL bằng plpgsql_bm25
    • Hỗ trợ tìm kiếm lai kết hợp với pgvector + Reciprocal Rank Fusion
  • Áp embedding cho đường dẫn tệp + signature rồi fusion với BM25 cũng có thể cho kết quả tốt
  • Cách agentic chạy gpt-oss 20B cùng với ripgrep trong vòng lặp while cũng tỏ ra hiệu quả

Các giải pháp dựa trên cơ sở dữ liệu

  • SQLite FTS5: phù hợp với tài liệu dạng file Markdown, có thể triển khai RAG ngay cả khi không có vector DB
    • Mỗi file có thể có một trường mô tả ngắn để duyệt tài liệu bằng tìm kiếm từ khóa
    • Cũng có thể thiết kế theo kiểu lưu vector fp16 vào SQLite dưới dạng BLOB, lọc ra tập con trước rồi tính độ tương đồng trong bộ nhớ
    • Ngoài ra còn có các lựa chọn như sqlite-vec, sqlite-vector, vec0, bm25 của SQLite
    • “SQLite hoạt động tốt đến mức đáng ngạc nhiên”
  • PostgreSQL + pgvector: tận dụng được kiến thức Postgres sẵn có, dễ bàn giao cho đội vận hành
    • Cũng có thư viện llmemory hỗ trợ BM25 lai, mở rộng multi-query và reranking
  • LanceDB: vector DB nhúng, khá tiện để sử dụng
    • Được dùng cùng embedding nomic-embed-text của Ollama
  • DuckDB: cung cấp extension tìm kiếm tương đồng vector, phù hợp với dự án nhỏ dưới 3GB
  • Meilisearch, Typesense, Manticore: đơn giản hơn Elasticsearch/OpenSearch về mặt vận hành

Tìm kiếm lai và kiểu agentic

  • nori (usenori.ai): kết hợp tìm kiếm ngữ nghĩa và tìm kiếm từ vựng bằng SQLite + vec0 + fts5
  • Turbopuffer: hỗ trợ tìm kiếm lai vector + BM25
  • Chỉ với tổ hợp tìm kiếm agentic và tìm kiếm văn bản cũng đã có thể đạt kết quả khá tốt
    • Nếu thêm tìm kiếm vector và graph RAG thì có thể cải thiện thêm một chút về tốc độ và chất lượng
  • Claude Code/Codex nội bộ sử dụng ripgrep
  • Embedding áp vào đường dẫn tệp cũng có hiệu quả, và khi fusion với BM25 thì còn tốt hơn

Các trường hợp sử dụng BM25

  • shebe: công cụ CLI/MCP để lập chỉ mục và tìm kiếm codebase dựa trên BM25
    • Đặc biệt hữu ích trong workflow refactor (ví dụ: liệt kê các vị trí cần thay đổi khi nâng cấp Istio)
  • Trong 85% trường hợp, chỉ cần khớp tag là đủ, không cần vector DB
    • Người vận hành thêm tag vào cả đầu vào lẫn tài liệu để đạt mức khớp 100%
  • Có ý kiến cho rằng phần lớn vector DB chỉ là “cái búa dành cho bài toán không tìm thấy thứ cần tìm”

Công cụ và thư viện chuyên biệt

  • qmd: công cụ CLI để tìm kiếm file Markdown, cho kết quả truy vấn mờ tốt hơn fzf
  • ck: công cụ semantic grep viết bằng Rust
  • Kiln: thêm file bằng kéo thả, có thể so sánh nhiều cấu hình khác nhau
    • Hỗ trợ so sánh cách trích xuất, mô hình embedding, phương thức tìm kiếm (BM25, hybrid, vector)
    • Có chức năng đánh giá độ chính xác tìm kiếm và tự động tạo bộ dữ liệu đánh giá
  • libragen: CLI/MCP server để tạo thư viện nội dung RAG có quản lý phiên bản
    • Có thể chuyển kho GitHub thành RAG DB
  • piragi: thư viện Python RAG đơn giản, hỗ trợ nhiều nguồn như local/S3/API
  • ragtune: công cụ CLI để debug và benchmark truy xuất của RAG cục bộ

Xử lý tài liệu và OCR

  • discovery: dùng Qwen-3-VL-8B để OCR tài liệu, lưu vector bằng ChromaDB
    • Triển khai RAG lai BM25 + embedding
  • docling: công cụ trích xuất tài liệu, được dùng trong nhiều dự án RAG
  • Khi chuyển đổi PDF, việc xử lý bảng, nhiều cột, hoặc bảng kéo dài qua nhiều trang vẫn khó
    • Mô hình Mistral OCR cho kết quả tốt nhất (mô hình đóng)

Quản lý bộ nhớ và ngữ cảnh

  • Thứ RAG truyền cho LLM chỉ là các chuỗi kết quả tìm kiếm ngắn
    • Với mô hình nhỏ, TOP_K=5 thường đã là giới hạn; nhiều hơn có thể gây quên ngữ cảnh
  • Có thể cải thiện bằng cách tóm tắt trước file và thư mục
  • Cũng có người dùng Sonnet + cửa sổ ngữ cảnh 1M để đưa toàn bộ nội dung vào context
  • Có trường hợp xây dựng hệ thống memory cho Claude Code bằng tìm kiếm ngữ nghĩa trên file phiên làm việc

Ứng dụng doanh nghiệp và quy mô lớn

  • Khi xử lý 300.000 tương tác khách hàng mỗi ngày, độ trễ và độ chính xác là rất quan trọng
    • Sử dụng cách tiếp cận lai gồm embedding + full-text search + IVF-HNSW
    • Một bài toán khó là quản lý việc lan truyền thông tin trong khoảng 600 hệ thống phân tán
  • Đang thử nghiệm cách tiếp cận KAG (Knowledge Augmented Generation) để ánh xạ các quy tắc nghiệp vụ
  • Đã triển khai thành công RAG hoàn toàn cục bộ cho hơn 500.000 bài báo bằng Postgres vector DB

Các công cụ và cách tiếp cận khác

  • AnythingLLM: đi kèm vector DB đóng gói sẵn cho tài liệu
  • LibreChat: cũng bao gồm vector DB đóng gói sẵn cho tài liệu
  • ChromaDB: được dùng trong extension Obsidian để triển khai tìm kiếm ngữ nghĩa/hybrid
  • SurrealDB: được dùng kết hợp với vector hóa cục bộ
  • Giao diện truy vấn OData: khi cung cấp như một công cụ cho LLM thì khá hiệu quả, có thể phân tích file Excel 40.000 dòng
  • Nextcloud MCP Server: dùng Qdrant làm vector DB, cung cấp tìm kiếm ngữ nghĩa cho tài liệu cá nhân
  • LSP (Language Server Protocol): đã được thêm vào Claude Code nhưng hiện còn lỗi
    • TreeSitter có thể hữu ích hơn (tra cứu theo tên symbol, tìm vị trí định nghĩa/sử dụng)

3 bình luận

 
tensun 2026-01-16

Không rõ có xử lý tốt tiếng Hàn hay không.

 
ryj0902 2026-01-20

Nhìn hiệu năng của một hệ thống RAG nội bộ còn khá thô sơ của công ty, đọc bài viết như thế này khiến góc nhìn của tôi cũng thay đổi đôi chút.

 
GN⁺ 2026-01-16
Ý kiến trên Hacker News
  • Nhóm chúng tôi đang vận hành một cơ sở dữ liệu hỏi đáp
    Cả câu hỏi và câu trả lời đều được lập chỉ mục bằng chỉ mục trigramembedding, rồi lưu vào Postgres
    Khi tìm kiếm, chúng tôi dùng cả pgvector và tìm kiếm trigram, rồi kết hợp kết quả bằng điểm mức độ liên quan

  • Ở bước truy xuất, chúng tôi đã phát triển một mô hình embedding văn bản hiệu quả cao, thân thiện với CPU
    Đó là mô hình MongoDB/mdbr-leaf-ir, hiện đứng số 1 trên leaderboard trong cùng phân khúc kích thước
    Mô hình này tương thích với Snowflake/snowflake-arctic-embed-m-v1.5
    Có thể so sánh tìm kiếm ngữ nghĩa vs BM25 vs hybrid qua bản demo search-sensei
    Ví dụ, mô hình embedding nhận ra rằng “j lo” có nghĩa là “Jennifer Lopez”
    Chúng tôi cũng đã công bố quy trình huấn luyện, và có thể huấn luyện dễ dàng ngay cả với phần cứng mức phổ thông

    • Tôi tò mò không biết tốc độ embedding và recall của mô hình này so với các embedding từ tĩnh như minish hay model2vec ra sao
  • Từ tháng 4 năm 2024, tôi đã dùng Meta-Llama-3-8B để tạo vector
    Tôi dùng Python và Transformers trên RTX-A6000; nhanh nhưng ồn và nóng khá nhiều
    Sau đó tôi chuyển sang M1 Ultra và dùng thư viện MLX của Apple, tốc độ tương tự nhưng yên tĩnh hơn nhiều
    Mô hình Llama có 4k chiều nên mỗi chunk chiếm 8KB theo fp16, và tôi lưu chúng bằng numpy.save() vào cột BLOB của SQLite
    Khi tìm kiếm, tôi tải toàn bộ vector từ SQLite, tạo numpy.array, rồi tìm bằng FAISS
    faiss-gpu trên RTX6000 rất nhanh, còn faiss-cpu trên M1 Ultra cũng đủ nhanh cho nhu cầu của tôi (vài truy vấn mỗi ngày)
    Với 5 triệu chunk, mức dùng bộ nhớ vào khoảng 40GB, cả hai máy đều xử lý dư sức

  • Phần lớn tài liệu phức tạp của tôi là các file Markdown
    Tôi khuyên dùng một công cụ CLI đơn giản là tobi/qmd
    Trước đây tôi dùng quy trình dựa trên fzf, nhưng công cụ này cung cấp tìm kiếm mờ tốt hơn
    Tôi không dùng nó để tìm kiếm mã nguồn

    • Xem phần giới thiệu, tôi tưởng đó sẽ là một công cụ thay thế grep viết bằng golang, và kỳ vọng nó có những tính năng như trọng số theo heading Markdown
  • Tôi khuyên đừng dùng cơ sở dữ liệu vector cho tìm kiếm mã nguồn
    Embedding chậm và không hợp với code
    Kết hợp BM25 + trigram cho kết quả tốt hơn và phản hồi cũng nhanh hơn

    • Ngay trong Postgres cũng có thể làm tìm kiếm hybrid
      Có thể tham khảo dự án plpgsql_bm25
      Dự án có ví dụ kết hợp BM25 và pgvector bằng Reciprocal Rank Fusion cùng với notebook Jupyter
    • Tôi cũng đồng ý. Trước đây tôi từng thử tìm kiếm hybrid cho một công cụ thay thế grep, nhưng việc lập chỉ mục lại liên tục khá phiền
      Nếu dùng mô hình không dành cho code thì tìm kiếm vector gây ra rất nhiều nhiễu
      Giờ đây cách chạy vòng lặp gpt-oss 20B cùng ripgrep vừa nhanh hơn vừa chính xác hơn nhiều
    • Có ai biết dịch vụ đơn giản hoặc image Docker nào hỗ trợ cả BM25 lẫn tìm kiếm vector không?
    • Tôi đã có kết quả tốt khi áp dụng cho đường dẫn file hoặc chữ ký hàm
      Nếu kết hợp (fusion) với BM25 thì còn tốt hơn nữa
    • Tôi muốn nghe ý kiến về việc dùng RAG cho tìm kiếm tài liệu
  • Tôi đã tạo local-LLM-with-RAG để thử nghiệm RAG cục bộ
    Nó tạo embedding bằng “nomic-embed-text” của Ollama và dùng LanceDB làm vector DB
    Gần đây tôi đã cập nhật sang “agentic RAG”, nhưng với các dự án nhỏ thì có thể là hơi quá mức

    • Tôi cũng đang làm thứ tương tự. Tôi dùng lance-context, là một phiên bản đơn giản hơn nhiều
    • Cảm ơn vì đã giải thích “RAG” nghĩa là gì. Tôi đã bị rối khi đọc chủ đề này
  • Tôi lưu vector fp16 dưới dạng BLOB trong SQLite, lọc trước rồi tải vào bộ nhớ để tính độ tương đồng bằng phép nhân ma trận-vectơ (matvec)
    Nếu numpy hoặc torch tận dụng đa luồng/BLAS/GPU thì sẽ rất nhanh
    Nếu gặp nút thắt cổ chai, tôi dự định chuyển sang sqlite-vector
    Cách này hiệu quả vì dữ liệu được thu hẹp đáng kể bằng các bộ lọc như ngày tháng hoặc vị trí
    Phần backend được ẩn sau một giao diện có thể thay thế

  • 95% tài liệu của tôi là các file Markdown nhỏ nên tôi dùng SQLite FTS5 làm chỉ mục tìm kiếm văn bản thuần
    Tôi đã có sẵn chỉ mục nên kết nối thẳng vào mastra agent
    Mỗi file có một trường mô tả ngắn; sau khi tìm theo từ khóa, nếu mô tả khớp thì tôi tải toàn bộ tài liệu
    Mất khoảng một giờ để thiết lập, và hoạt động rất tốt

    • Thực ra đó chính là RAG (Retrieval-Augmented Generation)
      Tìm kiếm dựa trên embedding phổ biến hơn, nhưng về bản chất thì giống nhau
  • Chúng tôi quen dùng Postgres nên đã bắt đầu với PGVector
    Sau đó chúng tôi phát hiện nội dung có khớp 100% với các trường bán cấu trúc trong prompt
    Vì người vận hành bắt đầu gắn thẻ cả cho đầu vào lẫn tài liệu (khoảng 50 tài liệu)
    Thế là chúng tôi tìm theo trường trước để đưa file tương ứng vào prompt, rồi mới thực hiện tìm kiếm embedding
    Kết quả là trong 85% trường hợp không cần vectordb

    • Phần lớn vectordb giống như một cái búa đi tìm cái đinh
  • Tôi đã tạo llmemory và đang dùng nó cả cục bộ lẫn trong ứng dụng công ty
    Nó dựa trên PostgreSQL + pgvector, và bao gồm BM25 hybrid, mở rộng đa truy vấn, cùng reranking
    Đây là lần đầu tôi công khai nó nên có thể vẫn còn vài lỗi nhỏ
    Tôi khá hài lòng với hiệu năng của nó