┌─────────────────────────────────────────────────────────────┐
│ FastAPI Backend (Python) │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Upload Endpoint → File Storage (uploads/) │ │
│ └──────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Text Extraction Pipeline │ │
│ │ 1. pdfplumber (text-layer) → Fast, 95% confidence │ │
│ │ 2. If <50 chars → OCR Fallback │ │
│ │ a. pdf2image (150 DPI) → OpenCV preprocessing │ │
│ │ b. EasyOCR (primary) + Tesseract (fallback) │ │
│ │ c. Merge results (prefer higher confidence) │ │
│ └──────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Heuristic Extraction (Deterministic) │ │
│ │ - Invoice ID (regex + label proximity) │ │
│ │ - Dates (dateutil + multiple formats) │ │
│ │ - Amounts (currency symbols + regex) │ │
│ │ - Vendor (label matching + fuzzy) │ │
│ │ - Line items (table detection) │ │
│ └──────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Confidence Scoring │ │
│ │ Formula: 0.2 + 0.7*min(ocr, label, regex) + 0.1*LLM │ │
│ │ - >=0.85: Auto-accept (green) │ │
│ │ - 0.5-0.85: Flag for review (yellow) │ │
│ │ - <0.5: LLM fallback (red) │ │
│ └──────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ LLM Fallback (Surgical) │ │
│ │ Priority: Groq → Gemini → OpenAI → Anthropic │ │
│ │ - Only for low-confidence fields │ │
│ │ - Top K=12 OCR blocks as context │ │
│ │ - Cached by SHA256 of context │ │
│ └──────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Canonicalization │ │
│ │ - Dates → YYYY-MM-DD (ISO) │ │
│ │ - Currency → ISO4217 codes │ │
│ │ - Vendor → Canonical ID (RapidFuzz matching) │ │
│ └──────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Validation & Audit │ │
│ │ - Regex validation │ │
│ │ - Type checking │ │
│ │ - Audit log (all corrections) │ │
│ └──────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Output: InvoiceExtract JSON │ │
│ │ - All fields with confidence scores │ │
│ │ - Field reasons (1-line rationale) │ │
│ │ - Timings breakdown │ │
│ │ - LLM usage flags │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
- pdfplumber: Primary text-layer extraction (fast, 95% confidence)
- pdf2image: PDF → Image conversion (150 DPI for speed)
- OpenCV: Image preprocessing (deskew, denoise, binarize)
- EasyOCR: Primary OCR engine (good accuracy, moderate speed)
- pytesseract: Fallback OCR (fast, reliable)
- RapidFuzz: Vendor name fuzzy matching (token_sort_ratio)
- python-dateutil: Flexible date parsing (multiple formats)
- regex: Pattern matching for IDs, amounts, dates
- Groq API (Llama3 8B) - Fastest, free tier
- Google Gemini 1.5 Flash - Fast, free tier
- OpenAI GPT-4o-mini - Good accuracy, pay-per-use
- Anthropic Claude - Best accuracy, pay-per-use
- Local Ollama (last resort) - Zero cost, slow
- SQLite: Job storage, cache, audit logs (dev/hackathon)
- File system: Uploads, outputs, cache files
- FastAPI: Backend API server
- React + Tailwind: Frontend (keyboard-first UI)
- Docker: Containerization (optional)
- Vercel/Render: Free tier hosting
-
pdfplumber (text-layer PDFs)
- Extract words with positions
- Confidence: 0.95 (text-layer)
- Fast: <1s for typical PDF
-
OCR Fallback (scanned PDFs)
- Convert PDF → Images (150 DPI)
- Preprocess: grayscale only (fast)
- Run Tesseract first (faster)
- Fallback to EasyOCR if needed
- Merge results by confidence
- Invoice ID: Label proximity + regex patterns
- Dates: Multiple format support + dateutil parsing
- Amounts: Currency symbols + number extraction
- Vendor: Label matching + fuzzy search
- Line Items: Table detection (future)
confidence = 0.2 + 0.7 * min(ocr_c, label_score, regex_score) + (0.1 if llm_agree)
- Trigger: confidence < 0.5 OR required field missing
- Context: Top K=12 OCR blocks (by confidence + proximity)
- Caching: SHA256 of context text
- Validation: Post-process LLM output with regex
- Dates: All formats → YYYY-MM-DD
- Currency: Symbols/codes → ISO4217
- Vendor: Fuzzy match → canonical_id
- Text PDFs: <2s (pdfplumber only)
- Scanned PDFs: <10s (OCR, no LLM)
- With LLM: +5-10s per low-confidence field
- Accuracy: >90% on typical invoices
- pdfplumber fails → OCR fallback
- EasyOCR fails → Tesseract fallback
- Both OCR fail → Return empty, flag for manual
- Heuristics fail → LLM fallback
- LLM fails → Flag for manual review
- All fail → Return partial results with low confidence
- Unit Tests: Each module independently
- Integration Tests: Full pipeline with sample PDFs
- Golden Tests: Compare against 1.json, 2.json, etc.
- Performance Tests: Timing benchmarks
- Accuracy Tests: Precision/recall on labeled data