--- title: DocNeedle emoji: 📑 colorFrom: blue colorTo: indigo sdk: gradio sdk_version: 6.30.0 app_file: app.py pinned: false ---

DocNeedle Logo

DocNeedle

Privacy-first local document extraction microservice.
Extract structured key-value data with verified citations and confidence scores using local in-process AI models.

--- ## Features - **Strict Zero-Disk Privacy:** Document chunks and vectors reside strictly in RAM and are purged immediately after extraction. No external vector databases, no cloud APIs. - **In-Process AI:** Runs quantized Gemma 4, Harrier-OSS embeddings, RapidOCR, and BM25 directly in Python via `llama-cpp-python` and ONNX Runtime. - **Free-Threaded Performance:** Runs on Python 3.14t (GIL disabled) with speculative prompt lookup decoding and 8-bit quantized KV caching. - **Web UI & API:** Unified dark-mode Gradio 6 dashboard and FastAPI REST API with real-time Server-Sent Events (SSE) streaming on port `7860`. --- ## Quickstart ### Prerequisites (Linux) ```bash sudo apt-get install -y libgl1 libglib2.0-0 # Required for OCR/OpenCV ``` ### Setup & Run ```bash # 1. Clone & create Python 3.14t virtual environment git clone https://github.com/your-username/DocNeedle.git && cd DocNeedle uv python install 3.14t uv venv --python 3.14t && source .venv/bin/activate # 2. Install dependencies & download local models (~3.7 GB) uv sync uv run python scripts/download_models.py # 3. Launch application (UI + API) uv run python app.py ``` - **Web Dashboard:** `http://localhost:7860` - **Swagger API Docs:** `http://localhost:7860/docs` - **Health Check:** `http://localhost:7860/healthz` --- ## API Usage ### Extract Data (`POST /v1/extract`) ```bash curl -X POST "http://localhost:7860/v1/extract" \ -F "files=@contract.pdf" \ -F 'schema=[ {"key": "monthly_rent", "description": "Agreed monthly rent amount", "type": "money"}, {"key": "tenant_name", "description": "Full name of the tenant", "type": "person"} ]' ``` **Response:** ```json { "status": "completed", "processing_time_ms": 1240.0, "total_items": 2, "found_items": 2, "results": [ { "key": "monthly_rent", "found": true, "value": "25.000 TL", "confidence": 0.96, "evidence": { "document": "contract.pdf", "page": 1, "snippet": "Kira Bedeli: Aylık 25.000 TL olup her ayın 5. gününe kadar..." }, "thinking": null }, { "key": "tenant_name", "found": true, "value": "Tolga Arslan", "confidence": 0.95, "evidence": { "document": "contract.pdf", "page": 1, "snippet": "KİRACI: Tolga Arslan (T.C. Kimlik No: 12345678901)" }, "thinking": null } ] } ``` *For large documents, use `POST /v1/jobs` and stream real-time progress via `GET /v1/jobs/{job_id}/events` (SSE).* --- ## Configuration Settings are configured in `config.toml` or overridden via environment variables: | Setting | Default | Description | | :--- | :--- | :--- | | `gpu_enabled` | `true` | Enable CUDA GPU offloading (`true` / `false`) | | `llm_n_gpu_layers` | `-1` | Layers offloaded to GPU (`-1` = all, `0` = CPU) | | `ocr_enabled` | `true` | Ephemeral RapidOCR for scanned files | | `retrieval_top_k` | `10` | Candidate chunks retrieved via hybrid RRF | | `reranker_enabled`| `true` | Qwen3 cross-encoder logit reranker | --- ## Docker Run the complete stack with Docker Compose: ```bash docker compose up --build -d ``` --- ## Development ```bash # Run test suite uv run pytest # Lint and format uv run ruff check . uv run ruff format . ``` --- ## License [Apache 2.0](LICENSE)