Skip to content

mftnakrsu/rag-by-hand

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rag-by-hand — a stack of documents on the left dissolves into an embedding vector space; its nearest points converge through a small pipeline into a single grounded answer card on the right

rag-by-hand

Build a Retrieval-Augmented Generation system from first principles — one runnable Python file per concept, no frameworks hiding the moving parts. Companion code for the RAG from First Principles series on mefby.com: a 20-part arc, a 12-part core plus a 2026 Frontier Track.

"Build it by hand, understand every line."

Each folder maps 1:1 to an essay. The early parts (2–5) are pure NumPy / standard library and run offline with no API key. Part 6 assembles them into a working "chat with your documents" app; Parts 7–12 layer on hybrid retrieval, reranking, advanced patterns, evaluation, and production hardening. Parts 13–20 are a 2026 Frontier Track continuing past the finale: late-interaction retrieval (ColBERT to ColPali), context-aware chunking, and adaptive routing by query complexity, then RAG vs long-context vs CAG, securing RAG, structured/SQL RAG, building a RAG agent, and conversational RAG.

Every part ships two ways to learn the same concept: a single runnable .py (the whole idea, top to bottom) and a step-by-step Jupyter notebook (.ipynb) that rebuilds it cell by cell, with the why spelled out before each small step. Both run offline — a real embedding model / LLM is used automatically when one is available, and a transparent, deterministic fallback keeps every cell runnable otherwise. Part 1 is a concept-only notebook (the code starts in Part 2).

The RAG pipeline stage by stage — an indexing phase (document → chunk → embed → store) and a querying phase (retrieve → augment → generate), each stage mapped to the part that builds it

The series

Part Topic Code Notebook Essay
1 Why RAG Exists part-01-why-rag (concept) why-rag.ipynb read
2 Embeddings embeddings.py embeddings.ipynb read
3 Measuring Similarity similarity.py similarity.ipynb read
4 Vector Databases & Indexing vector_db.py vector_db.ipynb read
5 Documents & Chunking chunking.py chunking.ipynb read
6 Build Your First RAG rag_app.py rag_app.ipynb read
7 Retrieval Deep Dive rag_hybrid.py rag_hybrid.ipynb read
8 Making Retrieval Smarter rag_rerank.py rag_rerank.ipynb read
9 Advanced Retrieval Patterns rag_parent_document.py rag_parent_document.ipynb read
10 Advanced RAG Architectures corrective_rag.py · agentic_loop.py corrective_rag.ipynb read
11 Evaluating RAG rag_eval.py rag_eval.ipynb read
12 RAG in Production rag_production.py rag_production.ipynb read
13 Late-Interaction Retrieval late_interaction.py late_interaction.ipynb read
14 Context-Aware Chunking context_aware_chunking.py context_aware_chunking.ipynb read
15 Adaptive RAG adaptive_rag.py adaptive_rag.ipynb read
16 RAG vs Long-Context vs CAG rag_vs_long_context.py rag_vs_long_context.ipynb read
17 Securing RAG rag_security.py rag_security.ipynb read
18 Structured and SQL RAG sql_rag.py sql_rag.ipynb read
19 Building a RAG Agent rag_agent.py rag_agent.ipynb read
20 Conversational RAG conversational_rag.py conversational_rag.ipynb read

Parts 13–20 are the Frontier Track (2026 advances), a continuation past the Part 12 finale. Part 11 also ships a second runnable, long_context_vs_rag.py (notebook): a leakage-free, fictional-corpus long-context-LLM vs RAG head-to-head.

Quick start

git clone https://github.com/mftnakrsu/rag-by-hand
cd rag-by-hand
pip install -r requirements.txt

# Parts 2–5 run offline, no API key:
python part-03-measuring-similarity/similarity.py

# Part 6 — the full app. Set one provider (below), then:
python part-06-build-your-first-rag/rag_app.py

Prefer to learn step by step? Open the matching notebook instead — every cell runs offline, no API key required:

pip install jupyter           # one-time, to run the notebooks
jupyter notebook part-03-measuring-similarity/similarity.ipynb

Or run any notebook in your browser with zero setup — every notebook carries an Open in Colab badge at the top.

Example run

similarity.py is pure NumPy and runs with no model, key, or network. You should see:

Three tiny 2-D vectors (real embeddings just have more dimensions):
  A = [3, 4]
  B = [4, 3]
  C = [6, 8]   (A doubled: same direction, twice as long)

Pairwise scores -- three metrics, three different verdicts:
  pair | euclidean |   dot |  cosine
--------------------------------------
   A,B |      1.41 |    24 |    0.96
   A,C |      5.00 |    50 |    1.00
   B,C |      5.39 |    48 |    0.96

Top-k retrieval (the RAG ranking function):
  query = [1.0, 0.0]
  1. score=  1.00  chunk_0  same direction, far away
  2. score=  0.97  chunk_2  near-aligned
  3. score=  0.71  chunk_1  45 degrees off

  Note chunk_0 ties for first despite being 9x longer than the query:
  cosine ignores length and rewards pure direction -- the whole point.

LLM providers

The generation step (Part 6 onward) is isolated behind a single generate(prompt) function so the provider is a one-line swap. Three backends are shown: OpenAI (the default), Ollama (local, free, no key), and Anthropic / Claude. Set the matching API key — or run Ollama locally — and swap the function body. The retrieval, chunking, and similarity code is provider- agnostic and needs no key at all.

License

MIT — see LICENSE.

About

Build RAG from first principles — runnable, framework-free companion code for the 20-part series on mefby.com

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages