diff --git a/Deployment/resourcedeployment.ps1 b/Deployment/resourcedeployment.ps1 index 6b3ccbbe..9d5c4a62 100644 --- a/Deployment/resourcedeployment.ps1 +++ b/Deployment/resourcedeployment.ps1 @@ -1,7 +1,14 @@ -# Copyright (c) Microsoft Corporation. +# Copyright (c) Microsoft Corporation. # Licensed under the MIT license. #https://patorjk.com/software/taag + + +param ( + [Parameter(Mandatory=$false)] + [string]$ResourceGroupName +) + function startBanner() { Write-Host " _____ _ " Write-Host " | __ \ | | " @@ -195,7 +202,10 @@ function Show-Banner { } # Get all environment values -$envValues = azd env get-values --output json | ConvertFrom-Json +if (!$ResourceGroupName) { + $envValues = azd env get-values --output json | ConvertFrom-Json +} + function Get-AzdEnvValueOrDefault { param ( [Parameter(Mandatory = $true)] @@ -290,7 +300,7 @@ class DeploymentResult { } - [void]MapResult() { + [void]MapResultAzd() { # Replace direct $envValues lookups with function calls $this.TenantId = Get-AzdEnvValueOrDefault -KeyName "AZURE_TENANT_ID" -Required $true @@ -335,6 +345,68 @@ class DeploymentResult { $this.AzAppConfigEndpoint = Get-AzdEnvValueOrDefault -KeyName "AZURE_APP_CONFIG_ENDPOINT" $this.AzAppConfigName = Get-AzdEnvValueOrDefault -KeyName "AZURE_APP_CONFIG_NAME" } + + [void]MapResultAz([string]$resourceGroupName) { + # Get deployment outputs + $deploymentName=$(az group show --name "$resourceGroupName" --query "tags.DeploymentName" -o tsv) + if (!$deploymentName) { + Write-Error "Deployment name not found in the resource group tags." + exit 1 + } + + $deploymentOutputs=$(az deployment group show --resource-group "$resourceGroupName" --name "$deploymentName" --query "properties.outputs" -o json | ConvertFrom-Json) + + $this.TenantId = $deploymentOutputs.azurE_TENANT_ID.value + if (!$this.TenantId) { + $this.TenantId = $(az account show --query tenantId -o tsv) + } + + $this.SubscriptionId = $(az account show --query id -o tsv) + + # Resource Group + $this.ResourceGroupName = $resourceGroupName + $this.ResourceGroupId = $deploymentOutputs.azurE_RESOURCE_GROUP_ID.value + if (!$this.ResourceGroupId) { + Write-Error "Required value 'AZURE_RESOURCE_GROUP_ID' not found in the deployment outputs." + exit 1 + } + + # Storage Account + $this.StorageAccountName = $deploymentOutputs.storagE_ACCOUNT_NAME.value + + # Search Service + $this.AzSearchServiceName = $deploymentOutputs.azurE_SEARCH_SERVICE_NAME.value + $this.AzSearchServicEndpoint = "https://$($this.AzSearchServiceName).search.windows.net" + + # AKS + $this.AksName = $deploymentOutputs.azurE_AKS_NAME.value + $this.AksMid = $deploymentOutputs.azurE_AKS_MI_ID.value + + # Container Registry + $this.AzContainerRegistryName = $deploymentOutputs.azurE_CONTAINER_REGISTRY_NAME.value + + # Cognitive Service - Azure AI Document Intelligence Service + $this.AzCognitiveServiceName = $deploymentOutputs.azurE_COGNITIVE_SERVICE_NAME.value + $this.AzCognitiveServiceEndpoint = $deploymentOutputs.azurE_COGNITIVE_SERVICE_ENDPOINT.value + + # Open AI Service + $this.AzOpenAiServiceName = $deploymentOutputs.azurE_OPENAI_SERVICE_NAME.value + $this.AzOpenAiServiceEndpoint = $deploymentOutputs.azurE_OPENAI_SERVICE_ENDPOINT.value + + # Cosmos DB + $this.AzCosmosDBName = $deploymentOutputs.azurE_COSMOSDB_NAME.value + + # Open AI Service Models + $this.AzGPT4oModelName = $deploymentOutputs.aZ_GPT4O_MODEL_NAME.value + $this.AzGPT4oModelId = $deploymentOutputs.aZ_GPT4O_MODEL_ID.value + $this.AzGPTEmbeddingModelName = $deploymentOutputs.aZ_GPT_EMBEDDING_MODEL_NAME.value + $this.AzGPTEmbeddingModelId = $deploymentOutputs.aZ_GPT_EMBEDDING_MODEL_ID.value + + # App Configuration + $this.AzAppConfigEndpoint = $deploymentOutputs.azurE_APP_CONFIG_ENDPOINT.value + $this.AzAppConfigName = $deploymentOutputs.azurE_APP_CONFIG_NAME.value + + } } function Check-Docker { @@ -379,7 +451,12 @@ try { Write-Host "Retrieving the deployment details.....`r`n" -ForegroundColor Yellow # Map the deployment result to DeploymentResult object from .env file - $deploymentResult.MapResult() + if ($ResourceGroupName) { + $deploymentResult.MapResultAz($ResourceGroupName.Trim()) + } + else { + $deploymentResult.MapResultAzd() + } LoginAzure $deploymentResult.TenantId $deploymentResult.SubscriptionId diff --git a/docs/AVMPostDeploymentGuide.md b/docs/AVMPostDeploymentGuide.md new file mode 100644 index 00000000..233e87d8 --- /dev/null +++ b/docs/AVMPostDeploymentGuide.md @@ -0,0 +1,196 @@ +# AVM Post Deployment Guide + +> **📋 Note**: This guide is specifically for post-deployment steps after using the AVM template. For complete deployment from scratch, see the main [Deployment Guide](./DeploymentGuide.md). + +--- + +This document provides guidance on post-deployment steps after deploying the Document Knowledge Mining Solution Accelerator from the [AVM (Azure Verified Modules) repository](https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/sa/document-knowledge-mining). + +## Overview + +After deploying the infrastructure using AVM, you'll need to complete the application layer setup, which includes: +- Configuring Kubernetes infrastructure +- Building and deploying container images +- Setting up certificates and ingress controllers +- Configuring application settings + +## Prerequisites + +Before starting the post-deployment process, ensure you have the following: + +### Required Software + +1. **[PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.4)** (v7.0+ recommended, v5.1+ minimum) - Available for Windows, macOS, and Linux + +2. **[Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli)** (v2.50+) - Command-line tool for managing Azure resources + +3. **kubectl** - Kubernetes command-line tool + Install using Azure CLI: + ```powershell + az aks install-cli + ``` + +4. **aks-preview extension** - Azure CLI extension for AKS preview features + ```powershell + az extension add --name aks-preview + ``` + +5. **[Helm](https://helm.sh/docs/intro/install/)** (v3.0+) - Package manager for Kubernetes + +6. **[Docker Desktop](https://docs.docker.com/get-docker/)** - Container platform for building and publishing images + > ⚠️ **Important**: Ensure Docker Desktop is running before executing the deployment script + +### Azure Requirements + +7. **Azure Access** - One of the following roles on the subscription: + - `Owner` + - `User Access Administrator` + +8. **Microsoft.Compute Registration** - Verify this resource provider is registered: + 1. Navigate to [Azure Portal](https://portal.azure.com) + 2. Go to your **Azure subscription** + 3. Select **Settings** → **Resource Providers** + 4. Search for **Microsoft.Compute** and ensure it's **Registered** + + Resource Provider Registration + +9. **Deployed Infrastructure** - A successful Document Knowledge Mining Accelerator deployment from the [AVM repository](https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/sa/document-knowledge-mining) + +## Post-Deployment Steps + +### Step 1: Clone the Repository + +First, clone this repository to access the post-deployment scripts: + +```powershell +git clone https://github.com/microsoft/Document-Knowledge-Mining-Solution-Accelerator.git +``` +```powershell +cd Document-Knowledge-Mining-Solution-Accelerator +``` + +### Step 2: Run the Post-Deployment Script + +The post-deployment process is automated through a single PowerShell script that completes the following tasks in approximately 20-30 minutes: + +#### What the Script Does: +1. **Configure Kubernetes Infrastructure** - Set up AKS cluster settings and networking +2. **Update Configuration Files** - Generate FQDN, container image paths, and certificate settings +3. **Deploy Kubernetes Components** - Install Cert Manager, Ingress Controller, and application pods +4. **Build and Push Container Images** - Compile and publish application containers to Azure Container Registry +5. **Provide Access Information** - Display the final application URL and next steps + +#### Execute the Script: + +1. Navigate to the deployment directory: + ```powershell + cd .\Deployment\ + ``` + +2. **Choose the appropriate command based on your deployment method:** + + **If you deployed using custom templates, ARM/Bicep deployments, or `az deployment group` commands:** + ```powershell + .\resourcedeployment.ps1 -ResourceGroupName "" + ``` + + **If you deployed using `azd up` command:** + ```powershell + .\resourcedeployment.ps1 + ``` + + > **Note**: Replace `` with the actual name of the resource group containing your deployed Azure resources. + + > **💡 Tip**: Since this guide is for AVM deployments, you'll most likely use the first command with the `-ResourceGroupName` parameter. + +3. **If you encounter execution policy issues**, use this alternative command: + ```powershell + powershell.exe -ExecutionPolicy Bypass -File ".\resourcedeployment.ps1" -ResourceGroupName "" + ``` + +### Step 3: Provide Required Information + +During script execution, you'll be prompted for: + +#### Email Address for SSL Certificates +Input Parameters + +- **Purpose**: Used for issuing SSL certificates through [Let's Encrypt](https://letsencrypt.org/) +- **Requirement**: Must be a valid email address + +#### Azure Authentication +Azure Login + +- You'll be prompted to authenticate with Azure +- Select the appropriate Azure account +- Ensure you have the required permissions on the target subscription + +### Step 4: Deployment Completion + +Upon successful completion, you'll see a success message with important information: + +Deployment Success + +**🎉 Congratulations!** Your deployment is complete. + +**Important**: Save the application URL displayed in the console - you'll need it for data upload and accessing the application. + +## Next Steps + +### 1. Configure Azure OpenAI Rate Limits + +> **⚠️ Critical**: The default deployment creates models with minimal TPM (Tokens Per Minute) limits. You **must** increase these limits for proper performance. + +#### Recommended TPM Thresholds + +| Model Name | Recommended TPM | Minimum TPM | +|------------------------|----------------|-------------| +| gpt-4.1-mini | 100K TPM | 10K TPM | +| text-embedding-3-large | 200K TPM | 50K TPM | + +> **⚠️ Warning**: Insufficient quota will cause failures during document upload and processing. Ensure adequate capacity before proceeding. + +#### How to Update TPM Limits: + +1. **Navigate to Azure AI Foundry**: + - Go to [Azure AI Foundry](https://ai.azure.com/) + - Select your project + - Go to **Deployments** section + +2. **Update Each Model**: + + Select Model + + - Select each deployed model + - Click **Edit deployment** + - Increase the **Tokens per Minute Rate Limit** + + Set TPM Limit + +3. **Apply Changes**: Save the configuration for each model + +### 2. Upload and Process Sample Documents + +After configuring the TPM limits, upload sample documents: + +1. **Navigate to the deployment directory** (if not already there): + ```powershell + cd .\Deployment\ + ``` + +2. **Execute the upload script** with the URL from the deployment output: + ```powershell + .\uploadfiles.ps1 -EndpointUrl https://kmgs..cloudapp.azure.com + ``` + +3. **Alternative execution** (if you encounter policy issues): + ```powershell + powershell.exe -ExecutionPolicy Bypass -File ".\uploadfiles.ps1" -EndpointUrl https://kmgs..cloudapp.azure.com + ``` + +### 3. Access Your Application + +Once document upload is complete, you can: +- **Access the web application** at the URL provided in the deployment output +- **Start exploring** the knowledge mining capabilities +- **Upload additional documents** through the web interface diff --git a/docs/DeploymentGuide.md b/docs/DeploymentGuide.md index f23e278a..5567213b 100644 --- a/docs/DeploymentGuide.md +++ b/docs/DeploymentGuide.md @@ -165,10 +165,23 @@ Open PowerShell, change directory where you code cloned, then run the deploy scr ``` cd .\Deployment\ ``` + +#### Choose the appropriate command based on your deployment method: + +**If you deployed using `azd up` command:** ``` .\resourcedeployment.ps1 ``` +**If you deployed using custom templates, ARM/Bicep deployments, or `az deployment group` commands:** +``` +.\resourcedeployment.ps1 -ResourceGroupName "" +``` + +> **Note:** Replace `` with the actual name of the resource group containing your deployed Azure resources. + +> **💡 Tip**: Since this guide is for azd deployment, you'll typically use the first command without the `-ResourceGroupName` parameter. + If you run into issue with PowerShell script file not being digitally signed, you can execute below command: ``` diff --git a/docs/images/deployment/Control_Model_TPM000.png b/docs/images/deployment/Control_Model_TPM000.png index 01f1777d..fb1b1188 100644 Binary files a/docs/images/deployment/Control_Model_TPM000.png and b/docs/images/deployment/Control_Model_TPM000.png differ diff --git a/docs/images/deployment/Control_Model_TPM001.png b/docs/images/deployment/Control_Model_TPM001.png index 53fba65a..e1af2c7b 100644 Binary files a/docs/images/deployment/Control_Model_TPM001.png and b/docs/images/deployment/Control_Model_TPM001.png differ diff --git a/docs/images/deployment/Deployment_Screen02.png b/docs/images/deployment/Deployment_Screen02.png index 7e9b776d..0de4e337 100644 Binary files a/docs/images/deployment/Deployment_Screen02.png and b/docs/images/deployment/Deployment_Screen02.png differ diff --git a/infra/main.bicep b/infra/main.bicep index 0927a2b9..e285c11c 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -115,6 +115,7 @@ resource resourceGroupTags 'Microsoft.Resources/tags@2021-04-01' = { TemplateName: 'DKM' Type: enablePrivateNetworking ? 'WAF' : 'Non-WAF' CreatedBy: createdBy + DeploymentName: deployment().name } } } @@ -824,7 +825,7 @@ module managedCluster 'br/public:avm/res/container-service/managed-cluster:0.10. location: solutionLocation tags: tags enableTelemetry: enableTelemetry - kubernetesVersion: '1.30.4' + kubernetesVersion: '1.32.7' dnsPrefix: 'aks-${solutionSuffix}' enableRBAC: true disableLocalAccounts: false diff --git a/infra/main.json b/infra/main.json index c2c5cf3c..d14ab73a 100644 --- a/infra/main.json +++ b/infra/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.37.4.10188", - "templateHash": "8418820476800736272" + "templateHash": "2904572962142281757" } }, "parameters": { @@ -66,7 +66,7 @@ }, "gptModelCapacity": { "type": "int", - "defaultValue": 150, + "defaultValue": 100, "minValue": 10, "metadata": { "description": "Optional. Capacity of the GPT model deployment:" @@ -183,6 +183,13 @@ }, "description": "Required. Location for AI Foundry deployment. This is the location where the AI Foundry resources will be deployed." } + }, + "createdBy": { + "type": "string", + "defaultValue": "[if(contains(deployer(), 'userPrincipalName'), split(deployer().userPrincipalName, '@')[0], deployer().objectId)]", + "metadata": { + "description": "Optional created by user name" + } } }, "variables": { @@ -285,6 +292,14 @@ "applicationInsightsResourceName": "[format('appi-{0}', variables('solutionSuffix'))]" }, "resources": { + "resourceGroupTags": { + "type": "Microsoft.Resources/tags", + "apiVersion": "2021-04-01", + "name": "default", + "properties": { + "tags": "[shallowMerge(createArray(parameters('tags'), createObject('TemplateName', 'DKM', 'Type', if(parameters('enablePrivateNetworking'), 'WAF', 'Non-WAF'), 'CreatedBy', parameters('createdBy'), 'DeploymentName', deployment().name)))]" + } + }, "avmPrivateDnsZones": { "copy": { "name": "avmPrivateDnsZones", @@ -39783,8 +39798,8 @@ } }, "dependsOn": [ - "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').storageBlob)]", "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').storageQueue)]", + "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').storageBlob)]", "network", "userAssignedIdentity" ] @@ -47131,7 +47146,7 @@ "value": "[parameters('enableTelemetry')]" }, "kubernetesVersion": { - "value": "1.30.4" + "value": "1.32.7" }, "dnsPrefix": { "value": "[format('aks-{0}', variables('solutionSuffix'))]" @@ -50479,8 +50494,8 @@ "flowType": { "value": "Bluefield" }, - "workspaceResourceId": "[if(parameters('enableMonitoring'), createObject('value', reference('logAnalyticsWorkspace').outputs.resourceId.value), createObject('value', ''))]", - "diagnosticSettings": "[if(parameters('enableMonitoring'), createObject('value', createArray(createObject('workspaceResourceId', reference('logAnalyticsWorkspace').outputs.resourceId.value))), createObject('value', null()))]" + "workspaceResourceId": "[if(parameters('enableMonitoring'), if(variables('useExistingLogAnalytics'), createObject('value', parameters('existingLogAnalyticsWorkspaceId')), createObject('value', reference('logAnalyticsWorkspace').outputs.resourceId.value)), createObject('value', ''))]", + "diagnosticSettings": "[if(parameters('enableMonitoring'), createObject('value', createArray(createObject('workspaceResourceId', if(variables('useExistingLogAnalytics'), parameters('existingLogAnalyticsWorkspaceId'), reference('logAnalyticsWorkspace').outputs.resourceId.value)))), createObject('value', null()))]" }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",