A comprehensive Retrieval-Augmented Generation (RAG) system designed to ingest, process, and query astrophysics research papers from arXiv. Built to support the South African Astronomical Observatory (SAAO) research community with intelligent paper discovery and question-answering capabilities.
- Features
- Architecture Overview
- Prerequisites
- Installation
- Quick Start
- Service Deployment Profiles
- Microservices & Ports
- Usage Guide
- Development
- Configuration
- Troubleshooting
- License
- Author
- Automated Paper Ingestion: Fetch papers from arXiv using a configurable list of paper IDs
- PDF Processing: Deep parsing with Docling for structured text extraction
- Hybrid Search: Combined BM25 + vector search using OpenSearch for optimal retrieval
- RAG Question Answering: Ask natural language questions and receive contextual answers with citations
- Streaming Responses: Real-time streaming answers for better user experience
- Workflow Orchestration: Apache Airflow DAGs for automated ingestion pipelines
- Observability: Full tracing with Langfuse for debugging and analytics
- Caching: Redis-based query caching for improved performance
- Modern UI: Gradio-powered web interface for interactive exploration
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SAAO arXiv RAG System β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ β
β β Gradio β β FastAPI β β Airflow β β Langfuse β β
β β (UI) βββββΆβ (API) ββββββ (DAGs) β β (Tracing) β β
β β Port 7860 β β Port 8000 β β Port 8080 β β Port 3001 β β
β βββββββββββββββ ββββββββ¬βββββββ ββββββββ¬βββββββ βββββββββββββββ β
β β β β
β βββββββββββββββββββββββββββΌβββββββββββββββββββΌβββββββββββββββββββββββββ β
β β βΌ βΌ β β
β β βββββββββββββββ βββββββββββββββ βββββββββββββββ β β
β β β OpenSearch β β PostgreSQL β β MinIO β β β
β β β (Vectors) β β (DB) β β (Storage) β β β
β β β Port 9200 β β Port 5432 β β Port 9000 β β β
β β βββββββββββββββ βββββββββββββββ βββββββββββββββ β β
β β β β
β β βββββββββββββββ βββββββββββββββ βββββββββββββββ β β
β β β Ollama β β Redis β β ClickHouse β β β
β β β (LLM) β β (Cache) β β (Analytics) β β β
β β β Port 11434 β β Port 6379 β β β β β
β β βββββββββββββββ βββββββββββββββ βββββββββββββββ β β
β β Data Layer β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Before installing the application, ensure you have the following tools installed on your system.
| Tool | Version | Purpose |
|---|---|---|
| Docker | 24.0+ | Container runtime |
| Docker Compose | 2.20+ | Multi-container orchestration |
| Python | 3.12+ | Runtime environment |
| uv | 0.4+ | Fast Python package manager |
| Make | 3.80+ | Build automation |
Download and install Docker Desktop.
# Verify installation
docker --version
docker compose versionImportant: For this application, configure Docker Desktop with at least:
- Memory: 12GB+ (required for PDF processing and LLM inference)
- Swap: 4GB+
- Disk: 50GB+
Install uv - a blazing-fast Python package manager:
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
# Verify installation
uv --version# macOS (with Xcode Command Line Tools)
xcode-select --install
# Ubuntu/Debian
sudo apt-get install build-essential
# Windows (using Chocolatey)
choco install makegit clone https://github.com/Danselem/saao-arxiv-paper.git
cd saao-arxiv-paper# Create virtual environment and install dependencies
make init
make install# Copy the example environment file
make env
# or manually:
cp .env.example .envEdit .env to configure your settings. Key variables include:
# Database
POSTGRES_DATABASE_URL=postgresql+psycopg2://rag_user:rag_password@localhost:5432/rag_db
# OpenSearch
OPENSEARCH__HOST=http://localhost:9200
# Ollama (LLM)
OLLAMA__HOST=http://localhost:11434
OLLAMA__MODEL=llama3.2:1b
# MinIO (Object Storage)
MINIO__ENDPOINT=http://localhost:9000
MINIO__ACCESS_KEY=minioadmin
MINIO__SECRET_KEY=minioadmin
# Redis (Cache)
REDIS__HOST=localhost
REDIS__PORT=6379
# Langfuse (Observability) - Optional
LANGFUSE__ENABLED=true
LANGFUSE__PUBLIC_KEY=your_public_key
LANGFUSE__SECRET_KEY=your_secret_key# Start all services
make start
# Or start specific service groups (see Service Deployment Profiles below)
make up-core # Core infrastructure only
make up-api # API + Core dependencies
make ingest # Full ingestion pipeline
make rag-app # Complete RAG application with observabilitymake pull-modelsThis downloads the required Ollama models:
nomic-embed-text- For generating embeddingsllama3.2:1b- For RAG answer generation
After installation, get up and running in minutes:
# 1. Start the full stack
make rag-app
# 2. Pull LLM models (first time only)
make pull-models
# 3. Add paper IDs to airflow/papers.txt
echo "2401.12345" >> airflow/papers.txt
# 4. Open Airflow UI and trigger the ingestion DAG
open http://localhost:8080
# Login: admin / admin
# Trigger: fetch_saao_papers DAG
# 5. Launch the Gradio UI
make app
# 6. Open the application
open http://localhost:7860The application supports flexible deployment with different service combinations:
| Command | Services Started | Use Case |
|---|---|---|
make up-core |
PostgreSQL, Redis, MinIO | Development/Testing |
make up-api |
Core + OpenSearch + API | API Development |
make up-pipeline |
Core + OpenSearch + Ollama + Dashboards | Indexing Pipeline |
make ingest |
Pipeline + Airflow | Full Ingestion Workflow |
make rag-app |
All services including Langfuse | Production RAG App |
make start |
Everything | Full Stack |
| Service | Container Name | Port | Description |
|---|---|---|---|
| FastAPI | rag-api |
8000 |
REST API for RAG queries and search |
| Gradio UI | Local | 7860 |
Web interface for interactive queries |
| Airflow | rag-airflow |
8080 |
Workflow orchestration and DAG management |
| OpenSearch | rag-opensearch |
9200 |
Vector search and BM25 indexing |
| OpenSearch Dashboards | rag-dashboards |
5601 |
Search analytics and visualization |
| PostgreSQL | rag-postgres |
5432 |
Paper metadata and application state |
| Redis | rag-redis |
6379 |
Query caching and rate limiting |
| MinIO | rag-minio |
9000 / 9001 |
PDF storage (API / Console) |
| Ollama | rag-ollama |
11434 |
Local LLM inference (embeddings + generation) |
| Langfuse Web | rag-langfuse-web |
3001 |
Observability and tracing dashboard |
| ClickHouse | rag-clickhouse |
8123 |
Analytics database for Langfuse |
-
Add arXiv paper IDs to
airflow/papers.txt:2401.12345 2312.67890 2311.54321 -
Trigger the ingestion pipeline through Airflow UI:
- Navigate to
http://localhost:8080 - Login with
admin/admin - Enable and trigger the
fetch_saao_papersDAG
- Navigate to
# Health check
curl http://localhost:8000/api/v1/health
# Search papers
curl -X POST http://localhost:8000/api/v1/search \
-H "Content-Type: application/json" \
-d '{"query": "exoplanet detection methods", "size": 5}'
# Ask a question (RAG)
curl -X POST http://localhost:8000/api/v1/ask \
-H "Content-Type: application/json" \
-d '{"query": "What are the main techniques for detecting exoplanets?", "top_k": 3}'make app
# Open http://localhost:7860 in your browserFeatures:
- Query Input: Enter natural language questions
- Category Filters: Filter by arXiv categories (astro-ph.GA, astro-ph.SR, etc.)
- Model Selection: Choose between different LLM models
- Hybrid Search Toggle: Enable/disable vector + BM25 search
- Source Links: Direct links to source papers
# Format code
make format
# Lint and fix issues
make lint
# Run tests
make test
# Run tests with coverage
make test-cov# View service logs
make logs
# Check service health
make health
# View running containers
make status
# Stop all services
make stop
# Clean up (remove volumes)
make cleansaao-arxiv-paper/
βββ airflow/ # Airflow DAGs and configuration
β βββ dags/ # DAG definitions
β β βββ arxiv_ingestion/ # Paper ingestion pipeline
β βββ papers.txt # List of arXiv IDs to ingest
β βββ Dockerfile # Airflow container
βββ src/ # Main application source
β βββ config.py # Centralized configuration
β βββ main.py # FastAPI application entry
β βββ gradio_app.py # Gradio UI
β βββ routers/ # API endpoints
β βββ services/ # Business logic
β β βββ arxiv/ # arXiv API client
β β βββ embeddings/ # Ollama embeddings
β β βββ indexing/ # Hybrid indexer
β β βββ opensearch/ # Search client
β β βββ pdf_parser/ # Docling parser
β β βββ ollama/ # LLM client
β βββ models/ # SQLAlchemy models
β βββ schemas/ # Pydantic schemas
β βββ repositories/ # Data access layer
βββ compose.yaml # Docker Compose configuration
βββ Dockerfile # API container
βββ Makefile # Build automation
βββ pyproject.toml # Python project configuration
βββ requirements.txt # Python dependencies
| Variable | Default | Description |
|---|---|---|
POSTGRES_DATABASE_URL |
postgresql+psycopg2://rag_user:rag_password@localhost:5432/rag_db |
PostgreSQL connection string |
OPENSEARCH__HOST |
http://localhost:9200 |
OpenSearch endpoint |
OLLAMA__HOST |
http://localhost:11434 |
Ollama API endpoint |
OLLAMA__MODEL |
llama3.2:1b |
Default LLM model |
EMBEDDING_MODEL |
nomic-embed-text |
Embedding model name |
MINIO__ENDPOINT |
http://localhost:9000 |
MinIO endpoint |
MINIO__ACCESS_KEY |
minioadmin |
MinIO access key |
MINIO__SECRET_KEY |
minioadmin |
MinIO secret key |
MINIO__BUCKET_NAME |
arxiv-pdfs |
PDF storage bucket |
REDIS__HOST |
localhost |
Redis host |
REDIS__PORT |
6379 |
Redis port |
CHUNKING__CHUNK_SIZE |
600 |
Words per chunk |
CHUNKING__OVERLAP_SIZE |
100 |
Overlap between chunks |
Cannot connect to Ollama service: All connection attempts failed
Solution: Ensure Ollama is running and the OLLAMA__HOST is correctly configured.
# Check if Ollama is running
docker ps | grep ollama
# Restart Ollama
docker compose restart ollama
# Verify connectivity
curl http://localhost:11434/api/versionTask exited with return code -9
Solution: Increase Docker memory allocation to at least 12GB in Docker Desktop settings.
index_not_found_exception
Solution: Run the indexing pipeline to create the index:
# Trigger indexing through Airflow or directly
make ingestmodel 'nomic-embed-text' not found
Solution: Pull the required models:
make pull-modelsThis project is licensed under the MIT License - see the LICENSE file for details.
Daniel Egbo
- GitHub: @Danselem
- Docling - PDF document processing
- Ollama - Local LLM inference
- OpenSearch - Search and vector database
- Langfuse - LLM observability
- FastAPI - Modern Python web framework
- Gradio - ML web interfaces
Made with β€οΈ for the Astrophysics Research Community