A production-ready, modular Retrieval-Augmented Generation (RAG) system demonstrating design patterns and best practices for building scalable AI applications.
This project showcases how to build a configurable RAG pipeline where embedding models and vector stores can be swapped via configuration files, without modifying code. Built with clean architecture principles and containerized for easy deployment.
- Factory Pattern: Dynamic component instantiation based on YAML configuration
- Document Loaders: Extract text from multiple file formats
- PDF documents (PyMuPDF)
- Word documents (.docx)
- Multiple Embedders:
- Ollama (local LLM embeddings)
- Mock embedder (testing)
- Multiple Vector Stores:
- SimpleVectorStore (in-memory keyword search)
- ChromaDB (persistent vector database)
- Configuration-Driven: Change behavior via
settings.yaml
factory-poc/
├── api.py # FastAPI REST API server
├── main.py # CLI entry point - demo script
├── settings.yaml # Configuration file
├── requirements.txt # Python dependencies
├── Dockerfile # Docker container configuration
├── docker-compose.yml # Docker Compose setup
├── .dockerignore # Docker ignore patterns
├── .gitignore # Git ignore patterns
├── examples/
│ ├── sample.pdf # Sample PDF document
│ └── sample.docx # Sample Word document
├── config/
│ └── settings.py # Configuration loader
└── src/
├── core/
│ └── factory.py # RAGFactory class (Factory Pattern)
├── interfaces/ # Abstract base classes
│ ├── base_embedder.py # Embedder interface
│ ├── base_vector_store.py # Vector store interface
│ └── base_document_loader.py # Document loader interface
└── adapters/ # Concrete implementations (Adapter Pattern)
├── embedders/
│ ├── ollama_embedder.py # Ollama integration
│ └── mock_embedder.py # Mock for testing
├── vector_store/
│ ├── simple_store.py # In-memory search
│ └── chroma_store.py # ChromaDB integration
└── loaders/
├── document_loader.py # Unified loader
├── pdf_loader.py # PDF support (PyMuPDF)
└── docx_loader.py # Word support (python-docx)
- Python 3.9+
- Ollama (for real embeddings)
- Clone the repository:
git clone https://github.com/A-Najjar/rag-factory.git
cd factory-poc- Create virtual environment:
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate- Install dependencies:
pip install -r requirements.txt- Install Ollama embedding model:
ollama pull embeddinggemma:latestEdit settings.yaml to switch between components:
rag:
vector_store_type: "chroma" # Options: simple, chroma
embedder_type: "ollama" # Options: mock, ollama
embedding:
model: "embeddinggemma:latest"
dimension: 2048Run the standalone demo script:
python main.pyStart the FastAPI server:
# Without Docker
uvicorn api:app --reload
# With Docker
docker-compose upAccess the interactive API documentation at: http://localhost:8000/docs
- GET / - Health check
- POST /upload - Upload PDF/DOCX documents
- POST /search - Search documents by query
- GET /health - Component status
Example API usage:
# Upload a document
curl -X POST "http://localhost:8000/upload" \
-F "file=@examples/sample.pdf"
# Search documents
curl -X POST "http://localhost:8000/search" \
-H "Content-Type: application/json" \
-d '{"query": "RAG system", "top_k": 2}'Initializing RAG System Components...
Loading documents from files...
Loaded sample.pdf
Loaded sample.docx
Sample embedding (first 3 dims): [-0.127, -0.002, 0.006]...
Adding 2 documents to vector store...
Generating embeddings...
Added 2 documents to ChromaDB.
Searching for: 'RAG system'
1. [pdf] sample.pdf: RAG System Documentation What is a RAG System? A Retrieval-Augmented Generation...
2. [docx] sample.docx: Factory Design Pattern The Factory Pattern is a creational design pattern...
Searching for: 'Factory pattern'
1. [docx] sample.docx: Factory Design Pattern The Factory Pattern is a creational design pattern...
2. [pdf] sample.pdf: RAG System Documentation What is a RAG System?...
- Configuration Loading:
settings.yamldefines which components to use - Factory Pattern:
RAGFactoryinstantiates components based on configuration - Document Processing: Files are loaded, embedded, and stored in the vector database
- Semantic Search: Queries are embedded and matched using cosine similarity
The RAGFactory class decouples object creation from business logic:
embedder = RAGFactory.get_embedder() # Returns Ollama or Mock
vector_store = RAGFactory.get_vector_store() # Returns Simple or ChromaEach implementation adapts external libraries to common interfaces:
OllamaEmbedderadapts the Ollama client to theBaseEmbedderinterfaceChromaVectorStoreadapts ChromaDB to theBaseVectorStoreinterface
- Python 3.11
- Ollama - Local LLM embeddings
- ChromaDB - Vector database
- PyMuPDF - PDF document processing
- python-docx - Word document processing
- PyYAML - Configuration management
MIT License - see LICENSE file for details.
Abdullah Al-Najjar
- Built as a proof-of-concept for demonstrating design patterns in AI systems
- Inspired by modular architecture best practices