This project demonstrates a modular, enterprise-style Retrieval-Augmented Generation (RAG) application built with modern LangChain components.
- DocumentLoader/: load source documents from disk
- TextSplitter/: split documents into retrievable chunks
- Embeddings/: generate vector embeddings
- VectorStores/: persist and query vector indexes
- Retriever/: retrieve relevant context for a query
- Prompts/: prompt templates for generation
- Models/: chat model wrappers
- Chains/: orchestrate the full RAG pipeline
- Environment-based configuration
- Structured logging
- PEP8-friendly modular code
- Exception handling and validation
- LangChain v0.3+ style architecture
- FAISS-backed vector search
- Gemini-based embeddings and chat model
- Create and activate a virtual environment
- Install dependencies
- Copy .env.example to .env and fill in your values
- Run the application
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
python main.py- GOOGLE_API_KEY
- RAG_SOURCE_PATH
- RAG_QUERY
- EMBEDDING_MODEL
- CHAT_MODEL
- MODEL_TEMPERATURE
- VECTOR_STORE_PATH
- LOG_LEVEL
Running the app prints a concise answer generated from the retrieved context.
User Query
|
v
RAG Chain
|-> DocumentLoader
|-> TextSplitter
|-> Embeddings
|-> VectorStores
|-> Retriever
|-> Prompts + Models
v
Final Answer
1. Load document from disk
2. Split into chunks
3. Create embeddings
4. Build FAISS index
5. Retrieve relevant chunks
6. Generate answer with Gemini
- Keep modules small and focused
- Use environment variables for secrets and configuration
- Add logging everywhere
- Handle exceptions explicitly
- Prefer dependency injection over hard-coded values
- Version-pin dependencies for reproducibility
- What is the difference between retrieval and generation in a RAG system?
- How does chunk size affect retrieval performance?
- Why are embeddings important in vector search?
- What is the role of the retriever in a RAG pipeline?
- How would you scale this architecture for production?