← Back to list

AI-Powered Invoice Processing with LandingAI ADE and Python

OCR reads characters. AI understands documents. That distinction is everything when you’re processing invoices at scale.

asif malek · 2026-06-28 14:44 · 26 claps · 3.6 min read
#genai #ai-document-processing #llm
Open on Medium ↗
Wiki topics: LLM · Large Language Models AI · AI · General

AI-Powered Invoice Processing with LandingAI ADE and Python

OCR reads characters. AI understands documents. That distinction is everything when you’re processing invoices at scale.

The Problem with OCR

Traditional OCR has been the default for invoice processing for years. It works — until it doesn’t.

OCR gives you raw text. It has no idea what that text means. It can read 15/01/2024 but it doesn't know if that's an invoice date, a due date, or a delivery date. It reads £1,800.00 but can't tell you if that's a subtotal, a tax amount, or the grand total.

And the real killer? Every supplier formats their invoices differently.

  • One says Invoice Date. Another says Billing Date. A third says Date of Issue.
  • One puts the total at the bottom. Another buries it in a summary table on page 2.
  • One uses a clean table for line items. Another just lists them as free text.

With OCR you end up writing brittle regex patterns and field-mapping rules per supplier template. It breaks every time a vendor updates their invoice layout. Your engineering team spends more time maintaining parsers than building product.

There’s a better way.

Enter LandingAI ADE

LandingAI’s Agentic Document Extraction (ADE) flips the model entirely. Instead of reading characters and hoping you can map them, it understands the document — layout, context, and meaning — and maps content directly to a schema you define.

The pipeline is three steps:

Invoice PDF  →  Parse (DPT-2 model)  →  Extract (LLM)  →  Structured JSON

Step 1 — Parse: The DPT-2 model converts your PDF into structured Markdown, preserving tables, headers, and layout context. Not raw text dumps — semantically aware chunks.

Step 2 — Extract: An LLM reads that Markdown and maps every field to your Pydantic schema using semantic understanding, not keyword matching.

Step 3 — Output: You get clean, consistent JSON every time — regardless of how the invoice was formatted.

Define Your Schema Once

This is where the magic lives. You define what you want to extract using Pydantic, and crucially — you tell it what the field means, not just what it’s called.

from pydantic import BaseModel, Field
from typing import List, Optional
class LineItem(BaseModel):
    description: str   = Field(..., description="Product or service description")
    quantity:    float = Field(..., description="Quantity of units")
    unit_price:  float = Field(..., description="Price per unit excluding tax")
    line_total:  float = Field(..., description="Total for this line")
class InvoiceExtraction(BaseModel):
    invoice_number: Optional[str] = Field(
        None, description="Unique invoice reference number or ID"
    )
    invoice_date: Optional[str] = Field(
        None,
        description="Date the invoice was issued. May appear as: Invoice Date, "
                    "Billing Date, Date of Issue, Tax Date, Document Date."
    )
    seller_name:  Optional[str] = Field(
        None,
        description="Issuing party. May appear as: Seller, Vendor, Supplier, From."
    )
    buyer_name:   Optional[str] = Field(
        None,
        description="Billed party. May appear as: Buyer, Client, Bill To, Sold To."
    )
    grand_total:  Optional[float] = Field(
        None,
        description="Final payable amount. May appear as: Grand Total, Total Due, "
                    "Amount Payable, Balance Due."
    )
    line_items:   Optional[List[LineItem]] = Field(
        None, description="All line items on the invoice"
    )

See what’s happening in those descriptions? You’re not hardcoding field names — you’re describing intent. The LLM figures out the mapping at runtime.

Run the Extraction

Three lines to go from PDF to structured JSON:

from landingai_ade import LandingAIADE
from landingai_ade.lib import pydantic_to_json_schema
from pathlib import Path
client = LandingAIADE()
# Step 1: Parse PDF → Markdown
parse_response = client.parse(
    document=Path("./invoice.pdf"),
    model="dpt-2-latest"
)
# Step 2: Extract fields using your schema
extract_response = client.extract(
    schema=pydantic_to_json_schema(InvoiceExtraction),
    markdown=parse_response.markdown,
    model="extract-latest"
)
print(extract_response.extraction)

Output:

{
  "invoice_number": "INV-2024-001",
  "invoice_date": "2024-01-15",
  "seller_name": "Stellar Tech Labs Ltd",
  "buyer_name": "Acme Corporation",
  "grand_total": 1800.00,
  "line_items": [
    {
      "description": "AI Consulting Services",
      "quantity": 10,
      "unit_price": 150.00,
      "line_total": 1500.00
    }
  ]
}

Same schema. Same output structure. Whether the invoice says Invoice Date or Billing Date — it maps correctly every time.

OCR vs ADE — Side by Side

OCR LandingAI ADE Output Raw text dump Structured JSON Field mapping Manual regex / rules per template Semantic — described once in schema Handles label variations ❌ Breaks ✅ Understood automatically Tables & line items Fragile Native support Missing fields Silent failure / wrong value Returns null cleanly New supplier format Rewrite parser No change needed Maintenance overhead High Near zero

The Schema is the Contract

The real shift in thinking here is this: your Pydantic schema becomes the single source of truth for what every invoice looks like in your system — regardless of the chaos in the source documents.

Every invoice your system processes, from any supplier, in any format, produces the same JSON shape. Downstream code — your ERP integration, your accounting system, your payment pipeline — talks to that schema. It never needs to know what the original PDF looked like.

That’s the difference between OCR giving you data and AI giving you structured information.

Bonus: Batch Processing

Processing a folder of invoices is a loop:

for pdf in Path("./invoices").glob("*.pdf"):
    parse_resp   = client.parse(document=pdf, model="dpt-2-latest")
    extract_resp = client.extract(
        schema=pydantic_to_json_schema(InvoiceExtraction),
        markdown=parse_resp.markdown,
        model="extract-latest"
    )
    results.append({"file": pdf.name, "data": extract_resp.extraction})

No template management. No per-supplier configuration. Just results.

Get Started

pip install landingai-ade pydantic
export VISION_AGENT_API_KEY=your-api-key

Get your API key at va.landing.ai. Full docs at docs.landing.ai/ade/ade-python.

The full notebook with batch processing, classification, and output saving is available on **GitHub**.

If this saved you from writing another regex parser, hit follow — more practical AI engineering content coming.


메타데이터
post_id
b450dabc16c2
slug
ai-powered-invoice-processing-with-landingai-ade-and-python-b450dabc16c2
url
https://medium.com/@asif.malek/ai-powered-invoice-processing-with-landingai-ade-and-python-b450dabc16c2
canonical_url
https://medium.com/@asif.malek/ai-powered-invoice-processing-with-landingai-ade-and-python-b450dabc16c2
author_url
https://medium.com/@asif.malek
status
ok
fetched_at
2026-07-29 17:11:55