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

AspectRAG Truyền ThốngAgentic RAG
FlowPipeline cố địnhAgent tự quyết
Đánh giáKhôngTự đánh giá kết quả
Self-correctionKhôngCó, tự retry
Multi-source1 vector DBNhiều sources, tools
Phức tạpThấpCao

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

  1. Đặt ngưỡng similarity phù hợp — quá cao (>0.9) bỏ lỡ kết quả, quá thấp (<0.5) trả rác
  2. Giới hạn vòng lặp — maxSteps 5-8 là hợp lý, tránh infinite loops
  3. Log mọi bước — observability là chìa khoá debug Agentic RAG
  4. 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