Dashboard Part 5 Document Intelligence
📄 Part 5 · Topic 2 of 3

Azure Document Intelligence

Azure Document Intelligence (formerly Form Recognizer) is an AI service that reads and extracts structured data from documents — invoices, receipts, ID cards, contracts, tables — using pre-trained models or custom trained models. It understands the layout, structure, and meaning of documents, not just the raw text.

🐍 Python — every line explained ⏱️ ~50 min 🔥 High exam weight

Document Intelligence terms — defined before code

💡
Building on what you know

You have already learned about REST APIs, endpoints, API keys, and managed identity in Part 1. You have learned about async API patterns (POST then GET) in the context of other services. Document Intelligence uses that exact same async pattern. Every term below is brand new for this topic.

Document Intelligence

An Azure AI service that extracts structured data from documents. It understands document layout (where text is on the page), structure (tables, key-value pairs, checkboxes), and semantics (what type of field this is — total amount, vendor name, date). Formerly called Form Recognizer. The name changed in 2023 — the exam uses both.

Prebuilt Model

A ready-to-use model that Microsoft has already trained on millions of real-world documents of a specific type — invoices, receipts, ID documents, tax forms, etc. You do not need to label your own documents or train anything. You just call the API with your document and get back structured fields immediately. Best for standard document types.

Custom Model

A model you train yourself using your own documents — for document types that prebuilt models don't cover (e.g. your company's unique form layout). You label at least 5 sample documents to "teach" the model what each field means. Two kinds: custom template (fixed layout, like a printed form) and custom neural (varying layouts, like different invoice formats from different vendors).

Composed Model

A model built by combining multiple custom models into one. The service automatically routes each document to the most appropriate component model based on the document's layout. Used when you handle many different form layouts — e.g. invoices from 10 different vendors, each with a custom model — and want a single API call to handle all of them.

Layout Model

A prebuilt model that extracts the raw structural layout of any document — text, tables, checkboxes, paragraphs and their positions — without assuming what kind of document it is. Use this when you need structure (table rows/columns) but don't need field-specific extraction (vendor name, total amount). The foundation of all other models.

Read Model

The simplest prebuilt model — extracted printed and handwritten text only. No structure, no tables, no key-value pairs. Equivalent to the OCR Read API in Azure Vision. Used when you only need raw text extraction from an image or PDF — not document structure understanding.

Key-Value Pairs

The most common extraction output format. Every form has labels (keys) and their values — "Invoice Number: INV-2024-001". Document Intelligence identifies these pairs automatically. Output: {"key": "Invoice Number", "value": "INV-2024-001", "confidence": 0.99}. This is exactly what makes form processing automation possible.

Bounding Box

The x/y coordinates (as a polygon) of where each extracted piece of text appears on the document page. Format: {polygon: [x1,y1, x2,y2, x3,y3, x4,y4]}. Useful for visual highlighting — you can draw boxes around extracted fields on a rendered document image.

Confidence Score

A number between 0 and 1 expressing how certain the model is about each extracted value. A score of 0.98 means the model is 98% confident. Low-confidence extractions (below ~0.8) are candidates for human review. Your application should check confidence scores before using extracted values in automated workflows.

Custom Template Model

A custom model for documents with a fixed layout — the same field always appears in the same position on every document. Example: a printed government tax form where Box 1 is always in the top-left corner. Faster to train, requires only 5 sample documents. Works through positional pattern matching.

Custom Neural Model

A custom model for documents with varying layouts — the same information might appear in different positions on different versions of the document. Example: invoices from different suppliers, each formatted differently. Requires more training documents (5+ minimum, but more improves accuracy). Uses deep learning — understands semantic meaning, not just position.

Analyze Document (async)

The API operation to submit a document for processing. It is asynchronous — you POST the document and get back an operation ID, then poll a GET endpoint until the operation completes (status: "succeeded"). This is the same POST-then-poll pattern as the OCR Read API and Azure AI batch operations. Processing can take seconds to minutes depending on document length.

Document Intelligence Studio

