Skill-Lite

Practical tutorials & tools for modern developers.

Home/RAG/Introduction

Introduction to RAG

Retrieval-Augmented Generation (RAG) combines the generative power of LLMs with the precision of information retrieval. Instead of relying solely on what a model learned during training, RAG pulls in relevant, up-to-date documents at query time and feeds them to the LLM as context — giving you accurate, grounded answers on your own data.

Why RAG?

Problem with plain LLMsHow RAG fixes it
Knowledge cutoff — no data after trainingRetrieves current documents at query time
Hallucinations — confident but wrong answersGrounds answers in retrieved source text
No access to private / company dataIndexes your own documents in a vector store
Context window limits on long documentsRetrieves only the relevant chunks, not everything
Expensive fine-tuning to add new knowledgeJust re-index — no model retraining needed

The RAG pipeline

1. Load

  • PDF, Web, CSV, DB
  • Document loaders
  • Any data source

2. Split

  • Chunk into segments
  • Preserve context
  • Overlap at borders

3. Embed

  • Convert text → vector
  • Capture semantic meaning
  • OpenAI / local models

4. Store

  • Save in vector DB
  • Chroma, FAISS, Pinecone
  • Indexed for fast search

5. Retrieve

  • User asks a question
  • Embed question
  • Similarity search → top-k chunks

6. Generate

  • LLM + question + chunks
  • Grounded answer
  • Can cite sources

Two phases: indexing vs querying

PhaseWhenSteps
IndexingOnce (or on data update)Load → Split → Embed → Store
QueryingEvery user requestEmbed question → Retrieve → Generate

Minimal end-to-end RAG

pip install langchain langchain-openai langchain-chroma langchain-community
pip install pypdf python-dotenv tiktoken
import os
from dotenv import load_dotenv
load_dotenv()   # OPENAI_API_KEY from .env

from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_chroma import Chroma
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

# ── 1. INDEXING PHASE ──────────────────────────────────────
docs   = PyPDFLoader("handbook.pdf").load()
chunks = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200).split_documents(docs)
db     = Chroma.from_documents(chunks, OpenAIEmbeddings(), persist_directory="./db")

# ── 2. QUERYING PHASE ──────────────────────────────────────
retriever = db.as_retriever(search_kwargs={"k": 4})
llm       = ChatOpenAI(model="gpt-4o-mini", temperature=0)

prompt = ChatPromptTemplate.from_messages([
    ("system", "Answer using ONLY the context below. If unsure, say 'I don't know'.\n\nContext:\n{context}"),
    ("human", "{question}"),
])

rag_chain = (
    {"context": retriever | (lambda docs: "\n\n".join(d.page_content for d in docs)),
     "question": RunnablePassthrough()}
    | prompt | llm | StrOutputParser()
)

print(rag_chain.invoke("What is the vacation policy?"))

RAG use cases

Use caseDocuments indexed
Enterprise Q&A botInternal wikis, Confluence, HR policies
Customer supportProduct docs, FAQs, troubleshooting guides
Legal / complianceContracts, regulations, case law
Code assistantCodebase, API docs, architecture docs
Medical referenceResearch papers, clinical guidelines
Financial analysisEarnings reports, SEC filings, market data

RAG vs fine-tuning

RAGFine-tuning
CostLow — just indexingHigh — GPU compute
Update dataRe-index in minutesRe-train (hours/days)
Hallucination controlHigh — grounded in docsLow
Teach new skillsNoYes
Best forKnowledge, facts, documentsStyle, format, tasks
Start simple: A basic RAG pipeline — PDF → split → Chroma → retrieve → GPT-4o-mini — often outperforms fine-tuned models on factual Q&A tasks and takes under an hour to build. Only reach for advanced techniques (re-ranking, HyDE, CRAG) after measuring where your baseline falls short.