A fully self-contained Retrieval-Augmented Generation (RAG) system for querying academic abstracts using local LLMs and vector search.
Python
1
19 commits
updated Dec 20, 2025
A fully self-contained Retrieval-Augmented Generation (RAG) system for querying academic abstracts using local LLMs and vector search.
/answer and /stream endpoints for programmatic accessβββββββββββββββ
β Dataset β (.jsonl)
β (abstracts) β
ββββββββ¬βββββββ
β
βΌ
βββββββββββββββ
β Indexer β (sentence-transformers + FAISS)
β Embeddings β
ββββββββ¬βββββββ
β
βΌ
βββββββββββββββ ββββββββββββββββ
β Retriever β ββββΆ β Local LLM β (Llama-3.2-3B)
β (RAG) β β (llama.cpp) β
ββββββββ¬βββββββ ββββββββββββββββ
β
βΌ
βββββββββββββββ ββββββββββββββββ
β Web UI β β Image Gen β (Optional)
β (FastAPI) β ββββΆ β (External) β
βββββββββββββββ ββββββββββββββββ
# Clone or create the project directory
mkdir genai-rag && cd genai-rag
# Add all the code files (main.py, indexer.py, retriever.py, image_gen.py, index.html)
# Build the image
docker build -t navedanan/genai-app:latest .
docker run --rm -p 8080:8080 \
-e DATA_PATH=/data/arxiv_2.9k.jsonl \
-v $(pwd)/arxiv_2.9k.jsonl:/data/arxiv_2.9k.jsonl:ro \
navedanan/genai-app:latest
Open your browser and navigate to:
http://127.0.0.1:8080
{
"id": "2509.21245v1",
"submitter": "Team Hunyuan3D",
"authors": "Team Hunyuan3D, :, Bowen Zhang, Chunchao Guo, Haolin Liu, Hongyu Yan, Huiwen Shi, Jingwei Huang, Junlin Yu, Kunhong Li, Linus, Penghao Wang, Qingxiang Lin, Sicong Liu, Xianghui Yang, Yixuan Tang, Yunfei Zhao, Zeqiang Lai, Zhihao Liang, Zibo Zhao",
"title": "Hunyuan3D-Omni: A Unified Framework for Controllable Generation of 3D Assets",
"comments": "Technical Report; 3D Generation",
"journal-ref": "",
"doi": "",
"categories": "cs.CV cs.AI",
"abstract": "Recent advances in 3D-native generative models have accelerated asset creation for games, film, and design. However, most methods still rely primarily on image or text conditioning and lack fine-grained, cross-modal controls, which limits controllability and practical adoption. To address this gap, we present Hunyuan3D-Omni, a unified framework for fine-grained, controllable 3D asset generation built on Hunyuan3D 2.1. In addition to images, Hunyuan3D-Omni accepts point clouds, voxels, bounding boxes, and skeletal pose priors as conditioning signals, enabling precise control over geometry, topology, and pose. Instead of separate heads for each modality, our model unifies all signals in a single cross-modal architecture. We train with a progressive, difficulty-aware sampling strategy that selects one control modality per example and biases sampling toward harder signals (e.g., skeletal pose) while downweighting easier ones (e.g., point clouds), encouraging robust multi-modal fusion and graceful handling of missing inputs. Experiments show that these additional controls improve generation accuracy, enable geometry-aware transformations, and increase robustness for production workflows.",
"source": "arxiv"
}
RAG_PDF/
βββ Dockerfile # Docker configuration
βββ docker-compose.yml # Docker Compose configuration
βββ requirements.txt # Python dependencies
βββ pyproject.toml # Python project configuration
βββ README.md # This file
βββ DEPLOYMENT_CHECKLIST.md # Deployment checklist
βββ main.py # FastAPI application
βββ data/
β βββ arxiv_2.9k.jsonl # Dataset file
βββ Documentation/
β βββ ARCHITECTURE.md # System design and components
β βββ CONFIGURATION.md # Configuration options
β βββ DOCKER_DEPLOYMENT.md # Docker deployment guide
β βββ IMAGE_GENERATION.md # Image generation setup
β βββ LATEX_UTILS.md # LaTeX utilities documentation
β βββ OFFLINE_SETUP.md # Offline/air-gapped deployment
β βββ QUICKSTART.md # Quick start guide
βββ index/
β βββ dataset_hash.txt # Dataset hash for change detection
β βββ embeddings.npy # Cached embeddings
β βββ faiss.index # FAISS vector index
βββ models/
β βββ Llama-3.2-3B-Instruct-Q4_K_M.gguf # Main LLM model
β βββ llama-model.gguf # Symlink to active LLM
β βββ Qwen3-4B-Instruct-2507-Q4_K_M.gguf # Alternative LLM
β βββ embeddings/ # Embedding models cache
β βββ sdxl-turbo/ # SDXL Turbo model
β βββ stable-diffusion-3.5-medium/ # SD 3.5 Medium model
βββ static/
β βββ index.html # Web UI
β βββ generated_images/ # Generated images cache
βββ tests/
β βββ evaluate_rag.py # RAG evaluation tests
β βββ test_api.py # API endpoint tests
β βββ test_image_gen.py # Image generation tests
β βββ test_sd35_local.py # SD 3.5 local tests
β βββ test_sd35.py # SD 3.5 tests
βββ tools/
β βββ docker_build.ps1 # Docker build script (PowerShell)
β βββ docker_build.sh # Docker build script (Bash)
β βββ download_models.py # Model download utility
β βββ sample_generator.py # Sample data generator
β βββ validate_offline.py # Offline setup validator
βββ utils/
βββ __init__.py # Utils package init
βββ config.py # Configuration management
βββ encoders.py # Text encoding utilities
βββ image_gen.py # Image generation utilities
βββ indexer.py # Vector indexing (FAISS)
βββ latex_utils.py # LaTeX processing utilities
βββ retriever.py # RAG pipeline with LLM
| Variable | Default | Description |
|---|---|---|
DATA_PATH | /data/arxiv_2.9k.jsonl | Path to dataset file |
INDEX_DIR | /app/index | Directory for vector index |
MODEL_PATH | /app/models/llama-model.gguf | Path to LLM model |
IMAGE_API_PROVIDER | pollinations | Image generation provider |
IMAGE_API_KEY | (empty) | API key for OpenAI (if using) |
No configuration needed! It works out of the box.
docker run --rm -p 8080:8080 \
-e DATA_PATH=/data/arxiv_2.9k.jsonl \
-v $(pwd)/arxiv_2.9k.jsonl:/data/arxiv_2.9k.jsonl:ro \
navedanan/genai-app:latest
Requires an OpenAI API key:
docker run --rm -p 8080:8080 \
-e DATA_PATH=/data/arxiv_2.9k.jsonl \
-e IMAGE_API_PROVIDER=openai \
-e IMAGE_API_KEY=sk-your-api-key-here \
-v $(pwd)/arxiv_2.9k.jsonl:/data/arxiv_2.9k.jsonl:ro \
navedanan/genai-app:latest
/answerQuery the system and get a complete answer.
Request:
{
"query": "What are recent advances in transformers?",
"generate_image": false,
"top_k": 5
}
Response:
{
"answer": "Recent advances in transformers include...",
"citations": [
{"doc_id": "2509.01234", "title": "A New Approach to Transformers"}
],
"retrieved_context": ["Abstract text..."],
"image_url": null
}
/streamStream the answer generation (Server-Sent Events).
[!NOTE] Because of curl's buffering behavior, It buffers the output and doesn't display Server-Sent Events (SSE) in real-time. This is a common problem with streaming endpoints. for real-time update use CLI command with --stream flag
curl -X POST http://localhost:8080/stream \
-H "Content-Type: application/json" \
-d '{"query": "Tell me about neural networks"}'
/healthCheck system health and statistics.
curl http://localhost:8080/health
/statsGet indexing statistics.
curl http://localhost:8080/stats
The system expects a .jsonl file where each line is a JSON object. Based on the arxiv dataset structure:
{
"id": "2509.21245v1",
"submitter": "Team Hunyuan3D",
"authors": "Bowen Zhang, Chunchao Guo, Haolin Liu, Hongyu Yan, ...",
"title": "Hunyuan3D-Omni: A Unified Framework for Controllable Generation of 3D Assets",
"comments": "Technical Report; 3D Generation",
"journal-ref": "",
"doi": "",
"categories": "cs.CV cs.AI",
"abstract": "Recent advances in 3D-native generative models have accelerated asset creation for games, film, and design. However, most methods still rely primarily on image or text conditioning and lack fine-grained, cross-modal controls...",
"source": "arxiv"
}
Required fields (system will skip records without these):
id: Unique document identifier (e.g., "2509.21245v1")title: Paper title (used for citations and reranking)abstract: Full abstract text (used for embeddings and retrieval)Optional fields (preserved but not used):
authors: Author names (comma-separated)submitter: Paper submittercategories: Subject categories (e.g., "cs.CV cs.AI")comments: Additional metadatajournal-ref: Journal referencedoi: Digital Object Identifiersource: Data source (e.g., "arxiv")The system automatically:
Processed 500 documents...
Line 234: Missing required fields, skipping
Line 567: JSON decode error, skipping - Expecting ',' delimiter
Processed 1000 documents...
...
Loaded 2897 documents (3 records skipped)
The system automatically detects dataset changes:
docker run --rm -p 8080:8080 \
-e DATA_PATH=/data/new_dataset.jsonl \
-v $(pwd)/new_dataset.jsonl:/data/new_dataset.jsonl:ro \
navedanan/genai-app:latest
The default configuration is optimized for CPU:
To enable GPU support:
Dockerfile to use GPU-enabled llama-cpp:RUN pip install llama-cpp-python --extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cu124
docker run --rm --gpus all -p 8080:8080 \
-e DATA_PATH=/data/arxiv_2.9k.jsonl \
-v $(pwd)/arxiv_2.9k.jsonl:/data/arxiv_2.9k.jsonl:ro \
navedanan/genai-app:latest
retriever.py to set n_gpu_layers:self.llm = Llama(
model_path=model_path,
n_gpu_layers=35, # Adjust based on GPU memory
...
)
curl -X POST http://localhost:8080/answer \
-H "Content-Type: application/json" \
-d '{
"query": "What are recent advances in natural language processing?",
"generate_image": false,
"top_k": 5
}'
curl -X POST http://localhost:8080/answer \
-H "Content-Type: application/json" \
-d '{
"query": "Explain deep learning architectures",
"generate_image": true,
"top_k": 3
}'
You can choose between two embedding models based on your needs:
allenai/specter2_baseallenai/specter2 (proximity) - For document retrievalallenai/specter2_adhoc_query - For ad-hoc queriesallenai/specter2_classification - For classification tasksadapter-transformers libraryall-mpnet-base-v2Configuration: Set EMBEDDING_MODEL in .env file:
# For scientific papers (more accurate, slower)
EMBEDDING_MODEL=allenai/specter2_base
# For general use (faster, good accuracy)
EMBEDDING_MODEL=all-mpnet-base-v2 # Default
# Use a different port
docker run --rm -p 8081:8080 ...
# Access at http://localhost:8081
# Increase Docker memory allocation or use smaller model
# Adjust N_GPU_LAYERS or switch to CPU-only mode
top_k parameter# Verify the volume mount path matches DATA_PATH
docker run --rm -p 8080:8080 \
-e DATA_PATH=/data/arxiv_2.9k.jsonl \
-v /absolute/path/to/arxiv_2.9k.jsonl:/data/arxiv_2.9k.jsonl:ro \
navedanan/genai-app:latest
For detailed setup and configuration guides, see:
For CLI usage, run: python main.py --help
To run completely offline with all models stored locally:
# 1. Download all models (requires internet, one-time)
python tools/download_models.py --all
# 2. Configure for offline mode (edit .env)
EMBEDDING_LOCAL_ONLY=true
EMBEDDING_CACHE_DIR=models/embeddings
# 3. Validate offline setup
python tools/validate_offline.py
# 4. Run the application
python main.py
See Documentation/OFFLINE_SETUP.md for detailed instructions.
This project is licensed under the MIT License - see the LICENSE file for details.
Copyright (c) 2025 Naved Danan
For issues or questions, please refer to the documentation or create an issue in the repository.
A fully self-contained Retrieval-Augmented Generation (RAG) system for querying academic abstracts using local LLMs and vector search.
Python
1
19 commits
updated Dec 20, 2025
A fully self-contained Retrieval-Augmented Generation (RAG) system for querying academic abstracts using local LLMs and vector search.
/answer and /stream endpoints for programmatic accessβββββββββββββββ
β Dataset β (.jsonl)
β (abstracts) β
ββββββββ¬βββββββ
β
βΌ
βββββββββββββββ
β Indexer β (sentence-transformers + FAISS)
β Embeddings β
ββββββββ¬βββββββ
β
βΌ
βββββββββββββββ ββββββββββββββββ
β Retriever β ββββΆ β Local LLM β (Llama-3.2-3B)
β (RAG) β β (llama.cpp) β
ββββββββ¬βββββββ ββββββββββββββββ
β
βΌ
βββββββββββββββ ββββββββββββββββ
β Web UI β β Image Gen β (Optional)
β (FastAPI) β ββββΆ β (External) β
βββββββββββββββ ββββββββββββββββ
# Clone or create the project directory
mkdir genai-rag && cd genai-rag
# Add all the code files (main.py, indexer.py, retriever.py, image_gen.py, index.html)
# Build the image
docker build -t navedanan/genai-app:latest .
docker run --rm -p 8080:8080 \
-e DATA_PATH=/data/arxiv_2.9k.jsonl \
-v $(pwd)/arxiv_2.9k.jsonl:/data/arxiv_2.9k.jsonl:ro \
navedanan/genai-app:latest
Open your browser and navigate to:
http://127.0.0.1:8080
{
"id": "2509.21245v1",
"submitter": "Team Hunyuan3D",
"authors": "Team Hunyuan3D, :, Bowen Zhang, Chunchao Guo, Haolin Liu, Hongyu Yan, Huiwen Shi, Jingwei Huang, Junlin Yu, Kunhong Li, Linus, Penghao Wang, Qingxiang Lin, Sicong Liu, Xianghui Yang, Yixuan Tang, Yunfei Zhao, Zeqiang Lai, Zhihao Liang, Zibo Zhao",
"title": "Hunyuan3D-Omni: A Unified Framework for Controllable Generation of 3D Assets",
"comments": "Technical Report; 3D Generation",
"journal-ref": "",
"doi": "",
"categories": "cs.CV cs.AI",
"abstract": "Recent advances in 3D-native generative models have accelerated asset creation for games, film, and design. However, most methods still rely primarily on image or text conditioning and lack fine-grained, cross-modal controls, which limits controllability and practical adoption. To address this gap, we present Hunyuan3D-Omni, a unified framework for fine-grained, controllable 3D asset generation built on Hunyuan3D 2.1. In addition to images, Hunyuan3D-Omni accepts point clouds, voxels, bounding boxes, and skeletal pose priors as conditioning signals, enabling precise control over geometry, topology, and pose. Instead of separate heads for each modality, our model unifies all signals in a single cross-modal architecture. We train with a progressive, difficulty-aware sampling strategy that selects one control modality per example and biases sampling toward harder signals (e.g., skeletal pose) while downweighting easier ones (e.g., point clouds), encouraging robust multi-modal fusion and graceful handling of missing inputs. Experiments show that these additional controls improve generation accuracy, enable geometry-aware transformations, and increase robustness for production workflows.",
"source": "arxiv"
}
RAG_PDF/
βββ Dockerfile # Docker configuration
βββ docker-compose.yml # Docker Compose configuration
βββ requirements.txt # Python dependencies
βββ pyproject.toml # Python project configuration
βββ README.md # This file
βββ DEPLOYMENT_CHECKLIST.md # Deployment checklist
βββ main.py # FastAPI application
βββ data/
β βββ arxiv_2.9k.jsonl # Dataset file
βββ Documentation/
β βββ ARCHITECTURE.md # System design and components
β βββ CONFIGURATION.md # Configuration options
β βββ DOCKER_DEPLOYMENT.md # Docker deployment guide
β βββ IMAGE_GENERATION.md # Image generation setup
β βββ LATEX_UTILS.md # LaTeX utilities documentation
β βββ OFFLINE_SETUP.md # Offline/air-gapped deployment
β βββ QUICKSTART.md # Quick start guide
βββ index/
β βββ dataset_hash.txt # Dataset hash for change detection
β βββ embeddings.npy # Cached embeddings
β βββ faiss.index # FAISS vector index
βββ models/
β βββ Llama-3.2-3B-Instruct-Q4_K_M.gguf # Main LLM model
β βββ llama-model.gguf # Symlink to active LLM
β βββ Qwen3-4B-Instruct-2507-Q4_K_M.gguf # Alternative LLM
β βββ embeddings/ # Embedding models cache
β βββ sdxl-turbo/ # SDXL Turbo model
β βββ stable-diffusion-3.5-medium/ # SD 3.5 Medium model
βββ static/
β βββ index.html # Web UI
β βββ generated_images/ # Generated images cache
βββ tests/
β βββ evaluate_rag.py # RAG evaluation tests
β βββ test_api.py # API endpoint tests
β βββ test_image_gen.py # Image generation tests
β βββ test_sd35_local.py # SD 3.5 local tests
β βββ test_sd35.py # SD 3.5 tests
βββ tools/
β βββ docker_build.ps1 # Docker build script (PowerShell)
β βββ docker_build.sh # Docker build script (Bash)
β βββ download_models.py # Model download utility
β βββ sample_generator.py # Sample data generator
β βββ validate_offline.py # Offline setup validator
βββ utils/
βββ __init__.py # Utils package init
βββ config.py # Configuration management
βββ encoders.py # Text encoding utilities
βββ image_gen.py # Image generation utilities
βββ indexer.py # Vector indexing (FAISS)
βββ latex_utils.py # LaTeX processing utilities
βββ retriever.py # RAG pipeline with LLM
| Variable | Default | Description |
|---|---|---|
DATA_PATH | /data/arxiv_2.9k.jsonl | Path to dataset file |
INDEX_DIR | /app/index | Directory for vector index |
MODEL_PATH | /app/models/llama-model.gguf | Path to LLM model |
IMAGE_API_PROVIDER | pollinations | Image generation provider |
IMAGE_API_KEY | (empty) | API key for OpenAI (if using) |
No configuration needed! It works out of the box.
docker run --rm -p 8080:8080 \
-e DATA_PATH=/data/arxiv_2.9k.jsonl \
-v $(pwd)/arxiv_2.9k.jsonl:/data/arxiv_2.9k.jsonl:ro \
navedanan/genai-app:latest
Requires an OpenAI API key:
docker run --rm -p 8080:8080 \
-e DATA_PATH=/data/arxiv_2.9k.jsonl \
-e IMAGE_API_PROVIDER=openai \
-e IMAGE_API_KEY=sk-your-api-key-here \
-v $(pwd)/arxiv_2.9k.jsonl:/data/arxiv_2.9k.jsonl:ro \
navedanan/genai-app:latest
/answerQuery the system and get a complete answer.
Request:
{
"query": "What are recent advances in transformers?",
"generate_image": false,
"top_k": 5
}
Response:
{
"answer": "Recent advances in transformers include...",
"citations": [
{"doc_id": "2509.01234", "title": "A New Approach to Transformers"}
],
"retrieved_context": ["Abstract text..."],
"image_url": null
}
/streamStream the answer generation (Server-Sent Events).
[!NOTE] Because of curl's buffering behavior, It buffers the output and doesn't display Server-Sent Events (SSE) in real-time. This is a common problem with streaming endpoints. for real-time update use CLI command with --stream flag
curl -X POST http://localhost:8080/stream \
-H "Content-Type: application/json" \
-d '{"query": "Tell me about neural networks"}'
/healthCheck system health and statistics.
curl http://localhost:8080/health
/statsGet indexing statistics.
curl http://localhost:8080/stats
The system expects a .jsonl file where each line is a JSON object. Based on the arxiv dataset structure:
{
"id": "2509.21245v1",
"submitter": "Team Hunyuan3D",
"authors": "Bowen Zhang, Chunchao Guo, Haolin Liu, Hongyu Yan, ...",
"title": "Hunyuan3D-Omni: A Unified Framework for Controllable Generation of 3D Assets",
"comments": "Technical Report; 3D Generation",
"journal-ref": "",
"doi": "",
"categories": "cs.CV cs.AI",
"abstract": "Recent advances in 3D-native generative models have accelerated asset creation for games, film, and design. However, most methods still rely primarily on image or text conditioning and lack fine-grained, cross-modal controls...",
"source": "arxiv"
}
Required fields (system will skip records without these):
id: Unique document identifier (e.g., "2509.21245v1")title: Paper title (used for citations and reranking)abstract: Full abstract text (used for embeddings and retrieval)Optional fields (preserved but not used):
authors: Author names (comma-separated)submitter: Paper submittercategories: Subject categories (e.g., "cs.CV cs.AI")comments: Additional metadatajournal-ref: Journal referencedoi: Digital Object Identifiersource: Data source (e.g., "arxiv")The system automatically:
Processed 500 documents...
Line 234: Missing required fields, skipping
Line 567: JSON decode error, skipping - Expecting ',' delimiter
Processed 1000 documents...
...
Loaded 2897 documents (3 records skipped)
The system automatically detects dataset changes:
docker run --rm -p 8080:8080 \
-e DATA_PATH=/data/new_dataset.jsonl \
-v $(pwd)/new_dataset.jsonl:/data/new_dataset.jsonl:ro \
navedanan/genai-app:latest
The default configuration is optimized for CPU:
To enable GPU support:
Dockerfile to use GPU-enabled llama-cpp:RUN pip install llama-cpp-python --extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cu124
docker run --rm --gpus all -p 8080:8080 \
-e DATA_PATH=/data/arxiv_2.9k.jsonl \
-v $(pwd)/arxiv_2.9k.jsonl:/data/arxiv_2.9k.jsonl:ro \
navedanan/genai-app:latest
retriever.py to set n_gpu_layers:self.llm = Llama(
model_path=model_path,
n_gpu_layers=35, # Adjust based on GPU memory
...
)
curl -X POST http://localhost:8080/answer \
-H "Content-Type: application/json" \
-d '{
"query": "What are recent advances in natural language processing?",
"generate_image": false,
"top_k": 5
}'
curl -X POST http://localhost:8080/answer \
-H "Content-Type: application/json" \
-d '{
"query": "Explain deep learning architectures",
"generate_image": true,
"top_k": 3
}'
You can choose between two embedding models based on your needs:
allenai/specter2_baseallenai/specter2 (proximity) - For document retrievalallenai/specter2_adhoc_query - For ad-hoc queriesallenai/specter2_classification - For classification tasksadapter-transformers libraryall-mpnet-base-v2Configuration: Set EMBEDDING_MODEL in .env file:
# For scientific papers (more accurate, slower)
EMBEDDING_MODEL=allenai/specter2_base
# For general use (faster, good accuracy)
EMBEDDING_MODEL=all-mpnet-base-v2 # Default
# Use a different port
docker run --rm -p 8081:8080 ...
# Access at http://localhost:8081
# Increase Docker memory allocation or use smaller model
# Adjust N_GPU_LAYERS or switch to CPU-only mode
top_k parameter# Verify the volume mount path matches DATA_PATH
docker run --rm -p 8080:8080 \
-e DATA_PATH=/data/arxiv_2.9k.jsonl \
-v /absolute/path/to/arxiv_2.9k.jsonl:/data/arxiv_2.9k.jsonl:ro \
navedanan/genai-app:latest
For detailed setup and configuration guides, see:
For CLI usage, run: python main.py --help
To run completely offline with all models stored locally:
# 1. Download all models (requires internet, one-time)
python tools/download_models.py --all
# 2. Configure for offline mode (edit .env)
EMBEDDING_LOCAL_ONLY=true
EMBEDDING_CACHE_DIR=models/embeddings
# 3. Validate offline setup
python tools/validate_offline.py
# 4. Run the application
python main.py
See Documentation/OFFLINE_SETUP.md for detailed instructions.
This project is licensed under the MIT License - see the LICENSE file for details.
Copyright (c) 2025 Naved Danan
For issues or questions, please refer to the documentation or create an issue in the repository.