A web-based graphical interface for working with Document Intelligence — accessed via documentintelligence.ai.azure.com. Used to: test prebuilt models on sample documents, label training documents for custom models, train and evaluate custom models, review extraction results interactively. You do not need to write code to label documents — the Studio handles this.

The problem it solves

📚
Analogy — A very experienced accountant who reads thousands of invoices per minute

Imagine you run a company that receives 50,000 invoices per month from 200 different suppliers. Each invoice has different layouts, fonts, and field positions — but they all contain the same information: vendor name, invoice number, line items, total amount, due date.

Traditionally, a team of data entry clerks would open each invoice and manually type these values into your ERP system. This is slow, expensive, and error-prone.

Document Intelligence is that expert digital accountant — it reads any invoice, regardless of layout, understands what each field means, and returns structured JSON data that your system can process automatically. No human data entry required.

Where Document Intelligence fits in the Microsoft ecosystem

ServiceWhat it doesWhen to use it
Document IntelligenceExtracts structured fields and tables from documents — understands document type (invoice, receipt, ID)When you need to understand what a document means and extract specific named fields
Azure AI Search (Topic 1)Makes document content searchable — indexes text so users can search across thousands of documentsWhen users need to search for documents by content
Content Understanding (Topic 3)Newer service — extracts and classifies content across documents, images, videos, and audio in a unified pipelineMulti-modal content pipelines, summarisation, classification at scale
Vision OCR (Part 6)Extracts raw text from images — no semantic understanding of what the text meansWhen you only need the raw text, not the document structure or field meaning
🎯
Exam Tip — Old name vs new name

Document Intelligence was called Form Recognizer until 2023. The exam may use either name — they refer to the same service. The Python package name changed too: Old: azure-ai-formrecognizer → New: azure-ai-documentintelligence. If the exam shows the old package name in a question, it is still Document Intelligence.

Three types of models — which to choose

Prebuilt Models — ready to use with no training

PREBUILT
Invoice

Extracts: VendorName, VendorAddress, InvoiceId, InvoiceDate, DueDate, SubTotal, TotalTax, InvoiceTotal, line items (Description, Quantity, UnitPrice, Amount). Works across many invoice layouts without training.

PREBUILT
Receipt

Extracts: MerchantName, MerchantAddress, TransactionDate, TransactionTime, Items (Name, Price, Quantity), Subtotal, Tax, Tip, Total. Optimised for point-of-sale receipts.

PREBUILT
ID Document

Extracts: FirstName, LastName, DocumentNumber, DateOfBirth, DateOfExpiration, Sex, Address, Country, Region from passports, driver's licenses, and national ID cards. Limited Access gated — requires Microsoft approval for production use.

PREBUILT
Business Card

Extracts: ContactNames (FirstName, LastName), CompanyName, JobTitles, Emails, Websites, Addresses, PhoneNumbers from business cards in various layouts.

PREBUILT
W-2 (US Tax Form)

Extracts all standard W-2 fields: Employee, Employer, Social Security wages, Federal income tax withheld, State tax information. US-specific.

PREBUILT
Health Insurance Card

Extracts: MemberName, MemberId, PlanName, Deductible, CopayInformation, GroupNumber, Payer details. US health insurance cards.

PREBUILT
General Document

Extracts key-value pairs, tables, and entities from any general document — without assuming the document type. Use when you need structured extraction but the document type isn't covered by a specific prebuilt model.

PREBUILT
Layout + Read

Layout: structure + tables + all text from any document. Read: raw printed and handwritten text only. These are the foundational models — all other models build on Layout internally.

Custom Models — train on your own documents

CUSTOM TEMPLATE
Fixed-layout documents

When to use: Forms where fields always appear in the same position — printed government tax forms, standardised registration forms, fixed-format lab reports.

Minimum samples: 5 labeled documents (same layout).

How it works: Learns field positions. If "Total Amount" is always at the bottom-right of page 1, it learns that position pattern.

CUSTOM NEURAL
Variable-layout documents

When to use: Documents where the same information appears in different positions — invoices from different suppliers, contracts from different law firms, medical reports from different hospitals.

