Skip to content

Commit 518e3f5

Browse files
Merge branch 'dev' into PSL-US-18922
2 parents 022893e + 069fc59 commit 518e3f5

7 files changed

Lines changed: 87 additions & 154 deletions

File tree

infra/abbreviations.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
"ai": {
33
"aiSearch": "srch-",
44
"aiServices": "aisa-",
5+
"aiFoundry": "aif-",
6+
"aiFoundryProject": "aifp-",
57
"aiVideoIndexer": "avi-",
68
"machineLearningWorkspace": "mlw-",
79
"openAIService": "oai-",

infra/deploy_ai_foundry.bicep

Lines changed: 7 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ param managedIdentityObjectId string
1111
param aiServicesEndpoint string
1212
param aiServicesKey string
1313
param aiServicesId string
14+
param aureaiFoundryEndpoint string
1415

16+
param aiFoundryName string
1517
param existingLogAnalyticsWorkspaceId string = ''
1618

1719
var useExisting = !empty(existingLogAnalyticsWorkspaceId)
@@ -24,15 +26,10 @@ var abbrs = loadJsonContent('./abbreviations.json')
2426
var storageName = '${abbrs.storage.storageAccount}${solutionName}'
2527

2628
var storageSkuName = 'Standard_LRS'
27-
var aiServicesName = '${abbrs.ai.aiServices}${solutionName}'
2829
var workspaceName = '${abbrs.managementGovernance.logAnalyticsWorkspace}${solutionName}'
2930
var keyvaultName = '${abbrs.security.keyVault}${solutionName}'
3031
var location = solutionLocation
31-
var azureAiHubName = '${abbrs.ai.aiHub}${solutionName}'
32-
var aiHubFriendlyName = azureAiHubName
33-
var aiHubDescription = 'AI Hub for KM template'
34-
var aiProjectName = '${abbrs.ai.aiHubProject}${solutionName}'
35-
var aiProjectFriendlyName = aiProjectName
32+
3633
var aiSearchName = '${solutionName}-search'
3734
var applicationInsightsName = '${solutionName}-appi'
3835

@@ -73,125 +70,6 @@ resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
7370

7471
var storageNameCleaned = replace(replace(replace(replace('${storageName}cast', '-', ''), '_', ''), '.', ''),'/', '')
7572

76-
77-
78-
79-
resource storage 'Microsoft.Storage/storageAccounts@2022-09-01' = {
80-
name: storageNameCleaned
81-
location: location
82-
sku: {
83-
name: storageSkuName
84-
}
85-
kind: 'StorageV2'
86-
identity: {
87-
type: 'SystemAssigned'
88-
}
89-
properties: {
90-
accessTier: 'Hot'
91-
allowBlobPublicAccess: false
92-
allowCrossTenantReplication: false
93-
allowSharedKeyAccess: false
94-
encryption: {
95-
keySource: 'Microsoft.Storage'
96-
requireInfrastructureEncryption: false
97-
services: {
98-
blob: {
99-
enabled: true
100-
keyType: 'Account'
101-
}
102-
file: {
103-
enabled: true
104-
keyType: 'Account'
105-
}
106-
queue: {
107-
enabled: true
108-
keyType: 'Service'
109-
}
110-
table: {
111-
enabled: true
112-
keyType: 'Service'
113-
}
114-
}
115-
}
116-
isHnsEnabled: false
117-
isNfsV3Enabled: false
118-
keyPolicy: {
119-
keyExpirationPeriodInDays: 7
120-
}
121-
largeFileSharesState: 'Disabled'
122-
minimumTlsVersion: 'TLS1_2'
123-
networkAcls: {
124-
bypass: 'AzureServices'
125-
defaultAction: 'Allow'
126-
}
127-
supportsHttpsTrafficOnly: true
128-
}
129-
}
130-
131-
@description('This is the built-in Storage Blob Data Contributor.')
132-
resource blobDataContributor 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' existing = {
133-
scope: subscription()
134-
name: 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'
135-
}
136-
137-
resource storageroleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
138-
name: guid(resourceGroup().id, managedIdentityObjectId, blobDataContributor.id)
139-
scope: storage
140-
properties: {
141-
principalId: managedIdentityObjectId
142-
roleDefinitionId: blobDataContributor.id
143-
principalType: 'ServicePrincipal'
144-
}
145-
}
146-
147-
resource aiHub 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = {
148-
name: azureAiHubName
149-
location: location
150-
identity: {
151-
type: 'SystemAssigned'
152-
}
153-
properties: {
154-
// organization
155-
friendlyName: aiHubFriendlyName
156-
description: aiHubDescription
157-
158-
// dependent resources
159-
keyVault: keyVault.id
160-
storageAccount: storage.id
161-
}
162-
kind: 'hub'
163-
164-
resource aiServicesConnection 'connections@2024-07-01-preview' = {
165-
name: '${azureAiHubName}-connection-AzureOpenAI'
166-
properties: {
167-
category: 'AIServices'
168-
target: aiServicesEndpoint
169-
authType: 'ApiKey'
170-
isSharedToAll: true
171-
credentials: {
172-
key: aiServicesKey
173-
}
174-
metadata: {
175-
ApiType: 'Azure'
176-
ResourceId: aiServicesId
177-
}
178-
}
179-
}
180-
}
181-
182-
resource aiHubProject 'Microsoft.MachineLearningServices/workspaces@2024-01-01-preview' = {
183-
name: aiProjectName
184-
location: location
185-
kind: 'Project'
186-
identity: {
187-
type: 'SystemAssigned'
188-
}
189-
properties: {
190-
friendlyName: aiProjectFriendlyName
191-
hubResourceId: aiHub.id
192-
}
193-
}
194-
19573
resource tenantIdEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = {
19674
parent: keyVault
19775
name: 'TENANT-ID'
@@ -248,11 +126,11 @@ resource azureOpenAIEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-
248126
}
249127
}
250128

