1. Tổng Quan & Phân Tích Hiện Trạng Hệ Thống
Bản chất vấn đề: Vì sao SmartRestaurant cần chuyển đổi sang Advanced RAG của Paper 01?
Dữ liệu nhà hàng bản chất là dữ liệu doanh nghiệp hỗn hợp có cấu trúc cao (thực đơn món ăn, danh mục, giá tiền, calorie, nguyên liệu, cảnh báo dị ứng, combo theo bàn, chính sách voucher/đổi trả). Hiện tại hệ thống đang sử dụng kỹ thuật lọc chuỗi thô sơ trong backend/src/services/ragService.js, dẫn đến việc không thể xử lý các câu hỏi phức tạp về thành phần, không nhận diện được đồng nghĩa/ngữ nghĩa, và hoàn toàn không bảo toàn được cấu trúc bảng biểu khi đưa vào prompt của Aria.
Hiện Trạng Hiện Tại (SmartRestaurant)
-
cancel
Lọc từ khoá thô sơ: Sử dụng hàm
stage1Filterso khớp chuỗisearchable.includes(kw). Bỏ sót hoàn toàn ngữ nghĩa (ví dụ: khách tìm "món ăn giải ngấy" sẽ không khớp với "salad thanh mát"). -
cancel
Fallback thiếu thông minh: Khi không tìm thấy món theo từ khoá, tự động trả về Top món
is_trendinghoặc ngẫu nhiên, không phục vụ đúng nhu cầu thực tế của khách hàng. -
cancel
Không có Vector Embeddings & Reranking: Không lưu trữ véc-tơ ngữ nghĩa trong Supabase pgvector hay FAISS, không có bộ tái xếp hạng Cross-Encoder để ưu tiên các món phù hợp nhất.
-
cancel
Cấu trúc bảng biểu bị làm phẳng: Dữ liệu món ăn chỉ được ghép nối dạng text thô, làm mất liên kết chặt chẽ giữa các thuộc tính dinh dưỡng, dị ứng và giá trị theo nhóm đối tượng.
Mục Tiêu Sau Khi Áp Dụng Paper 01
-
check_circle
Lập chỉ mục cấp độ hàng (Row-Level Indexing): Mỗi món ăn và chính sách được tuần tự hoá thành đơn vị JSON chuẩn quan hệ hàng - cột, giữ nguyên ngữ cảnh tiêu đề, thành phần và chỉ số dinh dưỡng.
-
check_circle
Truy xuất Lai Dung hợp (Hybrid Retrieval): Kết hợp song song Dense Vector (
all-mpnet-base-v2/BGE-M3) với Sparse BM25 theo tỷ lệ tối ưu: $$Score_{combined} = 0.6 \times Dense + 0.4 \times Sparse$$ -
check_circle
Lọc Siêu Dữ Liệu bằng SpaCy NER: Trích xuất tức thì các thực thể (Tên món, Giá tiền, Ngân sách, Dị ứng, Cấp độ cay, Thời gian) để pre-filter loại bỏ các món vi phạm kiêng cữ.
-
check_circle
Tái Xếp Hạng Ngữ Cảnh (Cross-Encoder Reranker): Chấm điểm trực tiếp cặp
(Query, Món)bằngms-marco-MiniLM-L-12-v2để chọn Top-5 món chuẩn xác nhất. -
check_circle
Bộ nhớ 10 Lượt & Vòng Lặp Phản Hồi: Khi thực khách đánh giá Thumbs-down (👎) hoặc phản hồi không hài lòng, hệ thống tự động tái cấu trúc truy vấn (Query Reformulation) và truy xuất lại.
2. 6 Trụ Cột Kỹ Thuật Đột Phá Cho Dữ Liệu Có Cấu Trúc
Thiết Kế Đặc Thù Cho Dữ Liệu Bảng Biểu & Quan Hệ Hàng Cột
Bài báo giải quyết triệt để sự thất bại của các hệ thống RAG văn bản truyền thống khi đối mặt với dữ liệu bảng biểu, hồ sơ nhân sự và bảng giá. Dưới đây là cách chuyển hóa từng trụ cột thành các thành phần kỹ thuật tương ứng trong kiến trúc SmartRestaurant.
Lập Chỉ Mục Cấp Hàng (Row-Level Indexing)
Thay vì làm phẳng cả trang menu hay bảng thành đoạn text dài làm đứt gãy quan hệ dữ liệu, hệ thống chia nhỏ từng món ăn và biến thể thành một bản ghi hàng có cấu trúc (Structured Row Unit).
Lọc Siêu Dữ Liệu (SpaCy NER Filter)
Tích hợp bộ trích xuất thực thể có tên SpaCy NER chuyên biệt cho F&B để bóc tách: loại món, hạn chế dị ứng (hải sản, gluten, đậu phộng), chế độ ăn (chay, keto), và ngân sách mong muốn.
is_vegetarian=True AND allergens NOT CONTAINS 'peanut'Truy Xuất Lai (Dense + BM25 Fusion)
Dung hợp giữa Dense Embeddings (bắt ngữ nghĩa trừu tượng: "món nhậu thanh nhẹ") và BM25 (khớp chính xác mã món, tên món cụ thể, từ khoá số lượng/giá).
Tái Xếp Hạng Ngữ Cảnh (Cross-Encoder)
Top 20 ứng viên sau bước lai được chuyển qua mô hình Cross-Encoder ms-marco-MiniLM-L-12-v2 để chấm điểm tương thích trực tiếp theo cặp (Query, Item).
Tinh Chỉnh Truy Vấn Động (Query Expansion)
Tự động viết lại (Query Rewriting) các câu hỏi mơ hồ ("uống gì ngon?") và mở rộng truy vấn (Query Expansion) với từ khoá đa dạng dựa trên LLM Groq để bao quát tối đa các món tiềm năng.
Vòng Lặp Phản Hồi (Human-in-the-Loop)
Duy trì bộ nhớ hội thoại 10 lượt tương tác (ConversationBufferMemory). Bổ sung nút Thích/Không thích (👍/👎); khi khách bấm 👎, hệ thống tự động kích hoạt truy xuất lại với chiến lược mới.
"Tiếp đất" (Grounding) là gì? Giống như một chiếc mỏ neo giữ chặt con tàu, "Tiếp đất" là kỹ thuật ép mô hình AI chỉ được phép đưa ra câu trả lời dựa trên 100% dữ liệu thực đơn thực tế được tìm thấy trong kho CSDL. AI bị cấm tuyệt đối việc tự suy đoán hay "bịa" (hallucination) ra món ăn, giá tiền hoặc thành phần không có thật.
- Khóa biên dữ liệu: Đặt toàn bộ thông tin món ăn vào thẻ
<retrieved_menu>để AI nhận thức rõ ranh giới thông tin. - Quy tắc cấm đoán (Hard Negative): Nếu khách hỏi món nhà hàng không có, AI bắt buộc phải trả lời: "Quán chưa có món này, em gợi ý món gần nhất...", cấm tự sáng tác món.
- Buộc trích dẫn thuộc tính: Mỗi món gợi ý đều phải kèm theo giá tiền, calo, và cảnh báo dị ứng lấy trực tiếp từ bảng dữ liệu.
- Tự động tóm tắt: Khống chế câu trả lời dưới 3-4 câu trọng tâm, tránh dài dòng để khách chốt món nhanh trên điện thoại.
Hệ thống duy trì 2 chỉ mục song song: Chỉ mục độ chính xác cao chạy trên FAISS HNSW + BGE-M3/all-mpnet-base-v2 phục vụ các truy vấn chuyên sâu về dinh dưỡng, và Chỉ mục hạng nhẹ In-Memory chạy tại Node.js Redis phục vụ tra cứu nhanh tên món và giá tiền với độ trễ < 15ms.
3. Kiến Trúc Hệ Thống & Luồng Dữ Liệu Tích Hợp
Kiến Trúc Tích Hợp Toàn Diện (End-to-End System Architecture)
Sơ đồ dưới đây minh họa sự tương tác giữa 3 tầng chính: Frontend (Web App khách hàng/nhân viên), Node.js Backend Gateway & Redis Cache, và Python AI-Service (FastAPI + Advanced RAG Core).
Hãy hình dung quy trình này tương tự như cách vận hành một bếp nhà hàng chuyên nghiệp:
Trước khi mở cửa đón khách, đầu bếp phải rửa rau, hầm nước dùng, ướp thịt sẵn. Tương tự, mỗi khi quản lý cập nhật thực đơn hoặc định kỳ ban đêm, hệ thống chạy ngầm để tuần tự hoá bảng món ăn thành text và tính toán sẵn Vector Embeddings + chỉ mục BM25. Quá trình này nặng về CPU/GPU nên làm trước dưới nền để không bắt khách chờ đợi.
Khi thực khách ngồi vào bàn và hỏi trợ lý Aria ("Cho tôi món thanh đạm không cay dưới 100k"), hệ thống không cần tạo lại embedding từ đầu, mà chỉ việc quét tìm trên các chỉ mục đã chuẩn bị sẵn, lọc dị ứng bằng SpaCy và xếp hạng Top 5 món. Nhờ đó, câu trả lời xuất hiện tức thì trong < 500ms.
Sơ Đồ Luồng Dữ Liệu: Xử Lý Ngoại Tuyến & Truy Vấn Trực Tuyến
flowchart TD
subgraph Offline["LUỒNG NGOẠI TUYẾN (Offline Pipeline) — 'Khâu Sơ Chế'"]
DB[(Supabase PostgreSQL)] --> Serializer["Module Row Serializer"]
Serializer --> RowSerialized["Văn bản Tuần Tự Hóa row_serialized"]
RowSerialized --> EmbeddingGen["Mô hình Embedding (768-dim)"]
RowSerialized --> BM25Corpus["Tokenize Tiếng Việt & BM25 Corpus"]
EmbeddingGen --> FAISSIndex["FAISS HNSW Index (M=32)"]
BM25Corpus --> BM25Index["Rank-BM25 Inverted Index"]
end
subgraph Online["LUỒNG TRỰC TUYẾN (Online Pipeline) — 'Phục Vụ Ra Bàn'"]
User["Khách Hàng (Web App)"] -->|"1. Đặt câu hỏi"| Gateway["Node.js Gateway / Express"]
Gateway -->|"2. Forward query"| AIService["Python AI-Service (FastAPI)"]
AIService --> RetCoord["Hybrid Retriever Orchestrator"]
RetCoord --> NERFilter["F&B NER Extractor (Bước 3.1)"]
RetCoord --> ParallelSearch{"Truy Vấn Song Song (Độ Sâu Mở Rộng)"}
ParallelSearch -->|"Dense Search"| FAISSIndex
ParallelSearch -->|"Sparse Search"| BM25Index
FAISSIndex -->|"Top 30 Dense"| Fusion["Score Fusion (0.6 / 0.4)"]
BM25Index -->|"Top 30 Sparse"| Fusion
Fusion --> HardFilter["Pre-Reranking Hard-Filter (Bước 3.1)
Loại 100% món dị ứng & quá giá"]
NERFilter -.->|"Truyền điều kiện lọc"| HardFilter
HardFilter -->|"Top 20 Ứng Viên Sạch"| Reranker["Cross-Encoder Reranker (ms-marco) (Bước 3.2)"]
Reranker -->|"Top 5 Món Tối Ưu"| GroundedPrompt["Grounded Prompting Builder"]
GroundedPrompt --> LLM["Groq LLaMA 3.3 70B"]
LLM -->|"SSE Stream Token"| Gateway
Gateway -->|"Hiển thị câu trả lời & món ăn"| User
end
subgraph FeedbackLoop["VÒNG LẶP PHẢN HỒI ĐÓNG (Closed-Loop Feedback)"]
User -.->|"Khách bấm Thumbs-Down 👎"| FeedbackAPI["POST /rag/feedback"]
FeedbackAPI -.-> Telemetry["Redis Telemetry Cache"]
Telemetry -.-> Reformulator["Query Reformulator (Bước 4.1)"]
Reformulator -.->|"Bắn câu truy vấn tái cấu trúc (< 1.2s)"| ParallelSearch
end
Trích Xuất F&B NER & Nới Rộng Truy Vấn
F&B NER bóc tách từ khóa dị ứng, ngân sách, ăn chay. Retriever tự động mở rộng độ sâu ứng viên (Top 30) để không bao giờ bị thiếu hụt sau khi lọc.
Truy Vấn Kép & Lọc Cứng An Toàn
FAISS + BM25 tìm kiếm song song < 5ms; Dung hợp điểm số 0.6/0.4 và loại bỏ 100% món dị ứng hoặc vượt giá theo quy tắc Zero Tolerance.
Tái Xếp Hạng Chuẩn Xác
Đưa danh sách Top 20 ứng viên đã lọc sạch qua mô hình Cross-Encoder để chấm điểm tương quan ngữ cảnh sâu, chọn ra đúng Top 5 món ngon nhất.
Tạo Sinh Có Tiếp Đất
Nhúng 5 món vào Grounded Prompt Template của Groq LLaMA 3.3. Trả về token streaming cực nhanh (TTFT < 400ms) kèm trích dẫn nguồn.
3.3. Khung Sườn Đánh Giá & Tự Phản Tỉnh Bằng AI (AI-in-the-Loop Evaluation)
Thay vì chỉ dựa vào kiểm thử thủ công, hệ thống tích hợp 4 tầng giám sát và đánh giá tự động bằng AI để đảm bảo trợ lý Aria luôn tư vấn trung thực, chuẩn xác và liên tục tự thích ứng:
Dùng LLaMA 3.3 70B hoặc GPT-4o chấm điểm định lượng tự động offline trên 3 tiêu chí: Tính trung thực (Faithfulness), Độ liên quan (Relevance), và Độ đầy đủ (Completeness).
Mini-agent chạy ngầm tự phản tỉnh trong thời gian thực (Real-Time Reflection): Quét vi phạm dị ứng và ngân sách trước khi stream token cuối cùng ra bàn ăn. Tự kích hoạt sửa lỗi nếu phát hiện vi phạm.
Mỗi khi thực khách nhấn nút 👎, AI tự động phân loại nguyên nhân lỗi (Miss retrieval, Sai rerank, Trả lời lạc đề, Câu hỏi mơ hồ) và chuyển giao cho bộ Query Reformulator viết lại truy vấn.
Đối soát định kỳ giữa chuyên gia ẩm thực (Human Evaluator) và AI Judge trên 50 lượt mẫu ngẫu nhiên (chỉ số $\kappa \ge 0.85$) để đảm bảo tiêu chuẩn đánh giá luôn khách quan và chuẩn vị.
4. Đặc Tả Mã Nguồn Kỹ Thuật (Code Specifications)
Chi Tiết Cấu Trúc File & Mã Nguồn Cần Thêm / Sửa Đổi
Được thiết kế mô-đun hoá, tương thích hoàn toàn với kiến trúc hiện có của SmartRestaurant
Cấu Hình Cây Thư Mục Làm Việc (Workspace Directory Structure)
Sơ đồ tổ chức phân cấp thư mục của toàn bộ dự án SmartRestaurant, thể hiện rõ ranh giới giữa Python AI Service (Advanced RAG Core), Node.js Gateway (Backend hiện có), và React Client:
SmartRestaurant/
├── ai-service/ # [NEW] Microservice Python độc lập chuyên trách Advanced RAG
│ ├── app/
│ │ ├── main.py # FastAPI App: Đăng ký routes, middleware CORS, health check
│ │ ├── api/routes/
│ │ │ ├── retrieve.py # POST /rag/retrieve - Truy vấn hybrid & rerank top-k
│ │ │ ├── chat.py # POST /rag/chat - Sinh câu trả lời Grounded SSE stream
│ │ │ └── sync.py # POST /rag/sync-menu - Webhook đồng bộ menu vào FAISS/BM25
│ │ ├── processors/ # Lõi 6 Trụ Cột Kỹ Thuật (Paper 01 Guidelines)
│ │ │ ├── row_serializer.py # Trụ 1: Table-Aware Row Serialization (giữ quan hệ hàng-cột)
│ │ │ ├── metadata_filter.py # Trụ 2: F&B NER & Pre-retrieval Hard-Filtering (bóc tách dị ứng/giá & lọc cứng)
│ │ │ ├── hybrid_retriever.py # Trụ 3: Dual-Index Fusion (FAISS HNSW dense + BM25 Okapi sparse)
│ │ │ ├── cross_encoder_reranker.py# Trụ 4: Tái xếp hạng ngữ cảnh sâu (ms-marco-MiniLM-L-12-v2)
│ │ │ └── query_reformulator.py # Trụ 5 & 6: Viết lại câu mơ hồ & mở rộng truy vấn khi nhận 👎
│ │ ├── memory/
│ │ │ └── conversation_buffer.py # Bộ nhớ hội thoại 10 lượt tương tác gần nhất
│ │ └── evaluation/ # Khung sườn đánh giá AI-in-the-Loop
│ │ ├── llm_judge.py # L1: Thẩm phán LLM-as-a-Judge chấm điểm định lượng
│ │ ├── guardrail_verifier.py # L2: Mini-agent tự phản tỉnh thời gian thực (Real-time Reflection)
│ │ └── run_eval.py # Test suite tự động 100 câu hỏi test benchmark
│ ├── data/indexes/ # Thư mục lưu file chỉ mục nhị phân FAISS (.bin) và BM25 (.pkl)
│ ├── Dockerfile # Multi-stage Docker build nhẹ (~850MB) tối ưu C++ CPU
│ └── requirements.txt # faiss-cpu, rank-bm25, sentence-transformers, spacy, groq
├── backend/ # [EXISTING] Node.js Express Gateway hiện tại
│ └── src/
│ ├── controllers/
│ │ └── feedbackController.js # [NEW] Tiếp nhận telemetry Thumbs 👍/👎 và sync vào DB
│ └── services/
│ └── ragService.js # [MODIFY] Chuyển đổi từ lọc từ khóa thô sang gọi ai-service
├── frontend/ # [EXISTING] React Web Client
│ └── src/components/
│ └── AriaChatWidget.jsx # [MODIFY] Bổ sung cặp nút đánh giá Thumbs Up / Thumbs Down
├── database/
│ └── migrations/
│ └── 20260912_add_rag_columns.sql # [NEW] Kích hoạt pgvector, thêm cột embedding & row_serialized
└── docker-compose.yml # [MODIFY] Bổ sung service ai-service kết nối chung internal network
ai-service/processors/row_serializer.py
Tuần tự hóa từng món ăn từ bảng menu_items thành các văn bản bán cấu trúc có tiêu đề ngữ cảnh rõ ràng, bảo toàn mối quan hệ hàng - cột theo đúng mục 3.1.2 của bài báo.
# ai-service/processors/row_serializer.py
from typing import Dict, Any
def serialize_menu_row(item: Dict[str, Any]) -> str:
"""
Tuần tự hoá 1 hàng của bảng menu_items thành chuỗi biểu diễn có cấu trúc.
Bảo toàn toàn bộ các thuộc tính hàng - cột để lập chỉ mục véc-tơ và BM25.
"""
category_name = item.get("category", {}).get("name") or item.get("categories", {}).get("name") or "Khác"
ingredients = ", ".join(item.get("ingredients") or []) or "Không ghi chú"
allergens = ", ".join(item.get("allergens") or []) or "Không có dị ứng phổ biến"
spice = item.get("spice_level", 0)
calories = item.get("calories", "N/A")
price_vnd = f"{int(item.get('price', 0)):,} VND"
serialized = (
f"[MÓN ĂN: {item.get('name', 'Chưa rõ')}]\n"
f"• Phân loại: {category_name}\n"
f"• Giá bán: {price_vnd}\n"
f"• Độ cay: {spice}/5\n"
f"• Lượng Calo: {calories} kcal\n"
f"• Thành phần nguyên liệu: {ingredients}\n"
f"• Cảnh báo dị ứng: {allergens}\n"
f"• Mô tả hương vị: {item.get('description', '')} {item.get('ai_description', '')}"
)
return serialized.strip()
ai-service/processors/hybrid_retriever.py
Thực thi công thức kết hợp điểm số tại Mục 3.3.3 của bài báo: Score = 0.6 * Dense + 0.4 * Sparse.
# ai-service/processors/hybrid_retriever.py
import numpy as np
import faiss
from rank_bm25 import BM25Okapi
from sentence_transformers import SentenceTransformer
from typing import List, Dict, Any, Tuple
class HybridMenuRetriever:
def __init__(self, dense_model_name: str = "sentence-transformers/all-mpnet-base-v2"):
# Load mô hình Dense Embeddings
self.encoder = SentenceTransformer(dense_model_name)
self.dimension = 768
# Cấu hình FAISS HNSW theo paper (M=32, efConstruction=200, efSearch=50)
self.index = faiss.IndexHNSWFlat(self.dimension, 32)
self.index.hnsw.efConstruction = 200
self.index.hnsw.efSearch = 50
self.corpus_items: List[Dict[str, Any]] = []
self.bm25: BM25Okapi = None
def build_index(self, serialized_rows: List[str], raw_items: List[Dict[str, Any]]):
self.corpus_items = raw_items
# 1. Xây dựng FAISS Dense Index
embeddings = self.encoder.encode(serialized_rows, convert_to_numpy=True, normalize_embeddings=True)
self.index.reset()
self.index.add(embeddings)
# 2. Xây dựng BM25 Sparse Index
tokenized_corpus = [doc.lower().split() for doc in serialized_rows]
self.bm25 = BM25Okapi(tokenized_corpus)
def retrieve(self, query: str, top_k: int = 20) -> List[Tuple[Dict[str, Any], float]]:
if not self.corpus_items:
return []
# A. Dense Query
q_emb = self.encoder.encode([query], convert_to_numpy=True, normalize_embeddings=True)
dense_distances, dense_indices = self.index.search(q_emb, len(self.corpus_items))
dense_scores = {dense_indices[0][i]: float(dense_distances[0][i]) for i in range(len(dense_indices[0]))}
# B. Sparse Query (BM25)
bm25_scores_raw = self.bm25.get_scores(query.lower().split())
max_bm25 = max(bm25_scores_raw) if max(bm25_scores_raw) > 0 else 1.0
sparse_scores = {i: float(bm25_scores_raw[i] / max_bm25) for i in range(len(bm25_scores_raw))}
# C. Weighted Score Fusion (0.6 Dense + 0.4 Sparse theo Paper 01)
combined_results = []
for idx in range(len(self.corpus_items)):
d_score = dense_scores.get(idx, 0.0)
s_score = sparse_scores.get(idx, 0.0)
final_score = 0.6 * d_score + 0.4 * s_score
combined_results.append((self.corpus_items[idx], final_score))
# Sắp xếp giảm dần và lấy Top-K
combined_results.sort(key=lambda x: x[1], reverse=True)
return combined_results[:top_k]
ai-service/processors/cross_encoder_reranker.py
Sử dụng mô hình mã hóa chéo ms-marco-MiniLM-L-12-v2 để chấm điểm tương thích ngữ cảnh theo cặp trực tiếp giữa câu hỏi của khách và nội dung món ăn.
# ai-service/processors/cross_encoder_reranker.py
from sentence_transformers import CrossEncoder
from typing import List, Dict, Any, Tuple
from processors.row_serializer import serialize_menu_row
class ContextualReranker:
def __init__(self, model_name: str = "cross-encoder/ms-marco-MiniLM-L-12-v2"):
self.reranker = CrossEncoder(model_name)
def rerank(self, query: str, candidate_items: List[Dict[str, Any]], top_k: int = 5) -> List[Dict[str, Any]]:
if not candidate_items:
return []
# Chuẩn bị cặp (query, passage)
pairs = [(query, serialize_menu_row(item)) for item in candidate_items]
# Dự đoán điểm liên quan trực tiếp
scores = self.reranker.predict(pairs)
# Ghép cặp item với điểm số và sắp xếp
scored_candidates = list(zip(candidate_items, scores))
scored_candidates.sort(key=lambda x: x[1], reverse=True)
return [item for item, _ in scored_candidates[:top_k]]
backend/src/services/ragService.js
Nâng cấp hàm gọi retrieveMenuContext để chuyển quyền tính toán RAG phức tạp sang Python AI-Service khi cần độ chính xác cao, đồng thời hỗ trợ ghi nhận phản hồi Thumbs-down để tự động kích hoạt truy xuất mở rộng.
// backend/src/services/ragService.js (Bổ sung hàm xử lý phản hồi người dùng)
async function handleUserFeedback(sessionId, messageId, feedbackType, lastQuery) {
// Ghi nhật ký feedback (thumbs up / thumbs down)
console.log(`[Feedback] Session: ${sessionId}, Type: ${feedbackType}, Query: "${lastQuery}"`);
if (feedbackType === 'thumbs_down') {
// Kích hoạt Query Reformulation trên ai-service theo Paper 01 Mục 3.7
try {
const response = await fetch(`${process.env.AI_SERVICE_URL || 'http://localhost:8000'}/reformulate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: lastQuery, sessionId })
});
return await response.json();
} catch (err) {
console.error('[ragService] Lỗi khi kích hoạt reformulate:', err.message);
}
}
return { status: 'recorded' };
}
5. Lộ Trình Triển Khai 5 Pha — Chuẩn Hóa Chi Tiết Từng Công Việc (AI Tăng Tốc)
Kế Hoạch Thực Chiến 3.5 – 4 Ngày (28 – 32 Giờ Làm Việc) Có AI Hỗ Trợ
Tất cả các đầu việc được chuẩn hóa đồng nhất theo 6 tiêu chí bắt buộc: Tên công việc, Mục đích của hành động, Nội dung chi tiết, Thời gian hoàn thiện (có AI hỗ trợ), Đối tượng tác động / nhắm đến (Target Entity) và Cách đánh giá mục tiêu đã xong.
Sơ Đồ Luồng Tương Tác Đa Tầng (Architecture Swimlane Pipeline Map)
Mô hình hóa quy trình tuần tự qua 5 Pha, 5 Cổng Nghiệm Thu Cứng (Gates) & Vòng lặp phản hồi ngược thời gian thực
Bảng Ma Trận Chuyển Giao Dữ Liệu & Điều Kiện Nghiệm Thu Giữa 5 Pha
Phase Handover Matrix • Quy định chuẩn giao tiếp dữ liệu đầu vào - đầu ra và cổng nghiệm thu cứng (Gates)
| Giai Đoạn | Đầu Vào Nhận Được (Inputs) | Module Xử Lý Trọng Tâm | Sản Phẩm Bàn Giao (Outputs) | Cổng Nghiệm Thu (Gate Criteria) | Tương Tác Phản Hồi |
|---|---|---|---|---|---|
| P1 Pha 1 (0.5d) |
Bảng CSDL menu_items, chính sách nhà hàng hiện hữu.
|
row_serializer.py + Migration pgvector
|
100% bản ghi được điền chuỗi row_serialized + cột vector 768d.
|
🛡️ Gate 1: Schema hợp lệ, 0 bản ghi lỗi tuần tự hóa. | Khởi tạo tuyến tính (Tầng dữ liệu gốc). |
| P2 Pha 2 (1.0d) |
Corpus row_serialized từ Pha 1 + Câu truy vấn người dùng.
|
FAISS HNSW + BM25 Okapi + Score Fusion ($0.6/0.4$) | Danh sách Top 20 ứng viên có điểm số lai cao nhất, bàn giao cho Pha 3. | 🛡️ Gate 2: Latency truy vấn < 20ms, Recall@5 ≥ 85%. | ⚡ Nhận tín hiệu: Nhận truy vấn viết lại từ Pha 4 để truy xuất lại khi khách 👎. |
| P3 Pha 3 (0.75d) | Top 20 ứng viên từ Pha 2 + Metadata thực khách (dị ứng, ăn kiêng). |
SpaCy F&B NER (Pre-filter) + Cross-Encoder ms-marco-MiniLM
|
Top 5 món chính xác tuyệt đối nhúng vào SSE Stream trả về cho người dùng. | 🛡️ Gate 3: MRR ≥ 0.82, 0% vi phạm dị ứng / kiêng cữ. | Bàn giao 5 món sang Giao diện Chatbot ở Pha 4. |
| P4 Pha 4 (0.75d) | Món ăn gợi ý của Pha 3 + Nút tương tác Thumbs Up / Down từ thực khách. |
Query Reformulator + Feedback Telemetry Controller
|
Ghi log telemetry vào Redis, tự sinh câu truy vấn phủ định món cũ. | 🛡️ Gate 4: Bấm 👎 trả món mới < 1.2s, bộ nhớ nhớ đủ 10 lượt. | 🔄 Phát tín hiệu: Bắn truy vấn ngược về Bước 2.2 (Pha 2) tức thì! |
| P5 Pha 5 (0.5d) | Toàn bộ pipeline RAG tích hợp hoàn chỉnh (Pha 1 đến Pha 4). | LLM-as-a-Judge (100 Golden Tests) + Docker Compose + Cân bằng A/B | Cụm 3 container microservices chạy Production ổn định, tài liệu API. | 🏆 Gate 5: Production Ready, Precision@5 ≥ 90.0%, zero downtime. | ✅ Đích đến hoàn tất toàn bộ lộ trình. |
Pha 1: Chuẩn Hóa Schema CSDL & Bộ Tuần Tự Hóa Hàng (Row-Level Serializer)
Thời gian: 0.5 ngày (~4 giờ) • Trọng tâm: Bền vững dữ liệu & Schema quan hệChuẩn bị nền tảng lưu trữ bền vững cho biểu diễn vector và văn bản tuần tự hóa, kích hoạt khả năng tìm kiếm vector lân cận ngay trong CSDL quan hệ chính mà không làm xáo trộn cấu trúc dữ liệu hiện hành.
Tạo script migration database/migrations/20260912_add_rag_vector_columns.sql: Kích hoạt extension pgvector, bổ sung cột embedding vector(768), các trường row_serialized TEXT, dietary_tags TEXT[], và khởi tạo chỉ mục HNSW CREATE INDEX idx_menu_hnsw ON menu_items USING hnsw (embedding vector_cosine_ops).
menu_items, restaurant_policies, extension pgvector và chỉ mục idx_menu_hnsw.
Chạy supabase db push thành công không cảnh báo; truy vấn SELECT * FROM menu_items LIMIT 1 trả về đầy đủ các trường mới; chỉ mục HNSW hiển thị trạng thái hợp lệ trong Postgres Catalog.
Chuyển đổi dữ liệu bảng nhiều cột (tên, danh mục, giá, dị ứng, calo, độ cay) thành chuỗi văn bản có cấu trúc chuẩn theo Paper 01 Mục 3.1.2, giúp mô hình Embedding và BM25 hiểu trọn vẹn ngữ nghĩa của từng thuộc tính trong món ăn.
Tạo module ai-service/processors/row_serializer.py: Cung cấp 2 hàm chính serialize_menu_row(item: dict) -> str và serialize_restaurant_policy(policy: dict) -> str. Format chuẩn: Giữ toàn bộ thuộc tính quan hệ (Tên, Danh mục, Giá tiền, Calo, Cảnh báo dị ứng, Thành phần, Cấp độ cay) thành văn bản chuẩn cấu trúc theo Paper 01 Mục 3.1.2.
row_serialized.
Chạy pytest tests/test_row_serializer.py -v vượt qua 100% test cases; chuỗi serialized chứa đầy đủ tên cột và giá trị tương ứng mà không bị null gãy.
Tự động hóa quá trình nạp và chuyển đổi toàn bộ kho dữ liệu thực đơn hiện có sang định dạng văn bản tuần tự hóa, đồng thời điền dữ liệu vào cột row_serialized phục vụ cho việc tạo chỉ mục kép.
Tạo script ai-service/scripts/seed_structured_corpus.py: Quét toàn bộ bảng menu_items và restaurant_policies từ Supabase, tuần tự hóa từng hàng và lưu ngược vào cột row_serialized theo lô (batch of 50).
menu_items và restaurant_policies trên Supabase Database.
Thực thi script hoàn tất; kiểm tra SELECT COUNT(*) FROM menu_items WHERE row_serialized IS NULL cho kết quả bằng đúng 0.
Pha 2: Lõi Hybrid Retrieval (FAISS HNSW Index + BM25 Okapi + Score Fusion)
Thời gian: 1.0 ngày (~8 giờ) • Trọng tâm: Tốc độ truy vấn & Độ bao phủ ngữ nghĩaXây dựng kho chỉ mục kép (Dual-Index) lưu trữ trong RAM của microservice Python, bao gồm vector index (FAISS HNSW) cho ngữ nghĩa và inverted index (BM25 Okapi) cho từ khóa chính xác, đảm bảo độ trễ truy xuất < 10ms.
Thêm vào ai-service/requirements.txt: faiss-cpu>=1.8.0, rank-bm25>=0.2.2, sentence-transformers>=3.0.0. Khởi tạo FAISS HNSW index với tham số tối ưu từ Paper 01: $M=32$, $efConstruction=200$, $efSearch=50$, token hóa tiếng Việt cho kho từ khóa BM25.
ai-service, đối tượng chỉ mục faiss.IndexHNSWFlat và mô hình rank_bm25.BM25Okapi.Build thành công container AI-Service; load thử 1,000 vector mẫu vào FAISS và truy vấn nearest neighbors trong thời gian < 5ms.
Hợp nhất điểm số giữa hai không gian tìm kiếm khác biệt (khoảng cách vector Cosine và điểm tần suất từ khóa BM25) theo công thức chuẩn hóa Min-Max của Paper 01 Mục 3.4, giúp loại bỏ thiên vị điểm số và tìm ra top 20 ứng viên cân bằng nhất.
Tạo file ai-service/processors/hybrid_retriever.py: Tải mô hình embedding BAAI/bge-m3 / all-mpnet-base-v2. Áp dụng công thức chuẩn hóa điểm số Min-Max cho cả Dense và BM25 về thang $[0, 1]$, sau đó kết hợp theo tỷ lệ tối ưu của Paper 01: $Score = 0.6 \times Dense + 0.4 \times BM25$.
HybridMenuRetriever), thuật toán Min-Max Score Normalization, danh sách ứng viên Top 20 CandidateRow.Truy vấn test với cả từ khóa chính xác (vd: "Phở Bò Tái Lăn") và từ khóa ngữ nghĩa (vd: "món giải ngấy thanh mát") đều trả về đúng ứng viên trong Top 10 với điểm combined > 0.75.
Đóng gói toàn bộ logic truy xuất thành một API RESTful độc lập, có tài liệu OpenAPI Swagger rõ ràng, cho phép kiểm thử độc lập và tách rời tầng truy xuất khỏi tầng sinh ngôn ngữ LLM.
Thêm endpoint POST /rag/retrieve trong ai-service/main.py nhận query và tham số filter, trả về Top 20 ứng viên kèm chi tiết breakdown điểm số (Dense Score, BM25 Score, Combined Score) để phục vụ debug và liên kết Gateway.
POST /rag/retrieve), hợp đồng dữ liệu request/response RetrieveRequest/RetrieveResponse.
Test bằng cURL hoặc Swagger UI (/docs) trả về mã HTTP 200 trong < 20ms; JSON trả về chứa đầy đủ danh sách 20 món và điểm số rõ ràng.
Pha 3: Metadata Pre-Filtering (SpaCy NER) & Cross-Encoder Contextual Reranking
Thời gian: 0.75 ngày (~6 giờ) • Trọng tâm: Tinh lọc vi phạm & Tái xếp hạng chính xácTách bạch các thực thể đặc thù ngành nhà hàng (thành phần gây dị ứng, giới hạn ngân sách, chế độ ăn chay/kiêng, phong cách món) từ câu hỏi người dùng để phục vụ lọc cứng (Metadata Hard-Filtering) trước khi xếp hạng, đảm bảo an toàn tuyệt đối cho thực khách.
Tạo module ai-service/processors/metadata_filter.py: Xây dựng CulinaryEntityExtractor kết hợp MetadataFilter định nghĩa danh mục thực thể F&B: ALLERGEN (tôm, cua, đậu phộng, trứng, sữa...), DIET_RESTRICTION (chay, vegan, không gluten...), SPICE_LEVEL (không cay, cay nhẹ...), BUDGET (số tiền tối đa). Tự động nới rộng độ sâu truy xuất ứng viên và loại trừ 100% món vi phạm trước khi xếp hạng.
raw_user_query), từ điển thực thể ẩm thực tùy chỉnh, và bộ lọc thuộc tính metadata (dietary_tags, price_range, spicy_level).Bộ 50 câu hỏi thử nghiệm chứa dị ứng (vd: "không ăn được hải sản", "dị ứng lạc") lọc chính xác 100% món chứa thành phần tương ứng khỏi danh sách gợi ý.
So sánh sâu ngữ cảnh giữa toàn bộ câu hỏi và thông tin chi tiết từng món ăn bằng mô hình Cross-Encoder để loại bỏ các ứng viên sai lệch ngữ nghĩa mà tầng truy xuất thô mang về, chọn ra Top 5 món chuẩn xác nhất theo đúng Paper 01 Mục 3.5.
Tạo module ai-service/processors/cross_encoder_reranker.py: Tải mô hình cross-encoder/ms-marco-MiniLM-L-12-v2. Hàm rerank(query, candidates, top_k=5) chấm điểm tương quan trực tiếp giữa câu hỏi và đoạn tóm tắt hàng món ăn để chọn lọc ra 5 món chính xác nhất. Tối ưu suy luận chạy trong < 25ms.
candidate_items), mô hình ngôn ngữ cross-encoder/ms-marco-MiniLM-L-12-v2, và trọng số xếp hạng ngữ cảnh cuối cùng.Chỉ số MRR trên tập dữ liệu kiểm thử nội bộ đạt ≥ 0.82; thời gian suy luận cho 20 ứng viên đạt < 25ms trên máy chủ CPU tiêu chuẩn.
Ràng buộc mô hình LLM (Gemini 1.5 Flash) chỉ được phép trả lời dựa trên thông tin món ăn thực tế được trích xuất (Grounded Generation), triệt tiêu hoàn toàn hiện tượng bịa đặt giá cả hoặc món không có trong thực đơn.
Cập nhật ai-service/pipelines/aria_pipeline.py: Kết nối chuỗi xử lý hoàn chỉnh: User Query $\rightarrow$ SpaCy Pre-filter $\rightarrow$ Hybrid Retrieval Top 20 $\rightarrow$ Cross-Encoder Top 5 $\rightarrow$ Grounded Prompting Template $\rightarrow$ Groq LLM SSE Stream.
system_prompt & context_block), luồng hội thoại của trợ lý ảo Aria (aria_pipeline.py) và câu trả lời hoàn thiện gửi tới thực khách.Kiểm tra end-to-end qua SSE Stream: Câu trả lời đầu tiên xuất hiện sau < 400ms (TTFT); phản hồi chứa đúng thông tin thực đơn kèm trích dẫn giá và calo.
Pha 4: Bộ Nhớ Hội Thoại 10 Lượt, UI Thumbs Feedback & Tinh Chỉnh Truy Vấn Động
Thời gian: 0.75 ngày (~6 giờ) • Trọng tâm: Tương tác người dùng & Tự thích ứng thời gian thựcTự động bổ sung ngữ cảnh từ lịch sử hội thoại nhiều lượt vào các câu hỏi ngắn hoặc câu hỏi rút gọn của người dùng (ví dụ: 'Món này có cay không?', 'Đổi sang món dưới 100k'), biến chúng thành câu truy vấn đầy đủ nghĩa để RAG tìm kiếm chính xác.
Tạo module ai-service/processors/query_reformulator.py: Cung cấp 2 cơ chế thích ứng của Paper 01: (1) Ambiguous Query Rewriting: Làm rõ câu hỏi mơ hồ ("uống gì ngon?" $\rightarrow$ "đồ uống thanh nhiệt, nước ép trái cây tươi, trà đào cam sả"); (2) Negative Feedback Expansion: Khi khách bấm 👎, trích xuất lịch sử 10 lượt hội thoại gần nhất và diễn đạt lại truy vấn với các thuộc tính thay thế để truy xuất lại danh sách món mới.
chat_history), câu hỏi rút gọn của thực khách, và câu truy vấn độc lập được tái cấu trúc (standalone_search_query).Test thử với 20 câu hỏi mơ hồ: 100% câu hỏi được viết lại rõ ràng, bổ sung danh từ món cụ thể; khi kích hoạt Negative Feedback, danh sách món trả về mới khác ít nhất 80% so với danh sách cũ bị từ chối.
Thu thập và lưu vết dữ liệu phản hồi đánh giá của người dùng cùng bối cảnh truy xuất (câu hỏi, ngữ cảnh món ăn trả về, điểm đánh giá), tạo nguồn dữ liệu vàng cho việc tinh chỉnh trọng số $\alpha$ và đánh giá chất lượng hệ thống liên tục.
Tạo controller backend/src/controllers/feedbackController.js và endpoint POST /api/chat/feedback: Lưu vết phản hồi (thumbs_up / thumbs_down) vào Redis và Supabase bảng chat_feedbacks kèm query, context_ids và thời gian phản hồi.
chat_feedbacks, API endpoint POST /api/chat/feedback, và luồng ghi nhận metric trong Redis.
Gọi POST feedback qua Postman; bản ghi xuất hiện ngay trong Redis key session:feedback:{id} và được sync vào PostgreSQL trong < 50ms.
Cung cấp giao diện tương tác trực quan, thân thiện cho phép thực khách dễ dàng bày tỏ sự hài lòng hoặc không hài lòng đối với từng câu trả lời gợi ý món ăn của trợ lý ảo, kích hoạt quy trình tìm món thay thế ngay lập tức.
Cập nhật frontend/src/components/AriaChatWidget.jsx: Thêm cặp nút tương tác 👍 và 👎 dưới mỗi câu trả lời của trợ lý Aria. Khi khách nhấn 👎, hiển thị thông báo nhẹ nhàng: "Aria đang tìm món khác phù hợp hơn với bạn..." và kích hoạt event tự động tìm kiếm lại mà khách không cần nhập lại câu hỏi.
AriaChatWidget.jsx), thanh nút đánh giá (Thumbs Up / Thumbs Down button strip), và trạng thái tương tác của thực khách trên màn hình di động.Kiểm thử trên trình duyệt di động: Nhấn 👍 đổi màu xanh; nhấn 👎 kích hoạt spinner và nhận danh sách món mới thay thế sau < 1.2s.
Pha 5: Kiểm Thử Tự Động Với LLM-as-a-Judge & Đóng Gói Triển Khai Production
Thời gian: 0.5 ngày (~4 giờ) • Trọng tâm: Đánh giá khoa học & Vận hành ổn địnhTự động hóa việc chấm điểm và thẩm định chất lượng câu trả lời RAG dựa trên 3 tiêu chí khoa học (Độ tin cậy ngữ cảnh - Faithfulness, Mức độ phù hợp câu trả lời - Answer Relevance, Mức độ chính xác thông tin bảng - Table Precision) theo Mục 4 Paper 01, loại bỏ đánh giá cảm tính chủ quan.
Tạo script thẩm định ai-service/evaluation/run_eval.py: Sử dụng bộ 100 câu hỏi test đại diện cho 5 nhóm khách hàng (Gia đình, Dân văn phòng, Người kiêng khem, Khách nhậu, Cặp đôi). Đánh giá tự động qua mô hình thẩm phán LLM-as-a-Judge trích xuất JSON: Faithfulness, Relevance, Completeness.
golden_benchmark_dataset), script đánh giá tự động run_eval.py, và file báo cáo chất lượng RAG report_eval.json.
Báo cáo report_eval.json được sinh ra tự động; không có bất kỳ câu trả lời nào vi phạm dị ứng hoặc sai giá tiền.
Đóng gói toàn bộ kiến trúc thành các container đồng bộ, thiết lập mạng nội bộ bảo mật cao và kích hoạt cơ chế phân luồng A/B Testing để so sánh trực tiếp hiệu quả giữa thuật toán cũ và hệ thống Advancing RAG mới trên môi trường thực tế.
Cập nhật docker-compose.yml: Đóng gói service ai-service chạy cùng Node.js Gateway và Redis. Cấu hình phân luồng A/B testing 50/50 tại Gateway để theo dõi tỷ lệ chuyển đổi thực tế (tỷ lệ nhấn "Thêm vào giỏ hàng") của thực khách.
docker-compose.yml, 3 container dịch vụ (backend, ai-service, redis), và cơ chế phân phối tải (Traffic Router 50/50).
Lệnh docker compose up -d khởi chạy cả 3 container khỏe mạnh (healthy); hệ thống phân phối request trơn tru không lỗi kết nối.
6. Ma Trận Đánh Đổi Kiến Trúc & Quyết Định Kỹ Thuật (Architecture Tradeoffs)
Cân Bằng Giữa Độ Phức Tạp Kỹ Thuật, Chi Phí Vận Hành & Độ Chính Xác
Mọi quyết định kiến trúc trong hệ thống RAG doanh nghiệp đều là một sự đánh đổi có tính toán (Tradeoff). Không có giải pháp hoàn hảo tuyệt đối, chỉ có giải pháp phù hợp nhất với ràng buộc tài nguyên, ngân sách và yêu cầu nghiệp vụ của SmartRestaurant.
Bảng Quản Trị Rủi Ro Kỹ Thuật Khi Vận Hành Kiến Trúc Advancing RAG (Paper 01)
Nhận diện trước 4 thách thức kỹ thuật nội tại của kiến trúc Advancing RAG và phương án hóa giải chuẩn Paper 01
| Rủi Ro Kỹ Thuật Của Advancing RAG | Mức Độ | Hậu Quả Tiềm Ẩn | Giải Pháp Giảm Thiểu (Paper 01 Guidelines) |
|---|---|---|---|
| 1. Độ trễ gia tăng do mô hình Cross-Encoder | Trung bình | Thời gian trả lời câu hỏi đầu tiên (TTFT) có thể vượt quá 1.5 giây nếu suy luận Cross-Encoder trên CPU chậm. |
Sử dụng mô hình lượng tử hóa nhẹ ms-marco-MiniLM-L-12-v2 (hoặc ONNX Runtime). Chỉ tái xếp hạng cho Top 15-20 ứng viên thay vì toàn bộ kho ngữ liệu.
|
| 2. Lập chỉ mục tĩnh & Trễ đồng bộ menu | Thấp | Khi nhà hàng cập nhật món mới hoặc đổi giá, chỉ mục FAISS chưa kịp cập nhật ngay lập tức. |
Tích hợp Webhook Invalidation từ Supabase: Khi bảng menu_items thay đổi, kích hoạt API cập nhật chỉ mục vi mô gia tăng (Incremental Index Update) vào FAISS.
|
| 3. Quá tải bộ nhớ RAM khi mở rộng nhiều chi nhánh | Trung bình | Lưu nhiều chỉ mục FAISS đồng thời trong RAM microservice có thể làm tràn bộ nhớ (OOM). |
Áp dụng kiến trúc Chỉ Mục Kép (Dual-Index Optimization - Mục 3.8): Phân vùng index theo restaurant_id; nạp lười (Lazy-load) từ đĩa và giải phóng các menu chi nhánh ít truy cập.
|
| 4. Người dùng không chủ động bấm nút Thumbs 👍/👎 | Thấp | Cơ chế tự điều chỉnh thiếu dữ liệu phản hồi từ thực khách. | Bổ sung tín hiệu thụ động ngầm định (Implicit Signals - Mục 6.1): Nếu khách hàng nhấn "Xem chi tiết món", "Thêm vào giỏ hàng" coi như Tích cực (+1); nếu khách yêu cầu lặp lại câu hỏi coi như Tiêu cực (-1). |
Phân Tích Đánh Đổi Kiến Trúc: Hiện Trạng Ban Đầu vs. Advancing RAG vs. Các Phương Án Khác
Naive Keyword 2-Stage Filter
Hệ thống hiện hành của SmartRestaurant: Dùng câu lệnh SQL WHERE LIKE/ILIKE kết hợp lọc category thô tại Node.js backend, nhồi danh sách món thô vào Prompt LLM để sinh câu trả lời.
Cực kỳ đơn giản, không cần microservice Python, 0 tốn thêm RAM máy chủ, tận dụng 100% mã nguồn backend Node.js có sẵn.
Ảo giác (Hallucination) nặng nề; mù ngữ nghĩa tương đồng ("thanh mát", "món ăn giải ngấy"); dễ bỏ sót món khi sai chính tả; thất bại hoàn toàn với lọc dị ứng khắt khe.
Advancing Hybrid RAG Service
Xây dựng microservice riêng bằng FastAPI tích hợp Dual-Index (FAISS HNSW ngữ nghĩa + BM25 Okapi từ khóa) kết hợp Row Serializer, SpaCy NER, Cross-Encoder và Feedback Loop.
Độ chính xác dữ liệu bảng cao nhất (MRR ≥ 0.82); triệt tiêu 100% rủi ro dị ứng món ăn; tốc độ truy xuất nội bộ < 30ms; 0 đồng phí SaaS; bảo mật nội bộ.
Cần duy trì thêm 1 container Python (~800MB RAM); đòi hỏi pipeline tuần tự hóa hàng và webhook cập nhật chỉ mục khi đổi menu.
Pure Supabase pgvector
Lưu trữ vector trực tiếp trong PostgreSQL (extension pgvector), dùng RPC SQL để tính cosine similarity, không dựng Python service hay Cross-Encoder.
Hạ tầng siêu tinh gọn, 0 thêm container, không lo lệch pha dữ liệu giữa DB và Cache bộ nhớ.
Thiếu BM25 Okapi nguyên bản để bắt từ khóa chính xác; không có Cross-Encoder reranker; tải tính toán vector ảnh hưởng DB giao dịch chính.
Managed Vector DB (Pinecone/Qdrant)
Ủy thác toàn bộ việc lưu trữ vector và tìm kiếm lân cận cho các dịch vụ đám mây chuyên dụng bên thứ ba (Pinecone Serverless, Qdrant Cloud).
Mở rộng quy mô tự động, không tốn RAM máy chủ nhà hàng, có giao diện dashboard giám sát chỉ mục trực quan.
Chi phí định kỳ hàng tháng (\$70-\$200/tháng); trễ mạng internet tăng thêm 80-150ms/truy vấn; dữ liệu món ăn bị gửi ra ngoài hạ tầng nội bộ.
SmartRestaurant Chọn Lựa Chọn Nào? Tại Sao Rời Bỏ Hiện Trạng Ban Đầu?
Quyết định kỹ thuật chiến lược được phê chuẩn dựa trên mục tiêu thực tế của nhà hàng
Dự án chính thức loại bỏ Hiện Trạng Ban Đầu (Naive Keyword Filter) và phê chuẩn Phương án Advancing Hybrid RAG (FAISS HNSW + BM25 + Cross-Encoder) theo chuẩn Paper 01. Chúng tôi chấp nhận đánh đổi việc phải duy trì thêm 1 microservice Python và ~800MB RAM để đổi lấy 4 giá trị then chốt không thể thay thế:
Hệ thống ban đầu thường xuyên gợi ý sai món khi khách có dị ứng nguy hiểm (ví dụ: dị ứng đậu phộng nhưng vẫn gợi ý món sốt sa tế đậu phộng). Advancing RAG với SpaCy NER và Grounded Generation triệt tiêu 100% rủi ro này.
FAISS và Cross-Encoder chạy trong mạng nội bộ (Local Docker Network) chỉ mất < 30ms cho khâu truy xuất, không chịu thêm 80-150ms trễ mạng internet như giải pháp Cloud SaaS (Pinecone/Qdrant).
FAISS và Rank-BM25 là thư viện mã nguồn mở tự host hoàn toàn miễn phí. Nhà hàng không bị ràng buộc hóa đơn hàng tháng (\$70-\$200/tháng) hay nguy cơ đội chi phí khi lượng khách đặt món tăng vọt.
Toàn bộ dữ liệu menu, thành phần dinh dưỡng và giá vốn của nhà hàng được lưu trữ và lập chỉ mục khép kín trong cụm máy chủ SmartRestaurant, không gửi sang bất kỳ bên thứ 3 nào, bảo vệ bí mật kinh doanh chuỗi nhà hàng.