Minimum samples: 5 labeled documents, but 50+ recommended for good accuracy across layout variations.

How it works: Uses deep learning to understand the semantic meaning of text context, not just position. Knows "Total Amount" because of surrounding words like "Due", "Total", "$", not its position.

Composed Models — one API, many layouts

COMPOSED

You have 5 suppliers, each with their own invoice layout. You train 5 custom models (one per layout). You then compose them into a single composed model. When a document arrives, the composed model automatically classifies which component model to use, then returns the extracted fields from the winning model — including a docType field telling you which component model was selected.

Exam trigger phrase: "documents from multiple formats / multiple suppliers / different layouts that need to go through a single endpoint."

🎯
Exam Tip — Custom template vs custom neural decision

Scenario says "same form, same layout" → Custom Template model

Scenario says "different suppliers / different layouts / variable format" → Custom Neural model

Scenario says "multiple different forms that all need one API" → Composed model (combining multiple custom models)

Scenario says "standard invoice / receipt / ID card" → Prebuilt model (no training needed)

How to train, test, and deploy a custom model

1
Collect and upload training documents

Gather at least 5 sample documents of the same type (minimum for a template model). More is better — 50+ for a neural model across varied layouts. Upload them to Azure Blob Storage in a container. Documents can be PDF, JPEG, PNG, BMP, TIFF formats. Ensure they are representative of real documents — different samples, not 5 copies of the same file.

2
Label the training documents in Document Intelligence Studio

Open Document Intelligence Studio at documentintelligence.ai.azure.com. Create a new project, connect your Blob Storage container, and open each document. For each document, draw bounding boxes around each field and assign a label name (e.g. "InvoiceNumber", "TotalAmount", "VendorName"). The studio shows the document and lets you annotate each page visually — no code needed.

3
Train the model

Click "Train" in Document Intelligence Studio. Select the model type (Template or Neural). Give the model a name. Training takes from a few minutes (template) to longer (neural with many documents). The Studio shows training progress and completion status.

4
Evaluate the model

After training completes, the Studio shows evaluation metrics: estimated accuracy per field and overall. Test the model by uploading a new document (not used in training) and reviewing the extracted fields and confidence scores. If accuracy is insufficient, add more labeled training samples for the fields with low accuracy.

5
Use the model via API

The trained model is now accessible via the REST API or Python SDK using your model ID. No separate "publish" step like some other services — once training completes, the model is immediately available. Pass the model_id to the begin_analyze_document call. The same async POST-then-poll pattern applies.

How analyze_document works — POST then poll

Document Intelligence uses an asynchronous API for all analysis operations. Here is why and how it works:

📚
Analogy — Like submitting a job to a printing queue

When you send a document to a print queue, you don't stand frozen waiting for it to print — you submit the job and then check if it's done periodically. Document analysis (especially multi-page PDFs) takes time, so the API works the same way:

Step 1 — Submit: POST the document → you get back an operation ID (like a ticket number).
Step 2 — Poll: Use the operation ID to GET the status repeatedly until it says "succeeded", then read the results.

The Python SDK hides this polling loop for you inside begin_analyze_document() — it returns a "poller" object. Calling .result() on the poller waits until the operation completes and returns the results.

Analyze a receipt with a prebuilt model, then a custom model

Install: pip install azure-ai-documentintelligence azure-core

import os
from azure.ai.documentintelligence import DocumentIntelligenceClient
from azure.ai.documentintelligence.models import AnalyzeDocumentRequest
from azure.core.credentials import AzureKeyCredential

# ── Connection details ─────────────────────────────────────────────────
# These come from your Document Intelligence resource in Azure portal
# Keys and Endpoint → copy the endpoint URL and one of the two keys
endpoint = os.environ.get("DOCUMENTINTELLIGENCE_ENDPOINT")
key      = os.environ.get("DOCUMENTINTELLIGENCE_KEY")

# Create a credential object — wraps the key in a standard credential type
credential = AzureKeyCredential(key)

