Nâng caoHướng dẫnClaude APINguồn: Anthropic

Retrieval Agent — Xây dựng Agentic RAG với Claude

Nghe bài viết
00:00

Điểm nổi bật

Nhấn để đến mục tương ứng

  1. 1 Agentic RAG giải quyết tất cả vấn đề này bằng cách biến quá trình retrieval thành một vòng lặp agent — nơi Claude tự quyết định cần tìm gì, từ đâu, và liệu kết quả đã đủ tốt chưa.
  2. 2 Bước 1: Định nghĩa retrieval tools // src/tools.ts import Anthropic from "@anthropic-ai/sdk"; export const retrievalTools: Anthropic.Messages.Tool[] = [ { name: "vector_search", description: "Tim kiem tai lieu theo ngu nghia (semantic search).
  3. 3 Mục tiêu: trên 80% Precision@K: Trong K kết quả trả về, bao nhiêu phần trăm thực sự liên quan?
  4. 4 Quan trọng cho dữ liệu thay đổi theo thời gian Authority (Uy tín): Nguồn thông tin có đáng tin cậy không?
  5. 5 RAG (Retrieval-Augmented Generation) đã trở thành kỹ thuật tiêu chuẩn để cung cấp kiến thức cho AI model.
A close up of a bird made out of paper

RAG (Retrieval-Augmented Generation) đã trở thành kỹ thuật tiêu chuẩn để cung cấp kiến thức cho AI model. Tuy nhiên, RAG truyền thống có nhiều hạn chế: query cố định, một lần truy xuất duy nhất, không đánh giá chất lượng kết quả. Agentic RAG giải quyết tất cả vấn đề này bằng cách biến quá trình retrieval thành một vòng lặp agent — nơi Claude tự quyết định cần tìm gì, từ đâu, và liệu kết quả đã đủ tốt chưa.

Basic RAG vs Agentic RAG

Basic RAG — Quy trình tuyến tính

Trong RAG truyền thống, quy trình diễn ra theo một chiều cố định:

  1. Người dùng đặt câu hỏi
  2. Hệ thống embed câu hỏi thành vector
  3. Tìm kiếm top-K documents gần nhất trong vector database
  4. Đưa documents vào context cho LLM
  5. LLM sinh câu trả lời dựa trên context

Hạn chế của cách tiếp cận này:

  • Một lần truy xuất: Nếu kết quả lần đầu không tốt, không có cơ hội thử lại
  • Query gốc có thể không tối ưu: Câu hỏi của người dùng thường mơ hồ hoặc thiếu context
  • Không đánh giá chất lượng: Hệ thống không biết documents trả về có thực sự liên quan không
  • Một nguồn duy nhất: Chỉ tìm trong một vector store, không thể kết hợp nhiều nguồn

Agentic RAG — Agent quyết định retrieval

Agentic RAG đặt một agent (Claude) vào vị trí điều phối. Agent có quyền:

  • Quyết định có cần retrieval không: Một số câu hỏi Claude đã biết, không cần tìm kiếm
  • Reformulate query: Chuyển câu hỏi mơ hồ thành query chính xác hơn
  • Chọn nguồn tìm kiếm: Vector DB, SQL database, API, web search
  • Đánh giá kết quả: Xem documents có liên quan không, nếu không thì tìm lại
  • Multi-step retrieval: Tìm kiếm nhiều lần với query khác nhau để bổ sung thông tin
  • Synthesize: Tổng hợp từ nhiều nguồn thành câu trả lời chính xác

Kiến trúc Agentic RAG

Kiến trúc Agentic RAG bao gồm ba lớp chính:

// Kien truc tong quan

// Lop 1: Agent Core (Claude)
// - Nhan cau hoi tu nguoi dung
// - Quyet dinh chien luoc retrieval
// - Danh gia ket qua
// - Sinh cau tra loi cuoi cung

// Lop 2: Retrieval Tools
// - Vector search (semantic similarity)
// - Keyword search (BM25, full-text)
// - SQL query (structured data)
// - Web search (real-time information)

// Lop 3: Knowledge Sources
// - Vector DB (Pinecone, Chroma, Qdrant)
// - Relational DB (PostgreSQL)
// - Document store (S3, file system)
// - External APIs

Triển khai với Claude SDK

Dưới đây là triển khai hoàn chỉnh một Retrieval Agent sử dụng Claude SDK với TypeScript.

