{"id":30017253,"url":"https://github.com/microsoftcloudessentials-learninghub/pdfs-multilayout-visualcue-azureai-document-processing","last_synced_at":"2026-02-09T03:02:18.473Z","repository":{"id":305711354,"uuid":"1021607112","full_name":"MicrosoftCloudEssentials-LearningHub/PDFs-MultiLayout-VisualCue-AzureAI-Document-Processing","owner":"MicrosoftCloudEssentials-LearningHub","description":"Extended solution for extracting tables, checkboxes, and visually selected values (e.g., shaded cells, Xs, checkmarks) from PDFs using Azure Document Intelligence and Vision.","archived":false,"fork":false,"pushed_at":"2025-11-14T04:59:48.000Z","size":172,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-14T06:20:05.318Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MicrosoftCloudEssentials-LearningHub.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-17T16:51:12.000Z","updated_at":"2025-11-14T04:59:51.000Z","dependencies_parsed_at":"2025-08-20T17:17:29.037Z","dependency_job_id":"1b18fdf6-3184-4dec-8605-4681e09af660","html_url":"https://github.com/MicrosoftCloudEssentials-LearningHub/PDFs-MultiLayout-VisualCue-AzureAI-Document-Processing","commit_stats":null,"previous_names":["microsoftcloudessentials-learninghub/pdfs-multilayout-visualcue-fapp-docintelligence","microsoftcloudessentials-learninghub/pdfs-multilayout-visualcue-azureai-document-processing"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MicrosoftCloudEssentials-LearningHub/PDFs-MultiLayout-VisualCue-AzureAI-Document-Processing","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MicrosoftCloudEssentials-LearningHub%2FPDFs-MultiLayout-VisualCue-AzureAI-Document-Processing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MicrosoftCloudEssentials-LearningHub%2FPDFs-MultiLayout-VisualCue-AzureAI-Document-Processing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MicrosoftCloudEssentials-LearningHub%2FPDFs-MultiLayout-VisualCue-AzureAI-Document-Processing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MicrosoftCloudEssentials-LearningHub%2FPDFs-MultiLayout-VisualCue-AzureAI-Document-Processing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MicrosoftCloudEssentials-LearningHub","download_url":"https://codeload.github.com/MicrosoftCloudEssentials-LearningHub/PDFs-MultiLayout-VisualCue-AzureAI-Document-Processing/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MicrosoftCloudEssentials-LearningHub%2FPDFs-MultiLayout-VisualCue-AzureAI-Document-Processing/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29255379,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-09T01:52:29.835Z","status":"online","status_checked_at":"2026-02-09T02:00:09.501Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-05T22:54:37.914Z","updated_at":"2026-02-09T03:02:18.461Z","avatar_url":"https://github.com/MicrosoftCloudEssentials-LearningHub.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Demo: Azure Implementation \u003cbr/\u003e PDF Layout Extraction with Azure AI Document Intelligence Supporting Multiple Document Versions with Visual Selection Cues (full-code approach)\n\n`Azure Storage + Document Intelligence + AI Vision + Azure Open AI (LLMs) + Function App +  Cosmos DB`\n\nCosta Rica\n\n[![GitHub](https://img.shields.io/badge/--181717?logo=github\u0026logoColor=ffffff)](https://github.com/)\n[brown9804](https://github.com/brown9804)\n\nLast updated: 2025-10-29\n\n-----------------------------\n\n\u003e `How we move from basic coding all the way to AI agents?`\n\n\n```mermaid\nflowchart LR\n    A[Scripting: Line-by-line instructions] --\u003e B[Machine Learning: Packages + statistical foundations]\n    B --\u003e C[LLMs: Reasoning, understanding, human-like responses]\n    C --\u003e D[Agents: LLMs with ability to act]\n\n    %% Styling\n    classDef step fill:#4a90e2,stroke:#333,stroke-width:2px,color:#fff,font-weight:bold;\n    class A,B,C,D step;\n\n    %% Extra notes\n    A:::step\n    B:::step\n    C:::step\n    D:::step\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e More details about it here \u003c/b\u003e (Click to expand)\u003c/summary\u003e\n  \n\u003e - We all `start with scripting`, no matter the language, it’s the first step. `Simple/complex instructions, written line by line`, to get something done\n\u003e - Then comes `machine learning`. At this stage, we’re not reinventing the math, we’re `leveraging powerful packages built on deep statistical and mathematical foundations.` These tools let us `automate smarter processes, like reviewing claims with predictive analytics. You’re not just coding anymore; you’re building systems that learn and adapt.`\n\u003e - `LLMs`. This is what most people mean when they say `AI.` Think of `yourself as the architect, and the LLM as your strategic engine. You can plug into it via an API, a key, or through integrated services. It’s not just about automation, it’s about reasoning, understanding, and generating human-like responses.`\n\u003e - And finally, `agents`. These are LLMs with the `ability to act`. They don’t just respond, `they take initiative. They can create code, trigger workflows, make decisions, interact with tools, with other agents. It’s where intelligence meets execution`\n\n\u003c/details\u003e\n\n\u003e [!NOTE]\n\u003e A landing zone is a general `cloud framework that sets up the core structure for all workloads`. Each use case (like an app, data pipeline, or API) then builds on top of this framework, using the `same environments (Dev → Test → UAT → Prod) and CI/CD pipelines to move code safely into production.` It’s general by design, but `applied per use case.`\n\n\u003e This solution is designed to be flexible and robust, supporting multiple versions of PDF documents with varying layouts, including those that use visual selection cues such as gray fills, hand-drawn Xs, checkmarks, or circles. By building on the [PDFs-Layouts-Processing-Fapp-DocIntelligence](https://github.com/MicrosoftCloudEssentials-LearningHub/PDFs-Layouts-Processing-Fapp-DocIntelligence) repository, modular approach aiming to:\n\n- Table structure and text are extracted using Azure Document Intelligence (Layout model).\n- Visual selection cues are detected using Azure AI Vision or image preprocessing.\n- Visual indicators are mapped to structured data, returning only the selected values in a clean JSON format.\n- Advanced semantic understanding is provided by Azure OpenAI to analyze document content and context.\n- Multiple file formats are supported, including PDFs and various image formats.\n- The logic is abstracted to support multiple layout variations, so the system adapts easily to new document formats and selection styles.\n\n\u003e [!IMPORTANT]\n\u003e This example is based on a `public network site and is intended for demonstration purposes only`. It showcases how several Azure resources can work together to achieve the desired result. Consider the section below about [Important Considerations for Production Environment](#important-considerations-for-production-environment). Please note that `these demos are intended as a guide and are based on my personal experiences. For official guidance, support, or more detailed information, please refer to Microsoft's official documentation or contact Microsoft directly`: [Microsoft Sales and Support](https://support.microsoft.com/contactus?ContactUsExperienceEntryPointAssetId=S.HP.SMC-HOME)\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eList of References\u003c/b\u003e (Click to expand)\u003c/summary\u003e\n\n- [Power Apps pricing](https://www.microsoft.com/en-us/power-platform/products/power-apps/)\n- [Create a Fabric data agent (preview)](https://learn.microsoft.com/en-us/fabric/data-science/how-to-create-data-agent) `enables users to interact with data stored in lakehouses, warehouses, Power BI semantic models, and KQL databases using natural language queries`. Key prerequisites include having a paid Fabric capacity, enabling specific tenant settings, and ensuring data sources are accessible.\n  - To create a data agent, users navigate to their workspace, select the data agent option, and configure it by adding `up to five data sources`. Users can ask questions in plain English, and the system translates these into structured queries (SQL, DAX, KQL) to retrieve data. The document outlines the process for creating, configuring, and sharing the data agent, including providing instructions and example queries to enhance performance.\n  - The data agent operates under the user’s Microsoft Entra ID permissions, ensuring secure access to data. `It does not support complex reasoning or advanced analytics, focusing instead on retrieving structured data based on user queries`. Users can publish their data agent for colleagues to use after testing its performance. We can extend this with [Extend your agent with Model Context Protocol](https://learn.microsoft.com/en-us/microsoft-copilot-studio/agent-extend-action-mcp) allows users to connect to existing knowledge servers and data sources, providing access to resources, tools, and predefined prompts for specific tasks.\n\n      \u003cimg width=\"1898\" height=\"995\" alt=\"image\" src=\"https://github.com/user-attachments/assets/3845e948-71be-4ce2-9eb6-94e52e51acde\" /\u003e\n\n- [Document Processor](https://learn.microsoft.com/en-us/microsoft-copilot-studio/template-managed-document-processor) managed agent in Microsoft Copilot Studio. `E2E solution for document processing, including extraction, validation, human monitoring, and exporting to downstream applications. Users can upload a sample document and configure extraction without needing to label data or train custom models. The agent informs users of the processing status and allows for manual verification of extracted data in the Validation Station`. Key prerequisites include licenses for Copilot Studio and Power Platform, enabling the Power Apps component framework, and specific security roles and permissions. Limitations on document processing include file size (less than 25 MB), file types (PNG, JPG, JPEG, PDF), and a maximum of 50 pages. Users can set up the agent by creating connections with required services, configuring data fields for extraction, and creating validation rules. The agent can notify reviewers when validation fails, and users can interact with the agent via Microsoft Teams. Here is more about `setting up the agent, including uploading sample documents, defining validation rules, and selecting document sources.` [Use an autonomous agent in Copilot Studio for document processing](https://learn.microsoft.com/en-us/power-platform/architecture/reference-architectures/document-processing-agent)\n\n    \u003cimg width=\"1332\" height=\"844\" alt=\"image\" src=\"https://github.com/user-attachments/assets/879c048d-1508-4ee1-a62f-1e1593b74f59\" /\u003e\n    \n- [Solution Accelerator for AI Document Processor (ADP)](https://github.com/azure/ai-document-processor) - AI Factory\n\n    | **Category**                  | **Details**                                                                                                                                                                                                 |\n    |------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n    | **Purpose**                  | Automate document processing using Azure services and LLMs. Extracts data from files (PDF, Word, MP3), processes via Azure OpenAI, and outputs structured insights (JSON/CSV) to blob storage.         |\n    | **Infrastructure Provisioning** | Uses Bicep templates to deploy all required Azure resources. Automates setup of networking, identity, and access controls using RBAC and managed identities to ensure secure and scalable deployment. |\n    | **Main Azure Resources**     | - **Azure Function App**: Hosts the orchestrator and activity functions using Durable Functions to manage the document processing workflow.\u003cbr\u003e- **Azure Storage Account**: Stores input documents (bronze container) and output results (gold container). Also holds prompt configurations if UI is not deployed.\u003cbr\u003e- **Azure Static Web App**: Provides a user-friendly interface for uploading files, editing prompts, and triggering workflows.\u003cbr\u003e- **Azure OpenAI**: Processes extracted text using LLMs to generate structured summaries or insights.\u003cbr\u003e- **Azure Cognitive Services**: Specifically uses Document Intelligence for OCR and text extraction from uploaded files.\u003cbr\u003e- **Cosmos DB**: Stores prompt configurations when the frontend UI is enabled, allowing dynamic updates from the web interface.\u003cbr\u003e- **Key Vault**: Securely stores secrets, keys, and credentials used by the Function App and other services.\u003cbr\u003e- **Application Insights**: Enables monitoring, logging, and diagnostics for the Function App and other components.\u003cbr\u003e- **App Service Plan**: Provides the compute resources for running the Function App.                                                                 |\n    | **Pipeline Components**      | - `function_app.py`: Main orchestrator using Durable Functions chaining pattern.\u003cbr\u003e- `activities/runDocIntel.py`: Extracts text from documents using Azure Document Intelligence.\u003cbr\u003e- `activities/callAoai.py`: Sends extracted text and prompt to Azure OpenAI and receives structured JSON.\u003cbr\u003e- `activities/writeToBlob.py`: Writes the final output to the gold container in blob storage. |\n    | **Data Flow**                | 1. Upload document to bronze container\u003cbr\u003e2. OCR via Document Intelligence\u003cbr\u003e3. Send extracted text + prompt to Azure OpenAI\u003cbr\u003e4. Receive structured JSON\u003cbr\u003e5. Write output to gold container           |\n    | **Frontend UI (Optional)**  | - Allows business users to upload files and edit prompts\u003cbr\u003e- Prompts are stored in Cosmos DB\u003cbr\u003e- Users can trigger workflows and view job status directly from the interface                             |\n    | **Prompt Configuration**     | - Without UI: Prompts are stored in `prompts.yaml` file in blob storage\u003cbr\u003e- With UI: Prompts are stored and managed in Cosmos DB via the web interface                                                  |\n    | **Deployment Steps**         | 1. Fork and clone the GitHub repo\u003cbr\u003e2. Run `az login`, `azd auth login`, `azd up`\u003cbr\u003e3. Provide User Principal ID for RBAC setup\u003cbr\u003e4. Choose whether to deploy frontend UI                              |\n    | **Execution (Without UI)**   | - Update `prompts.yaml` with desired instructions\u003cbr\u003e- Send POST request to `http_start` endpoint with blob metadata\u003cbr\u003e- Monitor pipeline execution via Log Stream                                       |\n    | **Execution (With UI)**      | - Upload files via web interface\u003cbr\u003e- Edit system and user prompts\u003cbr\u003e- Click \"Start Workflow\" to trigger pipeline\u003cbr\u003e- View success/failure messages and job status                                     |\n    | **Monitoring \u0026 Troubleshooting** | - Use Log Stream for real-time logs\u003cbr\u003e- Use Log Analytics Workspace to query exceptions and performance metrics\u003cbr\u003e- Use SSH console in Development Tools to inspect deployment logs and file system |\n    | **Pre-Requisites**           | - Azure CLI\u003cbr\u003e- Azure Developer CLI (azd)\u003cbr\u003e- Node.js 18.x.x\u003cbr\u003e- npm 9.x.x\u003cbr\u003e- Python 3.11                                                                                                             |\n    | **License**                  | MIT License – Free to use, modify, and distribute with attribution. No warranty provided.                                                                                                                  |\n\n    \u003cimg width=\"835\" height=\"535\" alt=\"image\" src=\"https://github.com/user-attachments/assets/61dbac57-f635-4dd6-9292-50e51823a8c4\" /\u003e\n    \n    \u003e Data flow: \n    \n    \u003cimg width=\"930\" height=\"620\" alt=\"image\" src=\"https://github.com/user-attachments/assets/2f01a07b-71cd-4ee9-b316-c0a2273d01b2\" /\u003e\n\n    \u003e ZTA:\n    \u003cimg width=\"1840\" height=\"935\" alt=\"image\" src=\"https://github.com/user-attachments/assets/947ddf0d-daf3-4df3-949c-1271a3fef7bb\" /\u003e\n\n- [Use Azure AI services with SynapseML in Microsoft Fabric](https://learn.microsoft.com/en-us/fabric/data-science/how-to-use-ai-services-with-synapseml)\n- [Plan and manage costs for Azure AI Foundry](https://learn.microsoft.com/en-us/azure/ai-foundry/how-to/costs-plan-manage)\n- [Azure AI Document Intelligence documentation](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/?view=doc-intel-4.0.0)\n- [Get started with the Document Intelligence Sample Labeling tool](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/v21/try-sample-label-tool?view=doc-intel-2.1.0#prerequisites-for-training-a-custom-form-model)\n- [Document Intelligence Sample Labeling tool](https://fott-2-1.azurewebsites.net/)\n- [Assign an Azure role for access to blob data](https://learn.microsoft.com/en-us/azure/storage/blobs/assign-azure-role-data-access?tabs=portal)\n- [Build and train a custom extraction model](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/how-to-guides/build-a-custom-model?view=doc-intel-2.1.0)\n- [Compose custom models - Document Intelligence](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/how-to-guides/compose-custom-models?view=doc-intel-2.1.0\u0026tabs=studio)\n- [Deploy the Sample Labeling tool](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/v21/deploy-label-tool?view=doc-intel-2.1.0)\n- [Train a custom model using the Sample Labeling tool](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/v21/label-tool?view=doc-intel-2.1.0)\n- [Train models with the sample-labeling tool](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/v21/supervised-table-tags?view=doc-intel-2.1.0)\n- [Azure Cosmos DB - Database for the AI Era](https://learn.microsoft.com/en-us/azure/cosmos-db/introduction)\n- [Consistency levels in Azure Cosmos DB](https://learn.microsoft.com/en-us/azure/cosmos-db/consistency-levels)\n- [Azure Cosmos DB SQL API client library for Python](https://learn.microsoft.com/en-us/python/api/overview/azure/cosmos-readme?view=azure-python)\n- [CosmosClient class documentation](https://learn.microsoft.com/en-us/python/api/azure-cosmos/azure.cosmos.cosmos_client.cosmosclient?view=azure-python)\n- [Cosmos AAD Authentication](https://learn.microsoft.com/en-us/python/api/overview/azure/cosmos-readme?view=azure-python#aad-authentication)\n- [Cosmos python examples](https://learn.microsoft.com/en-us/python/api/overview/azure/cosmos-readme?view=azure-python#examples)\n- [Use control plane role-based access control with Azure Cosmos DB for NoSQL](https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/security/how-to-grant-control-plane-role-based-access?tabs=built-in-definition%2Ccsharp\u0026pivots=azure-interface-portal)\n- [Use data plane role-based access control with Azure Cosmos DB for NoSQL](https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/security/how-to-grant-data-plane-role-based-access?tabs=built-in-definition%2Ccsharp\u0026pivots=azure-interface-cli)\n- [Create or update Azure custom roles using Azure CLI](https://learn.microsoft.com/en-us/azure/role-based-access-control/custom-roles-cli)\n- [Document Intelligence query field extraction](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/concept/query-fields?view=doc-intel-4.0.0)\n- [What's new in Azure AI Document Intelligence](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/whats-new?view=doc-intel-4.0.0)\n- [Managed identities for Document Intelligence](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/authentication/managed-identities?view=doc-intel-4.0.0)\n  \n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eTable of Content\u003c/b\u003e (Click to expand)\u003c/summary\u003e\n  \n- [Important Considerations for Production Environment](#important-considerations-for-production-environment)\n- [Prerequisites](#prerequisites)\n- [Where to start?](#where-to-start)\n- [Overview](#overview)\n- [Function App Hosting Options](#function-app-hosting-options)\n- [Function App: Configure/Validate the Environment variables](#function-app-configurevalidate-the-environment-variables)\n- [Function App: Develop the logic](#function-app-develop-the-logic)\n- [Test the solution](#test-the-solution)\n\n\u003c/details\u003e\n\n\u003e `How can you extract layout, text, visual, and other elements` from `PDFs` stored in an Azure Storage Account, process them using Azure AI services, and `store the results` in Cosmos DB for `further analysis?` This solution is `designed to accelerate the process` of building your own implementation. Please `feel free to use any of the provided reference.` I'm happy to contribute. Once this solution is deployed:\n\u003e\n\u003e 1. Upload your documents: Just `drop your PDFs or images into an Azure Storage container`and the system takes over from there. \n\u003e 2. Automated intelligent processing: Behind the scenes, `Azure Functions orchestrates a powerful AI workflow`: \n\u003e     - Document Intelligence pulls out tables, text, and form data\n\u003e     - AI Vision spots visual cues like checkmarks and highlights\n\u003e     - Azure OpenAI understands what the document actually means \n\u003e 3. Centralized information management: `All extracted data is stored in Cosmos DB`, organized and accessible. The system `adapts to differents document layouts without requiring custom code for each format.`\n\n\u003e [!NOTE]\n\u003e Advantages of Document Intelligence for organizations handling with large volumes of documents: \u003cbr/\u003e\n\u003e\n\u003e - Utilizes natural language processing, computer vision, deep learning, and machine learning. \u003cbr/\u003e\n\u003e - Handles structured, semi-structured, and unstructured documents. \u003cbr/\u003e\n\u003e - Automates the extraction and transformation of layout data into usable formats like JSON or CSV.\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/user-attachments/assets/322c8d9b-5ca3-4ba4-b0cd-ac14f198229e\" alt=\"Centered Image\" style=\"border: 2px solid #4CAF50; border-radius: 5px; padding: 5px;\"/\u003e\n\u003c/div\u003e\n\n\u003e [!NOTE]\n\u003e Azure Event Grid System Topics are free to create and manage, a System Topic is automatically created and managed by Azure for certain Azure services that emit events. It represents a source of events from an Azure resource (like a Storage Account, Key Vault, or Azure Maps). `You don't need to create or manage the topic yourself, Azure does it for you when you enable event publishing on a supported resource.` \u003cbr/\u003e\n\u003e\n\u003e - Emits predefined event types (e.g., Microsoft.Storage.BlobCreated, Microsoft.Resources.ResourceWriteSuccess). \u003cbr/\u003e\n\u003e - You can attach event handlers (like Azure Functions, Logic Apps, Webhooks) to respond to these events. \u003cbr/\u003e\n\u003e - Works seamlessly with serverless architectures for real-time automation. \u003cbr/\u003e\n\u003e For example:\n\u003e Suppose you have a Storage Account and want to trigger a function every time a new blob is uploaded: \u003cbr/\u003e\n\u003e - Azure automatically creates a System Topic for the Storage Account.\n\u003e - You subscribe to the BlobCreated event.\n\u003e - When a blob is uploaded, Event Grid routes the event to your Azure Function.\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/user-attachments/assets/298ce8db-af28-487c-8126-9ba74986e8a5\" alt=\"Centered Image\" style=\"border: 2px solid #4CAF50; border-radius: 5px; padding: 5px;\"/\u003e\n\u003c/div\u003e\n\n## Important Considerations for Production Environment\n\n\u003cdetails\u003e\n  \u003csummary\u003ePrivate Network Configuration\u003c/summary\u003e\n\n \u003e For enhanced security, consider configuring your Azure resources to operate within a private network. This can be achieved using Azure Virtual Network (VNet) to isolate your resources and control inbound and outbound traffic. Implementing private endpoints for services like Azure Blob Storage and Azure Functions can further secure your data by restricting access to your VNet.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eSecurity\u003c/summary\u003e\n\n  \u003e Ensure that you implement appropriate security measures when deploying this solution in a production environment. This includes: \u003cbr/\u003e\n  \u003e\n  \u003e - Securing Access: Use Azure Entra ID (formerly known as Azure Active Directory or Azure AD) for authentication and role-based access control (RBAC) to manage permissions. \u003cbr/\u003e\n  \u003e - Managing Secrets: Store sensitive information such as connection strings and API keys in Azure Key Vault. \u003cbr/\u003e\n  \u003e - Data Encryption: Enable encryption for data at rest and in transit to protect sensitive information.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eScalability\u003c/summary\u003e\n\n  \u003e While this example provides a basic setup, you may need to scale the resources based on your specific requirements. Azure services offer various scaling options to handle increased workloads. Consider using: \u003cbr/\u003e\n  \u003e\n  \u003e - Auto-scaling: Configure auto-scaling for Azure Functions and other services to automatically adjust based on demand. \u003cbr/\u003e\n  \u003e - Load Balancing: Use Azure Load Balancer or Application Gateway to distribute traffic and ensure high availability.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eCost Management\u003c/summary\u003e\n\n  \u003e Monitor and manage the costs associated with your Azure resources. Use Azure Cost Management and Billing to track usage and optimize resource allocation.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eCompliance\u003c/summary\u003e\n\n  \u003e Ensure that your deployment complies with relevant regulations and standards. Use Azure Policy to enforce compliance and governance policies across your resources.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eDisaster Recovery\u003c/summary\u003e\n   \n\u003e Implement a disaster recovery plan to ensure business continuity in case of failures. Use Azure Site Recovery and backup solutions to protect your data and applications.\n\n\u003c/details\u003e\n\n## Prerequisites\n\n- An `Azure subscription is required`. All other resources, including instructions for creating a Resource Group, are provided in this workshop.\n- `Contributor role assigned or any custom role that allows`: access to manage all resources, and the ability to deploy resources within subscription.\n- If you choose to use the Terraform approach, please ensure that:\n  - [Terraform is installed on your local machine](https://developer.hashicorp.com/terraform/tutorials/azure-get-started/install-cli#install-terraform).\n  - [Install the Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) to work with both Terraform and Azure commands.\n\n## Where to start? \n\n1. Please follow the [Terraform guide](./terraform-infrastructure/) to deploy the necessary Azure resources for the workshop.\n2. Next, as this method `skips the creation of each resource` manually. Proceed with the configuration from [Configure/Validate the Environment variables](#function-app-configurevalidate-the-environment-variables).\n\n\u003e [!IMPORTANT]\n\u003e Regarding `Networking`, this example will cover `Public access configuration`, and `system-managed identity`. However, please ensure you `review your privacy requirements and adjust network and access settings as necessary for your specific case`.\n\n## Overview \n\n\u003e Using Cosmos DB provides you with a flexible, scalable, and globally distributed database solution that can handle both structured and semi-structured data efficiently. \u003cbr/\u003e\n\u003e\n\u003e - `Azure Blob Storage`: Store the PDF invoices. \u003cbr/\u003e\n\u003e - `Azure Functions`: Trigger on new PDF uploads, extract data, and process it. \u003cbr/\u003e\n\u003e - `Azure SQL Database or Cosmos DB`: Store the extracted data for querying and analytics. \u003cbr/\u003e \n\n| Resource                  | Recommendation                                                                                                      |\n|---------------------------|----------------------------------------------------------------------------------------------------------------------|\n| **Azure Blob Storage**    | Use for storing the PDF files. This keeps your file storage separate from your data storage, which is a common best practice. |\n| **Azure SQL Database**    | Use if your data is highly structured and you need complex queries and transactions.                                  |\n| **Azure Cosmos DB**       | Use if you need a globally distributed database with low latency and the ability to handle semi-structured data.      |\n\n## Function App Hosting Options \n\n\u003e In the context of Azure Function Apps, a `hosting option refers to the plan you choose to run your function app`. This choice affects how your function app is scaled, the resources available to each function app instance, and the support for advanced functionalities like virtual network connectivity and container support.\n\n\u003e [!TIP]  \n\u003e\n\u003e - `Scale to Zero`: Indicates whether the service can automatically scale down to zero instances when idle.  \n\u003e   - **IDLE** stands for:  \n\u003e     - **I** – Inactive  \n\u003e     - **D** – During  \n\u003e     - **L** – Low  \n\u003e     - **E** – Engagement  \n\u003e   - In other words, when the application is not actively handling requests or events (it's in a low-activity or paused state).\n\u003e - `Scale Behavior`: Describes how the service scales (e.g., `event-driven`, `dedicated`, or `containerized`).  \n\u003e - `Virtual Networking`: Whether the service supports integration with virtual networks for secure communication.  \n\u003e - `Dedicated Compute \u0026 Reserved Cold Start`: Availability of always-on compute to avoid cold starts and ensure low latency.  \n\u003e - `Max Scale Out (Instances)`: Maximum number of instances the service can scale out to.  \n\u003e - `Example AI Use Cases`: Real-world scenarios where each plan excels.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eFlex Consumption\u003c/strong\u003e\u003c/summary\u003e\n\n| Feature | Description |\n|--------|-------------|\n| **Scale to Zero** | `Yes` |\n| **Scale Behavior** | `Fast event-driven` |\n| **Virtual Networking** | `Optional` |\n| **Dedicated Compute \u0026 Reserved Cold Start** | `Optional (Always Ready)` |\n| **Max Scale Out (Instances)** | `1000` |\n| **Example AI Use Cases** | `Real-time data processing` for AI models, `high-traffic AI-powered APIs`, `event-driven AI microservices`. Ideal for fraud detection, real-time recommendations, NLP, and computer vision services. |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eConsumption\u003c/strong\u003e\u003c/summary\u003e\n\n| Feature | Description |\n|--------|-------------|\n| **Scale to Zero** | `Yes` |\n| **Scale Behavior** | `Event-driven` |\n| **Virtual Networking** | `Optional` |\n| **Dedicated Compute \u0026 Reserved Cold Start** | `No` |\n| **Max Scale Out (Instances)** | `200` |\n| **Example AI Use Cases** | `Lightweight AI APIs`, `scheduled AI tasks`, `low-traffic AI event processing`. Great for sentiment analysis, simple image recognition, and batch ML tasks. |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eFunctions Premium\u003c/strong\u003e\u003c/summary\u003e\n\n| Feature | Description |\n|--------|-------------|\n| **Scale to Zero** | `No` |\n| **Scale Behavior** | `Event-driven with premium options` |\n| **Virtual Networking** | `Yes` |\n| **Dedicated Compute \u0026 Reserved Cold Start** | `Yes` |\n| **Max Scale Out (Instances)** | `100` |\n| **Example AI Use Cases** | `Enterprise AI applications`, `low-latency AI APIs`, `VNet integration`. Ideal for secure, high-performance AI services like customer support and analytics. |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eApp Service\u003c/strong\u003e\u003c/summary\u003e\n\n| Feature | Description |\n|--------|-------------|\n| **Scale to Zero** | `No` |\n| **Scale Behavior** | `Dedicated VMs` |\n| **Virtual Networking** | `Yes` |\n| **Dedicated Compute \u0026 Reserved Cold Start** | `Yes` |\n| **Max Scale Out (Instances)** | `Varies` |\n| **Example AI Use Cases** | `AI-powered web applications`, `dedicated resources`. Great for chatbots, personalized content, and intensive AI inference. |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eContainer Apps Env.\u003c/strong\u003e\u003c/summary\u003e\n\n| Feature | Description |\n|--------|-------------|\n| **Scale to Zero** | `No` |\n| **Scale Behavior** | `Containerized microservices environment` |\n| **Virtual Networking** | `Yes` |\n| **Dedicated Compute \u0026 Reserved Cold Start** | `Yes` |\n| **Max Scale Out (Instances)** | `Varies` |\n| **Example AI Use Cases** | `AI microservices architecture`, `containerized AI workloads`, `complex AI workflows`. Ideal for orchestrating AI services like image processing, text analysis, and real-time analytics. |\n\n\u003c/details\u003e\n\n## Function App: Configure/Validate the Environment variables\n\n\u003e [!IMPORTANT]\n\u003e `All environment variable names must exactly match between` your `Terraform deployment configuration` (in `main.tf`) and your `Function App environment settings`. Any mismatch will cause runtime failures when the application tries to access Azure resources.\n\n\u003e [!NOTE]\n\u003e This example is using system-assigned managed identity to assign RBACs (Role-based Access Control).\n\n- Under `Settings`, go to `Environment variables`. And `+ Add` the following variables. For example:\n\n  \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/ec5d60f3-5136-489d-8796-474b7250865d\"\u003e\n\n- Click on `Apply` to save your configuration.\n  \n    \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/437b44bb-7735-4d17-ae49-e211eca64887\"\u003e\n\n- Here are a few examples of how to get those values. `If a Terraform deployment template was used, these are linked automatically`, so please remember to review them.\n\n  \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/31d813e7-38ba-46ff-9e4b-d091ae02706a\"\u003e\n  \n  \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/45313857-b337-4231-9184-d2bb46e19267\"\u003e\n  \n  \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/074d2fa5-c64d-43bd-8ed7-af6da46d86a2\"\u003e\n  \n\u003e `These values depend on the specific you choose and deploy, like the AI models`, you can also adjust `LLM_MAX_TOKENS` based on your model's capabilities and `LLM_TEMPERATURE` based on your use case requirements.\n\n- `FUNCTIONS_EXTENSION_VERSION`: `~4` 🡢 `Review the existence of this, if not create it`\n- `WEBSITE_RUN_FROM_PACKAGE`: `1` 🡢 `Review the existence of this, if not create it`\n- `FUNCTIONS_WORKER_RUNTIME`: `python` 🡢 `Review the existence of this, if not create it`\n- `FUNCTIONS_NODE_BLOCK_ON_ENTRY_POINT_ERROR`: `true` (This setting ensures that all entry point errors are visible in your application insights logs) 🡢 `Review the existence of this, if not create it`\n- `COSMOS_DB_ENDPOINT`: Your Cosmos DB account endpoint 🡢 `Review the existence of this, if not create it`\n    \n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003e \u003c/b\u003e Click to see more\u003c/summary\u003e\n\n- `COSMOS_DB_KEY`: Your Cosmos DB account key 🡢 `Review the existence of this, if not create it`\n- `COSMOS_DB_CONNECTION_STRING`: Your Cosmos DB connection string 🡢 `Review the existence of this, if not create it`\n- `invoicecontosostorage_STORAGE`: Your Storage Account connection string 🡢 `Review the existence of this, if not create it`\n- `FORM_RECOGNIZER_ENDPOINT`: For example: `https://\u003cyour-form-recognizer-endpoint\u003e.cognitiveservices.azure.com/` 🡢 `Review the existence of this, if not create it`\n- `FORM_RECOGNIZER_KEY`: Your Document Intelligence Key (Form Recognizer) 🡢 `Review the existence of this, if not create it`\n- `APPINSIGHTS_INSTRUMENTATIONKEY`: Your Application Insights instrumentation key 🡢 `Review the existence of this, if not create it`\n- `APPLICATIONINSIGHTS_CONNECTION_STRING`: Your Application Insights connection string 🡢 `Review the existence of this, if not create it`\n- `VISION_API_ENDPOINT`: Your Azure AI Vision endpoint for visual cue detection 🡢 `Review the existence of this, if not create it`\n- `VISION_API_KEY`: Your Azure AI Vision API key 🡢 `Review the existence of this, if not create it`\n- `VISION_API_VERSION`: `2024-02-01` (Latest stable API version) 🡢 `Review the existence of this, if not create it`.  These values depend on the specific you choose and deploy\n- `AZURE_OPENAI_ENDPOINT`: Your Azure OpenAI service endpoint 🡢 `Review the existence of this, if not create it`\n- `AZURE_OPENAI_KEY`: Your Azure OpenAI API key 🡢 `Review the existence of this, if not create it`\n- `AZURE_OPENAI_API_VERSION`: e.g `2025-04-14`  🡢 `Review the existence of this, if not create it`. These values depend on the specific you choose and deploy\n- `AZURE_OPENAI_GPT4_DEPLOYMENT`: Your e.g GPT-4 deployment name for complex reasoning and analysis 🡢 `Review the existence of this, if not create it`. These values depend on the specific you choose and deploy\n- `AZURE_OPENAI_GPT4O_DEPLOYMENT`: Your e.g GPT-4o deployment name for advanced multimodal processing 🡢 `Review the existence of this, if not create it`. These values depend on the specific you choose and deploy\n- `AZURE_OPENAI_EMBEDDING_DEPLOYMENT`: Your text embedding deployment name for semantic search 🡢 `Review the existence of this, if not create it`\n- `AI_HUB_NAME`: Your AI Studio Hub name for model management 🡢 `Review the existence of this, if not create it`\n- `AI_PROJECT_NAME`: Your AI Studio Project name 🡢 `Review the existence of this, if not create it`\n- `AI_HUB_WORKSPACE_URL`: Your AI Hub workspace URL 🡢 `Review the existence of this, if not create it`\n- `AI_PROJECT_WORKSPACE_URL`: Your AI Project workspace URL 🡢 `Review the existence of this, if not create it`\n- `AI_STORAGE_ACCOUNT_NAME`: Your AI storage account name for model artifacts 🡢 `Review the existence of this, if not create it`\n- `AI_STORAGE_CONNECTION`: Your AI storage connection string 🡢 `Review the existence of this, if not create it`\n- `ENABLE_LLM_PROCESSING`: `true` (Enable LLM-powered PDF processing features) 🡢 `Review the existence of this, if not create it`\n- `LLM_MAX_TOKENS`: `4000` (Maximum tokens per request - adjust based on your model choice) 🡢 `Review the existence of this, if not create it`\n- `LLM_TEMPERATURE`: `0.1` (Low temperature for consistent extraction - adjust based on use case) 🡢 `Review the existence of this, if not create it`\n- `LLM_TIMEOUT_SECONDS`: `120` (Timeout for LLM requests - may need adjustment depending on model response time) 🡢 `Review the existence of this, if not create it`\n\n\u003c/details\u003e\n  \n## Function App: Develop the logic\n\n- You need to install [VSCode](https://code.visualstudio.com/download)\n- Install python from Microsoft store:\n    \n     \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/30f00c27-da0d-400f-9b98-817fd3e03b1c\"\u003e\n\n- Open VSCode, and install some extensions: `python`, and `Azure Tools`.\n\n     \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/715449d3-1a36-4764-9b07-99421fb1c834\"\u003e\n\n     \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/854aa665-dc2f-4cbf-bae2-2dc0a8ef6e46\"\u003e\n\n- Click on the `Azure` icon, and `sign in` into your account. Allow the extension `Azure Resources` to sign in using Microsoft, it will open a browser window. After doing so, you will be able to see your subscription and resources.\n\n    \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/4824ca1c-4959-4242-95af-ad7273c5530d\"\u003e\n\n- Under Workspace, click on `Create Function Project`, and choose a path in your local computer to develop your function.\n\n    \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/2c42d19e-be8b-48ef-a7e4-8a39989cea5a\"\u003e\n\n- Choose the language, in this case is `python`:\n\n   \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/2fb19a1e-bb2d-47e5-a56e-8dc8a708647a\"\u003e\n\n- Select the model version, for this example let's use `v2`:\n  \n   \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/fd46ee93-d788-463d-8b28-dbf2487e9a7f\"\u003e\n\n- For the python interpreter, let's use the one installed via `Microsoft Store`:\n\n   \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/3605c959-fc59-461f-9e8d-01a6a92004a8\"\u003e\n\n- Choose a template (e.g., **Blob trigger**) and configure it to trigger on new PDF uploads in your Blob container.\n\n   \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/0a4ed541-a693-485c-b6ca-7d5fb55a61d2\"\u003e\n\n- Provide a function name, like `BlobTriggerPDFsMultiLayoutsDocIntelligence`:\n\n   \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/263cef5c-4460-46cb-8899-fb609b191d81\"\u003e\n\n- Next, it will prompt you for the path of the blob container where you expect the function to be triggered after a file is uploaded. In this case is `pdfinvoices` as was previously created.\n\n  \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/7005dc44-ffe2-442b-8373-554b229b3042\"\u003e\n\n- Click on `Create new local app settings`, and then choose your subscription.\n\n  \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/07c211d6-eda0-442b-b428-cdaed2bf12ac\"\u003e\n\n- Choose `Azure Storage Account for remote storage`, and select one. I'll be using the `invoicecontosostorage`. \n\n  \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/3b5865fc-3e84-4582-8f06-cb5675d393f0\"\u003e\n\n- Then click on `Open in the current window`. You will see something like this:\n\n  \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/f30e8e10-0c37-4efc-8158-c83faf22a7d8\"\u003e\n\n- Now we need to update the function code to extract data from PDFs and store it in Cosmos DB, use this an example:\n\n  \u003e 1. **PDF Upload**: A PDF file is uploaded to the Azure Blob Storage container (`pdfinvoices`).\n  \u003e 2. **Trigger Azure Function**: The upload triggers the Azure Function `BlobTriggerPDFsMultiLayoutsAIDocIntelligence`.\n  \u003e 3. **Initialize Clients**: Sets up connections to Azure Document Intelligence, AI Vision, OpenAI, and Cosmos DB.  \n  \u003e    - Initializes the `DocumentAnalysisClient` using the `FORM_RECOGNIZER_ENDPOINT` and `FORM_RECOGNIZER_KEY` environment variables.  \n  \u003e    - Initializes the `AzureOpenAI` client for LLM analysis using OpenAI deployment details.\n  \u003e    - Configures the Vision API for visual cue detection.\n  \u003e    - Sets up the `CosmosClient` for data storage.\n  \u003e 4. **Read PDF from Blob Storage**: Reads the PDF content from the blob into a byte stream.\n  \u003e 5. **Analyze PDF**: Uses Azure Document Intelligence to analyze the layout of the PDF.  \n  \u003e    - Calls `begin_analyze_document` with the `prebuilt-layout` model.  \n  \u003e    - Waits for the analysis to complete and retrieves the layout result.\n  \u003e 6. **Extract Layout Data**: Parses and structures the layout data from the analysis result.  \n  \u003e    - Extracts lines, tables, and selection marks from each page.  \n  \u003e    - Identifies visual selection cues using AI Vision for enhanced form recognition.\n  \u003e    - Logs styles (e.g., handwritten content) and organizes data into a structured dictionary.\n  \u003e 7. **Enhance with AI Vision**: Analyzes visual elements for additional insights.\n  \u003e    - Detects and processes visual selection cues that Document Intelligence might miss.\n  \u003e    - Combines visual analysis with document structure understanding.\n  \u003e 8. **Apply LLM Analysis**: Uses Azure OpenAI for semantic understanding of document content.\n  \u003e    - Prepares structured content for the LLM with meaningful context.\n  \u003e    - Analyzes content relationships and extracts high-level insights.\n  \u003e 9. **Save Data to Cosmos DB**: Saves the structured layout data to Cosmos DB.  \n  \u003e    - Ensures the database (`DocumentAnalysisDB`) and container (`ProcessedDocuments`) exist or creates them.  \n  \u003e    - Prepares document for storage with metadata and timestamps.\n  \u003e    - Inserts or updates the layout data using `upsert_item`.\n  \u003e 10. **Logging (Process and Errors)**: Logs each step of the process, including success messages and detailed error handling for debugging and monitoring.\n  \u003e     - Uses structured logging for better traceability.\n  \u003e     - Includes processing time metrics for performance analysis.\n  \u003e     - Provides comprehensive error handling with meaningful diagnostics.\n\n  - Update the function_app.py, for example [see the code used in this demo](./src/function_app.py):\n\n      | Template Blob Trigger | Function Code updated |\n      | --- | --- |\n      |   \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/07a7b285-eed2-4b42-bb1f-e41e8eafd273\"\u003e |  \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/d364591b-817e-4f36-8c50-7de187c32a1e\"\u003e|\n\n  - Now, let's update the `requirements.txt`, [see the code used in this demo](./src/requirements.txt):\n\n    | Template `requirements.txt` | Updated `requirements.txt` |\n    | --- | --- |\n    | \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/239516e0-a4b7-4e38-8c2b-9be12ebb00de\"\u003e | \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/91bd6bd8-ec21-4e1a-ae86-df577d37bcbb\"\u003e| \n\n  - Since this function has already been tested, you can deploy your code to the function app in your subscription. If you want to test, you can use run your function locally for testing.\n    - Click on the `Azure` icon.\n    - Under `workspace`, click on the `Function App` icon.\n    - Click on `Deploy to Azure`.\n\n         \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/12405c04-fa43-4f09-817d-f6879fbff035\"\u003e\n\n    - Select your `subscription`, your `function app`, and accept the prompt to overwrite:\n\n         \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/b69212a5-ab79-45e2-8344-73198b231d07\"\u003e\n\n    - After completing, you see the status in your terminal:\n\n         \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/6214e246-5beb-4ae4-a54b-9101cac3e241\"\u003e\n\n         \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/78aab42c-af43-43aa-a4c0-545f4445755b\"\u003e\n\n\u003e [!IMPORTANT]\n\u003e If you need further assistance with the code, please click [here to view all the function code](./src/).\n\n\u003e [!NOTE]\n\u003e Please ensure that all specified roles are assigned to the Function App. The provided example used `System assigned` for the Function App to facilitate the role assignment.\n\n## Test the solution\n\n\u003e [!IMPORTANT]\n\u003e Please ensure that the user/system admin responsible for uploading the PDFs to the blob container has the necessary permissions. The error below illustrates what might occur if these roles are missing. \u003cbr/\u003e \n\u003e \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/d827775a-d419-467e-9b2d-35cb05bc0f8a\"\u003e \u003cbr/\u003e\n\u003e In that case, go to `Access Control (IAM)`, click on `+ Add`, and `Add role assignment`: \u003cbr/\u003e\n\u003e \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/aa4deff1-b6e1-49ec-9395-831ce2f982f5\"\u003e \u003cbr/\u003e\n\u003e Search for `Storage Blob Data Contributor`, click `Next`. \u003cbr/\u003e\n\u003e \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/1fd40ef8-53f7-42df-a263-5bc3c80e61ba\"\u003e \u003cbr/\u003e\n\u003e Then, click on `select members` and search for your user/systen admin. Finally click on `Review + assign`.\n\n\u003e Upload sample PDF invoices to the Blob container and verify that data is correctly ingested and stored in Cosmos DB.\n\n- Click on `Upload`, then select `Browse for files` and choose your PDF invoices to be stored in the blob container, which will trigger the function app to parse them.\n\n   \u003cimg width=\"950\" alt=\"image\" src=\"https://github.com/user-attachments/assets/a8456461-400b-4c68-b3d3-ac0b1630374d\"\u003e\n\n- Check the logs, and traces from your function with `Application Insights`:\n\n   \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/d499580a-76cb-4b4f-bb36-fd60c563a91c\"\u003e\n\n- Under `Investigate`, click on `Performance`. Filter by time range, and `drill into the samples`. Sort the results by date (if you have many, like in my case) and click on the last one.\n\n   \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/e266131c-e46f-4848-96ed-db2c04c5c18f\"\u003e\n\n- Click on `View all`:\n\n   \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/19356900-00c8-43ca-b888-fe493b25f258\"\u003e\n\n- Check all the logs, and traces generated. Also review the information parsed:\n\n  \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/2f28cc69-d389-4ef6-9209-57f76c9a09aa\" /\u003e\n\n- Validate that the information was uploaded to the Cosmos DB. Under `Data Explorer`, check your `Database`.\n\n   \u003cimg width=\"550\" alt=\"image\" src=\"https://github.com/user-attachments/assets/27309a6d-c654-4c76-bbc1-990a9338973c\"\u003e\n\n\u003c!-- START BADGE --\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Total%20views-1297-limegreen\" alt=\"Total views\"\u003e\n  \u003cp\u003eRefresh Date: 2025-10-29\u003c/p\u003e\n\u003c/div\u003e\n\u003c!-- END BADGE --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicrosoftcloudessentials-learninghub%2Fpdfs-multilayout-visualcue-azureai-document-processing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmicrosoftcloudessentials-learninghub%2Fpdfs-multilayout-visualcue-azureai-document-processing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicrosoftcloudessentials-learninghub%2Fpdfs-multilayout-visualcue-azureai-document-processing/lists"}