Skip to content

feat: fdp changes #132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jun 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions infra/abbreviations.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
"ai": {
"aiSearch": "srch-",
"aiServices": "aisa-",
"aiFoundry": "aif-",
"aiFoundryProject": "aifp-",
"aiVideoIndexer": "avi-",
"machineLearningWorkspace": "mlw-",
"openAIService": "oai-",
Expand Down
141 changes: 7 additions & 134 deletions infra/deploy_ai_foundry.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ param managedIdentityObjectId string
param aiServicesEndpoint string
param aiServicesKey string
param aiServicesId string
param aureaiFoundryEndpoint string

param aiFoundryName string
param existingLogAnalyticsWorkspaceId string = ''

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

var storageSkuName = 'Standard_LRS'
var aiServicesName = '${abbrs.ai.aiServices}${solutionName}'
var workspaceName = '${abbrs.managementGovernance.logAnalyticsWorkspace}${solutionName}'
var keyvaultName = '${abbrs.security.keyVault}${solutionName}'
var location = solutionLocation
var azureAiHubName = '${abbrs.ai.aiHub}${solutionName}'
var aiHubFriendlyName = azureAiHubName
var aiHubDescription = 'AI Hub for KM template'
var aiProjectName = '${abbrs.ai.aiHubProject}${solutionName}'
var aiProjectFriendlyName = aiProjectName

var aiSearchName = '${solutionName}-search'
var applicationInsightsName = '${solutionName}-appi'

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

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




resource storage 'Microsoft.Storage/storageAccounts@2022-09-01' = {
name: storageNameCleaned
location: location
sku: {
name: storageSkuName
}
kind: 'StorageV2'
identity: {
type: 'SystemAssigned'
}
properties: {
accessTier: 'Hot'
allowBlobPublicAccess: false
allowCrossTenantReplication: false
allowSharedKeyAccess: false
encryption: {
keySource: 'Microsoft.Storage'
requireInfrastructureEncryption: false
services: {
blob: {
enabled: true
keyType: 'Account'
}
file: {
enabled: true
keyType: 'Account'
}
queue: {
enabled: true
keyType: 'Service'
}
table: {
enabled: true
keyType: 'Service'
}
}
}
isHnsEnabled: false
isNfsV3Enabled: false
keyPolicy: {
keyExpirationPeriodInDays: 7
}
largeFileSharesState: 'Disabled'
minimumTlsVersion: 'TLS1_2'
networkAcls: {
bypass: 'AzureServices'
defaultAction: 'Allow'
}
supportsHttpsTrafficOnly: true
}
}

@description('This is the built-in Storage Blob Data Contributor.')
resource blobDataContributor 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' existing = {
scope: subscription()
name: 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'
}

resource storageroleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, managedIdentityObjectId, blobDataContributor.id)
scope: storage
properties: {
principalId: managedIdentityObjectId
roleDefinitionId: blobDataContributor.id
principalType: 'ServicePrincipal'
}
}

resource aiHub 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = {
name: azureAiHubName
location: location
identity: {
type: 'SystemAssigned'
}
properties: {
// organization
friendlyName: aiHubFriendlyName
description: aiHubDescription

// dependent resources
keyVault: keyVault.id
storageAccount: storage.id
}
kind: 'hub'

resource aiServicesConnection 'connections@2024-07-01-preview' = {
name: '${azureAiHubName}-connection-AzureOpenAI'
properties: {
category: 'AIServices'
target: aiServicesEndpoint
authType: 'ApiKey'
isSharedToAll: true
credentials: {
key: aiServicesKey
}
metadata: {
ApiType: 'Azure'
ResourceId: aiServicesId
}
}
}
}

resource aiHubProject 'Microsoft.MachineLearningServices/workspaces@2024-01-01-preview' = {
name: aiProjectName
location: location
kind: 'Project'
identity: {
type: 'SystemAssigned'
}
properties: {
friendlyName: aiProjectFriendlyName
hubResourceId: aiHub.id
}
}

resource tenantIdEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = {
parent: keyVault
name: 'TENANT-ID'
Expand Down Expand Up @@ -248,11 +126,11 @@ resource azureOpenAIEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-
}
}

resource azureAIProjectConnectionStringEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = {
resource azureAIProjectEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = {
parent: keyVault
name: 'AZURE-AI-PROJECT-CONN-STRING'
name: 'AI-PROJECT-ENDPOINT'
properties: {
value: '${split(aiHubProject.properties.discoveryUrl, '/')[2]};${subscription().subscriptionId};${resourceGroup().name};${aiHubProject.name}'
value: aureaiFoundryEndpoint
}
}

Expand Down Expand Up @@ -292,7 +170,7 @@ resource cogServiceNameEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-previ
parent: keyVault
name: 'COG-SERVICES-NAME'
properties: {
value: aiServicesName
value: aiFoundryName
}
}

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

output aiServicesName string = aiServicesName
output aiSearchName string = aiSearchName
output aiProjectName string = aiHubProject.name

output storageAccountName string = storageNameCleaned

output logAnalyticsId string = useExisting ? existingLogAnalyticsWorkspace.id : logAnalytics.id
output storageAccountId string = storage.id
output applicationInsightsConnectionString string = applicationInsights.properties.ConnectionString

output projectConnectionString string = '${split(aiHubProject.properties.discoveryUrl, '/')[2]};${subscription().subscriptionId};${resourceGroup().name};${aiHubProject.name}'
86 changes: 71 additions & 15 deletions infra/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ var cosmosdbLogContainer = 'cmsalog'
var containerName = 'appstorage'
var storageSkuName = 'Standard_LRS'
var storageContainerName = replace(replace(replace(replace('${ResourcePrefix}cast', '-', ''), '_', ''), '.', ''),'/', '')
var azureAiServicesName = '${abbrs.ai.aiServices}${ResourcePrefix}'


var aiFoundryName = '${abbrs.ai.aiFoundry}${ResourcePrefix}'
var aiProjectDescription = 'AI foundary project for CPS template'
var aiProjectName = '${abbrs.ai.aiFoundryProject}${ResourcePrefix}'
var aiProjectFriendlyName = aiProjectName

var aiModelDeployments = [
{
Expand All @@ -74,15 +76,39 @@ var aiModelDeployments = [
}
]

resource azureAiServices 'Microsoft.CognitiveServices/accounts@2024-04-01-preview' = {
name: azureAiServicesName
resource azureAiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = {
name: aiFoundryName
location: AzureAiServiceLocation
sku: {
name: 'S0'
}
kind: 'AIServices'
identity: {
type: 'SystemAssigned'
}
properties: {
allowProjectManagement: true
customSubDomainName: aiFoundryName
networkAcls: {
defaultAction: 'Allow'
virtualNetworkRules: []
ipRules: []
}
publicNetworkAccess: 'Enabled'
disableLocalAuth: false
}
}

resource aiFoundryProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' = {
parent: azureAiServices
name: aiProjectName
location: AzureAiServiceLocation
identity: {
type: 'SystemAssigned'
}
properties: {
customSubDomainName: azureAiServicesName
description: aiProjectDescription
displayName: aiProjectFriendlyName
}
}

Expand Down Expand Up @@ -137,6 +163,7 @@ module azureAifoundry 'deploy_ai_foundry.bicep' = {
params: {
solutionName: ResourcePrefix
solutionLocation: AzureAiServiceLocation
aiFoundryName: aiFoundryName
keyVaultName: kvault.outputs.keyvaultName
gptModelName: llmModel
gptModelVersion: gptModelVersion
Expand All @@ -145,6 +172,7 @@ module azureAifoundry 'deploy_ai_foundry.bicep' = {
aiServicesKey: azureAiServices.listKeys().key1
aiServicesId: azureAiServices.id
existingLogAnalyticsWorkspaceId: existingLogAnalyticsWorkspaceId
aureaiFoundryEndpoint: aiFoundryProject.properties.endpoints['AI Foundry API']
}
scope: resourceGroup(resourceGroup().name)
}
Expand Down Expand Up @@ -323,7 +351,7 @@ resource containerAppBackend 'Microsoft.App/containerApps@2023-05-01' = {
}
{
name: 'AZURE_OPENAI_ENDPOINT'
value: 'https://${azureAifoundry.outputs.aiServicesName}.openai.azure.com/'
value: 'https://${aiFoundryName}.openai.azure.com/'
}
{
name: 'MIGRATOR_AGENT_MODEL_DEPLOY'
Expand Down Expand Up @@ -359,7 +387,7 @@ resource containerAppBackend 'Microsoft.App/containerApps@2023-05-01' = {
}
{
name: 'AZURE_AI_AGENT_PROJECT_NAME'
value: azureAifoundry.outputs.aiProjectName
value: aiProjectName
}
{
name: 'AZURE_AI_AGENT_RESOURCE_GROUP_NAME'
Expand All @@ -370,8 +398,8 @@ resource containerAppBackend 'Microsoft.App/containerApps@2023-05-01' = {
value: subscription().subscriptionId
}
{
name: 'AZURE_AI_AGENT_PROJECT_CONNECTION_STRING'
value: azureAifoundry.outputs.projectConnectionString
name: 'AI_PROJECT_ENDPOINT'
value: aiFoundryProject.properties.endpoints['AI Foundry API']
}
]
resources: {
Expand Down Expand Up @@ -440,6 +468,7 @@ resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') // Storage Blob Data Contributor
principalId: containerAppBackend.identity.principalId
principalType: 'ServicePrincipal'
}
}
var openAiContributorRoleId = 'a001fd3d-188f-4b5d-821b-7da978bf7442' // Fixed Role ID for OpenAI Contributor
Expand All @@ -450,6 +479,7 @@ resource openAiRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-0
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', openAiContributorRoleId) // OpenAI Service Contributor
principalId: containerAppBackend.identity.principalId
principalType: 'ServicePrincipal'
}
}

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