Bước 1: Định nghĩa retrieval tools

// src/tools.ts
import Anthropic from "@anthropic-ai/sdk";

export const retrievalTools: Anthropic.Messages.Tool[] = [
  {
    name: "vector_search",
    description: "Tim kiem tai lieu theo ngu nghia (semantic search). "
      + "Dung khi can tim tai lieu lien quan den mot chu de "
      + "hoac khai niem. Tra ve cac doan van ban gan nghia nhat "
      + "voi query.",
    input_schema: {
      type: "object",
      properties: {
        query: {
          type: "string",
          description: "Cau truy van tim kiem. "
            + "Nen la cau mo ta chi tiet ve thong tin can tim."
        },
        collection: {
          type: "string",
          enum: ["product_docs", "support_tickets",
                 "knowledge_base", "policies"],
          description: "Bo suu tap tai lieu can tim."
        },
        top_k: {
          type: "number",
          description: "So luong ket qua toi da (mac dinh 5)."
        },
        min_score: {
          type: "number",
          description: "Diem tuong dong toi thieu (0-1, mac dinh 0.7)."
        }
      },
      required: ["query", "collection"]
    }
  },
  {
    name: "keyword_search",
    description: "Tim kiem theo tu khoa chinh xac (full-text search). "
      + "Dung khi can tim tai lieu chua tu khoa cu the "
      + "nhu ma san pham, ten rieng, thuat ngu chuyen mon.",
    input_schema: {
      type: "object",
      properties: {
        keywords: {
          type: "string",
          description: "Tu khoa tim kiem, cach nhau boi dau cach."
        },
        collection: {
          type: "string",
          enum: ["product_docs", "support_tickets",
                 "knowledge_base", "policies"]
        },
        exact_match: {
          type: "boolean",
          description: "Tim chinh xac cum tu (mac dinh false)."
        }
      },
      required: ["keywords", "collection"]
    }
  },
  {
    name: "sql_query",
    description: "Truy van du lieu co cau truc tu database. "
      + "Dung khi can thong tin so lieu, thong ke, "
      + "hoac du lieu bang bieu.",
    input_schema: {
      type: "object",
      properties: {
        question: {
          type: "string",
          description: "Cau hoi bang ngon ngu tu nhien "
            + "ve du lieu can truy van."
        },
        tables: {
          type: "array",
          items: { type: "string" },
          description: "Danh sach bang lien quan."
        }
      },
      required: ["question"]
    }
  },
  {
    name: "evaluate_sources",
    description: "Danh gia chat luong va do tin cay cua cac "
      + "nguon thong tin da thu thap. Goi sau khi da co "
      + "ket qua tu cac tool tim kiem khac.",
    input_schema: {
      type: "object",
      properties: {
        sources: {
          type: "array",
          items: {
            type: "object",
            properties: {
              content: { type: "string" },
              source_id: { type: "string" },
              relevance_score: { type: "number" }
            }
          },
          description: "Danh sach nguon thong tin can danh gia."
        },
        original_question: {
          type: "string",
          description: "Cau hoi goc cua nguoi dung."
        }
      },
      required: ["sources", "original_question"]
    }
  }
];

Bước 2: Implement tool handlers

// src/handlers.ts
import { ChromaClient } from "chromadb";
import { Pool } from "pg";

const chroma = new ChromaClient({ path: "http://localhost:8000" });
const pgPool = new Pool({
  connectionString: process.env.DATABASE_URL
});

export async function handleToolCall(
  name: string, input: any
): Promise<string> {
  switch (name) {
    case "vector_search":
      return await vectorSearch(input);
    case "keyword_search":
      return await keywordSearch(input);
    case "sql_query":
      return await sqlQuery(input);
    case "evaluate_sources":
      return await evaluateSources(input);
    default:
      throw new Error("Unknown tool: " + name);
  }
}

async function vectorSearch(input: {
  query: string;
  collection: string;
  top_k?: number;
  min_score?: number;
}): Promise<string> {
  const { query, collection, top_k = 5, min_score = 0.7 } = input;

  const col = await chroma.getCollection({ name: collection });
  const results = await col.query({
    queryTexts: [query],
    nResults: top_k,
  });

  // Loc theo min_score
  const filtered = [];
  for (let i = 0; i < (results.ids[0]?.length || 0); i++) {
    const distance = results.distances?.[0]?.[i] || 1;
    const score = 1 - distance; // Chuyen distance thanh similarity
    if (score >= min_score) {
      filtered.push({
        id: results.ids[0][i],
        content: results.documents[0]?.[i] || "",
        metadata: results.metadatas?.[0]?.[i] || {},
        relevance_score: Math.round(score * 100) / 100,
      });
    }
  }

  return JSON.stringify({
    total_found: filtered.length,
    query: query,
    results: filtered,
  });
}