# Create the client — this object provides all data extraction methods
# The endpoint format is: https://<your-resource-name>.cognitiveservices.azure.com/
client = DocumentIntelligenceClient(endpoint=endpoint, credential=credential)


# ══════════════════════════════════════════════════════════════════════
# EXAMPLE 1 — Prebuilt Receipt Model
# Use this when you have a standard point-of-sale receipt
# No training needed — Microsoft has pre-trained this model
# ══════════════════════════════════════════════════════════════════════

# URL of the document to analyse (can also use a local file — see Example 2)
receipt_url = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/contoso-receipt.png"

# begin_analyze_document() submits the document for analysis
# "prebuilt-receipt" is the model ID for the prebuilt receipt model
# Other prebuilt model IDs: "prebuilt-invoice", "prebuilt-idDocument", "prebuilt-businessCard"
# "prebuilt-layout" (structure + tables), "prebuilt-read" (text only)
# AnalyzeDocumentRequest wraps the document URL (can also use urlSource= parameter directly)
poller = client.begin_analyze_document(
    "prebuilt-receipt",                       # Which model to use
    AnalyzeDocumentRequest(url_source=receipt_url)  # The document URL to analyse
)

# .result() waits for the async operation to complete and returns the result
# The Python SDK handles the POST → poll → GET loop automatically
# This may take several seconds for large documents
result = poller.result()

# The result contains a list of documents — one per recognised document in the input
# For a single receipt image, there will be one document
for receipt in result.documents:
    # doc_type: which prebuilt sub-type was detected (e.g. "receipt.retailMeal")
    print(f"Document Type: {receipt.doc_type}")
    print(f"Confidence:    {receipt.confidence:.2f}")

    # receipt.fields is a dictionary of field name → AnalyzedDocumentField objects
    # Each field has: .value (the extracted value), .confidence (0.0 to 1.0)
    # .get() returns None if the field wasn't found in this document
    merchant = receipt.fields.get("MerchantName")
    total    = receipt.fields.get("Total")
    date     = receipt.fields.get("TransactionDate")

    # Always check if the field was found before accessing its value
    if merchant:
        # .value gives you the extracted value in a Python-friendly type
        # .confidence tells you how certain the model is (0.0 = uncertain, 1.0 = certain)
        print(f"Merchant: {merchant.value}  (confidence: {merchant.confidence:.2f})")
    if total:
        # For currency fields, .value is a CurrencyValue object with .amount and .currency_symbol
        print(f"Total: {total.value.amount} {total.value.currency_symbol}  (confidence: {total.confidence:.2f})")
    if date:
        # For date fields, .value is a Python datetime.date object
        print(f"Date: {date.value}")

    # Receipts also contain line items — stored as a list in the Items field
    items = receipt.fields.get("Items")
    if items:
        print("\nLine Items:")
        # items.value is a list of ValueArray objects, one per line item
        for item in items.value:
            # Each item is itself a dictionary of fields (Description, Price, Quantity)
            desc  = item.value.get("Description")
            price = item.value.get("Price")
            if desc and price:
                print(f"  {desc.value}: {price.value.amount}")


# ══════════════════════════════════════════════════════════════════════
# EXAMPLE 2 — Analyse a LOCAL FILE using the prebuilt Invoice model
# ══════════════════════════════════════════════════════════════════════

# Open a local PDF file in binary mode ("rb" = read binary)
# Binary mode is needed because we are sending raw bytes, not text
with open("invoice.pdf", "rb") as f:
    # f.read() reads the entire file as a bytes object
    document_bytes = f.read()

# When passing a local file, use bytes_source= instead of url_source=
poller = client.begin_analyze_document(
    "prebuilt-invoice",                              # Model: prebuilt invoice
    AnalyzeDocumentRequest(bytes_source=document_bytes)  # Local file as bytes
)
result = poller.result()

