Tasks 5-7: eval harness, FastAPI backend, Paper & Ink UI- src/eval/ β precision/recall/F1 harness with type-aware comparators,micro/macro F1, CSV + markdown reports, --model benchmark flag- src/api/ β FastAPI backend with /extract, /schemas, /health,request-ID middleware, typed error envelope, injectable extractor- ui/ β Vite + React + TS + Tailwind + Motion + React Three FiberPaper & Ink editorial UI with 3D paper hero, dark/light mode,confidence inkwell, wax-stamp metrics, kinetic typography- 95 passing tests (up from 54); UI is a separate npm workspace
557ab38 | """FastAPI dependencies + upload constraints. | |
| Why a `Depends`-based extractor: | |
| FastAPI's dependency injection lets tests override the extractor via | |
| `app.dependency_overrides[get_extractor] = fake_extractor`, so we can | |
| hit the endpoints in tests without an OpenAI key. In production the | |
| lru_cache means we build one DocumentExtractor per worker process. | |
| """ | |
| from __future__ import annotations | |
| from functools import lru_cache | |
| from src.extractors.extractor import DocumentExtractor | |
| from src.schemas.registry import list_doc_types | |
| # --- Upload constraints ---------------------------------------------------- | |
| # 10 MB by default. Set to something small for tests via monkeypatch if needed. | |
| MAX_UPLOAD_BYTES = 10 * 1024 * 1024 | |
| # MIME allowlist. Also accept common browser variants. `application/octet-stream` | |
| # is accepted because some clients (and Streamlit) send it for images. | |
| ALLOWED_MIME_TYPES = { | |
| "application/pdf", | |
| "image/png", | |
| "image/jpeg", | |
| "image/jpg", | |
| "image/webp", | |
| "image/bmp", | |
| "image/tiff", | |
| "application/octet-stream", | |
| "text/plain", # for inline text extraction convenience | |
| } | |
| # Extensions we can actually load (mirrors document_loader.py). | |
| ALLOWED_EXTENSIONS = {".pdf", ".png", ".jpg", ".jpeg", ".webp", ".bmp", ".tiff", ".tif", ".txt"} | |
| # --- Dependencies ---------------------------------------------------------- | |
| def get_extractor() -> DocumentExtractor: | |
| """Singleton DocumentExtractor. Overridden in tests via dependency_overrides.""" | |
| return DocumentExtractor() | |
| def get_allowed_doc_types() -> list[str]: | |
| """List of registered document type strings β used by /schemas.""" | |
| return list_doc_types() | |