async function keywordSearch(input: {
  keywords: string;
  collection: string;
  exact_match?: boolean;
}): Promise<string> {
  const { keywords, collection, exact_match = false } = input;

  // Su dung PostgreSQL full-text search
  const searchQuery = exact_match
    ? "SELECT id, content, metadata, "
      + "ts_rank(search_vector, phraseto_tsquery($1)) as rank "
      + "FROM " + collection + " "
      + "WHERE search_vector @@ phraseto_tsquery($1) "
      + "ORDER BY rank DESC LIMIT 10"
    : "SELECT id, content, metadata, "
      + "ts_rank(search_vector, plainto_tsquery($1)) as rank "
      + "FROM " + collection + " "
      + "WHERE search_vector @@ plainto_tsquery($1) "
      + "ORDER BY rank DESC LIMIT 10";

  const result = await pgPool.query(searchQuery, [keywords]);

  return JSON.stringify({
    total_found: result.rows.length,
    keywords: keywords,
    results: result.rows.map(row => ({
      id: row.id,
      content: row.content,
      metadata: row.metadata,
      relevance_score: Math.round(row.rank * 100) / 100,
    })),
  });
}

async function sqlQuery(input: {
  question: string;
  tables?: string[];
}): Promise<string> {
  // Trong production, su dung text-to-SQL model
  // hoac predefined queries de dam bao an toan
  const safeQueries: Record<string, string> = {
    "don hang": "SELECT * FROM orders ORDER BY created_at DESC LIMIT 20",
    "san pham ban chay": "SELECT p.name, SUM(oi.quantity) as total_sold "
      + "FROM order_items oi JOIN products p ON oi.product_id = p.id "
      + "GROUP BY p.id, p.name ORDER BY total_sold DESC LIMIT 10",
    "doanh thu": "SELECT DATE_TRUNC('month', created_at) as month, "
      + "SUM(total_amount) as revenue "
      + "FROM orders WHERE status = 'completed' "
      + "GROUP BY month ORDER BY month DESC LIMIT 12",
  };

  // Tim query phu hop nhat
  const question = input.question.toLowerCase();
  let matchedQuery = null;
  for (const [key, sql] of Object.entries(safeQueries)) {
    if (question.includes(key)) {
      matchedQuery = sql;
      break;
    }
  }

  if (!matchedQuery) {
    return JSON.stringify({
      error: "Khong tim thay query phu hop. "
        + "Cac loai truy van ho tro: don hang, "
        + "san pham ban chay, doanh thu.",
    });
  }

  const result = await pgPool.query(matchedQuery);
  return JSON.stringify({
    question: input.question,
    row_count: result.rows.length,
    data: result.rows,
  });
}

async function evaluateSources(input: {
  sources: Array<{
    content: string;
    source_id: string;
    relevance_score: number;
  }>;
  original_question: string;
}): Promise<string> {
  const evaluation = input.sources.map(source => {
    const hasContent = source.content.length > 50;
    const isRelevant = source.relevance_score >= 0.7;

    return {
      source_id: source.source_id,
      relevance_score: source.relevance_score,
      has_sufficient_content: hasContent,
      is_relevant: isRelevant,
      recommendation: isRelevant && hasContent
        ? "USE" : isRelevant
        ? "SUPPLEMENT" : "DISCARD",
    };
  });

  const usableSources = evaluation.filter(
    e => e.recommendation !== "DISCARD"
  );

  return JSON.stringify({
    total_evaluated: evaluation.length,
    usable_sources: usableSources.length,
    needs_more_search: usableSources.length < 2,
    evaluation: evaluation,
  });
}

Bước 3: Agentic loop

// src/agent.ts
import Anthropic from "@anthropic-ai/sdk";
import { retrievalTools } from "./tools.js";
import { handleToolCall } from "./handlers.js";

const client = new Anthropic();

