Xây dựng Chatbot RAG hỏi đáp Quy chế Sinh viên ĐHQT – Hybrid Search, Reranking & Evaluation

Xây dựng Chatbot RAG hỏi đáp Quy chế Sinh viên ĐHQT – Hybrid Search, Reranking & Evaluation

2026-04-14 5 min đọc
RAG chatbot hybrid search reranking NLP tiếng Việt GPT-4o Qdrant BM25 FastAPI Streamlit

Bài toán

Sinh viên Trường Đại học Quốc tế – ĐHQG-HCM thường xuyên cần tra cứu quy định: điều kiện thi lại, thủ tục hoãn thi, mức xử lý kỷ luật, tiêu chí xét học bổng... Thông tin nằm rải rác trong hàng chục văn bản PDF dài, ngôn ngữ pháp lý khô khan, không có công cụ tra cứu thống nhất.

Mục tiêu: xây hệ thống hỏi đáp tự nhiên bằng tiếng Việt, trả lời chính xác dựa trên nội dung văn bản chính thức — không bịa, không đoán mò, có trích dẫn nguồn và số trang.


Dữ liệu

Thu thập 35+ tài liệu PDF chính thức, phân loại vào 7 danh mục: quy chế học vụ, công tác sinh viên, kỷ luật và khen thưởng, học bổng, nội quy ký túc xá, ban cán sự lớp, luật quốc gia liên quan.

Phát hiện sớm: 7 trong 35 file là PDF scan (ảnh), PyMuPDF trả về 0 chunks. Giải pháp: thêm OCR fallback dùng Tesseract (lang=vie+eng, 200 DPI) — tự động kích hoạt khi một trang trích xuất được ít hơn 50 ký tự.


Kiến trúc RAG tổng thể


Indexing Pipeline

Pipeline gồm 3 bước chạy một lần khi có tài liệu mới:

Bước 1 — Parse & Chunk (01_parse_chunk.py): Dùng PyMuPDF đọc text từng trang. Áp dụng Vietnamese legal-aware chunking: ưu tiên tách theo header pháp lý (Điều X, Chương X, Mục X) trước khi fallback về sentence-level chunking. Config: chunk_size=800 ký tự, overlap=150. Output: 35 file JSONL, mỗi record gồm chunk_id, source, page, text.

Bước 2 — Embedding & Indexing (02_embed_index.py): Embed toàn bộ chunks bằng bkai-foundation-models/vietnamese-bi-encoder (768 chiều, batch_size=32). Upsert vào Qdrant collection "rag_docs" với cosine distance.

Bước 3 — BM25 Sparse Index (03_bm25_index.py): Tokenize tiếng Việt bằng underthesea, xây BM25Okapi index (k1=1.5, b=0.75), lưu thành bm25.pkl (~2.3 MB).

Tổng kết: 700+ chunks từ 28 file PDF có text. 7 file scan được xử lý sau khi bổ sung OCR.

Hybrid Search + RRF Fusion


Mỗi câu hỏi được xử lý song song qua hai nhánh:

Dense Retrieval: Embed query bằng vietnamese-bi-encoder, tìm top-20 chunks gần nhất trong Qdrant theo cosine similarity. Mạnh với câu hỏi ngữ nghĩa, paraphrase, diễn đạt khác từ nhưng cùng ý.

Sparse Retrieval (BM25): Tokenize query, tính BM25 score trên toàn corpus, lấy top-20. Mạnh với từ khóa chính xác như "Điều 5", "Quyết định 719", tên văn bản cụ thể.

Reciprocal Rank Fusion: Hợp nhất hai danh sách bằng công thức score(d) = tổng 1/(k + rank_i(d)) với k=60. Không cần học tham số, robust với cả hai loại query. Dedup theo chunk_id, giữ top-20 kết quả hợp nhất.

Hybrid vượt trội cả Dense-only lẫn BM25-only, đặc biệt với câu hỏi multi-hop và conditional.

Cross-Encoder Reranking


Sau RRF có top-20 candidates, áp dụng thêm tầng reranking để chọn 4 chunks tốt nhất đưa vào LLM:

Cross-Encoder (AITeamVN/Vietnamese_Reranker): Chấm điểm trực tiếp từng cặp (query, chunk). Khác bi-encoder ở chỗ cross-encoder nhìn đồng thời cả query lẫn document nên chính xác hơn nhiều — chỉ chậm hơn về tốc độ, nhưng chạy trên top-20 nên vẫn chấp nhận được.

Deduplication: Loại chunk trùng theo chunk_id và 50 ký tự đầu.

Source Diversity: Giới hạn tối đa 3 chunks từ cùng một tài liệu nguồn, tránh câu trả lời bị dominated bởi một văn bản duy nhất.

Output cuối: top_k=4 chunks với đầy đủ rrf_score và rerank_score để hiển thị trong UI.

Giao diện thực tế




FastAPI backend với 3 endpoints chính: POST /chat (full RAG pipeline), POST /retrieve (chỉ retrieval, không LLM, dùng để debug), POST /evaluate (chạy bộ đánh giá tự động).

Streamlit UI với 3 chế độ:


Đánh giá hệ thống


Sinh 134 câu hỏi test tổng hợp bằng LLM với 4 dạng: factoid ("X là gì?"), procedural ("Thủ tục để làm X?"), conditional ("Nếu... thì...?"), multi-hop (kết hợp thông tin từ 2+ chunk). Mỗi câu có ground-truth relevant_ids để tính retrieval metrics.

Đánh giá 2 pha song song: ThreadPool 8 workers cho RAG pipeline (GPU-bound), ThreadPool 30 workers cho LLM-as-Judge calls (I/O-bound).

Kết quả thực tế (134 queries, 13/04/2026):


Faithfulness 80% cho thấy hệ thống bám sát ngữ cảnh tốt, ít hallucination. Context Precision 49.6% là điểm còn cải thiện được — nhiều chunks được retrieve nhưng chưa thực sự liên quan đến câu hỏi.

Hướng cải thiện


← Quay lại Blogs