Back to articles
Technology Insight

Xây dựng hệ thống RAG không cần Vector DB: Tận dụng DuckDB làm Full-text Search siêu nhanh trên VPS

June 5, 2026

Đặt Vấn Đề: Gánh Nặng Chi Phí Khi Sử Dụng Vector Database

Trong kỷ nguyên của Trí tuệ nhân tạo (AI) và các Mô hình ngôn ngữ lớn (LLM), Retrieval-Augmented Generation (RAG) đã trở thành một kiến trúc chuẩn mực để giải quyết bài toán giới hạn tri thức và hiện tượng "ảo tưởng" (hallucination) của mô hình. Tuy nhiên, một thách thức lớn mà nhiều doanh nghiệp nhỏ và các kỹ sư phát triển phải đối mặt khi triển khai RAG là chi phí hạ tầng.

Thông thường, một hệ thống RAG tiêu chuẩn đòi hỏi phải cấu hình các Vector Database chuyên dụng như Pinecone, Milvus, Qdrant hoặc pgvector. Các cơ sở dữ liệu này hoạt động dựa trên cơ chế tính toán khoảng cách vector (Embedding Vectors) để tìm kiếm ngữ nghĩa. Dù mang lại độ chính xác cao về mặt ngữ nghĩa, phương pháp này lại đi kèm với những hạn chế đáng kể:

  • Tiêu tốn RAM dữ dội: Để đảm bảo tốc độ tìm kiếm nhanh, các Vector DB thường phải lưu chỉ mục (index) hoàn toàn trên bộ nhớ RAM.
  • Chi phí vận hành lớn: Việc thuê một VPS có cấu hình RAM từ 8GB đến 16GB trở lên chỉ để chạy Vector DB là một khoản đầu tư xa xỉ đối với các dự án vừa và nhỏ hoặc đang ở giai đoạn thử nghiệm (PoC).
  • Độ phức tạp trong vận hành: Bảo trì, đồng bộ dữ liệu giữa DB truyền thống và Vector DB tạo ra nhiều điểm lỗi tiềm ẩn (single point of failure).

Một giải pháp thay thế hiệu quả: Liệu chúng ta có thực sự cần đến Vector Embedding cho mọi bài toán RAG? Câu trả lời là Không. Đối với nhiều bài toán tìm kiếm tài liệu nội bộ, thông tin sản phẩm, hoặc văn bản pháp lý, kỹ thuật Full-text Search (FTS) truyền thống phối hợp với từ khóa chính xác hoàn toàn có thể đem lại hiệu quả tương đương, thậm chí tốt hơn ở một số khía cạnh, với chi phí phần cứng thấp hơn gấp nhiều lần.

Trong bài viết này, chúng ta sẽ cùng nhau khám phá cách tận dụng DuckDB — một hệ quản trị cơ sở dữ liệu phân tích dạng nhúng (Embedded Columnar Database) siêu nhẹ — để làm nền tảng tìm kiếm Full-text Search tốc độ cao cho RAG, chạy mượt mà chỉ trên một cấu hình VPS rẻ nhất.

---

Tại Sao Lại Là DuckDB Cho Hệ Thống RAG?

DuckDB thường được ví như "SQLite của thế giới phân tích dữ liệu (OLAP)". Nó là một thư viện C++ được nhúng trực tiếp vào tiến trình ứng dụng (in-process), nghĩa là bạn không cần cài đặt một dịch vụ server chạy ngầm nào. Dưới đây là những lý do khiến DuckDB trở thành "vũ khí bí mật" cho hệ thống RAG tối giản:

1. Cơ Chế Lưu Trữ Dạng Cột (Columnar Storage)

Khác với các DB truyền thống lưu trữ theo dòng (Row-oriented), DuckDB lưu trữ dữ liệu theo cột. Khi thực hiện tìm kiếm hoặc truy vấn thông tin văn bản, DuckDB chỉ đọc đúng cột chứa dữ liệu văn bản cần thiết từ đĩa cứng vào bộ nhớ, giúp giảm thiểu tối đa băng thông I/O và tăng tốc độ xử lý một cách kinh ngạc.

2. Tiện Ích Mở Rộng FTS (Full-Text Search Extension) Mạnh Mẽ

