feat: Maintenance receipt extraction pipeline in OCR microservice (#16) #150

Closed
opened 2026-02-13 02:54:10 +00:00 by egullickson · 1 comment
Owner

Relates to #16

Summary

Add maintenance receipt extraction to the Python OCR microservice. Uses Gemini-primary extraction (send OCR text to Gemini for all field extraction) with regex cross-validation for structured fields (dates, amounts, odometer).

Scope

  • New MaintenanceReceiptExtractor class (mirrors FuelReceiptExtractor pattern)
  • Gemini prompt for maintenance receipt field extraction (service name, date, cost, shop name, parts/labor breakdown, odometer, vehicle info)
  • Regex cross-validation to validate/boost confidence on structured fields
  • New FastAPI endpoint: POST /extract/maintenance-receipt
  • Per-field confidence scores (0.0-1.0)
  • Reuse existing ReceiptExtractionResult dataclass and ReceiptExtractionResponse Pydantic model

Files

  • ocr/app/extractors/maintenance_receipt_extractor.py (NEW)
  • ocr/app/patterns/maintenance_receipt_validation.py (NEW - cross-validation patterns)
  • ocr/app/routers/extract.py (MODIFY - add new route)

Technical Notes

  • Follow FuelReceiptExtractor pattern: extract first (via Gemini), cross-validate second (via regex)
  • Send OCR text to Gemini text API (not Vision API) - matches proven manual_extractor.py pattern
  • Reuse existing ReceiptExtractionResult dataclass (generic dict[str, ExtractedField] supports arbitrary field keys)
  • Reuse existing ReceiptExtractionResponse Pydantic model (same response shape, receiptType: "maintenance")
  • Regex validates dates (date_matcher), amounts (currency_matcher), odometer (numeric patterns)
  • Gemini handles semantic fields: service description, shop name, parts/labor breakdown, vehicle info
  • Default Gemini confidence: 0.85 (adjustable via cross-validation)
  • Sync processing for images (user waits with loading spinner)
  • File named maintenance_receipt_validation.py (NOT maintenance_receipt_patterns.py to avoid collision with existing maintenance_patterns.py)

Acceptance Criteria

  • Maintenance receipt extraction endpoint returns structured fields with confidence scores
  • Gemini extracts semantic fields (service name, shop, parts/labor)
  • Regex cross-validates structured fields (date, cost, odometer)
  • Response format compatible with frontend confidence indicator system
Relates to #16 ## Summary Add maintenance receipt extraction to the Python OCR microservice. Uses Gemini-primary extraction (send OCR text to Gemini for all field extraction) with regex cross-validation for structured fields (dates, amounts, odometer). ## Scope - New `MaintenanceReceiptExtractor` class (mirrors `FuelReceiptExtractor` pattern) - Gemini prompt for maintenance receipt field extraction (service name, date, cost, shop name, parts/labor breakdown, odometer, vehicle info) - Regex cross-validation to validate/boost confidence on structured fields - New FastAPI endpoint: `POST /extract/maintenance-receipt` - Per-field confidence scores (0.0-1.0) - Reuse existing `ReceiptExtractionResult` dataclass and `ReceiptExtractionResponse` Pydantic model ## Files - `ocr/app/extractors/maintenance_receipt_extractor.py` (NEW) - `ocr/app/patterns/maintenance_receipt_validation.py` (NEW - cross-validation patterns) - `ocr/app/routers/extract.py` (MODIFY - add new route) ## Technical Notes - Follow `FuelReceiptExtractor` pattern: extract first (via Gemini), cross-validate second (via regex) - Send OCR text to Gemini text API (not Vision API) - matches proven `manual_extractor.py` pattern - Reuse existing `ReceiptExtractionResult` dataclass (generic `dict[str, ExtractedField]` supports arbitrary field keys) - Reuse existing `ReceiptExtractionResponse` Pydantic model (same response shape, `receiptType: "maintenance"`) - Regex validates dates (date_matcher), amounts (currency_matcher), odometer (numeric patterns) - Gemini handles semantic fields: service description, shop name, parts/labor breakdown, vehicle info - Default Gemini confidence: 0.85 (adjustable via cross-validation) - Sync processing for images (user waits with loading spinner) - File named `maintenance_receipt_validation.py` (NOT `maintenance_receipt_patterns.py` to avoid collision with existing `maintenance_patterns.py`) ## Acceptance Criteria - [ ] Maintenance receipt extraction endpoint returns structured fields with confidence scores - [ ] Gemini extracts semantic fields (service name, shop, parts/labor) - [ ] Regex cross-validates structured fields (date, cost, odometer) - [ ] Response format compatible with frontend confidence indicator system
egullickson added the
status
backlog
type
feature
labels 2026-02-13 02:54:59 +00:00
egullickson added this to the Sprint 2026-02-02 milestone 2026-02-13 02:55:02 +00:00
egullickson added
status
in-progress
and removed
status
backlog
labels 2026-02-13 03:08:03 +00:00
Author
Owner

Milestone: Implementation Complete

Phase: Execution | Agent: Developer | Status: PASS

Summary

All three milestones implemented in a single commit (90401dc):

Milestone 1: Cross-validation patterns

  • File: ocr/app/patterns/maintenance_receipt_validation.py (NEW)
  • MaintenanceReceiptValidator class with per-field validation
  • Date validation via date_matcher (existing patterns)
  • Amount validation via currency_matcher (existing patterns)
  • Odometer validation via regex patterns (labeled, unit-based, standalone)
  • Returns MaintenanceReceiptValidation with per-field confidence adjustments

Milestone 2: Maintenance receipt extractor

  • File: ocr/app/extractors/maintenance_receipt_extractor.py (NEW)
  • MaintenanceReceiptExtractor class following FuelReceiptExtractor pattern
  • Gemini-primary extraction: OCR text sent to Gemini text API (not Vision)
  • Structured JSON response schema for 8 fields: serviceName, serviceDate, totalCost, shopName, laborCost, partsCost, odometerReading, vehicleInfo
  • Cross-validation adjusts confidence: regex-confirmed fields get 1.10x boost, unconfirmed get 0.80x reduction
  • Default Gemini confidence: 0.85
  • Graceful Gemini fallback (logs warning, returns empty fields)

Milestone 3: New endpoint

  • File: ocr/app/routers/extract.py (MODIFIED)
  • POST /extract/maintenance-receipt endpoint
  • Reuses existing ReceiptExtractionResponse Pydantic model (receiptType: "maintenance")
  • Follows existing /receipt endpoint validation pattern (400/413/422 errors)
  • Updated extractors/__init__.py and patterns/__init__.py exports

Technical Decisions

  • Lazy Gemini model initialization (same auth pattern as GeminiEngine)
  • Composition over inheritance: wraps receipt_extractor.extract() for OCR, then replaces fields with Gemini results
  • Cross-validation tolerance: 5% for amounts, 1% for odometer, exact match for dates

Verdict: PASS | Next: QR post-implementation review

## Milestone: Implementation Complete **Phase**: Execution | **Agent**: Developer | **Status**: PASS ### Summary All three milestones implemented in a single commit (`90401dc`): ### Milestone 1: Cross-validation patterns - **File**: `ocr/app/patterns/maintenance_receipt_validation.py` (NEW) - `MaintenanceReceiptValidator` class with per-field validation - Date validation via `date_matcher` (existing patterns) - Amount validation via `currency_matcher` (existing patterns) - Odometer validation via regex patterns (labeled, unit-based, standalone) - Returns `MaintenanceReceiptValidation` with per-field confidence adjustments ### Milestone 2: Maintenance receipt extractor - **File**: `ocr/app/extractors/maintenance_receipt_extractor.py` (NEW) - `MaintenanceReceiptExtractor` class following `FuelReceiptExtractor` pattern - Gemini-primary extraction: OCR text sent to Gemini text API (not Vision) - Structured JSON response schema for 8 fields: serviceName, serviceDate, totalCost, shopName, laborCost, partsCost, odometerReading, vehicleInfo - Cross-validation adjusts confidence: regex-confirmed fields get 1.10x boost, unconfirmed get 0.80x reduction - Default Gemini confidence: 0.85 - Graceful Gemini fallback (logs warning, returns empty fields) ### Milestone 3: New endpoint - **File**: `ocr/app/routers/extract.py` (MODIFIED) - `POST /extract/maintenance-receipt` endpoint - Reuses existing `ReceiptExtractionResponse` Pydantic model (receiptType: "maintenance") - Follows existing `/receipt` endpoint validation pattern (400/413/422 errors) - Updated `extractors/__init__.py` and `patterns/__init__.py` exports ### Technical Decisions - Lazy Gemini model initialization (same auth pattern as `GeminiEngine`) - Composition over inheritance: wraps `receipt_extractor.extract()` for OCR, then replaces fields with Gemini results - Cross-validation tolerance: 5% for amounts, 1% for odometer, exact match for dates *Verdict*: PASS | *Next*: QR post-implementation review
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: egullickson/motovaultpro#150