| [project] | |
| name = "lexora-api" | |
| version = "1.0.0" | |
| description = "Lexora β grounded RAG over UAE labour & Dubai tenancy law with hybrid retrieval, reranking and hallucination control" | |
| requires-python = ">=3.12,<3.13" | |
| license = { text = "MIT" } | |
| dependencies = [ | |
| # ββ web βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| "fastapi>=0.115,<1.0", | |
| "uvicorn[standard]>=0.32,<1.0", | |
| "pydantic>=2.9,<3.0", | |
| "pydantic-settings>=2.6,<3.0", | |
| "slowapi>=0.1.9,<1.0", | |
| "httpx>=0.27,<1.0", | |
| # ββ model / retrieval ββββββββββββββββββββββββββββββββββββββββββββββββ | |
| "anthropic>=0.40,<1.0", | |
| "fastembed>=0.5,<1.0", | |
| "qdrant-client>=1.12,<2.0", | |
| "rank-bm25>=0.2.2,<1.0", | |
| "tokenizers>=0.20,<1.0", | |
| # ββ corpus βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| "pymupdf>=1.24,<2.0", | |
| # ββ workspace: bring your own document βββββββββββββββββββββββββββββββ | |
| # python-multipart is what lets FastAPI parse an uploaded file at all; without it | |
| # the upload endpoint raises at import time rather than at request time. | |
| "python-multipart>=0.0.9,<1.0", | |
| "python-docx>=1.1,<2.0", | |
| "pytesseract>=0.3.10,<1.0", | |
| "pillow>=10.0,<12.0", | |
| # ββ observability ββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| "langfuse>=3.0,<4.0", | |
| ] | |
| [project.optional-dependencies] | |
| dev = [ | |
| "pytest>=8.3,<9.0", | |
| "pytest-asyncio>=0.24,<2.0", | |
| "pytest-cov>=6.0,<8.0", | |
| # Starlette 1.3's TestClient requires httpx2; importing it with httpx installed raises | |
| # StarletteDeprecationWarning, which `-W error` turns into a collection failure. | |
| "httpx2>=2.9,<3.0", | |
| "ruff>=0.8,<1.0", | |
| "mypy>=1.13,<2.0", | |
| ] | |
| [build-system] | |
| requires = ["hatchling"] | |
| build-backend = "hatchling.build" | |
| [tool.hatch.build.targets.wheel] | |
| packages = ["app"] | |
| # NOTE: ruff / mypy / pytest configuration lives in the repo-root pyproject.toml | |
| # so a single config covers apps/api, corpus/, eval/ and scripts/. Do not add | |
| # [tool.ruff] or [tool.mypy] here β a nested config would silently shadow it for | |
| # files under apps/api/. | |