251-
resource azureAIProjectConnectionStringEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = {
129+
resource azureAIProjectEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = {
252130
parent: keyVault
253-
name: 'AZURE-AI-PROJECT-CONN-STRING'
131+
name: 'AI-PROJECT-ENDPOINT'
254132
properties: {
255-
value: '${split(aiHubProject.properties.discoveryUrl, '/')[2]};${subscription().subscriptionId};${resourceGroup().name};${aiHubProject.name}'
133+
value: aureaiFoundryEndpoint
256134
}
257135
}
258136

@@ -292,7 +170,7 @@ resource cogServiceNameEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-previ
292170
parent: keyVault
293171
name: 'COG-SERVICES-NAME'
294172
properties: {
295-
value: aiServicesName
173+
value: aiFoundryName
296174
}
297175
}
298176

@@ -323,14 +201,9 @@ resource azureLocatioEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview
323201
output keyvaultName string = keyvaultName
324202
output keyvaultId string = keyVault.id
325203

326-
output aiServicesName string = aiServicesName
327204
output aiSearchName string = aiSearchName
328-
output aiProjectName string = aiHubProject.name
329205

330206
output storageAccountName string = storageNameCleaned
331207

332208
output logAnalyticsId string = useExisting ? existingLogAnalyticsWorkspace.id : logAnalytics.id
333-
output storageAccountId string = storage.id
334209
output applicationInsightsConnectionString string = applicationInsights.properties.ConnectionString
335-
336-
output projectConnectionString string = '${split(aiHubProject.properties.discoveryUrl, '/')[2]};${subscription().subscriptionId};${resourceGroup().name};${aiHubProject.name}'

infra/main.bicep

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,11 @@ var cosmosdbLogContainer = 'cmsalog'
5757
var containerName = 'appstorage'
5858
var storageSkuName = 'Standard_LRS'
5959
var storageContainerName = replace(replace(replace(replace('${ResourcePrefix}cast', '-', ''), '_', ''), '.', ''),'/', '')
60-
var azureAiServicesName = '${abbrs.ai.aiServices}${ResourcePrefix}'
61-
6260

