Automated pipeline that reads carrier invoice PDFs, extracts line-item data via a local vision model (Ollama), compares against the rate confirmation database, and flags every overcharge discrepancy.
Invoice PDF → pdf_to_images → Ollama minicpm-v → Structured JSON
│
lookup_rate_con (CSV)
│
Line-by-line comparison
│
Dispute CSV + Email digest
- Python 3.10+ with venv
- Ollama running with
minicpm-v:8b-2.6-q4_K_Mpulled - Poppler for
pdf2image(Windows download, macOS:brew install poppler, Ubuntu:sudo apt install poppler-utils) - Groq API key (free tier: https://console.groq.com)
- Gmail app password for email digests (optional for demo)
python -m venv venv
venv\Scripts\activate # Windows
# source venv/bin/activate # macOS/Linux
pip install -r requirements.txt
# Pull vision model
ollama pull minicpm-v:8b-2.6-q4_K_MCopy .env.example to .env and fill in your keys:
GROQ_API_KEY=gsk_your_key_here
SMTP_USER=yourgmail@gmail.com
SMTP_PASS=your_gmail_app_password
DIGEST_TO=broker@company.comA sample rate con CSV is included at data/rate_cons/rate_cons.csv with 5 loads.
Generate test invoice PDFs using any free invoice generator (or Word/Google Docs). Create invoices that match the rate con load numbers, some with intentional overcharges:
| Load | Expected Result |
|---|---|
| LC-1042 | Invoice with detention $180 → flagged (not agreed) |
| LC-1043 | Clean matching invoice → pass |
| LC-1044 | Invoice with detention → flagged (not agreed) |
Drop PDFs into data/invoices/.
python main.pyExpected output:
=== Freight Invoice Reconciliation Agent ===
Found 3 invoice(s) to process.
Processing: data/invoices/invoice_LC1042.pdf
! 2 discrepancy/discrepancies found!
Processing: data/invoices/invoice_LC1043.pdf
OK Invoice matches rate confirmation.
Processing: data/invoices/invoice_LC1044.pdf
! 1 discrepancy/discrepancies found!
Disputes saved to: output/disputes_2026-06-08.csv
Digest email sent for 3 dispute(s).
freight-recon/
├── main.py # Entry point
├── config.py # All env-driven settings
├── .env.example # Template for secrets
├── requirements.txt
│
├── agents/
│ ├── extractor.py # Specialist: PDF → structured data
│ └── orchestrator.py # Controls pipeline, runs comparison
│
├── tools/
│ ├── pdf_tools.py # PDF → PNG, file listing, archival
│ ├── vision_tools.py # Ollama vision model call
│ ├── sheets_tools.py # CSV rate con lookup
│ └── report_tools.py # Dispute CSV + email digest
│
├── data/
│ ├── rate_cons/ # Rate confirmation CSV
│ ├── invoices/ # Drop invoice PDFs here
│ └── processed/ # Archived after processing
│
├── output/ # Daily dispute CSVs
│
└── plans/ # Architecture documentation