Skip to content

Commit ffdceff

Browse files
Merge pull request #310 from microsoft/dev
feat: Move changes of Dev branch to Main
2 parents 3539f67 + 2dbe915 commit ffdceff

39 files changed

+1856
-551
lines changed

azure.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json
22
name: multi-agent-custom-automation-engine-solution-accelerator
33
metadata:
4-
4+
5+
requiredVersions:
6+
azd: '>= 1.15.0'

docs/CustomizingAzdParameters.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ By default this template will use the environment name as the prefix to prevent
1313
| `AZURE_ENV_OPENAI_LOCATION` | string | `swedencentral` | Specifies the region for OpenAI resource deployment. |
1414
| `AZURE_ENV_MODEL_DEPLOYMENT_TYPE` | string | `GlobalStandard` | Defines the deployment type for the AI model (e.g., Standard, GlobalStandard). |
1515
| `AZURE_ENV_MODEL_NAME` | string | `gpt-4o` | Specifies the name of the GPT model to be deployed. |
16+
| `AZURE_ENV_FOUNDRY_PROJECT_ID` | string | `<Existing Workspace Id>` | Set this if you want to reuse an AI Foundry Project instead of creating a new one. |
1617
| `AZURE_ENV_MODEL_VERSION` | string | `2024-08-06` | Version of the GPT model to be used for deployment. |
18+
| `AZURE_ENV_MODEL_CAPACITY` | int | `150` | Sets the GPT model capacity. |
1719
| `AZURE_ENV_IMAGETAG` | string | `latest` | Docker image tag used for container deployments. |
1820
| `AZURE_ENV_ENABLE_TELEMETRY` | bool | `true` | Enables telemetry for monitoring and diagnostics. |
1921
| `AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID` | string | `<Existing Workspace Id>` | Set this if you want to reuse an existing Log Analytics Workspace instead of creating a new one. |

docs/DeploymentGuide.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ If you're not using one of the above options for opening the project, then you'l
117117
1. Make sure the following tools are installed:
118118