for invoice in result.documents:
    vendor_name    = invoice.fields.get("VendorName")
    invoice_id     = invoice.fields.get("InvoiceId")
    invoice_total  = invoice.fields.get("InvoiceTotal")
    due_date       = invoice.fields.get("DueDate")

    print("\n--- Invoice Extraction ---")
    if vendor_name:   print(f"Vendor:       {vendor_name.value}")
    if invoice_id:    print(f"Invoice ID:   {invoice_id.value}")
    if invoice_total: print(f"Total Amount: {invoice_total.value.amount}")
    if due_date:      print(f"Due:          {due_date.value}")


# ══════════════════════════════════════════════════════════════════════
# EXAMPLE 3 — Custom Model
# Use the same client and same begin_analyze_document() call
# The only difference: pass YOUR model ID instead of a prebuilt model ID
# ══════════════════════════════════════════════════════════════════════

# Your custom model ID — found in Document Intelligence Studio after training
# Format: a GUID like "abc12345-1234-5678-abcd-123456789abc"
my_custom_model_id = "your-custom-model-id-here"

with open("my_custom_form.pdf", "rb") as f:
    document_bytes = f.read()

# Same API call — just replace the model ID with your trained custom model ID
poller = client.begin_analyze_document(
    my_custom_model_id,
    AnalyzeDocumentRequest(bytes_source=document_bytes)
)
result = poller.result()

for doc in result.documents:
    # doc_type: "your-model-id:Type" — the custom model type name you defined
    print(f"Doc type: {doc.doc_type}, Confidence: {doc.confidence:.2f}")
    # doc.fields is a dictionary of the LABEL NAMES you used when labeling in Studio
    for field_name, field_value in doc.fields.items():
        if field_value.value:
            print(f"  {field_name}: {field_value.value} (confidence: {field_value.confidence:.2f})")

Python — Extracting tables and bounding box positions

Documents often contain tables — rows and columns of structured data. Document Intelligence extracts them with full position information.

# Use the Layout model to extract tables from any document
# "prebuilt-layout" extracts text + tables + structure without assuming a document type
with open("contract_with_table.pdf", "rb") as f:
    document_bytes = f.read()

poller = client.begin_analyze_document(
    "prebuilt-layout",
    AnalyzeDocumentRequest(bytes_source=document_bytes)
)
result = poller.result()

# result.tables is a list of all detected tables in the document
for i, table in enumerate(result.tables):
    # row_count, column_count: dimensions of the detected table
    print(f"\nTable {i+1}: {table.row_count} rows × {table.column_count} cols")

    # table.cells is a flat list of all cells in the table
    # Each cell has: row_index, column_index, content, bounding_regions
    for cell in table.cells:
        # row_index and column_index tell you where in the table this cell sits
        # kind: "columnHeader" for header row cells, "content" for data cells
        label = "[HEADER]" if cell.kind == "columnHeader" else ""
        print(f"  Row {cell.row_index}, Col {cell.column_index} {label}: {cell.content}")

# Bounding box — where on the page each piece of content appears
# result.pages contains all the pages with their words and lines
for page in result.pages:
    print(f"\nPage {page.page_number}: {page.width}w × {page.height}h ({page.unit})")
    # page.words is a flat list of every recognised word on the page
    for word in page.words:
        # word.polygon: the [x1,y1, x2,y2, x3,y3, x4,y4] corners of the word's bounding box
        # word.confidence: how confident the OCR was about this word (0.0 to 1.0)
        # word.content: the text of the word
        print(f"  Word: '{word.content}' conf={word.confidence:.2f}")
        # The polygon lets you draw a box around the word on a rendered document image

Document Intelligence — what the exam tests

⚠️
Top 6 Tested Facts

1. Minimum 5 labeled documents to train a custom model — The exam uses 5 as a threshold question. "How many labeled documents are required to train a custom model?" → 5. More improves accuracy but 5 is the minimum.

2. Custom Template vs Custom Neural — Template = same field always in same position (fixed layout). Neural = fields in varying positions across documents (variable layout). Wrong model type = poor accuracy. This is a common scenario question.

3. Composed model = multiple custom models + automatic routing — "A company receives invoices from 8 different suppliers, each with a different format, via one API endpoint" → Composed model. Each supplier gets its own custom model, then composed into one.

