A production-ready FastAPI application that combines Document RAG (Retrieval-Augmented Generation) with Text-to-SQL capabilities, featuring intelligent query routing, evaluation metrics, and monitoring.
- π Document RAG: Upload and query documents (PDF, DOCX, CSV, JSON, TXT) using AI-powered retrieval
- ποΈ Text-to-SQL: Convert natural language questions to SQL queries with approval workflow
- π§ Intelligent Query Routing: Automatically routes queries to SQL, Documents, or both (HYBRID)
- π Evaluation & Monitoring: RAGAS metrics (faithfulness, relevancy) and OPIK tracking
- β Input Validation: Comprehensive validation for file uploads and queries
- π‘οΈ Error Handling: Structured error responses with detailed messages
- π Production-Ready: Full logging, monitoring, and graceful degradation
- Quick Start
- Prerequisites
- Installation
- Configuration
- Usage
- API Endpoints
- Query Routing
- Evaluation
- Architecture
- Troubleshooting
- Development
# 1. Clone the repository
cd multidata-rag-project
# 2. Create virtual environment (Python 3.12+)
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# 3. Install dependencies
pip install -r requirements.txt
# OR using UV (faster):
uv pip install -r requirements.txt
# 4. Configure environment variables
cp .env.example .env
# Edit .env with your API keys (see Configuration section)
# 5. Run the application
uvicorn app.main:app --reload
# 6. Visit the API docs
open http://localhost:8000/docs- Python 3.12+
- OpenAI API Key (for embeddings and LLM)
- Pinecone Account (for vector storage)
- Create an index with dimension=1536, metric=cosine
- PostgreSQL Database (for Text-to-SQL)
- Supabase recommended for easy setup
- OPIK API Key (for monitoring, can run locally without key)
macOS:
brew install libmagic poppler tesseractUbuntu/Debian:
sudo apt-get update
sudo apt-get install -y libmagic1 poppler-utils tesseract-ocrWindows:
# Using pip
pip install -r requirements.txt
# Using UV (faster, recommended)
uv pip install -r requirements.txt- Sign up at pinecone.io
- Create a new index:
- Dimensions: 1536 (for OpenAI text-embedding-3-small)
- Metric: cosine
- Region: us-east-1-aws (or your preferred region)
- Get your API key from the dashboard
- Sign up at supabase.com
- Create a new project
- Run the schema from
data/sql/schema.sqlin the SQL editor - Optionally, generate sample data:
python data/generate_sample_data.py
- Get your connection string from Project Settings β Database
- Sign up at opik.ai or run locally
- Get your API key (optional, works without key in local mode)
Create a .env file in the project root:
# OpenAI Configuration
OPENAI_API_KEY=sk-...
# Pinecone Configuration
PINECONE_API_KEY=pcsk_...
PINECONE_ENVIRONMENT=us-east-1-aws
PINECONE_INDEX_NAME=rag-documents
# Supabase/PostgreSQL Configuration
DATABASE_URL=postgresql://user:password@host:port/database
# OPIK Monitoring (Optional)
OPIK_API_KEY= # Leave empty for local tracking
# Text Chunking Configuration
CHUNK_SIZE=512
CHUNK_OVERLAP=50uvicorn app.main:app --reload --host 0.0.0.0 --port 8000curl -X POST "http://localhost:8000/upload" \
-F "file=@document.pdf"Response:
{
"status": "success",
"filename": "document.pdf",
"file_size": "2.5 MB",
"chunks_created": 15,
"total_tokens": 7680,
"message": "Document processed and 15 chunks stored in Pinecone"
}curl -X POST "http://localhost:8000/query/documents" \
-H "Content-Type: application/json" \
-d '{"question": "What is the return policy?", "top_k": 3}'curl -X POST "http://localhost:8000/query/sql/generate" \
-H "Content-Type: application/json" \
-d '{"question": "How many customers do we have?"}'# Automatically routes to the appropriate service
curl -X POST "http://localhost:8000/query" \
-H "Content-Type: application/json" \
-d '{"question": "Show total revenue and explain our pricing strategy"}'- GET
/health- Health check - GET
/info- System information and available features - GET
/- Welcome message with quick links
-
POST
/upload- Upload and process documents- Supported formats: PDF, DOCX, DOC, CSV, JSON, TXT
- Max size: 50 MB
- Returns: chunks created, token count
-
GET
/documents- List all uploaded documents- Returns: filename, size, upload timestamp
-
POST
/query/documents- Query documents using RAG- Parameters:
question(string),top_k(int, default=3) - Returns: answer, sources, chunks used
- Parameters:
-
POST
/query/sql/generate- Generate SQL from natural language- Parameters:
question(string) - Returns:
query_id, SQL, explanation
- Parameters:
-
POST
/query/sql/execute- Execute approved SQL query- Parameters:
query_id(string),approved(bool) - Returns: results, row count
- Parameters:
-
GET
/query/sql/pending- List pending SQL queries- Returns: all queries awaiting approval
- POST
/query- Intelligent query routing- Parameters:
question(string, required)auto_approve_sql(bool, default=false, testing only)top_k(int, default=3)
- Returns: routed response with explanation
- Parameters:
The system automatically routes queries based on keyword analysis:
Routed to Text-to-SQL service for data retrieval:
Keywords: count, total, sum, average, revenue, sales, orders, customers, list all, show all, how many, top, bottom, last, recent, etc.
Examples:
- "How many customers do we have?"
- "What is the total revenue from delivered orders?"
- "Show me the top 10 customers by spending"
Routed to RAG service for information retrieval:
Keywords: what is, explain, define, policy, procedure, guide, manual, how to, why, according to, etc.
Examples:
- "What is our return policy?"
- "Explain the customer complaint procedure"
- "How should I process a refund?"
Routed to both services, combining data with context:
Keywords: and explain, and describe, show data and explain, etc.
Examples:
- "Show total revenue by segment and explain our segmentation strategy"
- "List top products and describe pricing policies"
Run the RAGAS evaluation to measure system quality:
python evaluate.pyMetrics:
- Faithfulness (target > 0.7): Answer accuracy based on retrieved context
- Answer Relevancy (target > 0.8): How well the answer matches the question
Output:
- Console: Real-time progress and scores
- File:
evaluation_results.jsonwith detailed results
βββββββββββββββ
β Client β
ββββββββ¬βββββββ
β
v
ββββββββββββββββββββββββββββββββββββββββ
β FastAPI Application β
β (main.py with OPIK monitoring) β
ββββββββ¬ββββββββββββββββββββββββββββββββ
β
v
ββββββββββββββββββββ
β Query Router β β Keyword-based routing
ββββββββ¬ββββββββββββ
β
βββββββββββββββ¬ββββββββββββββββββ
β β β
v v v
[SQL Path] [Documents] [HYBRID]
β β β
v v β
ββββββββββββ ββββββββββββ β
β Vanna β β RAG β β
β SQL Gen β β Pipeline β β
ββββββ¬ββββββ ββββββ¬ββββββ β
β β β
v v v
ββββββββββββ ββββββββββββ ββββββββββββ
βPostgreSQLβ β Pinecone β β Both β
ββββββββββββ ββββββββββββ ββββββββββββ
- Document Service: Parses PDF/DOCX/CSV/JSON using Unstructured.io
- Embedding Service: OpenAI text-embedding-3-small (1536 dimensions)
- Vector Service: Pinecone with gRPC for fast vector operations
- RAG Service: Retrieval + GPT-4 generation with source citations
- SQL Service: Vanna.ai for Text-to-SQL with training on schema
- Query Router: Keyword-based intelligent routing
- Validation: File type/size, query length, SQL safety checks
- Monitoring: OPIK tracking on all key endpoints
Error: 503 Service Unavailable
Solution:
- Check
.envfile has correct API keys - Verify Pinecone index exists with dimension=1536
- Test database connection string
# Test Pinecone connection
python -c "from pinecone import Pinecone; pc = Pinecone(api_key='YOUR_KEY'); print(pc.list_indexes())"
# Test database connection
python -c "import sqlalchemy; engine = sqlalchemy.create_engine('YOUR_DB_URL'); print(engine.connect())"Error: 400 Validation Error - Invalid file type
Solution:
- Ensure file is PDF, DOCX, CSV, JSON, or TXT
- Check file size is under 50 MB
- Verify system dependencies installed (libmagic, poppler)
Error: No valid results to evaluate
Solution:
- Ensure API keys are configured
- Upload at least one document for document queries
- Run database schema setup for SQL queries
- Check
evaluation_results.jsonfor detailed errors
Error: ModuleNotFoundError: No module named 'opik'
Solution:
# Reinstall dependencies
pip install -r requirements.txt
# Verify installation
pip list | grep opikmultidata-rag-project/
βββ app/
β βββ __init__.py
β βββ main.py # FastAPI app with endpoints
β βββ config.py # Pydantic settings
β βββ utils.py # Validation and error handling
β βββ services/
β βββ document_service.py # Document parsing & chunking
β βββ embedding_service.py # OpenAI embeddings
β βββ vector_service.py # Pinecone operations
β βββ rag_service.py # RAG pipeline
β βββ sql_service.py # Vanna Text-to-SQL
β βββ router_service.py # Query routing
βββ data/
β βββ uploads/ # Uploaded documents (gitignored)
β βββ sql/
β β βββ schema.sql # Database schema
β βββ generate_sample_data.py # Sample data generator
βββ tests/
β βββ test_queries.json # Evaluation test queries
βββ evaluate.py # RAGAS evaluation script
βββ requirements.txt # Python dependencies
βββ .env.example # Environment template
βββ .gitignore # Git ignore rules
βββ README.md # This file
# Run evaluation
python evaluate.py
# Test individual endpoints
curl http://localhost:8000/health
curl http://localhost:8000/info- Type hints: All functions have type annotations
- Docstrings: Google-style docstrings for all public functions
- Validation: Input validation on all endpoints
- Error handling: Structured error responses
MIT License - See LICENSE file for details
Contributions welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
For issues and questions:
- Create an issue in the GitHub repository
- Check the Troubleshooting section above
- Review the API documentation at
/docs
| Metric | Target | How to Measure |
|---|---|---|
| Document Upload | All formats work | Test with PDF, DOCX, CSV, JSON |
| Document Retrieval | Top-3 relevant chunks | Manual review of query results |
| SQL Generation | 70%+ accuracy | Run evaluate.py |
| Query Routing | 80%+ correct | Test with mixed queries |
| RAGAS Faithfulness | > 0.7 | Run evaluate.py |
| RAGAS Relevancy | > 0.8 | Run evaluate.py |
| Response Time | < 15 seconds | Monitor OPIK dashboard |
The application is fully containerized and ready for Docker deployment.
# 1. Ensure .env file is configured
cp .env.example .env
# Edit .env with your API keys
# 2. Build and start the container
docker-compose up -d
# 3. View logs
docker-compose logs -f
# 4. Stop the container
docker-compose down# Build the image
docker build -t rag-text-to-sql:latest .
# Run the container
docker run -d \
--name rag-text-to-sql \
-p 8000:8000 \
-v $(pwd)/data/uploads:/app/data/uploads \
-v $(pwd)/data/vanna_chromadb:/app/data/vanna_chromadb \
--env-file .env \
rag-text-to-sql:latest
# View logs
docker logs -f rag-text-to-sql
# Stop and remove
docker stop rag-text-to-sql
docker rm rag-text-to-sql- Multi-stage build: Optimized image size (~800 MB)
- Health checks: Automatic health monitoring
- Persistent volumes: Documents and training data preserved
- System dependencies: All required packages pre-installed
- Production-ready: Runs with uvicorn, proper signal handling
All environment variables from .env are automatically loaded. Required variables:
OPENAI_API_KEY=sk-...
PINECONE_API_KEY=pcsk_...
PINECONE_INDEX_NAME=rag-documents
DATABASE_URL=postgresql://...Container fails to start:
# Check logs
docker logs rag-text-to-sql
# Verify .env file exists
ls -la .env
# Check port availability
lsof -i :8000Services not initialized:
- Verify API keys in
.env - Check Pinecone index exists
- Test database connection outside Docker first
Health check fails:
# Check health endpoint manually
docker exec rag-text-to-sql curl http://localhost:8000/healthRecommended platforms:
- Railway - Easy deployment with PostgreSQL
- Render - Free tier available
- Fly.io - Global edge deployment
- AWS EC2 - Full control, requires more setup
- FastAPI Documentation
- Pinecone Documentation
- Vanna.ai Documentation
- RAGAS Documentation
- OPIK Documentation
Built with β€οΈ using FastAPI, OpenAI, Pinecone, and Vanna.ai