119119
- [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.5) <small>(v7.0+)</small> - available for Windows, macOS, and Linux.
120-
- [Azure Developer CLI (azd)](https://aka.ms/install-azd)
120+
- [Azure Developer CLI (azd)](https://aka.ms/install-azd) <small>(v1.15.0+)</small> - version
121121
- [Python 3.9+](https://www.python.org/downloads/)
122122
- [Docker Desktop](https://www.docker.com/products/docker-desktop/)
123123
- [Git](https://git-scm.com/downloads)
@@ -150,6 +150,7 @@ When you start the deployment, most parameters will have **default values**, but
150150
| **Model Deployment Type** | Defines the deployment type for the AI model (e.g., Standard, GlobalStandard). | GlobalStandard |
151151
| **GPT Model Name** | Specifies the name of the GPT model to be deployed. | gpt-4o |
152152
| **GPT Model Version** | Version of the GPT model to be used for deployment. | 2024-08-06 |
153+
| **GPT Model Capacity** | Sets the GPT model capacity. | 150 |
153154
| **Image Tag** | Docker image tag used for container deployments. | latest |
154155
| **Enable Telemetry** | Enables telemetry for monitoring and diagnostics. | true |
155156

infra/main.bicep

Lines changed: 32 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ metadata description = 'This module contains the resources required to deploy th
44
@description('Set to true if you want to deploy WAF-aligned infrastructure.')
55
param useWafAlignedArchitecture bool
66

7+
@description('Use this parameter to use an existing AI project resource ID')
8+
param existingFoundryProjectResourceId string = ''
9+
710
@description('Optional. The prefix to add in the default names given to all deployed Azure resources.')
811
@maxLength(19)
912
param solutionPrefix string = 'macae${uniqueString(deployer().objectId, deployer().tenantId, subscription().subscriptionId, resourceGroup().id)}'
@@ -45,10 +48,6 @@ param gptModelCapacity int = 150
4548
@description('Set the image tag for the container images used in the solution. Default is "latest".')
4649
param imageTag string = 'latest'
4750

48-
// @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.')
49-
// param AZURE_LOCATION string=''
50-
// param solutionLocation string = empty(AZURE_LOCATION) ? resourceGroup().location
51-
5251
@description('Optional. The tags to apply to all deployed Azure resources.')
5352
param tags object = {
5453
app: solutionPrefix
@@ -233,32 +232,6 @@ param webSiteConfiguration webSiteConfigurationType = {
233232
environmentResourceId: null //Default value set on module configuration
234233
}
235234

236-
//
237-
// Add your parameters here
238-
//
239-
240-
// ============== //
241-
// Resources //
242-
// ============== //
243-
244-
/* #disable-next-line no-deployments-resources
245-
resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableTelemetry) {
246-
name: '46d3xbcp.[[REPLACE WITH TELEMETRY IDENTIFIER]].${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}'
247-
properties: {
248-
mode: 'Incremental'
249-
template: {
250-
'$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#'
251-
contentVersion: '1.0.0.0'
252-
resources: []
253-
outputs: {
254-
telemetry: {
255-
type: 'String'
256-
value: 'For more information, see https://aka.ms/avm/TelemetryInfo'
257-
}
258-
}
259-
}
260-
}
261-
} */
262235

263236
// ========== Log Analytics Workspace ========== //
264237
// WAF best practices for Log Analytics: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-log-analytics
@@ -595,8 +568,6 @@ module virtualNetwork 'br/public:avm/res/network/virtual-network:0.6.1' = if (vi
595568
name: 'administration'
596569
addressPrefix: '10.0.0.32/27'
597570
networkSecurityGroupResourceId: networkSecurityGroupAdministration.outputs.resourceId
598-
//defaultOutboundAccess: false TODO: check this configuration for a more restricted outbound access
599-
//natGatewayResourceId: natGateway.outputs.resourceId
600571
}
601572
{
602573
// For Azure Bastion resources deployed on or after November 2, 2021, the minimum AzureBastionSubnet size is /26 or larger (/25, /24, etc.).
@@ -610,7 +581,6 @@ module virtualNetwork 'br/public:avm/res/network/virtual-network:0.6.1' = if (vi
610581
// https://learn.microsoft.com/en-us/azure/container-apps/networking?tabs=workload-profiles-env%2Cazure-cli#custom-vnw-configuration
611582
name: 'containers'
612583
addressPrefix: '10.0.2.0/23' //subnet of size /23 is required for container app
613-
//defaultOutboundAccess: false TODO: check this configuration for a more restricted outbound access
614584
delegation: 'Microsoft.App/environments'
615585
networkSecurityGroupResourceId: networkSecurityGroupContainers.outputs.resourceId
616586
privateEndpointNetworkPolicies: 'Disabled'
@@ -640,9 +610,7 @@ module bastionHost 'br/public:avm/res/network/bastion-host:0.6.1' = if (virtualN
640610
disableCopyPaste: false
641611
enableFileCopy: false
642612
enableIpConnect: true
643-
//enableKerberos: bastionConfiguration.?enableKerberos
644613
enableShareableLink: true
645-
//scaleUnits: bastionConfiguration.?scaleUnits
646614
}
647615
}
648616

@@ -664,8 +632,6 @@ module virtualMachine 'br/public:avm/res/compute/virtual-machine:0.13.0' = if (v
664632
nicConfigurations: [
665633
{
666634
name: 'nic-${virtualMachineResourceName}'
667-
//networkSecurityGroupResourceId: virtualMachineConfiguration.?nicConfigurationConfiguration.networkSecurityGroupResourceId
668-
//nicSuffix: 'nic-${virtualMachineResourceName}'
669635
diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }]
670636
ipConfigurations: [
671637
{
@@ -691,18 +657,13 @@ module virtualMachine 'br/public:avm/res/compute/virtual-machine:0.13.0' = if (v
691657
diskSizeGB: 128
692658
caching: 'ReadWrite'
693659
}
694-
//patchMode: virtualMachineConfiguration.?patchMode
695660
osType: 'Windows'
696661
encryptionAtHost: false //The property 'securityProfile.encryptionAtHost' is not valid because the 'Microsoft.Compute/EncryptionAtHost' feature is not enabled for this subscription.
697662
zone: 0
698663
extensionAadJoinConfig: {
699664
enabled: true
700665
typeHandlerVersion: '1.0'
701666
}
702-
// extensionMonitoringAgentConfig: {
703-
// enabled: true
704-
// }
705-
// maintenanceConfigurationResourceId: virtualMachineConfiguration.?maintenanceConfigurationResourceId
706667
}
707668
}
708669

@@ -736,7 +697,9 @@ module privateDnsZonesAiServices 'br/public:avm/res/network/private-dns-zone:0.7
736697
]
737698

738699
// NOTE: Required version 'Microsoft.CognitiveServices/accounts@2024-04-01-preview' not available in AVM
739-
var aiFoundryAiServicesResourceName = aiFoundryAiServicesConfiguration.?name ?? 'aisa-${solutionPrefix}'
700+
var useExistingFoundryProject = !empty(existingFoundryProjectResourceId)
701+
var existingAiFoundryName = useExistingFoundryProject?split( existingFoundryProjectResourceId,'/')[8]:''
702+
var aiFoundryAiServicesResourceName = useExistingFoundryProject? existingAiFoundryName : aiFoundryAiServicesConfiguration.?name ?? 'aisa-${solutionPrefix}'
740703
var aiFoundryAIservicesEnabled = aiFoundryAiServicesConfiguration.?enabled ?? true
741704
var aiFoundryAiServicesModelDeployment = {
742705
format: 'OpenAI'
@@ -750,17 +713,20 @@ var aiFoundryAiServicesModelDeployment = {
750713
raiPolicyName: 'Microsoft.Default'
751714
}
752715

753-
module aiFoundryAiServices 'br/public:avm/res/cognitive-services/account:0.11.0' = if (aiFoundryAIservicesEnabled) {
716+
module aiFoundryAiServices 'modules/account/main.bicep' = if (aiFoundryAIservicesEnabled) {
754717
name: take('avm.res.cognitive-services.account.${aiFoundryAiServicesResourceName}', 64)
755718
params: {
756719
name: aiFoundryAiServicesResourceName
757720
tags: aiFoundryAiServicesConfiguration.?tags ?? tags
758721
location: aiFoundryAiServicesConfiguration.?location ?? aiDeploymentsLocation
759722
enableTelemetry: enableTelemetry
723+
projectName: 'aifp-${solutionPrefix}'
724+
projectDescription: 'aifp-${solutionPrefix}'
725+
existingFoundryProjectResourceId: existingFoundryProjectResourceId
760726
diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }]
761727
sku: aiFoundryAiServicesConfiguration.?sku ?? 'S0'
762728
kind: 'AIServices'
763-
disableLocalAuth: false //Should be set to true for WAF aligned configuration
729+
disableLocalAuth: true //Should be set to true for WAF aligned configuration
764730
customSubDomainName: aiFoundryAiServicesResourceName
765731
apiProperties: {
766732
//staticsEnabled: false
@@ -769,10 +735,12 @@ module aiFoundryAiServices 'br/public:avm/res/cognitive-services/account:0.11.0'
769735
managedIdentities: {
770736
systemAssigned: true
771737
}
772-
//publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled'
773-
//publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled'
774-
publicNetworkAccess: 'Enabled' //TODO: connection via private endpoint is not working from containers network. Change this when fixed
775-
privateEndpoints: virtualNetworkEnabled
738+
publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled'
739+
networkAcls: {
740+
bypass: 'AzureServices'
741+
defaultAction: (virtualNetworkEnabled) ? 'Deny' : 'Allow'
742+
}
743+
privateEndpoints: virtualNetworkEnabled && !useExistingFoundryProject
776744
? ([
777745
{
778746
name: 'pep-${aiFoundryAiServicesResourceName}'
@@ -786,19 +754,7 @@ module aiFoundryAiServices 'br/public:avm/res/cognitive-services/account:0.11.0'
786754
}
787755
}
788756
])
789-
: []
790-
// roleAssignments: [
791-
// // {
792-
// // principalId: userAssignedIdentity.outputs.principalId
793-
// // principalType: 'ServicePrincipal'
794-
// // roleDefinitionIdOrName: 'Cognitive Services OpenAI User'
795-
// // }
796-
// {
797-
// principalId: containerApp.outputs.?systemAssignedMIPrincipalId!
798-
// principalType: 'ServicePrincipal'
799-
// roleDefinitionIdOrName: 'Cognitive Services OpenAI User'
800-
// }
801-
// ]
757+
: []
802758
deployments: aiFoundryAiServicesConfiguration.?deployments ?? [
803759
{
804760
name: aiFoundryAiServicesModelDeployment.name
@@ -819,76 +775,27 @@ module aiFoundryAiServices 'br/public:avm/res/cognitive-services/account:0.11.0'
819775

820776
// AI Foundry: AI Project
821777
// WAF best practices for Open AI: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-openai
822-
// var aiFoundryAiProjectEnabled = aiFoundryAiProjectConfiguration.?enabled ?? true
823-
var aiFoundryAiProjectName = aiFoundryAiProjectConfiguration.?name ?? 'aifp-${solutionPrefix}'
824-
var aiProjectDescription = 'AI Foundry Project'
825-
826-
resource aiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing = {
827-
name: aiFoundryAiServicesResourceName
828-
dependsOn:[
829-
aiFoundryAiServices
830-
]
831-
}
778+
var existingAiFounryProjectName = useExistingFoundryProject ? last(split( existingFoundryProjectResourceId,'/')) : ''
779+
var aiFoundryAiProjectName = useExistingFoundryProject ? existingAiFounryProjectName : aiFoundryAiProjectConfiguration.?name ?? 'aifp-${solutionPrefix}'
832780

833-
resource aiFoundryProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' = {
834-
parent: aiServices
835-
name: aiFoundryAiProjectName
836-
location: aiFoundryAiProjectConfiguration.?location ?? aiDeploymentsLocation
837-
identity: {
838-
type: 'SystemAssigned'
839-
}
840-
properties: {
841-
description: aiProjectDescription
842-
displayName: aiFoundryAiProjectName
843-
}
844-
}
845-
846-
resource aiUser 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
847-
name: '53ca6127-db72-4b80-b1b0-d745d6d5456d'
848-
}
781+
var useExistingResourceId = !empty(existingFoundryProjectResourceId)
849782

850-
resource aiUserAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
851-
name: guid(containerApp.name, aiFoundryProject.id, aiUser.id)
852-
scope: aiFoundryProject
853-
properties: {
854-
roleDefinitionId: aiUser.id
855-
principalId: containerApp.outputs.?systemAssignedMIPrincipalId!
856-
}
857-
}
858-
859-
resource aiUserAccessFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
860-
name: guid(containerApp.name, aiServices.id, aiUser.id)
861-
scope: aiServices
862-
properties: {
863-
roleDefinitionId: aiUser.id
864-
principalId: containerApp.outputs.?systemAssignedMIPrincipalId!
865-
}
866-
}
867-
868-
resource aiDeveloper 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
869-
name: '64702f94-c441-49e6-a78b-ef80e0188fee'
870-
}
871-
872-
resource aiDeveloperAccessFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
873-
name: guid(containerApp.name, aiServices.id, aiDeveloper.id)
874-
scope: aiFoundryProject
875-
properties: {
876-
roleDefinitionId: aiDeveloper.id
783+
module cogServiceRoleAssignmentsNew './modules/role.bicep' = if(!useExistingResourceId) {
784+
params: {
785+
name: 'new-${guid(containerApp.name, aiFoundryAiServices.outputs.resourceId)}'
877786
principalId: containerApp.outputs.?systemAssignedMIPrincipalId!
787+
aiServiceName: aiFoundryAiServices.outputs.name
878788
}
789+
scope: resourceGroup(subscription().subscriptionId, resourceGroup().name)
879790
}
880791

881-
resource cognitiveServiceOpenAIUser 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
882-
name: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd'
883-
}
884-
885-
resource cognitiveServiceOpenAIUserAccessFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
886-
name: guid(containerApp.name, aiServices.id, cognitiveServiceOpenAIUser.id)
887-
scope: aiServices
888-
properties: {
889-
roleDefinitionId: cognitiveServiceOpenAIUser.id
792+
module cogServiceRoleAssignmentsExisting './modules/role.bicep' = if(useExistingResourceId) {
793+
params: {
794+
name: 'reuse-${guid(containerApp.name, aiFoundryAiServices.outputs.aiProjectInfo.resourceId)}'
890795
principalId: containerApp.outputs.?systemAssignedMIPrincipalId!
796+
aiServiceName: aiFoundryAiServices.outputs.name
891797
}
798+
scope: resourceGroup( split(existingFoundryProjectResourceId, '/')[2], split(existingFoundryProjectResourceId, '/')[4])
892799
}
893800

894801
// ========== Cosmos DB ========== //
@@ -966,7 +873,6 @@ module cosmosDb 'br/public:avm/res/document-db/database-account:0.12.0' = if (co
966873
'EnableServerless'
967874
]
968875
sqlRoleAssignmentsPrincipalIds: [
969-
//userAssignedIdentity.outputs.principalId
970876
containerApp.outputs.?systemAssignedMIPrincipalId
971877
]
972878
sqlRoleDefinitions: [
@@ -1003,13 +909,6 @@ module containerAppEnvironment 'modules/container-app-environment.bicep' = if (c
1003909
subnetResourceId: virtualNetworkEnabled
1004910
? containerAppEnvironmentConfiguration.?subnetResourceId ?? virtualNetwork.?outputs.?subnetResourceIds[3] ?? ''
1005911
: ''
1006-
//aspireDashboardEnabled: !virtualNetworkEnabled
1007-
// vnetConfiguration: virtualNetworkEnabled
1008-
// ? {
1009-
// internal: false
1010-
// infrastructureSubnetId: containerAppEnvironmentConfiguration.?subnetResourceId ?? virtualNetwork.?outputs.?subnetResourceIds[3] ?? ''
1011-
// }
1012-
// : {}
1013912
}
1014913
}
1015914

@@ -1117,7 +1016,7 @@ module containerApp 'br/public:avm/res/app/container-app:0.14.2' = if (container
11171016
}
11181017
{
11191018
name: 'AZURE_AI_AGENT_ENDPOINT'
1120-
value: aiFoundryProject.properties.endpoints['AI Foundry API']
1019+
value: aiFoundryAiServices.outputs.aiProjectInfo.apiEndpoint
11211020
}
11221021
{
11231022
name: 'AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME'
@@ -1189,19 +1088,6 @@ module webSite 'br/public:avm/res/web/site:0.15.1' = if (webSiteEnabled) {
11891088
@description('The default url of the website to connect to the Multi-Agent Custom Automation Engine solution.')
11901089
output webSiteDefaultHostname string = webSite.outputs.defaultHostname
11911090

1192-
// @description('The name of the resource.')
1193-
// output name string = <Resource>.name
1194-
1195-
// @description('The location the resource was deployed into.')
1196-
// output location string = <Resource>.location
1197-
1198-
// ================ //
1199-
// Definitions //
1200-
// ================ //
1201-
//
1202-
// Add your User-defined-types here, if any
1203-
//
1204-
12051091
@export()
12061092
@description('The type for the Multi-Agent Custom Automation Engine Log Analytics Workspace resource configuration.')
12071093
type logAnalyticsWorkspaceConfigurationType = {

infra/main.parameters.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
"gptModelCapacity": {
4040
"value": "${AZURE_ENV_MODEL_CAPACITY}"
4141
},
42+
"existingFoundryProjectResourceId": {
43+
"value": "${AZURE_ENV_FOUNDRY_PROJECT_ID}"
44+
},
4245
"imageTag": {
4346
"value": "${AZURE_ENV_IMAGE_TAG}"
4447
},

0 commit comments

Comments
 (0)