Instructions to use aelgendy/QModel with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use aelgendy/QModel with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf aelgendy/QModel:Q8_0 # Run inference directly in the terminal: llama cli -hf aelgendy/QModel:Q8_0
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf aelgendy/QModel:Q8_0 # Run inference directly in the terminal: llama cli -hf aelgendy/QModel:Q8_0
Build from source code
git clone https://github.com/ggml-org/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-app # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama serve -hf aelgendy/QModel:Q8_0 # Run inference directly in the terminal: ./build/bin/llama cli -hf aelgendy/QModel:Q8_0
Use Docker
docker model run hf.co/aelgendy/QModel:Q8_0
- Llama new
- LM Studio
- Jan
- Ollama
How to use aelgendy/QModel with Ollama:
ollama run hf.co/aelgendy/QModel:Q8_0
- Unsloth Desktop
- Pi
How to use aelgendy/QModel with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf aelgendy/QModel:Q8_0
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "aelgendy/QModel:Q8_0" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use aelgendy/QModel with Docker Model Runner:
docker model run hf.co/aelgendy/QModel:Q8_0
- Lemonade
How to use aelgendy/QModel with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull aelgendy/QModel:Q8_0
Run and chat with the model
lemonade run user.QModel-Q8_0
List all available models
lemonade list
- Hermes Agent
How to use aelgendy/QModel with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf aelgendy/QModel:Q8_0
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default aelgendy/QModel:Q8_0
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use aelgendy/QModel with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf aelgendy/QModel:Q8_0
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "aelgendy/QModel:Q8_0" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
QModel v8.5 β Islamic RAG System
Specialized Qur'an, Hadith & Fatwa Knowledge System with Multi-Vector RAG & Dual LLM Support
A production-ready Retrieval-Augmented Generation system specialized exclusively in authenticated Islamic knowledge. No hallucinations, no outside knowledgeβonly content from verified sources.
Features
π Qur'an Capabilities
- Verse Lookup: Find verses by topic or keyword
- Word Frequency: Count occurrences with Surah breakdown
- Root Analysis: Explore verses sharing the same 3-letter Arabic root with curated root dictionaries
- Parent-Document Windowing: Automatic $\pm 1$ verse context expansion for complete theological context
- Bilingual: Full Arabic + English translation support
- Tafsir Integration: Expanded contextual interpretation (up to 1,200 characters)
π Hadith Capabilities
- Isnad Highlighting: Chain of narrators emphasized in responses
- Authenticity Verification: Check if Hadith is in authenticated collections
- Grade Display: Show Sahih/Hasan/Da'if authenticity levels
- Matn Deduplication: Redundant narrations consolidated with Muttafaq 'Alayh detection
- Cross-Collection References: Displays alternative canonical collections (e.g. Bukhari, Muslim, Abu Dawood)
- Topic Search: Find relevant Hadiths across 9 major collections
- Collection Navigation: Filter by Bukhari, Muslim, Abu Dawud, etc.
βοΈ Fatwa & Fiqh Capabilities
- Verified Scholarly Rulings: 3,598 fatwas from Islamweb's Fatwa Center (Ω Ψ±ΩΨ² Ψ§ΩΩΨͺΩΩ) and Imam Ibn Baz
- Semantic & Source Filtering: Filter fatwas by scholar, council, or source
- Integrated RAG Context: Rulings retrieved alongside Quran and Hadith evidence
- Direct Lookup: Fast endpoint access via
/fatwa/{id},/fatwa/search, and/fatwa/sources
π‘οΈ Safety Features
- Relevance Gating: The LLM is only called when retrieval found something genuinely relevant (exact reference/text match, else the cross-encoder's relevance score); out-of-scope requests get a fixed "not found" answer
- Reasoning Support: Capture and stream model thinking/Chain-of-Thought
- Source Attribution: Every answer cites exact verse, Hadith, or Fatwa reference β hadith by collection and number, fatwas by source link (added automatically when the model omits it)
- Verbatim Scripture: Quoted verses and hadith (
ο΄Ώ...ο΄Ύ,β...β,Β«...Β») are checked against the retrieved passages; near-copies are restored to the canonical text, ungrounded quotes are removed - Language Guard: Answers that drift into Chinese are regenerated (or cut off when streaming)
π Integration
- OpenAI-Compatible API: Use with Open-WebUI, Langchain, or any OpenAI client
- OpenAI Schema: Full support for
/v1/chat/completionsand/v1/models - Streaming Responses: SSE streaming for long-form answers
- Conversational Multi-Turn Memory: Coreference resolution for continuous contextual dialogues
βοΈ Technical & RAG Architecture
- Asymmetric E5 Embedding: Proper
passage:andquery:prefixes for optimal vector similarity - Multi-Vector Dense Retrieval: Independent Arabic and English query vectors fused adaptively
- Inverted BM25 Sparse Index: Bilingual tokenization with stopword filtering and morphological root indexing
- Adaptive RRF Fusion: Language-weighted Reciprocal Rank Fusion balancing dense & sparse signals
- Cross-Encoder Reranker:
BAAI/bge-reranker-v2-m3rescoring and confidence gating (on by default) - Triple LLM Backend: Local GGUF, Ollama (dev), or HuggingFace (prod)
- Async API & Caching: FastAPI with TTL-based LRU response cache
Quick Start
Prerequisites
- Python 3.10+
- 16 GB RAM minimum (for embeddings + LLM)
- GPU recommended for HuggingFace backend
- Ollama installed (for local development) OR internet access (for HuggingFace)
Installation
# Download code + search index from Hugging Face (skips the 15 GB GGUF)
huggingface-cli download aelgendy/QModel --exclude "models/*" --local-dir QModel && cd QModel
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
# Configure (choose one backend)
# Option A β GGUF (self-contained, default):
export LLM_BACKEND=gguf
export GGUF_MODEL_PATH=./models/Qwen2.5-14B-Instruct-Q8_0.gguf
huggingface-cli download bartowski/Qwen2.5-14B-Instruct-GGUF Qwen2.5-14B-Instruct-Q8_0.gguf --local-dir ./models
# Option B β Ollama:
ollama pull arelgendy/qmodel:8.5 # or: ollama pull hf.co/aelgendy/QModel
export LLM_BACKEND=ollama
export OLLAMA_MODEL=arelgendy/qmodel:8.5
# Make sure Ollama is running: ollama serve
# Option C β HuggingFace (production):
export LLM_BACKEND=hf
export HF_MODEL_NAME=Qwen/Qwen2.5-14B-Instruct
# Run
python main.py
# Query
curl "http://localhost:8000/ask?q=What%20does%20Islam%20say%20about%20mercy?"
API docs: http://localhost:8000/docs
Data & Index
Pre-built data files are included:
metadata.jsonβ 56,250 documents (6,236 Quran verses + 46,416 hadiths from 15 collections + 3,598 fatwas)QModel.indexβ FAISS search index (~220 MB, 56,250 vectors, 1024-d)
To rebuild after dataset changes:
python build_index.py
Fatwas are read from data/fatwas/ (hand-collected) and data/fatwas_scraped/ (scraper output), de-duplicated by id and content; files listed in FATWA_EXCLUDE in build_index.py are skipped. To add fatwas without re-embedding the Qur'an and hadith:
python data_pipeline/scrape_fatwas.py --source islamweb --start 8001 --end 12000 --delay 1.0
python scripts/update_fatwa_index.py # writes QModel.fatwa-update.index / metadata.fatwa-update.json
python scripts/update_fatwa_index.py --in-place # or replace the live files (previous pair saved as .bak, overwriting older .bak)
Records without answer text, and scraped listing pages (e.g. audio-lecture indexes), are skipped.
Example Queries
# Basic question
curl "http://localhost:8000/ask?q=What%20does%20Islam%20say%20about%20mercy?"
# Word frequency
curl "http://localhost:8000/ask?q=How%20many%20times%20is%20mercy%20mentioned?"
# Authentic Hadiths only
curl "http://localhost:8000/ask?q=prayer&source_type=hadith&grade_filter=sahih"
# Quran text search
curl "http://localhost:8000/quran/search?q=bismillah"
# Quran topic search
curl "http://localhost:8000/quran/topic?topic=patience&top_k=5"
# Quran word frequency
curl "http://localhost:8000/quran/word-frequency?word=mercy"
# Single chapter
curl "http://localhost:8000/quran/chapter/2"
# Exact verse
curl "http://localhost:8000/quran/verse/2:255"
# Root-word analysis
curl "http://localhost:8000/quran/root/Ψ±ΨΩ
"
# Hadith text search
curl "http://localhost:8000/hadith/search?q=actions+are+judged+by+intentions"
# Hadith topic search (Sahih only)
curl "http://localhost:8000/hadith/topic?topic=fasting&grade_filter=sahih"
# Verify Hadith authenticity
curl "http://localhost:8000/hadith/verify?q=Actions%20are%20judged%20by%20intentions"
# Browse a collection
curl "http://localhost:8000/hadith/collection/bukhari?limit=5"
# Fatwa topic search (with scholar filter)
curl "http://localhost:8000/fatwa/search?q=Ψ§ΩΩΨ΅ΩΨ©&source=BinBaz&top_k=3"
# Fatwa direct ID lookup
curl "http://localhost:8000/fatwa/fatwa_binbaz_4210"
# List loaded Fatwa collections
curl "http://localhost:8000/fatwa/sources"
# Streaming (OpenAI-compatible)
curl -X POST http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"QModel","messages":[{"role":"user","content":"What does Islam say about charity?"}],"stream":true}'
Configuration
All configuration via environment variables (.env file or exported directly):
Backend Selection
| Backend | Pros | Cons | When to Use |
|---|---|---|---|
| GGUF | Self-contained, no external daemon, bundles with the repo/Space | Larger image/repo size | HF Spaces, offline/portable deployment |
| Ollama | Fast setup, no GPU, free | Smaller models, requires separate daemon | Development, testing |
| HuggingFace | Larger models, better quality | Requires GPU or significant RAM | Production |
GGUF Backend (Self-contained)
LLM_BACKEND=gguf
GGUF_MODEL_PATH=./models/Qwen2.5-14B-Instruct-Q8_0.gguf
GGUF_N_CTX=8192
GGUF_N_GPU_LAYERS=-1 # -1 = offload all layers to GPU, 0 = CPU-only
Requires the .gguf file to be present at GGUF_MODEL_PATH β download with:
huggingface-cli download bartowski/Qwen2.5-14B-Instruct-GGUF Qwen2.5-14B-Instruct-Q8_0.gguf --local-dir ./models
Model Profile
| Model | Size (Q8_0) |
RAM / VRAM | Generation Speed | Best Use Case |
|---|---|---|---|---|
| Qwen2.5-14B-Instruct (Default) | ~15 GB | ~16 GB | Blazing (~55 tok/s) | Production, Hugging Face Hub, and local GPU deployment |
Ollama Backend (Development)
ollama pull arelgendy/qmodel:8.5
LLM_BACKEND=ollama
OLLAMA_HOST=http://localhost:11434
OLLAMA_MODEL=arelgendy/qmodel:8.5
Requires ollama serve running. The model is published in two places, both built from Modelfile (chat template, system prompt and sampling settings):
| Source | Pull | Tags |
|---|---|---|
| ollama.com | ollama pull arelgendy/qmodel:8.5 |
release versions (8.5, latest) |
| Hugging Face | ollama pull hf.co/aelgendy/QModel |
quantization only (Q8_0); reads the repo's template, system and params files |
ollama run arelgendy/qmodelon its own gives the bare language model, without retrieval, citation checks or verse links. For grounded answers, run the QModel API withLLM_BACKEND=ollamaand send questions to it (or to Open-WebUI connected to it).
HuggingFace Backend (Production)
LLM_BACKEND=hf
HF_MODEL_NAME=Qwen/Qwen2.5-14B-Instruct
HF_DEVICE=auto # auto | cuda | cpu
HF_MAX_NEW_TOKENS=2048
All Environment Variables
| Variable | Default | Description |
|---|---|---|
| Backend | ||
LLM_BACKEND |
gguf |
gguf, ollama, or hf |
GGUF_MODEL_PATH |
./models/Qwen2.5-14B-Instruct-Q8_0.gguf |
Path to local .gguf file |
GGUF_N_CTX |
8192 |
Context window size |
GGUF_N_GPU_LAYERS |
-1 |
Layers to offload to GPU (-1 = all, 0 = CPU-only) |
OLLAMA_HOST |
http://localhost:11434 |
Ollama server URL |
OLLAMA_MODEL |
qwen2.5:14b |
Ollama model name |
HF_MODEL_NAME |
Qwen/Qwen2.5-14B-Instruct |
HuggingFace model ID |
HF_DEVICE |
auto |
auto, cuda, or cpu |
HF_MAX_NEW_TOKENS |
2048 |
Max output length |
| Embedding & Data | ||
EMBED_MODEL |
intfloat/multilingual-e5-large |
Embedding model |
FAISS_INDEX |
QModel.index |
Index file path |
METADATA_FILE |
metadata.json |
Dataset file |
| Retrieval | ||
TOP_K_SEARCH |
20 |
Candidate pool (5β100) |
TOP_K_RETURN |
5 |
Results shown to user (1β20) |
RERANK_ALPHA |
0.6 |
Dense vs Sparse weight (0.0β1.0) |
FAST_QUERY_REWRITE |
true |
Rewrite queries without the LLM (regex intent + thesaurus terms), saving ~2 s per question. The LLM rewrite still runs for follow-up questions with chat history |
USE_RERANKER |
true |
Cross-encoder reranker (true/false). Also drives the confidence gate: off-topic questions refused 92% with it vs 36% without |
RERANK_MODEL |
BAAI/bge-reranker-v2-m3 |
Cross-encoder model ID |
AYAH_WINDOW_SIZE |
1 |
Number of neighboring verses for context expansion |
ENABLE_HADITH_DEDUPLICATION |
true |
Cluster near-identical Hadith narrations |
TAFSIR_MAX_CHARS |
1200 |
Max Tafsir characters provided in LLM context |
| Generation | ||
TEMPERATURE |
0.2 |
Creativity (0.0β1.0, use 0.1β0.2 for religious) |
MAX_TOKENS |
2048 |
Max response length |
SHOW_THINKING |
false |
Include chain-of-thought/reasoning output (true/false) |
| Safety | ||
RERANK_MIN_SCORE |
0.05 |
Confidence gate with reranker on: min cross-encoder relevance (0β1) of the best retrieved passage to call the LLM |
DENSE_MIN_SCORE |
0.80 |
Confidence gate with reranker off: min dense cosine similarity (multilingual-e5-large scale) |
HADITH_BOOST |
0.08 |
Score boost for hadith on hadith queries |
QURAN_BOOST |
0.12 |
Score boost for Quran verses on tafsir/quran queries |
| Other | ||
CACHE_SIZE |
512 |
Query response cache entries |
CACHE_TTL |
3600 |
Cache expiry in seconds |
ALLOWED_ORIGINS |
* |
CORS origins |
MAX_EXAMPLES |
3 |
Few-shot examples in system prompt |
Configuration Examples
Self-contained (GGUF, e.g. HF Spaces)
LLM_BACKEND=gguf
GGUF_MODEL_PATH=./models/Qwen2.5-14B-Instruct-Q8_0.gguf
GGUF_N_CTX=8192
GGUF_N_GPU_LAYERS=-1
TEMPERATURE=0.2
Development (Ollama)
LLM_BACKEND=ollama
OLLAMA_HOST=http://localhost:11434
OLLAMA_MODEL=arelgendy/qmodel:8.5
TEMPERATURE=0.2
ALLOWED_ORIGINS=*
Production (HuggingFace + GPU)
LLM_BACKEND=hf
HF_MODEL_NAME=Qwen/Qwen2.5-14B-Instruct
HF_DEVICE=cuda
TOP_K_SEARCH=30
TEMPERATURE=0.1
USE_RERANKER=true
ALLOWED_ORIGINS=yourdomain.com,api.yourdomain.com
Tuning Tips
- Better results: keep
USE_RERANKER=true(the default: better ranking and a far more reliable confidence gate, ~1 s per answer), increaseTOP_K_SEARCH, useTEMPERATURE=0.1 - Faster performance: Lower
TOP_K_SEARCHandTOP_K_RETURN, reduceMAX_TOKENS, use Ollama - More conservative: Increase
RERANK_MIN_SCORE/DENSE_MIN_SCORE, lowerTEMPERATUREβ check the trade-off withpython -m eval.run_eval --show-failures
Measuring Retrieval Accuracy
eval/golden.jsonl holds 147 labelled queries (Qur'an topic/text/reference, Hadith topic/text/authenticity, Fatwa, and out-of-scope negatives). Each case lists the dataset ids that count as a correct hit; where one source is decisive (5:90 for "is alcohol forbidden?", while 2:219 alone would mislead), it is also listed under required and scored as complete@k. eval/run_eval.py runs them through retrieval (no LLM generation) using the local index:
python -m eval.run_eval --out eval/results/baseline.json # full pipeline, k = TOP_K_RETURN
python -m eval.run_eval --mode hybrid --k 20 # hybrid_search() alone
python -m eval.run_eval --only fatwa,negative --show-failures # subset + list misses
python -m eval.run_eval --compare eval/results/baseline.json # diff against a previous run
It reports Hit@1/3/k, MRR and Recall@k overall, by category and by language, plus the confidence gate's false-reject rate (answer found but refused) and false-accept rate (out-of-scope queries let through). Run it before and after any retrieval or config change; env vars such as USE_RERANKER=false or TOP_K_SEARCH=100 apply as usual.
Measuring Answer Quality
eval/run_answers.py runs the same golden set through the full pipeline with the LLM and checks what users read:
python -m eval.run_answers --limit 5 # smoke test
python -m eval.run_answers --only hadith_text,fatwa # subset
python -m eval.run_answers --out eval/results/answers.json # full run (~1 h at ~25 s/answer)
- Refusals: out-of-scope questions get the "not found" answer; real ones don't
- Citations: every cited verse / hadith / fatwa was retrieved, at least one is a golden-relevant source, and all
requiredsources are cited - Quotes: scripture quoted by the model, before verification β verbatim, altered copy of a real verse, or fabricated β and how many the verifier restored or removed
- Language: answer matches the question's language, no CJK leakage
Every answer is saved in the report for manual review.
The labels themselves need expert review: eval/label_review.csv lists every golden label (question, labelled source and its text) with columns for a reviewer's verdict. Categories with 5β11 cases move 10β20 points on a single case, so read per-category numbers with that in mind.
Docker Deployment
Docker Compose (Recommended)
docker-compose.yml is production-safe by default: it does not bind-mount
the repo, and it mounts QModel.index/metadata.json read-only so a dataset
update doesn't require an image rebuild. docker-compose.override.yml is
picked up automatically for local dev and layers a full repo bind-mount on
top for live code reload.
cp .env.example .env # Configure backend (see Configuration section)
# Development (live code reload via docker-compose.override.yml)
docker-compose up
# Production (base file only, no bind-mount β runs the image's own code)
docker-compose -f docker-compose.yml up -d
Docker CLI
docker build -t qmodel .
# With Ollama backend
docker run -p 8000:8000 \
--env-file .env \
--add-host host.docker.internal:host-gateway \
qmodel
# With HuggingFace backend
docker run -p 8000:8000 \
--env-file .env \
--env HF_TOKEN=your_token_here \
qmodel
Docker with GGUF
# .env
LLM_BACKEND=gguf
GGUF_MODEL_PATH=./models/Qwen2.5-14B-Instruct-Q8_0.gguf
GGUF_N_CTX=8192
GGUF_N_GPU_LAYERS=-1
The .gguf file must be present under ./models/ before building/running the
image (see download command in GGUF Backend) β
no external daemon or network access needed at runtime, which is what makes
this backend suitable for bundling directly into an HF Space.
Docker with Ollama
# .env
LLM_BACKEND=ollama
OLLAMA_HOST=http://host.docker.internal:11434
OLLAMA_MODEL=arelgendy/qmodel:8.5
Requires Ollama running on the host (ollama serve).
Docker with HuggingFace
# .env
LLM_BACKEND=hf
HF_MODEL_NAME=Qwen/Qwen2.5-14B-Instruct
HF_DEVICE=auto
# Pass HF token
export HF_TOKEN=hf_xxxxxxxxxxxxx
docker-compose up
Docker Compose with GPU (Linux)
The shipped Dockerfile installs the CPU-only torch wheel (paired with
faiss-cpu) to keep the image small. That build cannot use a GPU even if one
is passed through. For real GPU acceleration, build a variant that installs
the CUDA-enabled torch wheel instead (drop the --extra-index-url https://download.pytorch.org/whl/cpu line in the builder stage), then add:
services:
qmodel:
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
Production Tips
- Deploy with
docker-compose -f docker-compose.yml up -dso the dev-onlydocker-compose.override.yml(full repo bind-mount) isn't applied β the base file already omits it, restarts withon-failure:5, and mounts the data files read-only. - Use specific
ALLOWED_ORIGINSinstead of*
Open-WebUI Integration
QModel is fully OpenAI-compatible and works out of the box with Open-WebUI.
Setup
# Start QModel
python main.py
# Start Open-WebUI
docker run -d -p 3000:8080 --name open-webui ghcr.io/open-webui/open-webui:latest
Connect
- Settings β Models β Manage Models
- Click "Connect to OpenAI-compatible API"
- API Base URL:
http://localhost:8000/v1 - Model Name:
QModel - API Key: Leave blank
- Save & Test β β Connected
Docker Compose (QModel + Ollama + Open-WebUI)
version: '3.8'
services:
qmodel:
build: .
ports:
- "8000:8000"
environment:
- LLM_BACKEND=ollama
- OLLAMA_HOST=http://ollama:11434
ollama:
image: ollama/ollama:latest
ports:
- "11434:11434"
web-ui:
image: ghcr.io/open-webui/open-webui:latest
ports:
- "3000:8080"
depends_on:
- qmodel
Supported Features
| Feature | Status |
|---|---|
| Chat | β Full support |
| Streaming | β
stream: true |
| Multi-turn context | β Handled by Open-WebUI |
| Temperature | β Configurable |
| Token limits | β
max_tokens |
| Model listing | β
/v1/models |
| Source attribution | β
x_metadata.sources |
Architecture
Module Structure
main.py β FastAPI app + router registration
build_index.py β Dataset compilation, E5 asymmetric embedding & FAISS indexing
app/
config.py β Config class (env vars)
llm.py β LLM providers (GGUF, Ollama, HuggingFace)
cache.py β TTL-LRU async cache
arabic_nlp.py β Arabic normalization, stopwords, Quranic root index
search.py β Multi-vector FAISS + BM25, RRF, clustering, windowing, reranker
analysis.py β Intent detection, analytics, counting
prompts.py β Prompt engineering (persona, anti-hallucination)
models.py β Pydantic schemas (Quran, Hadith, Fatwa, Chat)
state.py β AppState, lifespan, multi-turn RAG pipeline
routers/
quran.py β 6 Quran endpoints
hadith.py β 5 Hadith endpoints
fatwa.py β 3 Fatwa endpoints
chat.py β /ask + OpenAI-compatible chat
ops.py β health, models, debug scores
tests/
test_enhancements.py β Unit tests for multi-vector, windowing, clustering, roots
test_fatwa.py β Unit tests for fatwa endpoints & RAG integration
Data Pipeline
- Ingest: Multi-source Islamic knowledge base:
- Quran: 6,236 verses across 114 Surahs
- Hadith: 40,943 hadiths across 9 canonical collections
- Fatwa: Verified rulings from recognized scholars and fiqh councils
- Embed: Asymmetric encoding with
intfloat/multilingual-e5-large(passage:prefix for indexing,query:prefix for inference) - Index: FAISS
IndexFlatIPfor inner-product dense vector retrieval + inverted index for BM25
Retrieval & Ranking Pipeline
- Conversational Coreference Rewriting: Query rewriter accepts dialogue
historyto resolve ambiguous pronouns and anaphoric references into standalone topical queries. - Dual-Vector Query Embedding: Encodes both Arabic (
query_ar) and English (query_en) query vectors usingmultilingual-e5-largewith the mandatoryquery:prefix. - Multi-Vector Dense Retrieval: Independent FAISS searches against Arabic and English dense vectors.
- Inverted BM25 Sparse Retrieval: BM25 scoring with bilingual stopword removal and Quranic morphological root expansion. The light stemmer only strips an affix when at least 3 letters remain, so short words keep their root letters (ΩΨΆΩ, Ψ§ΩΨ±Ψ¨Ψ§).
- Adaptive Reciprocal Rank Fusion (RRF): Merges Arabic dense, English dense, and BM25 sparse hits with dynamic language-weighted multipliers.
- Hadith Deduplication & Ayah Windowing:
- Clusters duplicate Hadith narrations ($\ge 0.85$ text similarity), tags Muttafaq 'Alayh (Bukhari + Muslim), and aggregates alternative collection references.
- Expands top Quran verses with $\pm N$ adjacent verses (
AYAH_WINDOW_SIZE) for complete theological context.
- Cross-Encoder Reranking: Rescores the top 25 candidates using
BAAI/bge-reranker-v2-m3(USE_RERANKER, on by default). Five of those slots are reserved for the best BM25-only hits, which RRF would otherwise rank below anything both dense searches found. Each passage is scored with its text in the query's language first, since the reranker truncates at 512 tokens and a long diacritized verse fills that on its own. - Confidence Gating & Context Assembly: Direct references and verbatim text matches pass; otherwise the best reranker relevance must reach
RERANK_MIN_SCORE(or dense similarityDENSE_MIN_SCOREwithout the reranker). Context carries copyable citation lines:[REF](verse + URLs),[HADITH_REF](collection and number in English and Arabic, grade),[FATWA_REF](source, scholar, URL).
Anti-Hallucination Measures
- Relevance gate before generation (see step 8 above)
- Citation format rules and copyable
[REF]/[HADITH_REF]/[FATWA_REF]lines in the context - Scope rule: non-Islamic requests (poems, sports, trivia) get the fixed "not found" answer; the model must either answer from the context or refuse, never both
- Quote verification: a quote must appear in a retrieved passage; a near-copy of a retrieved verse or hadith (β₯80% of its consonant skeleton) is replaced by the canonical text, anything else by a warning marker. LLMs corrupt scripture while copying it (foreign letters, changed word forms, truncation), so this runs on every answer, streamed or not
- Fatwa links: when the answer uses a retrieved fatwa (by title or by naming its source) without linking it, the link is appended
- CJK guard: an answer containing Chinese/Japanese/Korean text is regenerated once at temperature 0, then replaced by a list of the retrieved sources; when streaming, CJK is stripped and generation stops after sustained drift
- Grade inference from collection name
Performance
| Operation | Time | Backend |
|---|---|---|
| Query (cached) | ~50ms | Both |
| Query (Ollama) | 400β800ms | Ollama |
| Query (HF GPU) | 500β1500ms | CUDA |
| Query (HF CPU) | 2β5s | CPU |
Troubleshooting
"Cannot connect to Ollama"
ollama serve # Ensure Ollama is running on host
# In Docker, use OLLAMA_HOST=http://host.docker.internal:11434
"HuggingFace model not found"
export HF_TOKEN=hf_xxxxxxxxxxxxx # Set token for gated models
"Out of memory"
- Use smaller model:
HF_MODEL_NAME=mistralai/Mistral-7B-Instruct-v0.2 - Use Ollama with
neural-chat - Reduce
MAX_TOKENSto 1024 - Increase Docker memory limit in
docker-compose.yml
"Assistant returns 'Not found'"
This is expected β QModel rejects low-confidence queries. Try:
- More specific queries
- Lower
RERANK_MIN_SCORE(reranker on) orDENSE_MIN_SCORE(reranker off) in.env - Check raw scores:
GET /debug/scores?q=your+query
"Port already in use"
docker-compose down && docker system prune
# Or change port: ports: ["8001:8000"]
Roadmap
- Batch processing (multiple questions per request)
- Islamic calendar integration (Hijri dates)
Data Sources
- Qur'an: risan/quran-json & semarketir/quranjson β 114 Surahs, 6,236 verses with Arabic text, transliteration, and English translation.
- Tafsir: Tafseer Dataset & Quran.com β 5,430 verses enriched with classical Arabic commentaries (Tafsir al-Sa'di, Tafsir al-Mukhtasar, Tafsir al-Jalalayn) + English Tafsir Ibn Kathir.
- Hadith: AhmedBaset/hadith-json & fawazahmed0/hadith-api β 15 authoritative collections (9 canonical + Riyad al-Salihin, Bulugh al-Maram, Al-Adab al-Mufrad, Ash-Shama'il al-Muhammadiyyah, An-Nawawi's 40 Hadith, Hadith Qudsi), 46,416 hadiths with 21,264 scholar authenticity grades.
- Fatwa: 3,598 rulings β Islamweb Fatwa Center (3,534) and Imam Ibn Baz (64).
License
This project uses open-source data from:
- Qur'an JSON β Open source
- Hadith API β Open source
See individual repositories for license details.
Made with β€οΈ for Islamic scholarship.
Version 8.5.0 | October 2026 | Production-Ready
- Downloads last month
- 62
8-bit