Skip to content

Commit 069fc59

Browse files
Merge pull request #132 from microsoft/psl-sw-cm-fdp
feat: fdp changes
2 parents 90f97be + eea319d commit 069fc59

7 files changed

Lines changed: 88 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: 71 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

@@ -137,6 +163,7 @@ module azureAifoundry 'deploy_ai_foundry.bicep' = {
137163
params: {
138164
solutionName: ResourcePrefix
139165
solutionLocation: AzureAiServiceLocation
166+
aiFoundryName: aiFoundryName
140167
keyVaultName: kvault.outputs.keyvaultName
141168
gptModelName: llmModel
142169
gptModelVersion: gptModelVersion
@@ -145,6 +172,7 @@ module azureAifoundry 'deploy_ai_foundry.bicep' = {
145172
aiServicesKey: azureAiServices.listKeys().key1
146173
aiServicesId: azureAiServices.id
147174
existingLogAnalyticsWorkspaceId: existingLogAnalyticsWorkspaceId
175+
aureaiFoundryEndpoint: aiFoundryProject.properties.endpoints['AI Foundry API']
148176
}
149177
scope: resourceGroup(resourceGroup().name)
150178
}
@@ -323,7 +351,7 @@ resource containerAppBackend 'Microsoft.App/containerApps@2023-05-01' = {
323351
}
324352
{
325353
name: 'AZURE_OPENAI_ENDPOINT'
326-
value: 'https://${azureAifoundry.outputs.aiServicesName}.openai.azure.com/'
354+
value: 'https://${aiFoundryName}.openai.azure.com/'
327355
}
328356
{
329357
name: 'MIGRATOR_AGENT_MODEL_DEPLOY'
@@ -359,7 +387,7 @@ resource containerAppBackend 'Microsoft.App/containerApps@2023-05-01' = {
359387
}
360388
{
361389
name: 'AZURE_AI_AGENT_PROJECT_NAME'
362-
value: azureAifoundry.outputs.aiProjectName
390+
value: aiProjectName
363391
}
364392
{
365393
name: 'AZURE_AI_AGENT_RESOURCE_GROUP_NAME'
@@ -370,8 +398,8 @@ resource containerAppBackend 'Microsoft.App/containerApps@2023-05-01' = {
370398
value: subscription().subscriptionId
371399
}
372400
{
373-
name: 'AZURE_AI_AGENT_PROJECT_CONNECTION_STRING'
374-
value: azureAifoundry.outputs.projectConnectionString
401+
name: 'AI_PROJECT_ENDPOINT'
402+
value: aiFoundryProject.properties.endpoints['AI Foundry API']
375403
}
376404
]
377405
resources: {
@@ -440,6 +468,7 @@ resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
440468
properties: {
441469
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') // Storage Blob Data Contributor
442470
principalId: containerAppBackend.identity.principalId
471+
principalType: 'ServicePrincipal'
443472
}
444473
}
445474
var openAiContributorRoleId = 'a001fd3d-188f-4b5d-821b-7da978bf7442' // Fixed Role ID for OpenAI Contributor
@@ -450,6 +479,7 @@ resource openAiRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-0
450479
properties: {
451480
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', openAiContributorRoleId) // OpenAI Service Contributor
452481
principalId: containerAppBackend.identity.principalId
482+
principalType: 'ServicePrincipal'
453483
}
454484
}
455485

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

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

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

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

510562
output AZURE_AIFOUNDRY_NAME string = azureAiServices.name
563+
564+
output aiFoundryName string = aiFoundryName
565+
output aiProjectName string = aiFoundryProject.name
566+
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)