Skip to content

Latest commit

 

History

History
97 lines (71 loc) · 4.47 KB

File metadata and controls

97 lines (71 loc) · 4.47 KB

Advance_rag

This is my second RAG project, built after Traditional_RAG. That one was the basic version — load docs, chunk them, embed, store, retrieve, answer. This one I built to actually learn what people mean when they say "advanced RAG," instead of just taking the term at face value.

Every technique in here I added because it fixes something specific that's actually wrong with basic RAG, not just to pad the project. I've listed the reasoning below so future-me (or anyone reading this) knows why each piece exists.

What it does

Question
   -> Query Expansion (LLM rewrites the question so retrieval isn't stuck on my exact wording)
   -> Hybrid Retrieval (BM25 keyword search + dense vector search, combined)
        -> MMR on the dense side (stops it from returning 3 chunks that all say the same thing)
   -> Re-ranking (LLM looks at the retrieved chunks again and reorders them by actual relevance)
   -> Answer

Before any of that can happen, there's a one-time setup step:

Load .txt files -> semantic chunking -> embed -> store in Astra DB

Files

Advance_rag/
├── data/
│   └── txt_file/          my two test docs (cloud computing + database indexing)
├── Load_file.py           loads the txt files
├── chunking.py             semantic chunking with SemanticChunker
├── vectordb.py              embeds the chunks and stores them in Astra DB
├── retrieval.py               hybrid retriever - BM25 + dense with MMR
├── query_expansion.py          LLM rewrites my question before it hits the retriever
├── re_ranker.py                  LLM reorders whatever retrieval gave back
├── qa_chain.py                    the file that actually wires all of this together
└── .env                             keys, not committed (learned this the hard way)

Setup

I'm using uv, Python 3.13.

uv venv
uv python pin 3.13
uv add langchain langchain-text-splitters langchain-openai langchain-experimental langchain-community langchain-astradb astrapy langchain-groq rank_bm25 python-dotenv numpy pandas openpyxl

.env file needs:

RAG_TOKEN=github models token
GROQ_API_KEY=groq key
ASTRADB_API_ENDPOINT=astra endpoint
ASTRADB_APPLICATION_TOKEN=astra token

Embeddings go through GitHub Models (text-embedding-3-small), everything else (expansion, re-ranking, final answer) goes through Groq (openai/gpt-oss-120b) since this pipeline makes several LLM calls per question and Groq is fast.

How to run it

Build the index once, in order:

python Load_file.py
python chunking.py
python vectordb.py

Then ask something:

python qa_chain.py

Change the question variable at the bottom of qa_chain.py to try other questions. retrieval.py, query_expansion.py, and re_ranker.py also run standalone if I want to check what one stage is doing on its own without running the whole thing.

Why I added each piece

  • Semantic chunking — splits at meaning boundaries instead of just cutting every N characters, so a chunk doesn't get sliced in the middle of an idea
  • Hybrid retrieval — vector search alone can miss exact keywords/terms since it's matching on meaning, not words. BM25 catches those. Combining both covers more ground than either alone.
  • MMR — without it, retrieval sometimes returns 2-3 chunks that basically repeat each other. MMR trades a bit of pure relevance for diversity so the LLM gets more varied context instead of the same point three times.
  • Query expansion — my questions are often short and vague. Expanding them with synonyms/related terms before searching helps catch chunks that use different wording than I did.
  • Re-ranking — the retriever's similarity score is fast but shallow. Having the LLM actually look at the question and each chunk together and re-rank them catches relevance the raw score misses.

Things I'm not pretending are solved

  • This makes several LLM calls per question now (expand, rerank, answer) so it's slower and costs more than Traditional_RAG per query
  • I've only tested this on two small text files I wrote myself — no idea how it holds up on messier, larger real data yet
  • Still single-turn, no memory across questions

Next up

  • Add conversational memory so follow-up questions actually work
  • Test on a bigger, messier dataset instead of my two clean sample files
  • Actually compare this against Traditional_RAG side by side on the same questions and see if it's really better, not just more complicated