61+
var aiFoundryName = '${abbrs.ai.aiFoundry}${ResourcePrefix}'
62+
var aiProjectDescription = 'AI foundary project for CPS template'
63+
var aiProjectName = '${abbrs.ai.aiFoundryProject}${ResourcePrefix}'
64+
var aiProjectFriendlyName = aiProjectName
6365

6466
var aiModelDeployments = [
6567
{
@@ -74,15 +76,39 @@ var aiModelDeployments = [
7476
}
7577
]
7678

77-
resource azureAiServices 'Microsoft.CognitiveServices/accounts@2024-04-01-preview' = {
78-
name: azureAiServicesName
79+
resource azureAiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = {
80+
name: aiFoundryName
7981
location: AzureAiServiceLocation
8082
sku: {
8183
name: 'S0'
8284
}
8385
kind: 'AIServices'
86+
identity: {
87+
type: 'SystemAssigned'
88+
}
89+
properties: {
90+
allowProjectManagement: true
91+
customSubDomainName: aiFoundryName
92+
networkAcls: {
93+
defaultAction: 'Allow'
94+
virtualNetworkRules: []
95+
ipRules: []
96+
}
97+
publicNetworkAccess: 'Enabled'
98+
disableLocalAuth: false
99+
}
100+
}
101+
102+
resource aiFoundryProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' = {
103+
parent: azureAiServices
104+
name: aiProjectName
105+
location: AzureAiServiceLocation
106+
identity: {
107+
type: 'SystemAssigned'
108+
}
84109
properties: {
85-
customSubDomainName: azureAiServicesName
110+
description: aiProjectDescription
111+
displayName: aiProjectFriendlyName
86112
}
87113
}
88114

@@ -136,6 +162,7 @@ module azureAifoundry 'deploy_ai_foundry.bicep' = {
136162
params: {
137163
solutionName: ResourcePrefix
138164
solutionLocation: AzureAiServiceLocation
165+
aiFoundryName: aiFoundryName
139166
keyVaultName: kvault.outputs.keyvaultName
140167
gptModelName: llmModel
141168
gptModelVersion: gptModelVersion
@@ -144,6 +171,7 @@ module azureAifoundry 'deploy_ai_foundry.bicep' = {
144171
aiServicesKey: azureAiServices.listKeys().key1
145172
aiServicesId: azureAiServices.id
146173
existingLogAnalyticsWorkspaceId: existingLogAnalyticsWorkspaceId
174+
aureaiFoundryEndpoint: aiFoundryProject.properties.endpoints['AI Foundry API']
147175
}
148176
scope: resourceGroup(resourceGroup().name)
149177
}
@@ -322,7 +350,7 @@ resource containerAppBackend 'Microsoft.App/containerApps@2023-05-01' = {
322350
}
323351
{
324352
name: 'AZURE_OPENAI_ENDPOINT'
325-
value: 'https://${azureAifoundry.outputs.aiServicesName}.openai.azure.com/'
353+
value: 'https://${aiFoundryName}.openai.azure.com/'
326354
}
327355
{
328356
name: 'MIGRATOR_AGENT_MODEL_DEPLOY'
@@ -358,7 +386,7 @@ resource containerAppBackend 'Microsoft.App/containerApps@2023-05-01' = {
358386
}
359387
{
360388
name: 'AZURE_AI_AGENT_PROJECT_NAME'
361-
value: azureAifoundry.outputs.aiProjectName
389+
value: aiProjectName
362390
}
363391
{
364392
name: 'AZURE_AI_AGENT_RESOURCE_GROUP_NAME'
@@ -369,8 +397,8 @@ resource containerAppBackend 'Microsoft.App/containerApps@2023-05-01' = {
369397
value: subscription().subscriptionId
370398
}
371399
{
372-
name: 'AZURE_AI_AGENT_PROJECT_CONNECTION_STRING'
373-
value: azureAifoundry.outputs.projectConnectionString
400+
name: 'AI_PROJECT_ENDPOINT'
401+
value: aiFoundryProject.properties.endpoints['AI Foundry API']
374402
}
375403
]
376404
resources: {
@@ -439,6 +467,7 @@ resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
439467
properties: {
440468
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') // Storage Blob Data Contributor
441469
principalId: containerAppBackend.identity.principalId
470+
principalType: 'ServicePrincipal'
442471
}
443472
}
444473
var openAiContributorRoleId = 'a001fd3d-188f-4b5d-821b-7da978bf7442' // Fixed Role ID for OpenAI Contributor
@@ -449,6 +478,7 @@ resource openAiRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-0
449478
properties: {
450479
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', openAiContributorRoleId) // OpenAI Service Contributor
451480
principalId: containerAppBackend.identity.principalId
481+
principalType: 'ServicePrincipal'
452482
}
453483
}
454484

@@ -465,20 +495,42 @@ resource containers 'Microsoft.Storage/storageAccounts/blobServices/containers@2
465495
dependsOn: [azureAifoundry]
466496
}]
467497

