Metadata-Version: 2.4
Name: quran-validator
Version: 1.0.1
Summary: Validate and verify Quranic verses in LLM-generated text with high accuracy
Author: Yazin Alirhayim
License-Expression: MIT
Keywords: quran,arabic,validation,llm,islamic
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Text Processing :: Linguistic
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"

# quran-validator

Validate and verify Quranic verses in LLM-generated text with high accuracy.

## The Problem

LLMs can misquote Quranic verses — subtly changing words, missing diacritics, or combining verses incorrectly. This library provides:

1. **System prompts** that instruct LLMs to tag Quran quotes in a parseable format
2. **Post-processing** that validates tagged quotes against the authentic Quran database
3. **Auto-correction** that fixes misquotes to the authentic text
4. **Detection** of untagged Arabic text that might be Quran verses

## Features

- **LLM Integration**: System prompts + post-processor for complete LLM pipelines
- **Multi-tier Matching**: Exact → Normalized matching with Uthmani script support
- **Auto-Correction**: Automatically fix misquoted verses
- **Arabic Normalization**: Handles diacritics, alef variants, alef-wasla, and more
- **Fabrication Detection**: Identify words that don't exist anywhere in the Quran
- **Full Quran Database**: All 6,236 verses (Uthmani script) bundled
- **Zero Dependencies**: Fully self-contained
- **Type Hints**: Full type annotations included

## Installation

```bash
pip install quran-validator
```

## Quick Start: LLM Integration (Recommended)

### Step 1: Add System Prompt to Your LLM

```python
from quran_validator import SYSTEM_PROMPTS

system_prompt = f"""
{SYSTEM_PROMPTS['xml']}

{your_other_instructions}
"""

# The LLM will now output Quran quotes like:
# <quran ref="1:1">بِسْمِ ٱللَّهِ ٱلرَّحْمَٰنِ ٱلرَّحِيمِ</quran>
```

### Step 2: Process LLM Response

```python
from quran_validator import LLMProcessor

processor = LLMProcessor()

result = processor.process(llm_response)

if not result.all_valid:
    invalid = [q for q in result.quotes if not q.is_valid]
    print("Some quotes need attention:", invalid)

# Use the corrected text (misquotes auto-fixed)
print(result.corrected_text)

# See all detected quotes
for quote in result.quotes:
    status = "valid" if quote.is_valid else "invalid"
    print(f"{quote.reference}: {status} ({quote.detection_method})")
```

### Step 3: Handle Warnings

```python
for warning in result.warnings:
    print(warning)
    # e.g., "Untagged Quran quote detected: قُلْ هُوَ... (112:1)"
```

## Direct Validation API

For validating specific text without the full LLM pipeline:

```python
from quran_validator import QuranValidator

validator = QuranValidator()

# Validate a specific quote
result = validator.validate("بِسْمِ ٱللَّهِ ٱلرَّحْمَٰنِ ٱلرَّحِيمِ")

print(result.is_valid)     # True
print(result.reference)    # "1:1"
print(result.match_type)   # "exact" | "normalized" | "none"

# Get corrections if needed
if result.match_type != "exact" and result.matched_verse:
    print("Correct text:", result.matched_verse.text)
```

## Validate Against a Specific Reference

```python
result = validator.validate_against("بسم الله", "1:1")

if not result.is_valid:
    print(f"Expected: {result.expected_normalized}")
    print(f"Got: {result.normalized_input}")
    print(f"Mismatch at index: {result.mismatch_index}")
```

## Verse Range Support

```python
# Look up verse ranges programmatically
range_result = validator.get_verse_range(112, 1, 4)  # Surah 112, verses 1-4

print(range_result["text"])    # Concatenated Arabic text
print(range_result["verses"])  # List of 4 QuranVerse objects
```

## Fabrication Detection

Identify words that don't exist anywhere in the Quran:

```python
analysis = validator.analyze_fabrication("بسم الله الفلان")

for word in analysis.words:
    status = "fabricated" if word.is_fabricated else "valid"
    print(f"{word.word}: {status}")
# بسم: valid
# الله: valid
# الفلان: fabricated

print(analysis.stats.fabricated_ratio)  # 0.333...
```

## System Prompt Formats

### XML (Recommended)
```python
SYSTEM_PROMPTS["xml"]
# LLM outputs: <quran ref="1:1">بِسْمِ ٱللَّهِ ٱلرَّحْمَٰنِ ٱلرَّحِيمِ</quran>
```

### Markdown
```python
SYSTEM_PROMPTS["markdown"]
# LLM outputs a fenced code block with quran ref
```

### Bracket
```python
SYSTEM_PROMPTS["bracket"]
# LLM outputs: [[Q:1:1|بِسْمِ ٱللَّهِ ٱلرَّحْمَٰنِ ٱلرَّحِيمِ]]
```

### Minimal
```python
SYSTEM_PROMPTS["minimal"]
# LLM outputs: بِسْمِ ٱللَّهِ ٱلرَّحْمَٰنِ ٱلرَّحِيمِ (1:1)
```

## LLMProcessor Options

```python
from quran_validator import LLMProcessor
from quran_validator.types import LLMProcessorOptions

processor = LLMProcessor(LLMProcessorOptions(
    auto_correct=True,      # Auto-fix misquoted verses (default: True)
    scan_untagged=True,     # Scan for untagged potential Quran (default: True)
    tag_format="xml",       # "xml" | "markdown" | "bracket" (default: "xml")
))
```

## Quick Validation

For simple use cases:

```python
from quran_validator import quick_validate

result = quick_validate(llm_response)

print(result["has_quran_content"])  # True if Quran quotes detected
print(result["all_valid"])          # True if all quotes are authentic
print(result["issues"])             # List of issues found
```

## Verse Lookup & Search

```python
# Get specific verse
verse = validator.get_verse(2, 255)  # Ayat al-Kursi
print(verse.text)

# Get surah info
surah = validator.get_surah(1)
print(surah.english_name)  # "Al-Fatiha"
print(surah.verses_count)  # 7

# Search verses
results = validator.search("الرحمن الرحيم", limit=5)
for r in results:
    print(f"{r['verse'].surah}:{r['verse'].ayah} ({r['similarity']:.2f})")
```

## Arabic Text Utilities

```python
from quran_validator import (
    normalize_arabic,
    remove_diacritics,
    contains_arabic,
    extract_arabic_segments,
)

normalize_arabic("السَّلَامُ عَلَيْكُمُ")   # "السلام عليكم"
remove_diacritics("بِسْمِ اللَّهِ")          # "بسم الله"
contains_arabic("Hello مرحبا world")         # True

segments = extract_arabic_segments("Say بسم الله and continue")
# [Segment(text="بسم الله", start_index=4, end_index=12)]
```

## Match Types

| Type | Description | Confidence |
|------|-------------|------------|
| `exact` | Perfect character-by-character match | 1.0 |
| `normalized` | Match after removing diacritics & normalizing | ~0.95 |
| `none` | No match found | 0 |

## Data Source

Uses Quranic data from [QUL (Quranic Universal Library)](https://qul.tarteel.ai/) by [Tarteel AI](https://tarteel.ai/):

- **Uthmani Script**: Authoritative Arabic text with full diacritics
- **Imlaei Simple**: Simplified phonetic Arabic for matching
- **6,236 verses** across **114 surahs**

## License

MIT

Quran data provided by [QUL/Tarteel](https://qul.tarteel.ai/).
