π Building a Scalable, Templated LLM Pipeline for Document Classification & Entity Extraction withβ¦
π Introduction
π Building a Scalable, Templated LLM Pipeline for Document Classification & Entity Extraction with Azure OpenAI
Photo by Victor on Unsplash
π Introduction
Enterprises sit on millions of documents β contracts, invoices, policies, medical records β all filled with valuable information. Extracting structured insights from them is slow, manual, and inconsistent.
I recently built a scalable document processing pipeline using Azure OpenAI, designed not as a one-off project but as a template that can be reused across multiple clients. In this article, Iβll walk through the full technical architecture, implementation, and templation approach.
πΉ The Problem
- 160,000+ documents across formats (PDF, Word, images)
- Needed classification (Invoice, Contract, Policy, etc.)
- Needed entity extraction (account numbers, dates, clauses, amounts)
- Must handle 100k+ docs efficiently, avoiding API rate limits
- Should be reusable across clients (different categories, endpoints, keys)
πΉ High-Level Architecture
- Documents uploaded β Azure Blob Storage
- OCR β Azure Document Intelligence for scanned files
- Pre-processing β chunk text into smaller pieces
- Generate JSONL batch file (one JSON per chunk)
- Submit JSONL β Azure OpenAI Batch API
- Batch job runs asynchronously at scale
- Download results β parse into CSV/Delta
- Clients consume via Excel, Power BI, or Neo4j
πΉ Why JSONL Batch Files?
Instead of sending 100k API requests (which would hit rate limits), Azure OpenAI Batch API accepts a single JSONL file:
{"custom_id": "doc1", "method": "POST", "url": "/chat/completions", "body": {"model": "gpt-4o-mini", "messages": [{"role":"system","content":"Classify and extract"},{"role":"user","content":"Invoice Number: INV001 Amount $450"}]}}js
- Each line = one request (
custom_id,method,url,body) - Runs asynchronously in the background
- Provides trackable outputs by matching
custom_idin responses
πΉ Classification Logic
- The AI doesnβt have predefined labels.
- Categories are defined in the prompt template, for example:
Classify the document into one of these categories: Invoice, Contract, Policy, Medical Report, Other
The AI assigns a category, provides a confidence score, and extracts entities in the same pass.
Example output:
{
"category": "Invoice",
"category_confidence": 0.94,
"entities": [
{"extracted_field": "Account No", "confidenceScore": 0.92, "justification": "Found in header text"}
]
}
πΉ Technical Implementation
π Repo Structure
azure-llm-template/
βββ config/ # client configs (YAML)
βββ prompts/ # classification/extraction prompts
βββ src/
β βββ ingest.py # downloads docs from Blob
β βββ ocr.py # OCR for scanned files
β βββ jsonl_builder.py # creates JSONL requests
β βββ batch_submit.py # upload, submit, poll Batch API
β βββ results_handler.py # parse results β CSV
β βββ main.py # orchestrator
βββ requirements.txt
βββ Dockerfile
Example Config (clientA.yaml)
storage:
connection_string: "<AZURE_BLOB_CONNECTION_STRING>"
container_raw: "raw-docs"
container_jsonl: "jsonl-input"
container_results: "batch-results"
openai:
endpoint: "https://client-openai.openai.azure.com/"
deployment_id: "gpt-4o-mini"
api_key: "<CLIENT_API_KEY>"
api_version: "2024-12-01-preview"
ocr:
endpoint: "https://client-ocr.cognitiveservices.azure.com/"
key: "<OCR_KEY>"
processing:
prompt_template: "prompts/classify_and_extract.txt"
max_tokens: 4000
batch_size_mb: 180
output:
results_file: "results.csv"
πΉ Dockerization for Easy Sharing
The pipeline is packaged into Docker, so clients donβt need to install Python or dependencies
docker pull myregistry.azurecr.io/llm-pipeline:latest
docker run -v $(pwd)/config:/app/config llm-pipeline:latest config/clientA.yaml
π Each client only changes their config file. The engine stays the same.
πΉ Automation of Prerequisites
To make onboarding easier:
- Terraform β provisions Blob Storage, OpenAI, OCR, Key Vault
- Azure Key Vault β stores secrets
- DevOps Pipeline β runs IaC + Docker automatically
For a new client:
git clone azure-llm-template
terraform apply -var-file=clientX.tfvars
docker run llm-pipeline:latest config/clientX.yaml
πΉ Continuous Automation with Azure DevOps
This pipeline can be fully automated:
- Client drops new documents into Blob (
raw-docs). - Azure DevOps pipeline triggers automatically.
- Terraform ensures resources are ready.
- Docker container runs with the clientβs config.
- Results are saved back to Blob β Power BI auto-refreshes dashboards.
π Fresh data = fresh results, with no manual reruns.
πΉ Results & Benefits
- Template approach = plug-and-play for multiple clients
- DevOps integration = automated, repeatable runs whenever new data arrives
π Conclusion
By combining Azure OpenAI Batch API, OCR, Docker, and Azure DevOps automation, we built a reusable document processing engine that can:
- Scale to 100k+ documents
- Work across multiple clients with minimal effort
- Deliver structured, business-ready insights directly into Power BI
Itβs a template that turns AI experiments into enterprise-grade, repeatable solutions.
About the author
Sarath Samynathan is a Senior Data Scientist here at Version 1.
λ©νλ°μ΄ν°
- post_id
- d75ffe7e7d4d
- slug
- building-a-scalable-templated-llm-pipeline-for-document-classification-entity-extraction-with-d75ffe7e7d4d
- url
- https://medium.com/version-1/building-a-scalable-templated-llm-pipeline-for-document-classification-entity-extraction-with-d75ffe7e7d4d
- canonical_url
- https://medium.com/version-1/building-a-scalable-templated-llm-pipeline-for-document-classification-entity-extraction-with-d75ffe7e7d4d
- author_url
- https://medium.com/@sarath.samynathan
- status
- ok
- fetched_at
- 2026-07-15 04:26:53