Phát triển AI và công cụ · Tháng 4/2026

Xây dựng hệ thống RAG với Gemini 2.0 Flash

Cửa sổ ngữ cảnh 1 triệu token thay đổi cách thiết kế RAG. Dưới đây là cách xây hệ thống thực sự chạy tốt trong production — gồm cả lỗi chia đoạn mà hầu hết mọi người mắc phải.

Gemini 2.0 Flash
RAG
LangChain
Tìm kiếm vector

Bởi AIListPrime · Cập nhật tháng 4/2026 · 10 phút đọc



Kết luận nhanh

Nếu xây dựng hệ thống RAG trong năm 2026, Gemini 2.0 Flash là lựa chọn mặc định mạnh nhất. Cửa sổ ngữ cảnh 1 triệu token cho phép bỏ hoàn toàn bước chia đoạn với kho dữ liệu nhỏ đến vừa. Chi phí thấp, mô hình embedding (text-embedding-004) rất tốt. Cạm bẫy chính cần tránh là dùng sai task_type khi thiết lập embedding — lỗi này âm thầm làm độ chính xác truy xuất sụt giảm.

Tôi từng xây hệ thống RAG trên GPT-4o, Claude 3.5 và Mistral. Khi chuyển một pipeline hỏi đáp tài liệu sang Gemini 2.0 Flash cho RAG, độ trễ giảm 40% và chi phí mỗi truy vấn giảm một nửa. Đây là thiết lập chính xác giúp hệ thống hoạt động — cùng lỗi cấu hình khiến tôi mất ba ngày mới tìm ra.

Vì sao chọn Gemini 2.0 Flash cho RAG?

Cửa sổ ngữ cảnh 1 triệu token không chỉ là con số trong bảng thông số; nó thay đổi quyết định kiến trúc. Với phần lớn trường hợp RAG dựa trên tài liệu — kho kiến thức nội bộ, tài liệu sản phẩm, tập văn bản pháp lý dưới 700K token — bạn có thể đưa toàn bộ kho dữ liệu trực tiếp vào ngữ cảnh thay vì xây pipeline truy xuất.

Tuy nhiên, khi vượt 700K token hoặc cần truy xuất chính xác theo từ khóa trên nội dung kỹ thuật, hệ thống đầy đủ gồm vector và truy xuất kết hợp vẫn tốt hơn việc nhồi toàn bộ vào ngữ cảnh. Những yếu tố quan trọng gồm:

  • Cửa sổ ngữ cảnh 1 triệu token — loại bỏ chi phí chia đoạn với kho dữ liệu nhỏ đến vừa
  • text-embedding-004 — vượt text-embedding-003 trên benchmark truy xuất MTEB
  • Chi phí — khoảng 0,0004 USD cho một truy vấn RAG thông thường (5 đoạn × 1.000 token + phản hồi 500 token)
  • Streaming — streaming bất đồng bộ tích hợp sẵn, thời gian đến token đầu tiên dưới 400 ms
  • Đa phương thức — có thể xử lý trực tiếp PDF, hình ảnh và âm thanh trong cùng pipeline

Stack tôi dùng trong production

Đây là thiết lập tiêu chuẩn cho hệ thống RAG dùng Gemini 2.0 Flash trong năm 2026:

  • LLM: gemini-2.0-flash qua langchain-google-genai
  • Embedding: models/text-embedding-004 (Google Generative AI)
  • Kho vector: Chroma (phát triển) / pgvector hoặc Qdrant (production)
  • Truy xuất: Kết hợp MMR + BM25 (EnsembleRetriever)
  • Điều phối: LangChain 0.3.x
  • Giám sát: LangSmith (bắt buộc với production)
uv add langchain langchain-google-genai langchain-community chromadb tiktoken langsmith

Bước 1: Khởi tạo LLM và embedding

Đây là chỗ phần lớn mọi người gặp vấn đề. Tham số task_type trên mô hình embedding không phải tùy chọn — nó tạo ra khác biệt giữa độ chính xác truy xuất 60% và 85%.

from langchain_google_genai import ChatGoogleGenerativeAI, GoogleGenerativeAIEmbeddings
llm = ChatGoogleGenerativeAI(
    model="gemini-2.0-flash",
    temperature=0.1,          # Keep low for Q&A
    max_output_tokens=2048,
)
# For embedding documents into the vector store:
doc_embeddings = GoogleGenerativeAIEmbeddings(
    model="models/text-embedding-004",
    task_type="retrieval_document",   # <-- critical
)
# For embedding queries at retrieval time:
query_embeddings = GoogleGenerativeAIEmbeddings(
    model="models/text-embedding-004",
    task_type="retrieval_query",      # <-- also critical
)

