B2B platform that automates the extraction and registration of surety bond policies from fiscal PDF documents using DeepSeek LLMs, OCR, and intelligent chunking.
The system solves data extraction from non-standardized fiscal documents issued by multiple insurance companies.
Multi-layer pipeline combining PyMuPDF to preserve visual layout, pdfplumber to detect tables, and Tesseract OCR for scanned documents. The LLM then processes all enriched context.
deepseek-v4-pro and deepseek-v4-flash models analyze each invoice identifying endorsement type, effective dates, premium, cancellations, credit notes, and more, with structured JSON response.
Algorithm that splits multi-invoice PDFs into overlapping fragments with 2-page overlap, detecting natural boundaries using regex patterns like "Invoice No." or "Total amount".
Graceful degradation strategy: retries on transient errors, fallback to local Ollama if DeepSeek is unavailable, and proactive staff notifications upon payment errors (402).
Celery + RabbitMQ + Redis queues for bulk background imports. The operator uploads the PDFs and the system processes them in parallel without blocking the interface.
The model identifies insurer-specific phrases —"Suspended Risk", "Total Cancellation due to Withdrawal"— and automatically marks policies as cancelled.
Manual vs. AI-automated process comparison. Values based on real insurtech sector benchmarks.
| KPI | Before (manual) | After (SGS + AI) | Improvement |
|---|---|---|---|
| Time per document | 300 seconds | 12 seconds | 96 % reduction |
| Extraction accuracy | 92 % (human error) | 91 % (model) | Equivalent, no fatigue |
| Docs/day/operator | 96 | 2,400 | 25× more capacity |
| Typing error rate | 8 per 100 (8 %) | 0 % (no typing) | Total elimination |
| Monthly operational cost | 320 operator-hours | 32 op-hours + $45 USD API | 90 % reduction |
| Batch import (100 PDFs) | 8.3 hours | 20 minutes | 96 % faster |
| Insurer coverage | Per-format training required | 8+ insurers, no configuration | Universal |
| Estimated ROI | — | — | 9:1 |
Technology stack, design decisions, and patterns used. Targeted at technical leaders and interviewers.
def extract_hybrid_content(self, pdf_source) -> Dict[str, Any]:
"""
Hybrid system combining multiple extraction methods.
PyMuPDF → visual layout · pdfplumber → tables · Tesseract → OCR
"""
content = {
"raw_text": "", "structured_text": "",
"tables": "", "metadata": "", "has_images": False,
"extraction_method": self.extraction_method,
}
# Method 1: PyMuPDF for general visual layout
if 'layout' in self.config['EXTRACTION_METHODS']:
content["structured_text"] = self.extract_text_with_layout(pdf_source)
# Method 2: pdfplumber for table detection
if 'tables' in self.config['EXTRACTION_METHODS']:
content["tables"] = self.extract_tables_with_pdfplumber(pdf_source)
# Method 3: Check if OCR is needed (scanned document)
needs_ocr = self._needs_ocr(pdf_source)
if needs_ocr and self.use_ocr:
content["raw_text"] = self._extract_with_ocr(pdf_source)
content["extraction_method"] = "ocr"
else:
# Combine structured text and tables
content["raw_text"] = content["structured_text"] + "\n\n" + content["tables"]
# Fallback to basic text if previous methods fail
if not content["raw_text"].strip():
content["raw_text"] = self.extract_text_from_pdf(pdf_source)
return content
try:
# Direct processing with DeepSeek
return self._process_with_deepseek(full_prompt)
except APIConnectionError as error:
# Connectivity error → notify and stop
error_msg = f"DeepSeek API connection error: {str(error)}"
return {"status": "error", "errors": [error_msg]}
except APIStatusError as error:
# HTTP error (402, 429, 500, etc.)
if error.status_code == 402:
# Notify staff via email: balance exhausted
send_email.delay(
subject="Error 402 - DeepSeek API Payment Required",
message=f"Error processing PDF. Balance exhausted.",
email=list(User.objects.filter(is_staff=True)
.values_list('email', flat=True))
)
return {"status": "error", "errors": [str(error)]}
except BadRequestError as error:
# Malformed prompt → do not retry
return {"status": "error", "errors": [str(error)]}
except Exception as error:
# Unknown error → fallback to iterative chunk processing
if hasattr(pdf_file, 'seek'):
pdf_file.seek(0)
return self.process_large_pdf_iteratively(
pdf_file, process_name, filename)
# DeepSeek call with response_format JSON
response = openai.chat.completions.create(
model=self.model, # deepseek-v4-pro or deepseek-v4-flash
messages=[
{"role": "system", "content": system_prompt}, # 17 business rules
{"role": "user", "content": "Analyze the provided fiscal document."}
],
response_format={'type': 'json_object'}, # Guaranteed JSON response
temperature=self.temperature,
max_tokens=self.max_tokens # Up to 384K output tokens
)
# The model response is a JSON with this structure:
{
"invoices": [
{
"policy": 229910,
"endorsement": 44,
"effective_from": "2025-01-01",
"effective_to": "2025-06-30",
"invoice": "0002-00294656",
"premium": 150000.00,
"insured_amount": 5000000.00,
"installment_due_date": "2025-02-15",
"status": "ok",
"messages": [],
"comments": "Invoice processed. Standard ACG layout.",
"cancelled": false,
"cancellation_reason": ""
}
]
}
AI pipeline diagram: PDF input → hybrid extraction (PyMuPDF, pdfplumber, OCR) → intelligent chunking → DeepSeek API → structured JSON → PostgreSQL storage.
Comparative dashboard with key KPIs: time per document, accuracy, processed volume, operational cost. Before vs after with bars and improvement percentages.
Document processing flow: PDF upload, hybrid extraction, chunk segmentation, LLM inference, invoice consolidation, and storage.
Screenshot of the document import interface. Admin panel with sidebar, import listing, and results log.
Model accuracy improvement curve over time, showing how iterative prompt engineering raised accuracy from initial 78 % to current 91 %.
Diagram of the resilience strategy: fallback layers (retry → chunking → local Ollama → staff notification) for different API error types.
This project is part of my professional portfolio. If you're interested in discussing the architecture, technical decisions, or seeing more case studies, reach out.