diff --git a/docs/CustomizingAzdParameters.md b/docs/CustomizingAzdParameters.md new file mode 100644 index 000000000..b4e194726 --- /dev/null +++ b/docs/CustomizingAzdParameters.md @@ -0,0 +1,34 @@ +## [Optional]: Customizing resource names + +By default this template will use the environment name as the prefix to prevent naming collisions within Azure. The parameters below show the default values. You only need to run the statements below if you need to change the values. + +> To override any of the parameters, run `azd env set ` before running `azd up`. On the first azd command, it will prompt you for the environment name. Be sure to choose 3-20 characters alphanumeric unique name. + +## Parameters + +| Name | Type | Default Value | Purpose | +| ------------------------------- | ------ | ----------------- | --------------------------------------------------------------------------------------------------- | +| `AZURE_ENV_NAME` | string | `macae` | Used as a prefix for all resource names to ensure uniqueness across environments. | +| `AZURE_LOCATION` | string | `swedencentral` | Location of the Azure resources. Controls where the infrastructure will be deployed. | +| `AZURE_ENV_OPENAI_LOCATION` | string | `swedencentral` | Specifies the region for OpenAI resource deployment. | +| `AZURE_ENV_MODEL_DEPLOYMENT_TYPE` | string | `GlobalStandard` | Defines the deployment type for the AI model (e.g., Standard, GlobalStandard). | +| `AZURE_ENV_MODEL_NAME` | string | `gpt-4o` | Specifies the name of the GPT model to be deployed. | +| `AZURE_ENV_MODEL_VERSION` | string | `2024-08-06` | Version of the GPT model to be used for deployment. | +| `AZURE_ENV_IMAGETAG` | string | `latest` | Docker image tag used for container deployments. | +| `AZURE_ENV_ENABLE_TELEMETRY` | bool | `true` | Enables telemetry for monitoring and diagnostics. | + +--- + +## How to Set a Parameter + +To customize any of the above values, run the following command **before** `azd up`: + +```bash +azd env set +``` + +**Example:** + +```bash +azd env set AZURE_LOCATION westus2 +``` diff --git a/docs/DeploymentGuide.md b/docs/DeploymentGuide.md index 2b5cc5105..c45603940 100644 --- a/docs/DeploymentGuide.md +++ b/docs/DeploymentGuide.md @@ -134,15 +134,19 @@ Consider the following settings during your deployment to modify specific settin
Configurable Deployment Settings -When you start the deployment, most parameters will have **default values**, but you can update the following settings: - -| **Setting** | **Description** | **Default value** | -| --------------------------------- | ------------------------------------------------------------------------------------------- | ----------------- | -| **Azure Region** | The region where resources will be created. | East US | -| **Secondary Location** | A **less busy** region for **Azure Cosmos DB**, useful in case of availability constraints. | eastus2 | -| **Deployment Type** | Select from a drop-down list. | GlobalStandard | -| **GPT Model** | Choose from **gpt-4, gpt-4o, gpt-4o-mini**. | gpt-4o | -| **GPT Model Deployment Capacity** | Configure capacity for **GPT models**. | 140k | +When you start the deployment, most parameters will have **default values**, but you can update the following settings [here](../docs/CustomizingAzdParameters.md): + +| **Setting** | **Description** | **Default value** | +| ------------------------------ | ------------------------------------------------------------------------------------ | ----------------- | +| **Environment Name** | Used as a prefix for all resource names to ensure uniqueness across environments. | macae | +| **Azure Region** | Location of the Azure resources. Controls where the infrastructure will be deployed. | swedencentral | +| **OpenAI Deployment Location** | Specifies the region for OpenAI resource deployment. | swedencentral | +| **Model Deployment Type** | Defines the deployment type for the AI model (e.g., Standard, GlobalStandard). | GlobalStandard | +| **GPT Model Name** | Specifies the name of the GPT model to be deployed. | gpt-4o | +| **GPT Model Version** | Version of the GPT model to be used for deployment. | 2024-08-06 | +| **Image Tag** | Docker image tag used for container deployments. | latest | +| **Enable Telemetry** | Enables telemetry for monitoring and diagnostics. | true | +
diff --git a/infra/main.bicep b/infra/main.bicep index 7c79874a4..ebaab8004 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -16,6 +16,19 @@ param enableTelemetry bool = true @description('Azure OpenAI Location') param azureOpenAILocation string +@minLength(1) +@description('Name of the GPT model to deploy:') +param gptModelName string = 'gpt-4o' + +param gptModelVersion string = '2024-08-06' + +@minLength(1) +@description('GPT model deployment type:') +param modelDeploymentType string = 'GlobalStandard' + +@description('Set the image tag for the container images used in the solution. Default is "latest".') +param imageTag string = 'latest' + // @description('Set this if you want to deploy to a different region than the resource group. Otherwise, it will use the resource group location by default.') // param AZURE_LOCATION string='' // param solutionLocation string = empty(AZURE_LOCATION) ? resourceGroup().location @@ -134,30 +147,10 @@ param aiFoundryAiServicesConfiguration aiServicesConfigurationType = { modelCapacity: 50 } -@description('Optional. The configuration to apply for the AI Foundry Storage Account resource.') -param aiFoundryStorageAccountConfiguration storageAccountType = { - enabled: true - name: replace('sthub${solutionPrefix}', '-', '') - location: azureOpenAILocation - tags: tags - sku: 'Standard_ZRS' - subnetResourceId: null //Default value set on module configuration -} - -@description('Optional. The configuration to apply for the AI Foundry AI Hub resource.') -param aiFoundryAiHubConfiguration aiHubType = { - enabled: true - name: 'aih-${solutionPrefix}' - location: azureOpenAILocation - sku: 'Basic' - tags: tags - subnetResourceId: null //Default value set on module configuration -} - @description('Optional. The configuration to apply for the AI Foundry AI Project resource.') param aiFoundryAiProjectConfiguration aiProjectConfigurationType = { enabled: true - name: 'aihb-${solutionPrefix}' + name: 'aifp-${solutionPrefix}' location: azureOpenAILocation sku: 'Basic' tags: tags @@ -194,7 +187,7 @@ param containerAppConfiguration containerAppConfigurationType = { containerMemory: '4.0Gi' containerImageRegistryDomain: 'biabcontainerreg.azurecr.io' containerImageName: 'macaebackend' - containerImageTag: 'latest' + containerImageTag: imageTag containerName: 'backend' ingressTargetPort: 8000 maxReplicas: 1 @@ -218,7 +211,7 @@ param webSiteConfiguration webSiteConfigurationType = { location: solutionLocation containerImageRegistryDomain: 'biabcontainerreg.azurecr.io' containerImageName: 'macaefrontend' - containerImageTag: 'latest' + containerImageTag: imageTag containerName: 'backend' tags: tags environmentResourceId: null //Default value set on module configuration @@ -731,17 +724,17 @@ var aiFoundryAiServicesResourceName = aiFoundryAiServicesConfiguration.?name ?? var aiFoundryAIservicesEnabled = aiFoundryAiServicesConfiguration.?enabled ?? true var aiFoundryAiServicesModelDeployment = { format: 'OpenAI' - name: 'gpt-4o' - version: '2024-08-06' + name: gptModelName + version: gptModelVersion sku: { - name: 'GlobalStandard' + name: modelDeploymentType //Curently the capacity is set to 140 for opinanal performance. capacity: aiFoundryAiServicesConfiguration.?modelCapacity ?? 50 } raiPolicyName: 'Microsoft.Default' } -module aiFoundryAiServices 'br/public:avm/res/cognitive-services/account:0.10.2' = if (aiFoundryAIservicesEnabled) { +module aiFoundryAiServices 'br/public:avm/res/cognitive-services/account:0.11.0' = if (aiFoundryAIservicesEnabled) { name: take('avm.res.cognitive-services.account.${aiFoundryAiServicesResourceName}', 64) params: { name: aiFoundryAiServicesResourceName @@ -756,6 +749,10 @@ module aiFoundryAiServices 'br/public:avm/res/cognitive-services/account:0.10.2' apiProperties: { //staticsEnabled: false } + allowProjectManagement: true + managedIdentities: { + systemAssigned: true + } //publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled' //publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled' publicNetworkAccess: 'Enabled' //TODO: connection via private endpoint is not working from containers network. Change this when fixed @@ -774,18 +771,18 @@ module aiFoundryAiServices 'br/public:avm/res/cognitive-services/account:0.10.2' } ]) : [] - roleAssignments: [ - // { - // principalId: userAssignedIdentity.outputs.principalId - // principalType: 'ServicePrincipal' - // roleDefinitionIdOrName: 'Cognitive Services OpenAI User' - // } - { - principalId: containerApp.outputs.?systemAssignedMIPrincipalId! - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'Cognitive Services OpenAI User' - } - ] + // roleAssignments: [ + // // { + // // principalId: userAssignedIdentity.outputs.principalId + // // principalType: 'ServicePrincipal' + // // roleDefinitionIdOrName: 'Cognitive Services OpenAI User' + // // } + // { + // principalId: containerApp.outputs.?systemAssignedMIPrincipalId! + // principalType: 'ServicePrincipal' + // roleDefinitionIdOrName: 'Cognitive Services OpenAI User' + // } + // ] deployments: aiFoundryAiServicesConfiguration.?deployments ?? [ { name: aiFoundryAiServicesModelDeployment.name @@ -804,167 +801,77 @@ module aiFoundryAiServices 'br/public:avm/res/cognitive-services/account:0.10.2' } } -// AI Foundry: storage account -// WAF best practices for Azure Blob Storage: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-blob-storage -var storageAccountPrivateDnsZones = { - 'privatelink.blob.${environment().suffixes.storage}': 'blob' - 'privatelink.file.${environment().suffixes.storage}': 'file' +// AI Foundry: AI Project +// WAF best practices for Open AI: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-openai +// var aiFoundryAiProjectEnabled = aiFoundryAiProjectConfiguration.?enabled ?? true +var aiFoundryAiProjectName = aiFoundryAiProjectConfiguration.?name ?? 'aifp-${solutionPrefix}' +var aiProjectDescription = 'AI Foundry Project' + +resource aiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing = { + name: aiFoundryAiServicesResourceName + dependsOn:[ + aiFoundryAiServices + ] } -module privateDnsZonesAiFoundryStorageAccount 'br/public:avm/res/network/private-dns-zone:0.3.1' = [ - for zone in objectKeys(storageAccountPrivateDnsZones): if (virtualNetworkEnabled && aiFoundryStorageAccountEnabled) { - name: take( - 'avm.res.network.private-dns-zone.storage-account.${uniqueString(aiFoundryStorageAccountResourceName,zone)}.${solutionPrefix}', - 64 - ) - params: { - name: zone - tags: tags - enableTelemetry: enableTelemetry - virtualNetworkLinks: [ - { - name: 'vnetlink-${split(zone, '.')[1]}' - virtualNetworkResourceId: virtualNetwork.outputs.resourceId - } - ] - } +resource aiFoundryProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' = { + parent: aiServices + name: aiFoundryAiProjectName + location: aiFoundryAiProjectConfiguration.?location ?? azureOpenAILocation + identity: { + type: 'SystemAssigned' } -] -var aiFoundryStorageAccountEnabled = aiFoundryStorageAccountConfiguration.?enabled ?? true -var aiFoundryStorageAccountResourceName = aiFoundryStorageAccountConfiguration.?name ?? replace( - 'sthub${solutionPrefix}', - '-', - '' -) - -module aiFoundryStorageAccount 'br/public:avm/res/storage/storage-account:0.18.2' = if (aiFoundryStorageAccountEnabled) { - name: take('avm.res.storage.storage-account.${aiFoundryStorageAccountResourceName}', 64) - dependsOn: [ - privateDnsZonesAiFoundryStorageAccount - ] - params: { - name: aiFoundryStorageAccountResourceName - location: aiFoundryStorageAccountConfiguration.?location ?? azureOpenAILocation - tags: aiFoundryStorageAccountConfiguration.?tags ?? tags - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - skuName: aiFoundryStorageAccountConfiguration.?sku ?? 'Standard_ZRS' - allowSharedKeyAccess: false - networkAcls: { - bypass: 'AzureServices' - defaultAction: 'Allow' - } - blobServices: { - deleteRetentionPolicyEnabled: false - containerDeleteRetentionPolicyDays: 7 - containerDeleteRetentionPolicyEnabled: false - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - } - publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled' - allowBlobPublicAccess: false - privateEndpoints: virtualNetworkEnabled - ? map(items(storageAccountPrivateDnsZones), zone => { - name: 'pep-${zone.value}-${aiFoundryStorageAccountResourceName}' - customNetworkInterfaceName: 'nic-${zone.value}-${aiFoundryStorageAccountResourceName}' - service: zone.value - subnetResourceId: aiFoundryStorageAccountConfiguration.?subnetResourceId ?? virtualNetwork.outputs.subnetResourceIds[0] ?? '' - privateDnsZoneResourceIds: [resourceId('Microsoft.Network/privateDnsZones', zone.key)] - }) - : null - roleAssignments: [ - { - principalId: userAssignedIdentity.outputs.principalId - roleDefinitionIdOrName: 'Storage Blob Data Contributor' - } - ] + properties: { + description: aiProjectDescription + displayName: aiFoundryAiProjectName } } -// AI Foundry: AI Hub -// WAF best practices for Open AI: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-openai -var mlTargetSubResource = 'amlworkspace' -var mlPrivateDnsZones = { - 'privatelink.api.azureml.ms': mlTargetSubResource - 'privatelink.notebooks.azure.net': mlTargetSubResource +resource aiUser 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '53ca6127-db72-4b80-b1b0-d745d6d5456d' } -module privateDnsZonesAiFoundryWorkspaceHub 'br/public:avm/res/network/private-dns-zone:0.3.1' = [ - for zone in objectKeys(mlPrivateDnsZones): if (virtualNetworkEnabled && aiFoundryAiHubEnabled) { - name: take('avm.res.network.private-dns-zone.ai-hub.${uniqueString(aiFoundryAiHubName,zone)}.${solutionPrefix}', 64) - params: { - name: zone - enableTelemetry: enableTelemetry - tags: tags - virtualNetworkLinks: [ - { - name: 'vnetlink-${split(zone, '.')[1]}' - virtualNetworkResourceId: virtualNetwork.outputs.resourceId - } - ] - } + +resource aiUserAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(containerApp.name, aiFoundryProject.id, aiUser.id) + scope: aiFoundryProject + properties: { + roleDefinitionId: aiUser.id + principalId: containerApp.outputs.?systemAssignedMIPrincipalId! } -] -var aiFoundryAiHubEnabled = aiFoundryAiHubConfiguration.?enabled ?? true -var aiFoundryAiHubName = aiFoundryAiHubConfiguration.?name ?? 'aih-${solutionPrefix}' -module aiFoundryAiHub 'modules/ai-hub.bicep' = if (aiFoundryAiHubEnabled) { - name: take('module.ai-hub.${aiFoundryAiHubName}', 64) - dependsOn: [ - privateDnsZonesAiFoundryWorkspaceHub - ] - params: { - name: aiFoundryAiHubName - location: aiFoundryAiHubConfiguration.?location ?? azureOpenAILocation - tags: aiFoundryAiHubConfiguration.?tags ?? tags - sku: aiFoundryAiHubConfiguration.?sku ?? 'Basic' - aiFoundryAiServicesName: aiFoundryAiServices.outputs.name - applicationInsightsResourceId: applicationInsights.outputs.resourceId - enableTelemetry: enableTelemetry - logAnalyticsWorkspaceResourceId: logAnalyticsWorkspaceId - storageAccountResourceId: aiFoundryStorageAccount.outputs.resourceId - virtualNetworkEnabled: virtualNetworkEnabled - privateEndpoints: virtualNetworkEnabled - ? [ - { - name: 'pep-${aiFoundryAiHubName}' - customNetworkInterfaceName: 'nic-${aiFoundryAiHubName}' - service: mlTargetSubResource - subnetResourceId: virtualNetworkEnabled - ? aiFoundryAiHubConfiguration.?subnetResourceId ?? virtualNetwork.?outputs.?subnetResourceIds[0] - : null - privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: map(objectKeys(mlPrivateDnsZones), zone => { - name: replace(zone, '.', '-') - privateDnsZoneResourceId: resourceId('Microsoft.Network/privateDnsZones', zone) - }) - } - } - ] - : [] +} + +resource aiUserAccessFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(containerApp.name, aiServices.id, aiUser.id) + scope: aiServices + properties: { + roleDefinitionId: aiUser.id + principalId: containerApp.outputs.?systemAssignedMIPrincipalId! } } -// AI Foundry: AI Project -// WAF best practices for Open AI: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-openai -var aiFoundryAiProjectEnabled = aiFoundryAiProjectConfiguration.?enabled ?? true -var aiFoundryAiProjectName = aiFoundryAiProjectConfiguration.?name ?? 'aihb-${solutionPrefix}' +resource aiDeveloper 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '64702f94-c441-49e6-a78b-ef80e0188fee' +} -module aiFoundryAiProject 'br/public:avm/res/machine-learning-services/workspace:0.12.0' = if (aiFoundryAiProjectEnabled) { - name: take('avm.res.machine-learning-services.workspace.${aiFoundryAiProjectName}', 64) - params: { - name: aiFoundryAiProjectName - location: aiFoundryAiProjectConfiguration.?location ?? azureOpenAILocation - tags: aiFoundryAiProjectConfiguration.?tags ?? tags - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - sku: aiFoundryAiProjectConfiguration.?sku ?? 'Basic' - kind: 'Project' - hubResourceId: aiFoundryAiHub.outputs.resourceId - roleAssignments: [ - { - principalId: containerApp.outputs.?systemAssignedMIPrincipalId! - // Assigning the role with the role name instead of the role ID freezes the deployment at this point - roleDefinitionIdOrName: '64702f94-c441-49e6-a78b-ef80e0188fee' //'Azure AI Developer' - } - ] +resource aiDeveloperAccessFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(containerApp.name, aiServices.id, aiDeveloper.id) + scope: aiFoundryProject + properties: { + roleDefinitionId: aiDeveloper.id + principalId: containerApp.outputs.?systemAssignedMIPrincipalId! + } +} + +resource cognitiveServiceOpenAIUser 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' +} + +resource cognitiveServiceOpenAIUserAccessFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(containerApp.name, aiServices.id, cognitiveServiceOpenAIUser.id) + scope: aiServices + properties: { + roleDefinitionId: cognitiveServiceOpenAIUser.id + principalId: containerApp.outputs.?systemAssignedMIPrincipalId! } } @@ -1176,11 +1083,6 @@ module containerApp 'br/public:avm/res/app/container-app:0.14.2' = if (container name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' value: applicationInsights.outputs.connectionString } - { - name: 'AZURE_AI_AGENT_PROJECT_CONNECTION_STRING' - value: '${toLower(replace(azureOpenAILocation,' ',''))}.api.azureml.ms;${subscription().subscriptionId};${resourceGroup().name};${aiFoundryAiProjectName}' - //Location should be the AI Foundry AI Project location - } { name: 'AZURE_AI_SUBSCRIPTION_ID' value: subscription().subscriptionId @@ -1197,6 +1099,14 @@ module containerApp 'br/public:avm/res/app/container-app:0.14.2' = if (container name: 'FRONTEND_SITE_NAME' value: 'https://${webSiteName}.azurewebsites.net' } + { + name: 'AZURE_AI_AGENT_ENDPOINT' + value: aiFoundryProject.properties.endpoints['AI Foundry API'] + } + { + name: 'AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME' + value: aiFoundryAiServicesModelDeployment.name + } ] } ] @@ -1709,54 +1619,6 @@ type aiServicesConfigurationType = { modelCapacity: int? } -@export() -@description('The type for the Multi-Agent Custom Automation Engine Storage Account resource configuration.') -type storageAccountType = { - @description('Optional. If the Storage Account resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Storage Account resource.') - @maxLength(60) - name: string? - - @description('Optional. Location for the Storage Account resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Storage Account resource.') - tags: object? - - @description('Optional. The SKU for the Storage Account resource.') - sku: ('Standard_LRS' | 'Standard_GRS' | 'Standard_RAGRS' | 'Standard_ZRS' | 'Premium_LRS' | 'Premium_ZRS')? - - @description('Optional. The resource Id of the subnet where the Storage Account private endpoint should be created.') - subnetResourceId: string? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine AI Hub resource configuration.') -type aiHubType = { - @description('Optional. If the AI Hub resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the AI Hub resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the AI Hub resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the AI Hub resource.') - tags: object? - - @description('Optional. The SKU of the AI Hub resource.') - sku: ('Basic' | 'Free' | 'Standard' | 'Premium')? - - @description('Optional. The resource Id of the subnet where the AI Hub private endpoint should be created.') - subnetResourceId: string? -} - @export() @description('The type for the Multi-Agent Custom Automation Engine AI Foundry AI Project resource configuration.') type aiProjectConfigurationType = { diff --git a/infra/main.bicepparam b/infra/main.bicepparam index 69723341e..e0be7c709 100644 --- a/infra/main.bicepparam +++ b/infra/main.bicepparam @@ -1,8 +1,13 @@ using './main.bicep' -param solutionPrefix = null //Type a string value to customize the prefix for your resource names +param solutionPrefix = readEnvironmentVariable('AZURE_ENV_NAME', 'macae') param solutionLocation = readEnvironmentVariable('AZURE_LOCATION', 'swedencentral') param azureOpenAILocation = readEnvironmentVariable('AZURE_ENV_OPENAI_LOCATION', 'swedencentral') +param modelDeploymentType = readEnvironmentVariable('AZURE_ENV_MODEL_DEPLOYMENT_TYPE', 'GlobalStandard') +param gptModelName = readEnvironmentVariable('AZURE_ENV_MODEL_NAME', 'gpt-4o') +param gptModelVersion = readEnvironmentVariable('AZURE_ENV_MODEL_VERSION', '2024-08-06') +param imageTag = readEnvironmentVariable('AZURE_ENV_IMAGETAG', 'latest') +param enableTelemetry = bool(readEnvironmentVariable('AZURE_ENV_ENABLE_TELEMETRY', 'true')) param logAnalyticsWorkspaceConfiguration = { dataRetentionInDays: 30 existingWorkspaceResourceId: '' @@ -13,9 +18,6 @@ param applicationInsightsConfiguration = { param virtualNetworkConfiguration = { enabled: false } -param aiFoundryStorageAccountConfiguration = { - sku: 'Standard_LRS' -} param webServerFarmConfiguration = { skuCapacity: 1 skuName: 'B2' diff --git a/infra/main.waf-aligned.bicepparam b/infra/main.waf-aligned.bicepparam index 0a226da80..ac45cdcf3 100644 --- a/infra/main.waf-aligned.bicepparam +++ b/infra/main.waf-aligned.bicepparam @@ -1,8 +1,13 @@ using './main.bicep' -param solutionPrefix = null //Type a string value to customize the prefix for your resource names +param solutionPrefix = readEnvironmentVariable('AZURE_ENV_NAME', 'macae') param solutionLocation = readEnvironmentVariable('AZURE_LOCATION', 'swedencentral') param azureOpenAILocation = readEnvironmentVariable('AZURE_ENV_OPENAI_LOCATION', 'swedencentral') +param modelDeploymentType = readEnvironmentVariable('AZURE_ENV_MODEL_DEPLOYMENT_TYPE', 'GlobalStandard') +param gptModelName = readEnvironmentVariable('AZURE_ENV_MODEL_NAME', 'gpt-4o') +param gptModelVersion = readEnvironmentVariable('AZURE_ENV_MODEL_VERSION', '2024-08-06') +param imageTag = readEnvironmentVariable('AZURE_ENV_IMAGETAG', 'latest') +param enableTelemetry = bool(readEnvironmentVariable('AZURE_ENV_ENABLE_TELEMETRY', 'true')) param virtualMachineConfiguration = { adminUsername: 'adminuser' adminPassword: 'P@ssw0rd1234' diff --git a/src/backend/.env.sample b/src/backend/.env.sample index ddc1103d3..2a651df39 100644 --- a/src/backend/.env.sample +++ b/src/backend/.env.sample @@ -12,10 +12,10 @@ AZURE_AI_PROJECT_ENDPOINT= AZURE_AI_SUBSCRIPTION_ID= AZURE_AI_RESOURCE_GROUP= AZURE_AI_PROJECT_NAME= -AZURE_AI_AGENT_PROJECT_CONNECTION_STRING= AZURE_AI_MODEL_DEPLOYMENT_NAME=gpt-4o APPLICATIONINSIGHTS_CONNECTION_STRING= +AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME=gpt-4o +AZURE_AI_AGENT_ENDPOINT= - -BACKEND_API_URL='http://localhost:8000' -FRONTEND_SITE_NAME='http://127.0.0.1:3000' \ No newline at end of file +BACKEND_API_URL=http://localhost:8000 +FRONTEND_SITE_NAME=http://127.0.0.1:3000 \ No newline at end of file diff --git a/src/backend/app_config.py b/src/backend/app_config.py index 798a510d2..d4b1a9e9a 100644 --- a/src/backend/app_config.py +++ b/src/backend/app_config.py @@ -49,9 +49,7 @@ def __init__(self): self.AZURE_AI_SUBSCRIPTION_ID = self._get_required("AZURE_AI_SUBSCRIPTION_ID") self.AZURE_AI_RESOURCE_GROUP = self._get_required("AZURE_AI_RESOURCE_GROUP") self.AZURE_AI_PROJECT_NAME = self._get_required("AZURE_AI_PROJECT_NAME") - self.AZURE_AI_AGENT_PROJECT_CONNECTION_STRING = self._get_required( - "AZURE_AI_AGENT_PROJECT_CONNECTION_STRING" - ) + self.AZURE_AI_AGENT_ENDPOINT = self._get_required("AZURE_AI_AGENT_ENDPOINT") # Cached clients and resources self._azure_credentials = None @@ -177,10 +175,8 @@ def get_ai_project_client(self): "Unable to acquire Azure credentials; ensure DefaultAzureCredential is configured" ) - connection_string = self.AZURE_AI_AGENT_PROJECT_CONNECTION_STRING - self._ai_project_client = AIProjectClient.from_connection_string( - credential=credential, conn_str=connection_string - ) + endpoint = self.AZURE_AI_AGENT_ENDPOINT + self._ai_project_client = AIProjectClient(endpoint=endpoint, credential=credential) return self._ai_project_client except Exception as exc: diff --git a/src/backend/app_kernel.py b/src/backend/app_kernel.py index a1ba44567..217371d20 100644 --- a/src/backend/app_kernel.py +++ b/src/backend/app_kernel.py @@ -10,7 +10,7 @@ from auth.auth_utils import get_authenticated_user_details # Azure monitoring -from azure.monitor.opentelemetry import configure_azure_monitor +# from azure.monitor.opentelemetry import configure_azure_monitor from config_kernel import Config from event_utils import track_event_if_configured @@ -38,7 +38,7 @@ connection_string = os.getenv("APPLICATIONINSIGHTS_CONNECTION_STRING") if connection_string: # Configure Application Insights if the Instrumentation Key is found - #configure_azure_monitor(connection_string=connection_string) + # configure_azure_monitor(connection_string=connection_string) logging.info( "Application Insights configured with the provided Instrumentation Key" ) diff --git a/src/backend/config_kernel.py b/src/backend/config_kernel.py index 6227292dd..80d0738af 100644 --- a/src/backend/config_kernel.py +++ b/src/backend/config_kernel.py @@ -26,9 +26,7 @@ class Config: AZURE_AI_SUBSCRIPTION_ID = config.AZURE_AI_SUBSCRIPTION_ID AZURE_AI_RESOURCE_GROUP = config.AZURE_AI_RESOURCE_GROUP AZURE_AI_PROJECT_NAME = config.AZURE_AI_PROJECT_NAME - AZURE_AI_AGENT_PROJECT_CONNECTION_STRING = ( - config.AZURE_AI_AGENT_PROJECT_CONNECTION_STRING - ) + AZURE_AI_AGENT_ENDPOINT = config.AZURE_AI_AGENT_ENDPOINT @staticmethod def GetAzureCredentials(): diff --git a/src/backend/kernel_agents/agent_base.py b/src/backend/kernel_agents/agent_base.py index 9abab5fbe..2214751b5 100644 --- a/src/backend/kernel_agents/agent_base.py +++ b/src/backend/kernel_agents/agent_base.py @@ -276,8 +276,8 @@ async def _create_azure_ai_agent_definition( # # First try to get an existing agent with this name as assistant_id try: agent_id = None - agent_list = await client.agents.list_agents() - for agent in agent_list.data: + agent_list = client.agents.list_agents() + async for agent in agent_list: if agent.name == agent_name: agent_id = agent.id break diff --git a/src/backend/kernel_agents/agent_factory.py b/src/backend/kernel_agents/agent_factory.py index 440fa2058..770dcf94f 100644 --- a/src/backend/kernel_agents/agent_factory.py +++ b/src/backend/kernel_agents/agent_factory.py @@ -6,8 +6,8 @@ # Import the new AppConfig instance from app_config import config -from azure.ai.projects.models import (ResponseFormatJsonSchema, - ResponseFormatJsonSchemaType) +from azure.ai.agents.models import (ResponseFormatJsonSchema, + ResponseFormatJsonSchemaType) from context.cosmos_memory_kernel import CosmosMemoryContext from kernel_agents.agent_base import BaseAgent from kernel_agents.generic_agent import GenericAgent diff --git a/src/backend/kernel_agents/planner_agent.py b/src/backend/kernel_agents/planner_agent.py index 2bc5ad5b8..c87516542 100644 --- a/src/backend/kernel_agents/planner_agent.py +++ b/src/backend/kernel_agents/planner_agent.py @@ -3,8 +3,8 @@ import uuid from typing import Any, Dict, List, Optional, Tuple -from azure.ai.projects.models import (ResponseFormatJsonSchema, - ResponseFormatJsonSchemaType) +from azure.ai.agents.models import (ResponseFormatJsonSchema, + ResponseFormatJsonSchemaType) from context.cosmos_memory_kernel import CosmosMemoryContext from event_utils import track_event_if_configured from kernel_agents.agent_base import BaseAgent diff --git a/src/backend/pyproject.toml b/src/backend/pyproject.toml index b989b2f14..e02186fdb 100644 --- a/src/backend/pyproject.toml +++ b/src/backend/pyproject.toml @@ -26,6 +26,6 @@ dependencies = [ "pytest-cov==5.0.0", "python-dotenv>=1.1.0", "python-multipart>=0.0.20", - "semantic-kernel>=1.28.1", + "semantic-kernel>=1.32.2", "uvicorn>=0.34.2", ] diff --git a/src/backend/requirements.txt b/src/backend/requirements.txt index 76568fc86..5cac25b2f 100644 --- a/src/backend/requirements.txt +++ b/src/backend/requirements.txt @@ -14,9 +14,9 @@ opentelemetry-instrumentation-fastapi opentelemetry-instrumentation-openai opentelemetry-exporter-otlp-proto-http -semantic-kernel[azure]==1.28.1 -azure-ai-projects==1.0.0b10 -openai +semantic-kernel[azure]==1.32.2 +azure-ai-projects==1.0.0b11 +openai==1.84.0 azure-ai-inference==1.0.0b9 azure-search-documents azure-ai-evaluation