DuckDB tích hợp sẵn một extension FTS vô cùng mạnh mẽ dựa trên thuật toán BM25 (Best Matching 25). Đây là thuật toán xếp hạng tài liệu kinh điển nhưng cực kỳ hiệu quả, được sử dụng trong các hệ thống tìm kiếm lớn như Elasticsearch. BM25 tính toán điểm số dựa trên tần suất xuất hiện của từ khóa trong văn bản (TF) và tần suất nghịch đảo của từ khóa đó trong toàn bộ kho tài liệu (IDF).

3. Khả Năng Chạy Khớp Trên VPS Cấu Hình Thấp

Vì hoạt động dưới dạng in-process và tối ưu hóa việc quản lý bộ nhớ đệm, DuckDB có thể xử lý hàng triệu dòng dữ liệu chỉ với vài trăm Megabyte RAM. Bạn hoàn toàn có thể triển khai một hệ thống RAG hoàn chỉnh trên một VPS có cấu hình tối thiểu là 1 vCPU và 1GB RAM với chi phí chỉ vài USD mỗi tháng.

---

Kiến Trúc RAG Tối Giản Với DuckDB trên VPS

Kiến trúc RAG truyền thống dựa trên Vector DB thường bao gồm các bước: Document -> Chunking -> Embedding Model -> Vector DB -> LLM. Trong khi đó, kiến trúc RAG dựa trên DuckDB FTS sẽ được tối giản hóa như sau:

  1. Thu thập dữ liệu (Ingestion): Các tài liệu thô được chia nhỏ thành các đoạn văn bản (chunks).
  2. Lưu trữ & Indexing: Các chunks này được lưu trực tiếp vào file cơ sở dữ liệu DuckDB (với định dạng đuôi .db hoặc .duckdb). Sau đó, kích hoạt tính năng FTS để tạo chỉ mục từ khóa.
  3. Truy vấn (Retrieval): Khi người dùng đặt câu hỏi, hệ thống dùng câu hỏi đó làm từ khóa truy vấn FTS trong DuckDB. Thuật toán BM25 sẽ trả về các đoạn văn bản có độ liên quan cao nhất.
  4. Tổng hợp câu trả lời (Generation): Các đoạn văn bản liên quan được nhét vào Prompt làm ngữ cảnh (Context) để gửi cho LLM (qua OpenAI API, Anthropic API, hoặc các mô hình mã nguồn mở chạy local) để tạo ra câu trả lời cuối cùng.
---

Hướng Dẫn Từng Bước Triển Khai Thực Tế Với Python

Hãy cùng bắt tay vào xây dựng một prototype RAG bằng Python sử dụng DuckDB. Đầu tiên, chúng ta cần cài đặt thư viện cần thiết:

pip install duckdb openai

Bước 1: Khởi Tạo DuckDB và Lưu Trữ Dữ Liệu

Chúng ta sẽ tạo một file database và một bảng lưu trữ các đoạn tài liệu văn bản.

import duckdb

# Kết nối tới file database cục bộ
con = duckdb.connect('rag_knowledge.db')

# Tạo bảng lưu trữ tài liệu
con.execute("""
    CREATE TABLE IF NOT EXISTS documents (
        id INTEGER PRIMARY KEY,
        content TEXT,
        source TEXT
    );
""")

# Thêm dữ liệu mẫu
data = [
    (1, "Quy định nghỉ phép của công ty: Nhân viên được nghỉ 12 ngày phép năm có hưởng lương.", "HR_Policy.pdf"),
    (2, "Chính sách bảo mật: Toàn bộ mật khẩu của hệ thống phải được mã hóa bằng thuật toán bcrypt trước khi lưu trữ.", "Security_Guide.md"),
    (3, "Hướng dẫn cấu hình VPS: Để tối ưu hiệu năng, nên bật swap file tương đương với dung lượng RAM hiện tại.", "Ops_Manual.txt")
]

con.executemany("INSERT INTO documents VALUES (?, ?, ?);", data)
print("Đã lưu trữ tài liệu thành công.")

Bước 2: Tạo Chỉ Mục Full-Text Search (FTS)

Để tìm kiếm nhanh chóng, chúng ta cần cài đặt và khởi tạo extension FTS trên bảng dữ liệu vừa tạo.

# Cài đặt và tải extension fts
con.execute("INSTALL fts;")
con.execute("LOAD fts;")

# Tạo chỉ mục FTS trên cột 'content' của bảng 'documents'
con.execute("""
    PRAGMA create_fts_index(
        'documents',
        'id',
        'content',
        stemmer='none' -- Để 'none' hoặc cấu hình phù hợp cho ngôn ngữ cụ thể
    );
""")
print("Đã tạo chỉ mục FTS thành công.")