const SYSTEM_PROMPT = "Ban la mot Retrieval Agent thong minh. "
  + "Nhiem vu cua ban la tra loi cau hoi cua nguoi dung "
  + "bang cach tim kiem va tong hop thong tin tu nhieu nguon.\n\n"
  + "Quy trinh lam viec:\n"
  + "1. Phan tich cau hoi - xac dinh thong tin can tim\n"
  + "2. Chon chien luoc tim kiem phu hop:\n"
  + "   - vector_search cho cau hoi ve khai niem, chu de\n"
  + "   - keyword_search cho tu khoa cu the, ma san pham\n"
  + "   - sql_query cho so lieu, thong ke\n"
  + "3. Danh gia ket qua - goi evaluate_sources\n"
  + "4. Neu ket qua chua du, reformulate query va tim lai\n"
  + "5. Tong hop cau tra loi cuoi cung voi trich dan nguon\n\n"
  + "Nguyen tac:\n"
  + "- Luon trich dan nguon thong tin\n"
  + "- Neu khong tim thay thong tin, noi ro rang\n"
  + "- Khong bao gio dua ra thong tin khong co trong nguon\n"
  + "- Uu tien do chinh xac hon do day du";

export async function askRetrievalAgent(
  question: string
): Promise<string> {
  const messages: Anthropic.Messages.MessageParam[] = [
    { role: "user", content: question },
  ];

  let maxIterations = 10; // Gioi han vong lap agent
  let iteration = 0;

  while (iteration < maxIterations) {
    iteration++;

    const response = await client.messages.create({
      model: "claude-sonnet-4-20250514",
      max_tokens: 4096,
      system: SYSTEM_PROMPT,
      tools: retrievalTools,
      messages: messages,
    });

    // Neu Claude tra loi truc tiep (khong can tool)
    if (response.stop_reason === "end_turn") {
      const textBlocks = response.content.filter(
        b => b.type === "text"
      );
      return textBlocks.map(b => b.text).join("
");
    }

    // Xu ly tool calls
    messages.push({ role: "assistant", content: response.content });

    const toolResults: Anthropic.Messages.ToolResultBlockParam[] = [];

    for (const block of response.content) {
      if (block.type === "tool_use") {
        try {
          const result = await handleToolCall(block.name, block.input);
          toolResults.push({
            type: "tool_result",
            tool_use_id: block.id,
            content: result,
          });
        } catch (error) {
          toolResults.push({
            type: "tool_result",
            tool_use_id: block.id,
            content: "Error: " + (error as Error).message,
            is_error: true,
          });
        }
      }
    }

    messages.push({ role: "user", content: toolResults });
  }

  return "Agent da vuot qua so vong lap toi da "
    + "ma chua tim duoc cau tra loi.";
}

Multi-step Retrieval

Sức mạnh thực sự của Agentic RAG nằm ở khả năng thực hiện nhiều bước retrieval liên tiếp. Agent phân tích câu hỏi phức tạp thành nhiều sub-query và tổng hợp kết quả.

Ví dụ: Câu hỏi đa chiều

Cau hoi: "So sanh doanh thu Q1/2025 voi Q1/2024,
va phan tich nguyen nhan tu feedback khach hang"

Agent se thuc hien:
Buoc 1: sql_query - Lay doanh thu Q1/2025
Buoc 2: sql_query - Lay doanh thu Q1/2024
Buoc 3: vector_search - Tim feedback khach hang
         lien quan den su thay doi doanh thu
Buoc 4: evaluate_sources - Danh gia chat luong thong tin
Buoc 5: (Neu can) keyword_search - Tim them chi tiet
         ve san pham cu the duoc nhac den
Buoc 6: Tong hop bao cao so sanh voi trich dan nguon

Query Reformulation

Khi kết quả tìm kiếm lần đầu không đủ tốt, agent tự động reformulate query để tìm lại. Đây là một trong những lợi thế lớn nhất so với RAG truyền thống.

Các chiến lược reformulation:

  • Expansion: Mở rộng query với các từ đồng nghĩa hoặc liên quan. Ví dụ: "lỗi thanh toán" mở rộng thành "payment error, giao dịch thất bại, không thanh toán được"
  • Decomposition: Tách câu hỏi phức tạp thành nhiều câu hỏi đơn giản
  • Abstraction: Nâng câu hỏi cụ thể lên mức khái quát hơn. Ví dụ: "iPhone 15 Pro Max pin yếu" trở thành "vấn đề pin điện thoại Apple"
  • Specification: Thu hẹp phạm vi tìm kiếm. Ví dụ: "vấn đề giao hàng" thu hẹp thành "giao hàng chậm khu vực TP.HCM tháng 3/2025"

Source Evaluation — Đánh giá nguồn tin

Agent đánh giá chất lượng nguồn thông tin trước khi sử dụng, dựa trên các tiêu chí:

  • Relevance (Liên quan): Tài liệu có thực sự trả lời câu hỏi không? Đo bằng similarity score và keyword overlap
  • Recency (Mới): Thông tin có còn cập nhật không? Quan trọng cho dữ liệu thay đổi theo thời gian
  • Authority (Uy tín): Nguồn thông tin có đáng tin cậy không? Tài liệu chính thức có trọng số cao hơn ghi chú nội bộ
  • Completeness (Đầy đủ): Tài liệu có cung cấp đủ thông tin hay chỉ đề cập một phần?

Vector DB Integration

Agentic RAG hoạt động tốt nhất khi kết hợp với vector database chất lượng. Dưới đây là hướng dẫn tích hợp hai lựa chọn phổ biến.

Pinecone — Managed vector database

// src/vector-stores/pinecone.ts
import { Pinecone } from "@pinecone-database/pinecone";

const pinecone = new Pinecone({
  apiKey: process.env.PINECONE_API_KEY!,
});

export async function searchPinecone(
  query: string,
  namespace: string,
  topK: number = 5
) {
  const index = pinecone.index("knowledge-base");

  // Embed query bang API embedding
  const embedding = await embedText(query);

  const results = await index.namespace(namespace).query({
    vector: embedding,
    topK: topK,
    includeMetadata: true,
    includeValues: false,
  });

  return results.matches?.map(match => ({
    id: match.id,
    score: match.score || 0,
    content: (match.metadata as any)?.content || "",
    source: (match.metadata as any)?.source || "",
    date: (match.metadata as any)?.date || "",
  })) || [];
}

Chroma — Self-hosted vector database

// src/vector-stores/chroma.ts
import { ChromaClient, OpenAIEmbeddingFunction } from "chromadb";

const chroma = new ChromaClient({ path: "http://localhost:8000" });

const embedder = new OpenAIEmbeddingFunction({
  openai_api_key: process.env.OPENAI_API_KEY!,
  openai_model: "text-embedding-3-small",
});

export async function searchChroma(
  query: string,
  collectionName: string,
  topK: number = 5,
  minScore: number = 0.7
) {
  const collection = await chroma.getCollection({
    name: collectionName,
    embeddingFunction: embedder,
  });

  const results = await collection.query({
    queryTexts: [query],
    nResults: topK,
    where: undefined,
  });

  const items = [];
  for (let i = 0; i < (results.ids[0]?.length || 0); i++) {
    const distance = results.distances?.[0]?.[i] || 1;
    const score = 1 - distance;
    if (score >= minScore) {
      items.push({
        id: results.ids[0][i],
        score: Math.round(score * 100) / 100,
        content: results.documents[0]?.[i] || "",
        metadata: results.metadatas?.[0]?.[i] || {},
      });
    }
  }

  return items;
}

Hybrid Search — Kết hợp vector và keyword

Hybrid search kết hợp ưu điểm của cả semantic search (vector) và keyword search (BM25) để cho kết quả tốt hơn.

// src/hybrid-search.ts
export async function hybridSearch(
  query: string,
  collection: string,
  topK: number = 10,
  alpha: number = 0.7 // Trong so cho vector search
): Promise<SearchResult[]> {
  // Chay dong thoi ca hai loai search
  const [vectorResults, keywordResults] = await Promise.all([
    searchChroma(query, collection, topK * 2),
    keywordSearchPg(query, collection, topK * 2),
  ]);

  // Reciprocal Rank Fusion (RRF)
  const scores = new Map<string, number>();
  const contents = new Map<string, any>();
  const k = 60; // RRF constant

  // Tinh diem tu vector results
  vectorResults.forEach((result, rank) => {
    const rrf = alpha * (1 / (k + rank + 1));
    scores.set(result.id, (scores.get(result.id) || 0) + rrf);
    contents.set(result.id, result);
  });

  // Tinh diem tu keyword results
  keywordResults.forEach((result, rank) => {
    const rrf = (1 - alpha) * (1 / (k + rank + 1));
    scores.set(result.id, (scores.get(result.id) || 0) + rrf);
    if (!contents.has(result.id)) {
      contents.set(result.id, result);
    }
  });

  // Sap xep theo diem tong hop
  return Array.from(scores.entries())
    .sort((a, b) => b[1] - a[1])
    .slice(0, topK)
    .map(([id, score]) => ({
      ...contents.get(id),
      hybrid_score: Math.round(score * 1000) / 1000,
    }));
}

Evaluation Metrics

Đánh giá chất lượng Agentic RAG cần đo lường trên nhiều chiều:

Retrieval Metrics

  • Recall@K: Trong K kết quả trả về, bao nhiêu phần trăm tài liệu liên quan được tìm thấy? Mục tiêu: trên 80%
  • Precision@K: Trong K kết quả trả về, bao nhiêu phần trăm thực sự liên quan? Mục tiêu: trên 70%
  • MRR (Mean Reciprocal Rank): Tài liệu liên quan đầu tiên xuất hiện ở vị trí nào? Mục tiêu: trên 0.8

Generation Metrics

  • Faithfulness: Câu trả lời có trung thành với nội dung nguồn không? Không bịa đặt thông tin. Mục tiêu: trên 95%
  • Answer Relevancy: Câu trả lời có đúng với câu hỏi không? Mục tiêu: trên 85%
  • Completeness: Câu trả lời có đầy đủ không? Có bỏ sót thông tin quan trọng không?

Agent Metrics

  • Steps to Answer: Agent cần bao nhiêu bước để trả lời? Ít bước hơn = hiệu quả hơn = chi phí thấp hơn
  • Query Reformulation Rate: Bao nhiêu phần trăm queries cần reformulate? Tỷ lệ cao có thể chỉ ra vấn đề với embedding hoặc chunking
  • Source Coverage: Agent có sử dụng đúng nguồn dữ liệu không?
  • Cost per Query: Chi phí trung bình cho mỗi câu hỏi (API tokens + vector DB operations)
// src/evaluation.ts
export interface EvalResult {
  question: string;
  expected_answer: string;
  actual_answer: string;
  sources_used: string[];
  steps_taken: number;
  total_tokens: number;
  latency_ms: number;
  faithfulness: number;  // 0-1
  relevancy: number;     // 0-1
}

export function calculateMetrics(results: EvalResult[]) {
  const avgSteps = results.reduce(
    (sum, r) => sum + r.steps_taken, 0
  ) / results.length;

  const avgTokens = results.reduce(
    (sum, r) => sum + r.total_tokens, 0
  ) / results.length;

  const avgLatency = results.reduce(
    (sum, r) => sum + r.latency_ms, 0
  ) / results.length;

  const avgFaithfulness = results.reduce(
    (sum, r) => sum + r.faithfulness, 0
  ) / results.length;

  const avgRelevancy = results.reduce(
    (sum, r) => sum + r.relevancy, 0
  ) / results.length;

  return {
    total_questions: results.length,
    avg_steps: Math.round(avgSteps * 10) / 10,
    avg_tokens: Math.round(avgTokens),
    avg_latency_ms: Math.round(avgLatency),
    avg_faithfulness: Math.round(avgFaithfulness * 100) / 100,
    avg_relevancy: Math.round(avgRelevancy * 100) / 100,
    cost_per_query_usd:
      Math.round(avgTokens * 0.000003 * 10000) / 10000,
  };
}

Bước tiếp theo

Agentic RAG là bước tiến lớn so với RAG truyền thống, biến quá trình truy xuất thông tin từ quy trình tuyến tính thành vòng lặp thông minh. Bắt đầu với kiến trúc đơn giản (một vector store, vài retrieval tools), đo lường metrics, sau đó mở rộng dần. Khám phá thêm về xây dựng AI Agent tại Thư viện Nâng cao Claude.

Tính năng liên quan:Agentic RAGMulti-step RetrievalQuery ReformulationVector DB

Bai viet co huu ich khong?

Bản quyền thuộc về tác giả. Vui lòng dẫn nguồn khi chia sẻ.

Bình luận (0)
Ảnh đại diện
Đăng nhập để bình luận...
Đăng nhập để bình luận
  • Đang tải bình luận...

Đăng ký nhận bản tin

Nhận bài viết hay nhất về sản phẩm và vận hành, gửi thẳng vào hộp thư của bạn.

Bảo mật thông tin. Hủy đăng ký bất cứ lúc nào. Chính sách bảo mật.