Agentic RAG
Kết hợp Retrieval-Augmented Generation với Agent — tự tìm, tự đánh giá, tự sửa
RAG Thường vs Agentic RAG
RAG Truyền Thống
User query → Embed → Search vector DB → Return top-K → Generate answer
Pipeline cố định, không có khả năng tự đánh giá kết quả.
Agentic RAG
User query → Agent phân tích → Chọn chiến lược tìm kiếm
→ Tìm kiếm → Đánh giá kết quả
→ Không đủ? → Thay đổi query → Tìm lại
→ Đủ tốt? → Generate answer
Agent tự quyết định cách tiếp cận, đánh giá kết quả, và tự sửa khi cần.
Sự Khác Biệt Chính
| Aspect | RAG Truyền Thống | Agentic RAG |
|---|---|---|
| Flow | Pipeline cố định | Agent tự quyết |
| Đánh giá | Không | Tự đánh giá kết quả |
| Self-correction | Không | Có, tự retry |
| Multi-source | 1 vector DB | Nhiều sources, tools |
| Phức tạp | Thấp | Cao |
Xây Dựng Agentic RAG Với Supabase pgvector
Bước 1: Setup Vector Store
-- Trong Supabase SQL Editor
create extension if not exists vector;
create table documents (
id bigserial primary key,
content text,
metadata jsonb,
embedding vector(1536) -- OpenAI text-embedding-3-small
);
create index on documents
using ivfflat (embedding vector_cosine_ops)
with (lists = 100);
-- Function tìm kiếm semantic
create or replace function match_documents(
query_embedding vector(1536),
match_threshold float default 0.7,
match_count int default 5
) returns table (
id bigint,
content text,
metadata jsonb,
similarity float
) language plpgsql as $$
begin
return query
select
d.id, d.content, d.metadata,
1 - (d.embedding <=> query_embedding) as similarity
from documents d
where 1 - (d.embedding <=> query_embedding) > match_threshold
order by d.embedding <=> query_embedding
limit match_count;
end;
$$;
Bước 2: Embedding & Retrieval Agent
import { generateText, tool } from "ai";
import { openai } from "@ai-sdk/openai";
import { createClient } from "@supabase/supabase-js";
import { z } from "zod";
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_KEY!
);
// Tool tìm kiếm semantic
const searchDocuments = tool({
description: "Tìm kiếm tài liệu liên quan trong knowledge base",
parameters: z.object({
query: z.string().describe("Câu hỏi hoặc chủ đề cần tìm"),
threshold: z.number().default(0.7).describe("Ngưỡng similarity (0-1)")
}),
execute: async ({ query, threshold }) => {
// 1. Tạo embedding cho query
const embeddingResponse = await openai.embeddings.create({
model: "text-embedding-3-small",
input: query
});
const queryEmbedding = embeddingResponse.data[0].embedding;
// 2. Tìm kiếm trong Supabase
const { data, error } = await supabase.rpc("match_documents", {
query_embedding: queryEmbedding,
match_threshold: threshold,
match_count: 5
});
if (error) return { success: false, error: error.message };
return { success: true, documents: data };
}
});
// Tool refine query khi kết quả không tốt
const refineSearch = tool({
description: "Tìm kiếm lại với query được điều chỉnh khi kết quả ban đầu không đủ tốt",
parameters: z.object({
originalQuery: z.string(),
refinedQuery: z.string(),
reason: z.string().describe("Lý do cần refine")
}),
execute: async ({ refinedQuery }) => {
// Tương tự searchDocuments nhưng với refined query
// ...
return { success: true, documents: [] };
}
});
Bước 3: Agent Loop Tự Đánh Giá
const result = await generateText({
model: openai("gpt-4o"),
system: `Bạn là trợ lý tìm kiếm thông minh. Quy trình:
1. Tìm kiếm tài liệu liên quan
2. Đánh giá chất lượng kết quả (relevance, completeness)
3. Nếu kết quả chưa đủ tốt, refine query và tìm lại
4. Chỉ trả lời khi có đủ thông tin đáng tin cậy
5. Nếu không tìm được, nói thẳng là không biết`,
tools: { searchDocuments, refineSearch },
maxSteps: 8, // Cho phép nhiều vòng tìm kiếm
prompt: userQuestion
});
Corrective RAG
Pattern quan trọng: agent tự sửa khi phát hiện vấn đề.
// Agent tự đánh giá và sửa
const evaluateAndCorrect = tool({
description: "Đánh giá kết quả retrieval và quyết định bước tiếp theo",
parameters: z.object({
retrievedDocs: z.array(z.string()),
queryIntent: z.string(),
assessment: z.enum(["sufficient", "partial", "insufficient"]),
nextAction: z.enum(["answer", "refine_query", "try_different_source", "admit_unknown"])
}),
execute: async ({ assessment, nextAction }) => {
return { assessment, nextAction, message: `Đánh giá: ${assessment}. Hành động: ${nextAction}` };
}
});
Self-Correction Flow
Query → Search → Evaluate results
├── Sufficient → Generate answer
├── Partial → Refine query → Search again
├── Insufficient → Try different source
└── Repeatedly failing → Admit unknown
Best Practices
- Đặt ngưỡng similarity phù hợp — quá cao (>0.9) bỏ lỡ kết quả, quá thấp (<0.5) trả rác
- Giới hạn vòng lặp — maxSteps 5-8 là hợp lý, tránh infinite loops
- Log mọi bước — observability là chìa khoá debug Agentic RAG
- Fallback on human — khi agent không chắc chắn, hỏi người dùng
Tổng Kết
- Agentic RAG = RAG + Agent tự quyết, tự đánh giá, tự sửa
- Dùng Supabase pgvector cho vector store
- Corrective RAG pattern: evaluate → refine → retry
- Agent biết khi nào nên dừng và thừa nhận không biết