Bước 3: Thực Hiện Tìm Kiếm Ngữ Cảnh (Retrieval)

Bây giờ, chúng ta sẽ giả lập một câu hỏi từ người dùng và tiến hành truy vấn tìm các đoạn văn bản liên quan nhất bằng thuật toán BM25 tích hợp.

user_query = "quy định nghỉ phép năm như thế nào"

# Truy vấn FTS
query_result = con.execute(f"""
    SELECT content, source, fts_main_documents.match_bm25(id, '{user_query}') AS score
    FROM documents
    WHERE score IS NOT NULL
    ORDER BY score DESC
    LIMIT 2;
""").fetchall()

context = ""
for row in query_result:
    print(f"[Score: {row[2]:.2f}] Source: {row[1]} -> Content: {row[0]}")
    context += row[0] + "\n"

Bước 4: Gửi Ngữ Cảnh Đến LLM Để Tạo Câu Trả Lời

Sau khi lấy được đoạn văn bản phù hợp nhất từ DuckDB, ta ghép nó vào Prompt cấu trúc để gửi đến LLM xử lý tiếp.

from openai import OpenAI

client = OpenAI(api_key="YOUR_OPENAI_API_KEY")

prompt = f"""
Hãy trả lời câu hỏi của người dùng dựa vào ngữ cảnh được cung cấp dưới đây.
Nếu ngữ cảnh không chứa thông tin, hãy nói 'Tôi không biết'.

Ngữ cảnh:
{context}

Câu hỏi: {user_query}
Câu trả lời:
"""

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": prompt}]
)

print("\n=== Kết quả RAG ===")
print(response.choices[0].message.content)
---

Đánh Giá Hiệu Năng và Giới Hạn Tối Ưu

Giải pháp RAG không dùng Vector DB dựa trên DuckDB mang lại sự cân bằng hoàn hảo giữa chi phí và hiệu suất cho rất nhiều kịch bản thực tế:

Tiêu chí Vector Database (Chạy Embedding) DuckDB Full-text Search (BM25)
Yêu cầu phần cứng Cao (Cần nhiều RAM để giữ index) Cực thấp (Chạy tốt trên VPS 1GB RAM)
Chi phí vận hành Đắt đỏ (Phí API Embedding + Phí thuê DB) Gần như bằng 0 (Lưu file local trên đĩa)
Tìm kiếm từ khóa chính xác Kém (Dễ bỏ sót mã lỗi, số model, tên riêng) Xuất sắc (Khớp chính xác từng ký tự)
Hiểu sâu sắc về mặt ngữ nghĩa Tuyệt vời (Hiểu được từ đồng nghĩa) Hạn chế (Chỉ dựa trên tần suất từ khóa)

Kỹ Thuật Kết Hợp (Hybrid Search) Để Nâng Cao Chất Lượng

Nếu bạn lo ngại việc chỉ sử dụng FTS sẽ làm giảm khả năng hiểu ngữ nghĩa của hệ thống RAG, có một tin vui: DuckDB hoàn toàn có thể lưu trữ mảng số thực (Arrays). Bạn có thể xây dựng một hệ thống Hybrid Search ngay trong DuckDB:

  • Sử dụng FTS để lấy ra top 100 tài liệu chứa từ khóa chính xác.
  • Sử dụng một mô hình Embedding siêu nhẹ (như các dòng BGE chạy local bằng thư viện ONNX/SentenceTransformers) để tính khoảng cách Cosine trên top 100 tài liệu đó nhằm sắp xếp lại kết quả (Reranking).

Cách tiếp cận này giúp bạn vừa có được độ chính xác cao của mô hình ngữ nghĩa, vừa giữ được cấu hình VPS ở mức tối giản do không phải lưu trữ và tìm kiếm vector trên hàng triệu tài liệu cùng lúc.

---

Kết Luận

Xây dựng hệ thống RAG không nhất thiết phải đồng nghĩa với việc gia tăng chi phí hạ tầng cloud. Bằng cách tận dụng triệt để sức mạnh xử lý dạng cột và tính năng Full-text Search ưu việt của DuckDB, bạn hoàn toàn có thể triển khai một hệ thống tìm kiếm thông tin thông minh, tốc độ phản hồi tính bằng mili-giây ngay trên những cấu hình VPS phổ thông nhất.

Hãy bắt đầu tối giản hóa kiến trúc AI của bạn ngay hôm nay bằng cách thử nghiệm DuckDB cho dự án RAG tiếp theo!