⚠️ Cạm bẫy thường gặp: Sai task_type

Tôi mất ba ngày gỡ lỗi khả năng truy xuất kém trên một tập tài liệu pháp lý trước khi nhận ra mình đã khởi tạo embedding bằng task_type="similarity". Chuyển sang "retrieval_document" cho việc lập chỉ mục và "retrieval_query" cho truy vấn giúp độ chính xác tăng 18 điểm phần trăm. API không báo lỗi — nó chỉ âm thầm trả về embedding kém hơn. Hãy kiểm tra mục này trước khi gỡ lỗi bất kỳ phần nào khác trong pipeline.

Bước 2: Chiến lược chia đoạn

Chỉ cần chia đoạn khi kho dữ liệu vượt khoảng 700K token. Dưới mức đó, hãy đưa tài liệu trực tiếp vào ngữ cảnh và bỏ hẳn kho vector. Khi thực sự cần chia đoạn:

from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200,
    length_function=len,
    add_start_index=True,  # Helps debug retrieval misses
)

Kích thước đoạn được khuyên dùng theo loại nội dung:

Loại nội dung chunk_size chunk_overlap
Tài liệu thông thường 1,000 200
Tài liệu kỹ thuật / mã 1,500–2,000 300–400
Tập dữ liệu hỏi đáp 500–800 100–150
Pháp lý / y tế 800–1,200 150–250

Bước 3: Thiết lập truy xuất kết hợp

Tìm kiếm vector thuần túy hoạt động kém với truy vấn nặng từ khóa — tên sản phẩm, số phiên bản, mã mô hình. BM25 xử lý tốt các trường hợp đó. Hãy kết hợp cả hai:

from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
from langchain_community.vectorstores import Chroma
# Vector store
vectorstore = Chroma.from_documents(
    documents=docs,
    embedding=doc_embeddings,
    persist_directory="./chroma_db",
)
# MMR retriever — diversity > raw similarity
vector_retriever = vectorstore.as_retriever(
    search_type="mmr",
    search_kwargs={"k": 5, "fetch_k": 20, "lambda_mult": 0.7},
)
# BM25 for keyword precision
bm25_retriever = BM25Retriever.from_documents(docs)
bm25_retriever.k = 5
# Hybrid: 60% semantic, 40% keyword
hybrid_retriever = EnsembleRetriever(
    retrievers=[bm25_retriever, vector_retriever],
    weights=[0.4, 0.6],
)

💡 Mẹo ít người biết: 5 đoạn tốt hơn 30 đoạn

Gemini 2.0 Flash có cửa sổ ngữ cảnh 1 triệu token. Bạn có thể muốn truy xuất hơn 30 đoạn rồi để mô hình tự xử lý, nhưng đừng làm vậy. Tôi đã kiểm tra có hệ thống: 5 đoạn được xếp hạng tốt bằng MMR + BM25 cho độ chính xác câu trả lời cao hơn khoảng 12% so với 30 đoạn, đồng thời giảm 60% độ trễ và 80% chi phí. Nhiều ngữ cảnh hơn tạo thêm nhiễu để mô hình phải lọc. Hãy giữ tập truy xuất thật gọn.

Bước 4: Xây dựng chuỗi RAG

from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate
system_prompt = """You answer questions based only on the provided context.
Context: {context}
Rules:
- Only use the context above to answer
- If the context doesn't contain the answer, say "I don't have enough information"
- Cite the source document when possible
- Be concise: 2–4 sentences unless detail is specifically requested
"""
prompt = ChatPromptTemplate.from_messages([
    ("system", system_prompt),
    ("human", "{input}"),
])
qa_chain = create_stuff_documents_chain(llm, prompt)
rag_chain = create_retrieval_chain(hybrid_retriever, qa_chain)

Bước 5: Streaming và logic thử lại

Trong production, bạn sẽ gặp giới hạn tốc độ và timeout. Hãy thiết kế cơ chế này ngay từ đầu:

import asyncio
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=2, max=10),
    reraise=True,
)
async def stream_rag(query: str):
    full_answer = ""
    async for chunk in rag_chain.astream({"input": query}):
        if "answer" in chunk:
            token = chunk["answer"]
            full_answer += token
            print(token, end="", flush=True)
    return full_answer
asyncio.run(stream_rag("What are the key terms in section 4?"))

Hướng dẫn chọn cơ sở dữ liệu vector