4. Old name = Form Recognizer, new name = Document Intelligence — Both names appear in exam questions. The Python package changed from azure-ai-formrecognizer to azure-ai-documentintelligence. Don't let the old name confuse you.

5. Analyze operation is asynchronous — Document Intelligence never returns results immediately. It always follows the POST → operation ID → poll GET → status "succeeded" → read results pattern. The Python SDK's .result() handles the polling for you.

6. ID Document model requires Limited Access approval — Just like Face API identification. If a scenario involves extracting data from passports or driver's licenses you need Microsoft's gated approval — can't just enable and use freely.

Test your understanding

Topic 2 — Document Intelligence 1 / 5
Scenario: A bank receives mortgage application forms from customers. Each form has a fixed layout — the applicant's name is always at the top of page 1, the loan amount is always in box 7, and the property address is always in the same section. The bank wants to automate extraction of these specific fields.

Which Document Intelligence model type is most appropriate, and approximately how many labeled training samples are required to start?

💡 Explanation

C is correct. The key phrase is "fixed layout" — fields always appear in the same position. This perfectly matches the Custom Template model, which learns positional patterns rather than semantic meaning. The minimum training requirement is 5 labeled documents. Custom Neural (B) is for varying layouts and benefits from more samples but 50 isn't a hard requirement. Prebuilt Invoice (A) is for standard invoices — not mortgage applications. Layout (D) extracts raw structure but doesn't extract named semantic fields like "loan amount".

Scenario: A logistics company receives invoices from 12 different shipping carriers. Each carrier has a completely different invoice format — different layouts, different field positions, different terminology. The company wants a single API endpoint to process any carrier invoice and extract: carrier name, invoice number, shipment date, and total charges.

Which approach best meets this requirement?

💡 Explanation

B is correct. The scenario describes multiple distinct layouts that need one endpoint — that is exactly the Composed model use case. Each carrier gets its own Custom Neural model (variable layouts across documents from the same carrier) and all 12 are composed into one. The single composed model automatically classifies incoming documents and routes to the best model. Option D (single neural model for all 12) is less accurate — composition is the purpose-built solution. Option C (prebuilt Invoice) may not extract carrier-specific fields precisely. Template models (A) don't handle variable layouts.

A developer calls the Document Intelligence API to analyse a 40-page contract PDF. Which statement correctly describes how the API returns results?

💡 Explanation

B is correct. Document Intelligence uses an asynchronous API pattern for all analysis operations. The POST request queues the job and returns a 202 Accepted response with an operation URL. The developer (or SDK) polls that URL until the status field says "succeeded" — then the result JSON is available on the same operation URL. The Python SDK's begin_analyze_document(...).result() handles this polling loop automatically. Multi-page documents are submitted as a whole — no splitting required (D).

A developer notices that the Document Intelligence Python import has changed. The old code used from azure.ai.formrecognizer import FormRecognizerClient. What is the correct import for the current SDK?

💡 Explanation

B is correct. When Microsoft renamed Form Recognizer to Document Intelligence in 2023, both the service name and the Python package changed. The old package azure-ai-formrecognizer is deprecated. The new package is azure-ai-documentintelligence and the client class is DocumentIntelligenceClient. Both old and new names may appear on the exam — they refer to the same underlying service. Always use the new names in new code.

Scenario: A company wants to automate the extraction of data from passports submitted during employee onboarding — extracting first name, last name, date of birth, document number, and expiry date. The solution must be production-ready within 2 weeks.

Which action is REQUIRED before using Document Intelligence to process passport images in a production application?

💡 Explanation

C is correct. The prebuilt ID Document model (passports, driver's licenses, national ID cards) is a Limited Access feature — just like Face API identification. Microsoft requires organisations to submit a request and receive approval before using it in production. This is a privacy and identity protection policy. The model does exist (A is wrong). There is no "feature flag" (B). The Layout model only extracts raw text and structure — it doesn't know what "date of birth" or "document number" mean (D).

Mark this topic as complete