resource aiHubProject 'Microsoft.MachineLearningServices/workspaces@2024-01-01-preview' existing = {
name: '${abbrs.ai.aiHubProject}${ResourcePrefix}' // aiProjectName must be calculated - available at main start.
}

resource aiDeveloper 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
name: '64702f94-c441-49e6-a78b-ef80e0188fee'
}

resource aiDeveloperAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(containerAppBackend.name, aiHubProject.id, aiDeveloper.id)
scope: aiHubProject
name: guid(containerAppBackend.name, aiDeveloper.id)
scope: resourceGroup()
properties: {
roleDefinitionId: aiDeveloper.id
principalId: containerAppBackend.identity.principalId
principalType: 'ServicePrincipal'
}
}


resource aiUser 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
name: '53ca6127-db72-4b80-b1b0-d745d6d5456d'
}

resource aiUserAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(containerAppBackend.name, aiUser.id)
scope: resourceGroup()
properties: {
roleDefinitionId: aiUser.id
principalId: containerAppBackend.identity.principalId
principalType: 'ServicePrincipal'
}
}

resource aiUserAccessFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(containerAppBackend.name, aiFoundryProject.id)
scope: resourceGroup()
properties: {
roleDefinitionId: aiUser.id
principalId: containerAppBackend.identity.principalId
principalType: 'ServicePrincipal'
}
}

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

output AZURE_AIFOUNDRY_NAME string = azureAiServices.name

output aiFoundryName string = aiFoundryName
output aiProjectName string = aiFoundryProject.name
output projectEndpointString string = aiFoundryProject.properties.endpoints['AI Foundry API']
2 changes: 2 additions & 0 deletions src/backend/common/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def __init__(self):
self.azure_queue_name = os.getenv("AZURE_QUEUE_NAME")

self.azure_openai_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
self.ai_project_endpoint = os.getenv("AI_PROJECT_ENDPOINT")
self.migrator_agent_model_deploy = os.getenv("MIGRATOR_AGENT_MODEL_DEPLOY")
self.picker_agent_model_deploy = os.getenv("PICKER_AGENT_MODEL_DEPLOY")
self.fixer_agent_model_deploy = os.getenv("FIXER_AGENT_MODEL_DEPLOY")
Expand All @@ -62,3 +63,4 @@ def get_azure_credentials(self):


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