Azure deep dive
Document Intelligence
Provision the F0 Document Intelligence resource with the CLI, fetch endpoint and key, and analyze a first invoice.
By the end of this stage the second Azure service is live. A free-tier Document Intelligence resource exists in your resource group, its endpoint and key are in backend/.env, and you have analyzed a first invoice and seen typed fields with confidence scores come back.
What Document Intelligence is
Azure AI Document Intelligence is a document extraction service with prebuilt models for common document types. This project uses two of them. prebuilt-invoice returns invoice-specific fields such as supplier, invoice ID, dates, totals, currency, and line items. prebuilt-receipt does the same for receipts, with merchant and transaction fields instead.
The important property is that these are purpose-built extraction models. They return semantic field names with confidence values per field, and they were trained on enormous volumes of real documents. That makes Document Intelligence the primary extractor in this project, with the general-purpose LLM in a supporting role. Why that division of labor holds up is the subject of the next stage.
Provision it from the CLI
Create the resource in the existing group. One historical quirk to know about, the CLI still uses the service's old product name FormRecognizer as the kind:
az cognitiveservices account create \
--name di-invoice-review \
--resource-group rg-invoice-review \
--kind FormRecognizer \
--sku F0 \
--location westeurope \
--yes \
--output tableThe resource name becomes part of a DNS hostname, so it must be unique. If creation fails on the name, add your own suffix, for example di-invoice-review-7314.
--sku F0 is the free tier, and it is genuinely useful rather than a token gesture. F0 processes 500 pages per month at no cost, limited to the first two pages per request, 4 MB per file, and one request per second. There is no paid overage; when the quota is spent you either wait for the monthly reset or move to the paid S0 tier ($10 per 1,000 prebuilt pages). Our full corpus is 14 pages, so one complete evaluation uses 2.8% of a month's allowance.
Fetch the endpoint and key:
az cognitiveservices account show \
--name di-invoice-review \
--resource-group rg-invoice-review \
--query properties.endpoint \
--output tsv
az cognitiveservices account keys list \
--name di-invoice-review \
--resource-group rg-invoice-review \
--query key1 \
--output tsvPut both values in backend/.env:
AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT=https://your-resource.cognitiveservices.azure.com/
AZURE_DOCUMENT_INTELLIGENCE_KEY=your-keySecrets exist only in the gitignored .env file. Check git status one more time if you want the habit to stick.
Analyze a first invoice
Microsoft publishes a sample invoice that is perfect for a first call. Download it, then run the project's check script, which sends it through the real provider adapter:
curl -L \
https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/sample-invoice.pdf \
-o samples/sample-invoice.pdf
cd backend
uv run --locked --no-sync python scripts/check_document_intelligence.pyThe script prints one normalized JSON document with the supplier, invoice number, dates, totals, currency, line items, and a confidence value. Abbreviated, the shape looks like this:
{
"document_type": "invoice",
"vendor_name": "CONTOSO LTD.",
"invoice_number": "INV-100",
"invoice_date": "2019-11-15",
"due_date": "2019-12-15",
"currency": "USD",
"invoice_total": "110.00",
"line_items": [
{ "description": "Consulting service", "quantity": "2", "amount": "60.00" }
],
"field_confidence": { "vendor_name": 0.94, "invoice_total": 0.98 }
}Analysis is a long-running operation on Azure's side. The SDK submits the document, polls, and returns the result, which is why the call takes a few seconds.
Also open Document Intelligence Studio once and run the same document through the invoice model there. The Studio shows the raw provider fields with bounding boxes and per-field confidence, which is the best way to build intuition for what the service actually sees. Compare it with the normalized JSON the script printed; the difference between those two shapes is work our code does, and you will build that mapping in the pipeline stage.
Checkpoint
az cognitiveservices account showreports a ready endpoint- Both Document Intelligence values are filled in
backend/.env check_document_intelligence.pyprints normalized fields with a confidence value- You have seen the same document in Document Intelligence Studio
Next: Explore the outputs
Run both providers against the corpus, compare what they return, and design the normalized data model.
Azure AI Foundry
Create the Azure OpenAI resource in Foundry, deploy a structured-output model, and verify it end to end from the backend.
Explore the outputs
Inspect what each provider returns in isolation, understand the inputs and outputs, and design the normalized data model everything else depends on.