Welcome to Lesson 1. By the end of this lesson, you will have a working RAG system that answers questions about any document. No PhD required. Let's climb.
What is RAG?
RAG = Retrieval-Augmented Generation. In plain English:
- Retrieval: Break documents into small pieces (chunks). Turn chunks into numbers (embeddings). Search for the most similar numbers when someone asks a question.
- Generation: Feed the matching chunks to an LLM (like GPT-4). The LLM answers based ONLY on those chunks.
The result? An AI that answers questions grounded in your client's actual data — reducing hallucinations compared to plain ChatGPT.
Step-by-Step Instructions
Go to colab.research.google.com. Click "New Notebook". Name it "My First RAG System".
Copy this code into the first cell. Press Shift + Enter to run.
!pip install langchain-openai langchain-community langchain-chroma langchain-text-splitters chromadb openai pypdfIf you don't have one, go to platform.openai.com → Sign up. New accounts may receive trial credits; check the OpenAI pricing page for current offers.
import os
os.environ["OPENAI_API_KEY"] = "YOUR_API_KEY_HERE"Download one of the Northwind Traders practice files from the Downloads page (e.g., northwind_products.txt). Click the folder icon in Colab (left sidebar), drag the file in, then run this code:
from langchain_community.document_loaders import TextLoader
# Change the file name to match your uploaded file
loader = TextLoader("/content/northwind_products.txt")
documents = loader.load()
print(f"Loaded {len(documents)} document(s)")RAG works best when documents are split into small pieces (chunks) before embedding. This makes retrieval more accurate.
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50
)
chunks = text_splitter.split_documents(documents)
print(f"Split into {len(chunks)} chunks")This turns your chunks into searchable numbers and stores them in a vector database.
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(chunks, embeddings)
print("Vector store ready!")Your RAG system is now live. This step does BOTH parts of RAG — retrieval (finding the right chunks) and generation (an LLM answers based on those chunks).
query = "Which products are discontinued?"
# Step A: Retrieve relevant chunks
docs = vectorstore.similarity_search(query)
context = "\n\n".join([d.page_content for d in docs])
# Step B: Generate an answer using the LLM
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Answer the question based ONLY on the context provided. If the answer is not in the context, say you don't know."},
{"role": "user", "content": f"Context:\n{context}\n\nQuestion: {query}"}
]
)
print(response.choices[0].message.content)Run all cells in order. Your first RAG system will be working in about 10 minutes.
# Cell 1: Install libraries
!pip install langchain-openai langchain-community langchain-chroma langchain-text-splitters chromadb openai pypdf
# Cell 2: API key
import os
os.environ["OPENAI_API_KEY"] = "YOUR_API_KEY_HERE"
# Cell 3: Load document (upload northwind_products.txt to Colab first)
from langchain_community.document_loaders import TextLoader
loader = TextLoader("/content/northwind_products.txt")
documents = loader.load()
print(f"Loaded {len(documents)} document(s)")
# Cell 4: Split into chunks
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = text_splitter.split_documents(documents)
print(f"Split into {len(chunks)} chunks")
# Cell 5: Create vector store
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(chunks, embeddings)
print("Vector store ready!")
# Cell 6: Retrieve and generate an answer
query = "Which products are discontinued?"
docs = vectorstore.similarity_search(query)
context = "\n\n".join([d.page_content for d in docs])
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Answer based ONLY on the context. If not in context, say you don't know."},
{"role": "user", "content": f"Context:\n{context}\n\nQuestion: {query}"}
]
)
print(response.choices[0].message.content)