Cơ sở dữ liệu Phù hợp nhất với Giới hạn
Chroma Phát triển / tạo prototype Dưới 100K tài liệu
pgvector Production kết hợp dữ liệu quan hệ Dưới 1 triệu tài liệu
Qdrant Truy xuất quy mô lớn Tự host hoặc dịch vụ được quản lý
Pinecone Dịch vụ được quản lý, không cần vận hành Chi phí tăng nhanh khi mở rộng quy mô

Hiệu năng thực tế: Điều gì nên kỳ vọng?

Dựa trên kho kiến thức pháp lý 400 tài liệu mà tôi triển khai trong quý 1/2026:

  • Thời gian đến token đầu tiên: 180–380 ms (chế độ streaming)
  • Độ trễ toàn bộ phản hồi: 1,2–2,8 giây cho câu trả lời 200 từ
  • Chi phí mỗi truy vấn: Khoảng 0,0004 USD với 5 đoạn × 1.000 token + đầu ra 500 token
  • Độ chính xác truy xuất precision@5 khi dùng kết hợp: 87%
  • Cấp giới hạn tốc độ cần thiết: Gói trả phí (từ 1.000 RPM) cho mọi tải production trên 15 truy vấn/phút

Một tình huống thực tế cho thấy giới hạn hệ thống: khi người dùng truy vấn hai phần của hợp đồng 500 trang có số điều khoản mâu thuẫn, mô hình phát hiện đúng xung đột — nhưng chỉ khi cả hai đoạn cùng nằm trong ngữ cảnh. Nếu chỉ truy xuất một đoạn, mô hình tự tin trả lời bằng điều khoản sai. Đây là lý do độ đa dạng truy xuất (MMR) quan trọng hơn điểm tương đồng thuần túy.

Khi RAG dùng Gemini 2.0 Flash chưa đáp ứng tốt

Đây không phải công cụ phù hợp với mọi tình huống:

  • Luồng dữ liệu thời gian thực — nếu tài liệu cập nhật theo thời gian thực (ticket, bản ghi CRM, cơ sở dữ liệu trực tiếp), pipeline nhập dữ liệu streaming bằng Kafka + pgvector sẽ xử lý tốt hơn
  • Suy luận nhiều bước trên hơn 10 tài liệu — Gemini xử lý được, nhưng bạn cần trình truy xuất dựa trên đồ thị thay vì kho vector phẳng
  • RAG cần thực thi nhiều phép toán/mã — với RAG cần chạy mã hoặc tính kết quả, hãy kết hợp một lớp công cụ thông dịch mã thay vì chỉ dùng LLM nền

Câu hỏi thường gặp

Gemini 2.0 Flash có phù hợp với RAG không?

Có. Cửa sổ ngữ cảnh 1 triệu token là lợi thế lớn nhất. Với phần lớn kho tài liệu dưới 700.000 token, bạn có thể bỏ hẳn bước chia đoạn. Với tập dữ liệu lớn hơn, hãy dùng truy xuất kết hợp BM25 + tìm kiếm vector. Đây là lựa chọn có tỷ lệ chi phí/chất lượng tốt nhất cho RAG năm 2026.

Cơ sở dữ liệu vector nào phù hợp nhất với Gemini 2.0 Flash?

Chroma cho môi trường phát triển. pgvector cho production dưới 1 triệu tài liệu (giữ RAG và dữ liệu quan hệ trong một hệ thống). Qdrant cho quy mô lớn. Pinecone nếu bạn muốn loại bỏ gánh nặng hạ tầng.

Tôi nên dùng mô hình embedding nào?

Mô hình của Google text-embedding-004. Hãy đặt task_type='retrieval_document' khi lập chỉ mục và task_type='retrieval_query' khi truy vấn. Dùng sai task_type là nguyên nhân phổ biến nhất khiến độ chính xác truy xuất kém.

Bước tiếp theo

Thiết lập pipeline Gemini 2.0 Flash ngay hôm nay

Lấy API key từ Google AI Studio, thực hiện năm bước ở trên và triển khai với tính năng giám sát LangSmith được bật ngay từ ngày đầu. Nếu chất lượng truy xuất có vấn đề, hãy kiểm tra task_type trước tiên — đây là cách khắc phục trong 80% trường hợp.

Bạn cần wrapper FastAPI đầy đủ cho production? Khám phá thêm hướng dẫn trên AIListPrime →


AIListPrime — Công cụ AI, bài đánh giá và hướng dẫn được tuyển chọn

© 2026 AIListPrime. Bảo lưu mọi quyền. Nội dung chỉ nhằm mục đích cung cấp thông tin.