468-
resource aiHubProject 'Microsoft.MachineLearningServices/workspaces@2024-01-01-preview' existing = {
469-
name: '${abbrs.ai.aiHubProject}${ResourcePrefix}' // aiProjectName must be calculated - available at main start.
470-
}
471-
472498
resource aiDeveloper 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
473499
name: '64702f94-c441-49e6-a78b-ef80e0188fee'
474500
}
475501

476502
resource aiDeveloperAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
477-
name: guid(containerAppBackend.name, aiHubProject.id, aiDeveloper.id)
478-
scope: aiHubProject
503+
name: guid(containerAppBackend.name, aiDeveloper.id)
504+
scope: resourceGroup()
479505
properties: {
480506
roleDefinitionId: aiDeveloper.id
481507
principalId: containerAppBackend.identity.principalId
508+
principalType: 'ServicePrincipal'
509+
}
510+
}
511+
512+
513+
resource aiUser 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
514+
name: '53ca6127-db72-4b80-b1b0-d745d6d5456d'
515+
}
516+
517+
resource aiUserAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
518+
name: guid(containerAppBackend.name, aiUser.id)
519+
scope: resourceGroup()
520+
properties: {
521+
roleDefinitionId: aiUser.id
522+
principalId: containerAppBackend.identity.principalId
523+
principalType: 'ServicePrincipal'
524+
}
525+
}
526+
527+
resource aiUserAccessFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
528+
name: guid(containerAppBackend.name, aiFoundryProject.id)
529+
scope: resourceGroup()
530+
properties: {
531+
roleDefinitionId: aiUser.id
532+
principalId: containerAppBackend.identity.principalId
533+
principalType: 'ServicePrincipal'
482534
}
483535
}
484536

@@ -508,3 +560,6 @@ module deploymentScriptCLI 'br/public:avm/res/resources/deployment-script:0.5.1'
508560

509561
output AZURE_AIFOUNDRY_NAME string = azureAiServices.name
510562
output WEB_APP_URL string = 'https://${containerAppFrontend.outputs.fqdn}'
563+
output aiFoundryName string = aiFoundryName
564+
output aiProjectName string = aiFoundryProject.name
565+
output projectEndpointString string = aiFoundryProject.properties.endpoints['AI Foundry API']

src/backend/common/config/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def __init__(self):
3838
self.azure_queue_name = os.getenv("AZURE_QUEUE_NAME")
3939

4040
self.azure_openai_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
41+
self.ai_project_endpoint = os.getenv("AI_PROJECT_ENDPOINT")
4142
self.migrator_agent_model_deploy = os.getenv("MIGRATOR_AGENT_MODEL_DEPLOY")
4243
self.picker_agent_model_deploy = os.getenv("PICKER_AGENT_MODEL_DEPLOY")
4344
self.fixer_agent_model_deploy = os.getenv("FIXER_AGENT_MODEL_DEPLOY")
@@ -62,3 +63,4 @@ def get_azure_credentials(self):
6263

6364

6465
app_config = Config()
66+
print(f"[DEBUG] AI_PROJECT_ENDPOINT: '{os.getenv('AI_PROJECT_ENDPOINT')}'")

0 commit comments

Comments
 (0)