Metadata-Version: 2.4
Name: hadith-detector
Version: 0.2.0
Summary: Deterministic offline Arabic textual matching against Sahih Bukhari and Sahih Muslim
Author: Mohamed Rayen Fekih
License-Expression: MIT
Project-URL: Repository, https://github.com/RayenFekih/hadith-detector
Project-URL: Issues, https://github.com/RayenFekih/hadith-detector/issues
Project-URL: Homepage, https://github.com/RayenFekih/hadith-detector
Project-URL: Changelog, https://github.com/RayenFekih/hadith-detector/blob/main/CHANGELOG.md
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: rapidfuzz<4,>=3.14.6
Requires-Dist: marisa-trie==1.4.1
Provides-Extra: mcp
Requires-Dist: mcp<2,>=1.30; extra == "mcp"
Dynamic: license-file

# Hadith Detector

**Detect Arabic Hadith text and find its sources. Offline, in Python.**

[![Python 3.11–3.14](https://img.shields.io/badge/Python-3.11%E2%80%933.14-3776AB?logo=python&logoColor=white)](https://github.com/RayenFekih/hadith-detector/blob/main/pyproject.toml)
[![PyPI](https://img.shields.io/pypi/v/hadith-detector.svg)](https://pypi.org/project/hadith-detector/)
[![CI](https://github.com/RayenFekih/hadith-detector/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/RayenFekih/hadith-detector/actions/workflows/ci.yml)
[![Code license: MIT](https://img.shields.io/badge/Code_license-MIT-blue.svg)](LICENSE)

`hadith-detector` is a Python library that finds Arabic passages matching Hadith texts and returns their supporting sources. It works with short quotations or longer documents, supports exact and configurable fuzzy matching, and runs locally without an API key or an internet connection after installation.

The current bundled corpus covers **Sahih al-Bukhari and Sahih Muslim**. Support for additional Hadith collections is planned.

## Installation

```bash
pip install hadith-detector
```

Or with [uv](https://docs.astral.sh/uv/):

```bash
uv add hadith-detector
```

Requires **Python 3.11–3.14**. The package includes the Hadith texts and a prebuilt search index, so there is no separate corpus download or index-building step. Detection works offline after installation.

## Quick start

### MCP-compatible assistants

To expose the library as local tools for an AI assistant, install the optional extra:

```bash
pip install "hadith-detector[mcp]"
hadith-detector-mcp
```

The client normally starts this stdio process automatically. It provides
`detect_hadith`, `annotate_hadith`, and `get_hadith` using the same offline bundled
corpus. Results are candidate textual matches requiring contextual review; they do
not establish quotation intent or authenticity. The regular Python installation
does not require MCP dependencies. See the [MCP guide](docs/mcp.md) for client
configuration, schemas, pagination, examples, and interpretation limits.

### Python

This example looks for Hadith passages in a short Arabic reflection about seeking forgiveness. It also shows how to inspect the original sources and highlight detected text.

**1. Configure the detector and find matches**

```python
from hadith_detector import HadithDetector, DetectorConfig

detector = HadithDetector(
    config=DetectorConfig(
        min_match_words=9,
        max_errors=0,
        max_missing_words=0,
    )
)

text = """
لا تجعل الاستغفار مرتبطًا بالوقوع في الذنب وحده،
بل اجعله عادة يومية تتقرب بها إلى الله، وتجدد بها توبتك
وتستشعر افتقارك إليه. فقد كان النبي صلى الله عليه وسلم
يكثر من الاستغفار، وقال:
إِنَّهُ لَيُغَانُ عَلَى قَلْبِي وَإِنِّي لأَسْتَغْفِرُ اللَّهَ فِي الْيَوْمِ مِائَةَ مَرَّةٍ
فاحرص على كثرة الاستغفار، وداوم عليه بقلب حاضر،
فهو عبادة وتعبير عن التواضع والافتقار إلى الله.
"""

matches = detector.detect(text)
print("Number of detections:", len(matches))
```

**2. Inspect the first detected passage and its source**

```python
if matches:
    match = matches[0]
    print("Detected text:", match.text)
    print("Position in input:", (match.start, match.end))
    print("Number of supporting records:", len(match.references))

    if match.references:
        reference = match.references[0]
        print("Reference:", reference.record.hadith_key)
        print("Full Hadith:", reference.record.text)
```

**3. Highlight detected passages**

```python
html = detector.annotate(text)
print("Annotated HTML:", html)
```

Run the three blocks in order in the same Python session. `detect()` returns **passages in the input**, not a single Hadith classification. `match.start` is inclusive and `match.end` is exclusive, so `text[match.start:match.end]` reproduces the matched text. Each passage may have multiple supporting source records; the example prints only the first match and its first reference. `annotate()` returns an escaped HTML fragment containing `<mark>` tags.

**Check what was actually matched.** A matching phrase may be an incidental attribution formula rather than the quotation you intended. The threshold of `9` reduces some short matches but does not filter generic phrases automatically; always review the returned passage and source. When pasting Arabic code into Windows PowerShell, save it as a UTF-8 `.py` file instead of piping the code through standard input to avoid character corruption.

## Features

- **Exact Arabic text matching**, with normalization of supported Arabic letter forms and diacritics.
- **Optional fuzzy matching** for limited spelling differences and omitted words from the source.
- **Source references** with complete original records, occurrences, offsets, and alignment details.
- **Multiple detections** within the same paragraph or document.
- **HTML highlighting** of detected passages using `annotate()`.
- **Offline and deterministic** operation with a bundled index; no LLM or external service required.

## Configuration

The default settings are intentionally strict:

| Parameter | Default | What it controls |
| --- | ---: | --- |
| `min_match_words` | `5` | Minimum number of matched input words. Lower values also detect more short, common expressions; higher values can miss short quotations. |
| `max_errors` | `0` | Total number of character edits allowed across the matched words. |
| `max_missing_words` | `0` | Number of internal words in the source passage that may be absent from the input. |

```python
from hadith_detector import DetectorConfig, HadithDetector

detector = HadithDetector(
    config=DetectorConfig(
        min_match_words=5,
        max_errors=1,
        max_missing_words=1,
    )
)

matches = detector.detect("إنما الأعمال بالنياث وإنما لكل امرئ ما نوى")

# Override the settings for one call without changing the configuration.
exact_matches = detector.detect(
    "إنما الأعمال بالنيات وإنما لكل امرئ ما نوى", max_errors=0, max_missing_words=0
)
```

For long Arabic documents, consider a higher `min_match_words` if short incidental matches create too much noise. Enable fuzzy budgets only when your input may contain spelling variations or source-word omissions. Broader settings can increase both detections and processing time. There is no universally best configuration; test the trade-offs on your own texts.

## More usage examples

**Retrieve a complete source record**

```python
from hadith_detector import get_hadith

record = get_hadith("bukhari:1")
print(record.text)
```

**Highlight matches in plain text**

```python
from hadith_detector import annotate

html = annotate("ورد في النص: إنما الأعمال بالنيات وإنما لكل امرئ ما نوى")
```

`annotate()` produces an escaped HTML fragment with matched passages wrapped in `<mark>` elements. It is designed for plain-text input, not for editing an existing HTML document.

## Important notes

- **Generic phrases can trigger incidental matches.** For example, a phrase such as `هو عبد الله` may also appear in Hadith records even when it occurs in an unrelated article. Likewise, narration formulas such as `عن النبي صلى الله عليه وسلم قال` may match without being meaningful standalone quotations. Shorter `min_match_words` values increase this risk, and permissive fuzzy budgets can introduce additional matches. **Tune `min_match_words`, `max_errors`, and `max_missing_words` for your text and use case**, especially for long documents; increasing the minimum can reduce short incidental matches but may miss genuine short quotations.
- **A match means textual support, not quotation intent.** Common expressions, honorifics, Quranic wording embedded in narrations, and narrator-chain fragments can also match. Do not automatically treat every detection as a deliberate Hadith quotation.
- **Review citations and source context.** Before publishing religious content or relying on the returned citation, inspect the original narration, relevant supporting occurrences, and data provenance. The library does not independently authenticate Hadith or interpret their meaning.
- **No match does not mean no Hadith exists.** Coverage is currently limited to the bundled Sahihayn collection, and configured matching thresholds may exclude short or modified quotations.
- **The dataset is preserved as supplied.** Source data can include duplicate narration texts, missing URLs, or damaged characters. Check that it meets your application’s accuracy and provenance requirements.

## Data

The package currently includes **14,940 Arabic Hadith records**:

| Collection | Records |
| --- | ---: |
| Sahih al-Bukhari | 7,580 |
| Sahih Muslim | 7,360 |

The data comes from the [QuranLab Hadith dataset on Hugging Face](https://huggingface.co/datasets/quranlab/hadith), using its `bukhari-ar` and `muslim-ar` configurations. Original Arabic records, source identities, and accompanying metadata are retained. **Additional Hadith books are planned for future versions.**

The library's **code is MIT-licensed**; the underlying Hadith data has separate source terms and notices. Consult the [dataset provenance and redistribution notes](tools/bundle-notices/PROVENANCE.md) before reusing or redistributing the data independently.

## Use cases

- **Arabic documents and articles:** Locate matching Hadith passages inside longer text.
- **Research and reference lookup:** Find supporting collections and inspect the original narration.
- **Educational and editorial tools:** Help reviewers locate quotations and check source wording.
- **Web applications:** Highlight text matches and show citations or source context.
- **AI and LLM applications:** Check generated Hadith wording, retrieve source passages, and provide grounding evidence for citation workflows. Human review remains important.

## Documentation and community

- [Public API and result structure](docs/public-api.md)
- [Local MCP server and client configuration](docs/mcp.md)
- [Matching and fuzzy behavior](docs/fuzzy-runtime.md)
- [HTML annotation](docs/html-annotation.md)
- [Evaluation and limitations](docs/phase6-evaluation.md)
- [Contributing](CONTRIBUTING.md)
- [Changelog](CHANGELOG.md)
- [Report a bug or request a feature](https://github.com/RayenFekih/hadith-detector/issues)

Contributions, issue reports, reproducible examples, and suggestions for additional Hadith sources are welcome.

---

### دعوة طيبة

أرجو منكم الدعاء لوالديَّ بأن يحفظهما الله، ويبارك في عمرهما وصحتهما، ويمتعهما بالعافية، ويغفر لهما ويرحمهما كما ربياني صغيرًا، وأن يرزقني برَّهما ورضاهما.

جزاكم الله خيرًا، وبارك فيكم.
