{"product_id":"rag-với-claude-retrieval-augmented-generation-toan-tập","title":"RAG với Claude — Retrieval-Augmented Generation toàn tập","description":"\n\u003ch2\u003eRAG là gì?\u003c\/h2\u003e\n\u003cp\u003eRetrieval-Augmented Generation (RAG) là kiến trúc kết hợp giữa hệ thống tìm kiếm thông tin (retrieval) và mô hình ngôn ngữ lớn (generation). Thay vì chỉ dựa vào kiến thức được huấn luyện sẵn, mô hình AI sẽ truy xuất các đoạn văn bản liên quan từ cơ sở dữ liệu của bạn trước khi sinh ra câu trả lời.\u003c\/p\u003e\n\n\u003cp\u003eKết quả là Claude có thể trả lời chính xác về tài liệu nội bộ, dữ liệu cập nhật theo thời gian thực, hoặc kiến thức chuyên ngành mà nó chưa được huấn luyện — tất cả mà không cần fine-tuning hay nhét toàn bộ tài liệu vào context window.\u003c\/p\u003e\n\n\u003ch2\u003eTại sao RAG thay vì fine-tuning hay long context?\u003c\/h2\u003e\n\n\u003ch3\u003eSo sánh ba phương pháp\u003c\/h3\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth\u003eTiêu chí\u003c\/th\u003e\n      \u003cth\u003eRAG\u003c\/th\u003e\n      \u003cth\u003eFine-tuning\u003c\/th\u003e\n      \u003cth\u003eLong context\u003c\/th\u003e\n    \u003c\/tr\u003e\n  \u003c\/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eCập nhật dữ liệu\u003c\/td\u003e\n      \u003ctd\u003eDễ — chỉ cần cập nhật vector DB\u003c\/td\u003e\n      \u003ctd\u003eKhó — phải train lại\u003c\/td\u003e\n      \u003ctd\u003eDễ nhưng tốn kém\u003c\/td\u003e\n    \u003c\/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eChi phí\u003c\/td\u003e\n      \u003ctd\u003eTrung bình\u003c\/td\u003e\n      \u003ctd\u003eCao (training)\u003c\/td\u003e\n      \u003ctd\u003eCao (nhiều token input)\u003c\/td\u003e\n    \u003c\/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eĐộ chính xác trích dẫn\u003c\/td\u003e\n      \u003ctd\u003eCao\u003c\/td\u003e\n      \u003ctd\u003eThấp (hallucination)\u003c\/td\u003e\n      \u003ctd\u003eCao nhưng phụ thuộc context\u003c\/td\u003e\n    \u003c\/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eKiểm soát nguồn\u003c\/td\u003e\n      \u003ctd\u003eCó — biết từ tài liệu nào\u003c\/td\u003e\n      \u003ctd\u003eKhông\u003c\/td\u003e\n      \u003ctd\u003eCó\u003c\/td\u003e\n    \u003c\/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eScale tài liệu\u003c\/td\u003e\n      \u003ctd\u003eTốt — hàng triệu tài liệu\u003c\/td\u003e\n      \u003ctd\u003eCần data lớn để hiệu quả\u003c\/td\u003e\n      \u003ctd\u003eGiới hạn bởi context window\u003c\/td\u003e\n    \u003c\/tr\u003e\n  \u003c\/tbody\u003e\n\u003c\/table\u003e\n\n\u003cp\u003eRAG phù hợp nhất khi dữ liệu thay đổi thường xuyên, tập tài liệu lớn hơn context window, và bạn cần khả năng truy xuất nguồn gốc câu trả lời. Claude với context window 200K token xử lý được nhiều tài liệu, nhưng đối với cơ sở tri thức doanh nghiệp lên đến hàng nghìn tài liệu, RAG vẫn là lựa chọn kinh tế hơn.\u003c\/p\u003e\n\n\u003ch2\u003eKiến trúc tổng quan của hệ thống RAG\u003c\/h2\u003e\n\u003cp\u003eMột pipeline RAG hoàn chỉnh gồm hai giai đoạn chính:\u003c\/p\u003e\n\n\u003ch3\u003eGiai đoạn 1: Indexing (Xử lý tài liệu)\u003c\/h3\u003e\n\u003col\u003e\n  \u003cli\u003eLoad tài liệu (PDF, DOCX, web pages, v.v.)\u003c\/li\u003e\n  \u003cli\u003eChunk (chia nhỏ) tài liệu thành các đoạn\u003c\/li\u003e\n  \u003cli\u003eTạo embedding cho mỗi chunk\u003c\/li\u003e\n  \u003cli\u003eLưu embedding vào vector database\u003c\/li\u003e\n\u003c\/ol\u003e\n\n\u003ch3\u003eGiai đoạn 2: Retrieval + Generation (Truy vấn)\u003c\/h3\u003e\n\u003col\u003e\n  \u003cli\u003eNhận câu hỏi từ người dùng\u003c\/li\u003e\n  \u003cli\u003eTạo embedding cho câu hỏi\u003c\/li\u003e\n  \u003cli\u003eTìm kiếm các chunks liên quan nhất trong vector DB (similarity search)\u003c\/li\u003e\n  \u003cli\u003eĐưa chunks + câu hỏi vào prompt của Claude\u003c\/li\u003e\n  \u003cli\u003eClaude sinh ra câu trả lời dựa trên context\u003c\/li\u003e\n\u003c\/ol\u003e\n\n\u003ch2\u003eDocument Processing — Chunking Strategies\u003c\/h2\u003e\n\u003cp\u003eChất lượng chunking ảnh hưởng trực tiếp đến chất lượng retrieval. Ba chiến lược phổ biến:\u003c\/p\u003e\n\n\u003ch3\u003e1. Fixed-size chunking\u003c\/h3\u003e\n\u003cp\u003eChia tài liệu thành các đoạn có kích thước cố định (ví dụ: 512 tokens), với overlap để tránh mất ngữ cảnh tại ranh giới.\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003edef fixed_chunk(text, chunk_size=512, overlap=50):\n    words = text.split()\n    chunks = []\n    for i in range(0, len(words), chunk_size - overlap):\n        chunk = ' '.join(words[i:i + chunk_size])\n        chunks.append(chunk)\n    return chunks\u003c\/code\u003e\u003c\/pre\u003e\n\u003cp\u003eƯu điểm: đơn giản, dễ triển khai. Nhược điểm: có thể cắt đứt câu hoặc đoạn có nghĩa quan trọng.\u003c\/p\u003e\n\n\u003ch3\u003e2. Semantic chunking\u003c\/h3\u003e\n\u003cp\u003eChia theo ranh giới ngữ nghĩa — đoạn văn, mục, tiêu đề. Phù hợp với tài liệu có cấu trúc rõ ràng như hợp đồng, báo cáo, tài liệu kỹ thuật.\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003edef semantic_chunk(text):\n    # Chia theo paragraph breaks\n    paragraphs = text.split('\n\n')\n    # Gộp các paragraph ngắn\n    chunks = []\n    current = \"\"\n    for para in paragraphs:\n        if len(current) + len(para) \u0026lt; 1000:\n            current += \"\n\n\" + para\n        else:\n            if current:\n                chunks.append(current.strip())\n            current = para\n    if current:\n        chunks.append(current.strip())\n    return chunks\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003e3. Recursive chunking\u003c\/h3\u003e\n\u003cp\u003ePhương pháp được khuyến nghị bởi LangChain và nhiều framework RAG. Thử chia theo hierarchy: paragraph → sentence → word, đảm bảo không vượt quá kích thước tối đa.\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003efrom langchain.text_splitter import RecursiveCharacterTextSplitter\n\nsplitter = RecursiveCharacterTextSplitter(\n    chunk_size=1000,\n    chunk_overlap=200,\n    separators=[\"\n\n\", \"\n\", \". \", \" \", \"\"]\n)\nchunks = splitter.split_text(document_text)\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eChọn chiến lược nào?\u003c\/h3\u003e\n\u003cul\u003e\n  \u003cli\u003eTài liệu có cấu trúc (manual, spec): semantic chunking\u003c\/li\u003e\n  \u003cli\u003eTài liệu thuần văn bản, liên tục: recursive chunking\u003c\/li\u003e\n  \u003cli\u003ePrototype nhanh: fixed-size với overlap 15-20%\u003c\/li\u003e\n  \u003cli\u003eChunk size khuyến nghị: 256-512 tokens cho Q\u0026amp;A, 512-1024 cho tóm tắt\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch2\u003eEmbedding Models\u003c\/h2\u003e\n\u003cp\u003eEmbedding model chuyển đổi văn bản thành vector số để so sánh độ tương đồng ngữ nghĩa. Các lựa chọn phổ biến:\u003c\/p\u003e\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003etext-embedding-3-small (OpenAI):\u003c\/strong\u003e 1536 dimensions, chi phí thấp, chất lượng tốt cho hầu hết use cases\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003etext-embedding-3-large (OpenAI):\u003c\/strong\u003e 3072 dimensions, chất lượng cao hơn, chi phí cao hơn\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003evoyage-3 (Voyage AI):\u003c\/strong\u003e Được Anthropic khuyến nghị, tối ưu cho Claude\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003ebge-m3 (BAAI):\u003c\/strong\u003e Open-source, hỗ trợ đa ngôn ngữ tốt, phù hợp tiếng Việt\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003emultilingual-e5-large:\u003c\/strong\u003e Open-source, hiệu suất tốt cho tiếng Việt\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cp\u003eLưu ý: embedding model và retrieval model phải nhất quán — bạn phải dùng cùng model để embed câu hỏi và tài liệu.\u003c\/p\u003e\n\n\u003ch2\u003eVector Databases\u003c\/h2\u003e\n\u003cp\u003eVector database lưu trữ và tìm kiếm embedding nhanh chóng theo độ tương đồng cosine hoặc dot product.\u003c\/p\u003e\n\n\u003ch3\u003ePinecone\u003c\/h3\u003e\n\u003cp\u003eManaged service, không cần tự quản lý infrastructure. Phù hợp cho production với tập dữ liệu lớn. Có free tier (100K vectors).\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003eimport pinecone\n\npc = pinecone.Pinecone(api_key=\"YOUR_API_KEY\")\nindex = pc.Index(\"my-rag-index\")\n\n# Upsert vectors\nindex.upsert(vectors=[\n    (\"doc-1\", embedding_vector, {\"text\": \"...\", \"source\": \"manual.pdf\"})\n])\n\n# Query\nresults = index.query(vector=query_embedding, top_k=5, include_metadata=True)\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eWeaviate\u003c\/h3\u003e\n\u003cp\u003eOpen-source, có thể self-host hoặc dùng managed cloud. Tích hợp sẵn với nhiều embedding model, hỗ trợ hybrid search tốt.\u003c\/p\u003e\n\n\u003ch3\u003epgvector (PostgreSQL extension)\u003c\/h3\u003e\n\u003cp\u003eLựa chọn tốt nhất nếu bạn đã dùng PostgreSQL. Không cần database mới, chi phí thấp, dễ maintain.\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003e-- Cài extension\nCREATE EXTENSION vector;\n\n-- Tạo bảng\nCREATE TABLE documents (\n  id bigserial PRIMARY KEY,\n  content text,\n  embedding vector(1536),\n  metadata jsonb\n);\n\n-- Tạo index\nCREATE INDEX ON documents USING ivfflat (embedding vector_cosine_ops);\n\n-- Query similarity\nSELECT content, metadata,\n  1 - (embedding \u0026lt;=\u0026gt; $1) AS similarity\nFROM documents\nORDER BY embedding \u0026lt;=\u0026gt; $1\nLIMIT 5;\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eChroma\u003c\/h3\u003e\n\u003cp\u003eOpen-source, nhẹ, phù hợp cho development và small-scale deployment. API đơn giản, tích hợp tốt với LangChain.\u003c\/p\u003e\n\n\u003ch2\u003eRetrieval Strategies\u003c\/h2\u003e\n\n\u003ch3\u003eDense retrieval (semantic search)\u003c\/h3\u003e\n\u003cp\u003eTìm kiếm theo nghĩa bằng cosine similarity giữa các embedding. Hiệu quả với câu hỏi diễn đạt khác nhau nhưng cùng nghĩa.\u003c\/p\u003e\n\n\u003ch3\u003eSparse retrieval (keyword search)\u003c\/h3\u003e\n\u003cp\u003eBM25 hoặc TF-IDF — tìm kiếm theo từ khóa chính xác. Vẫn hiệu quả cho tên riêng, số hiệu, mã code.\u003c\/p\u003e\n\n\u003ch3\u003eHybrid search (khuyến nghị)\u003c\/h3\u003e\n\u003cp\u003eKết hợp dense + sparse, sau đó rerank kết quả. Cho kết quả tốt nhất trong hầu hết trường hợp:\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003edef hybrid_search(query, vector_db, bm25_index, top_k=10):\n    # Dense search\n    query_embedding = embed(query)\n    dense_results = vector_db.query(query_embedding, top_k=top_k)\n\n    # Sparse search\n    sparse_results = bm25_index.search(query, top_k=top_k)\n\n    # Reciprocal Rank Fusion\n    return rrf_merge(dense_results, sparse_results)\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003ePrompt Template cho RAG\u003c\/h2\u003e\n\u003cp\u003eCấu trúc prompt hiệu quả khi dùng Claude với RAG:\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003eSYSTEM_PROMPT = \"\"\"Bạn là trợ lý hỗ trợ kỹ thuật. Trả lời câu hỏi DUY NHẤT dựa trên\ntài liệu được cung cấp trong phần CONTEXT. Nếu tài liệu không có thông tin,\nhãy nói rõ \"Tôi không tìm thấy thông tin này trong tài liệu.\"\n\nKhi trả lời, hãy trích dẫn nguồn tài liệu cụ thể.\"\"\"\n\ndef build_rag_prompt(question, retrieved_chunks):\n    context = \"\n\n---\n\n\".join([\n        f\"[Nguồn: {chunk['source']}]\n{chunk['text']}\"\n        for chunk in retrieved_chunks\n    ])\n\n    return f\"\"\"CONTEXT:\n{context}\n\nCÂU HỎI: {question}\n\nTrả lời dựa trên CONTEXT ở trên:\"\"\"\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eReranking\u003c\/h2\u003e\n\u003cp\u003eSau khi retrieve top-K chunks, reranker chấm điểm lại độ liên quan và chọn top-N thực sự nhất để đưa vào prompt. Giúp lọc ra kết quả giả tương đồng (false positives).\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003efrom voyageai import Client as VoyageClient\n\nvoyage = VoyageClient(api_key=\"YOUR_KEY\")\n\ndef rerank(query, documents, top_n=3):\n    result = voyage.rerank(\n        query=query,\n        documents=[doc['text'] for doc in documents],\n        model=\"rerank-2\",\n        top_k=top_n\n    )\n    return [documents[r.index] for r in result.results]\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eEvaluation Metrics\u003c\/h2\u003e\n\u003cp\u003eĐánh giá hệ thống RAG cần đo cả retrieval và generation:\u003c\/p\u003e\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003eRetrieval Recall@K:\u003c\/strong\u003e Trong K kết quả truy xuất, bao nhiêu phần trăm chứa câu trả lời đúng\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eRetrieval Precision@K:\u003c\/strong\u003e Tỉ lệ kết quả truy xuất thực sự liên quan\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eFaithfulness:\u003c\/strong\u003e Câu trả lời có trung thực với context không (không hallucinate)\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eAnswer Relevancy:\u003c\/strong\u003e Câu trả lời có thực sự trả lời câu hỏi không\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eContext Relevancy:\u003c\/strong\u003e Context truy xuất có liên quan đến câu hỏi không\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003cp\u003eFramework RAGAS (Python) giúp tự động đánh giá các metrics trên bằng cách dùng LLM làm judge.\u003c\/p\u003e\n\n\u003ch2\u003eProduction Tips và Cost Optimization\u003c\/h2\u003e\n\n\u003ch3\u003eGiảm chi phí embedding\u003c\/h3\u003e\n\u003cul\u003e\n  \u003cli\u003eCache embedding cho các tài liệu không thay đổi\u003c\/li\u003e\n  \u003cli\u003eDùng text-embedding-3-small thay vì large nếu chất lượng đủ\u003c\/li\u003e\n  \u003cli\u003eBatch embedding requests thay vì gọi từng cái\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch3\u003eTối ưu retrieval\u003c\/h3\u003e\n\u003cul\u003e\n  \u003cli\u003eTune chunk size: thử 256, 512, 1024 tokens và đánh giá\u003c\/li\u003e\n  \u003cli\u003eAdjust top-K: bắt đầu với K=5, tăng nếu recall thấp\u003c\/li\u003e\n  \u003cli\u003eMetadata filtering: lọc theo ngày, danh mục trước khi similarity search\u003c\/li\u003e\n  \u003cli\u003eParent document retrieval: retrieve chunk nhỏ nhưng đưa cả section lớn hơn vào context\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch3\u003ePrompt Caching với RAG\u003c\/h3\u003e\n\u003cp\u003eDùng Prompt Caching của Claude để cache system prompt và instructions — đặc biệt hữu ích nếu system prompt dài.\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003eimport anthropic\n\nclient = anthropic.Anthropic()\n\nresponse = client.messages.create(\n    model=\"claude-opus-4\",\n    max_tokens=1024,\n    system=[\n        {\n            \"type\": \"text\",\n            \"text\": long_system_instructions,\n            \"cache_control\": {\"type\": \"ephemeral\"}  # Cache system prompt\n        }\n    ],\n    messages=[\n        {\"role\": \"user\", \"content\": rag_prompt_with_context}\n    ]\n)\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eMonitoring và debugging\u003c\/h3\u003e\n\u003cul\u003e\n  \u003cli\u003eLog tất cả queries, retrieved chunks, và responses để phân tích\u003c\/li\u003e\n  \u003cli\u003eTrack retrieval failures: câu hỏi nào không tìm được context phù hợp\u003c\/li\u003e\n  \u003cli\u003eA\/B test chunking strategies và embedding models trên real queries\u003c\/li\u003e\n  \u003cli\u003eDùng Langfuse hoặc Arize để observability\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch2\u003eKết luận\u003c\/h2\u003e\n\u003cp\u003eRAG là nền tảng của hầu hết hệ thống AI production hiện nay. Với Claude, bạn có thể xây dựng RAG pipeline mạnh mẽ nhờ context window lớn (200K tokens), khả năng hiểu tài liệu phức tạp, và API Tool Use để tích hợp retrieval động.\u003c\/p\u003e\n\n\u003cp\u003eBắt đầu với recursive chunking, pgvector (nếu đã có Postgres) hoặc Chroma (nếu mới), và voyage-3 embedding. Sau khi có baseline hoạt động, mới tối ưu dần từng thành phần dựa trên evaluation metrics thực tế.\u003c\/p\u003e\n","brand":"Minh Tuấn","offers":[{"title":"Default Title","offer_id":66959025799213,"sku":null,"price":0.0,"currency_code":"VND","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0763\/9531\/5245\/files\/rag-v_i-claude-retrieval-augmented-generation-toan-t_p.jpg?v=1782891762","url":"https:\/\/claudeae.com\/products\/rag-v%e1%bb%9bi-claude-retrieval-augmented-generation-toan-t%e1%ba%adp","provider":"Claude.vn","version":"1.0","type":"link"}