@@ -62,6 +62,8 @@ param keyVaultName string = ''
62
62
param searchServiceName string = ''
63
63
@description ('The Azure Search connection name. If ommited will use a default value' )
64
64
param searchConnectionName string = ''
65
+ @description ('The search index name' )
66
+ param aiSearchIndexName string = ''
65
67
@description ('The Azure Storage Account resource name. If ommited will be generated' )
66
68
param storageAccountName string = ''
67
69
@description ('The log analytics workspace name. If ommited will be generated' )
@@ -103,7 +105,9 @@ param embedModelFormat string
103
105
@description ('Name of the embedding model to deploy' )
104
106
param embedModelName string
105
107
@description ('Name of the embedding model deployment' )
106
- param embedDeploymentName string
108
+ param embeddingDeploymentName string
109
+ @description ('Embedding model dimensionality' )
110
+ param embeddingDeploymentDimensions string
107
111
108
112
@description ('Version of the embedding model to deploy' )
109
113
// See version availability in this table:
@@ -121,16 +125,20 @@ param embedDeploymentCapacity int
121
125
122
126
param useContainerRegistry bool = true
123
127
param useApplicationInsights bool = true
124
- param useSearch bool = false
128
+ @description ('Do we want to use the Azure AI Search' )
129
+ param useSearchService bool = false
130
+
131
+ @description ('Random seed to be used during generation of new resources suffixes.' )
132
+ param seed string = newGuid ()
125
133
126
134
var abbrs = loadJsonContent ('./abbreviations.json' )
127
- var resourceToken = toLower (uniqueString (subscription ().id , environmentName , location ))
135
+ var resourceToken = toLower (uniqueString (subscription ().id , environmentName , location , seed ))
128
136
var projectName = !empty (aiProjectName ) ? aiProjectName : 'ai-project-${resourceToken }'
129
137
var tags = { 'azd-env-name' : environmentName }
130
138
131
139
var agentID = !empty (aiAgentID ) ? aiAgentID : ''
132
140
133
- var aiDeployments = [
141
+ var aiChatModel = [
134
142
{
135
143
name : agentDeploymentName
136
144
model : {
@@ -143,8 +151,10 @@ var aiDeployments = [
143
151
capacity : agentDeploymentCapacity
144
152
}
145
153
}
154
+ ]
155
+ var aiEmbeddingModel = [
146
156
{
147
- name : embedDeploymentName
157
+ name : embeddingDeploymentName
148
158
model : {
149
159
format : embedModelFormat
150
160
name : embedModelName
@@ -157,6 +167,10 @@ var aiDeployments = [
157
167
}
158
168
]
159
169
170
+ var aiDeployments = concat (
171
+ aiChatModel ,
172
+ useSearchService ? aiEmbeddingModel : [])
173
+
160
174
//for container and app api
161
175
param apiAppExists bool = false
162
176
@@ -173,6 +187,10 @@ var logAnalyticsWorkspaceResolvedName = !useApplicationInsights
173
187
? logAnalyticsWorkspaceName
174
188
: '${abbrs .operationalInsightsWorkspaces }${resourceToken }'
175
189
190
+ var resolvedSearchServiceName = !useSearchService
191
+ ? ''
192
+ : !empty (searchServiceName ) ? searchServiceName : '${abbrs .searchSearchServices }${resourceToken }'
193
+
176
194
var containerRegistryResolvedName = !useContainerRegistry
177
195
? ''
178
196
: !empty (containerRegistryName ) ? containerRegistryName : '${abbrs .containerRegistryRegistries }${resourceToken }'
@@ -197,15 +215,17 @@ module ai 'core/host/ai-environment.bicep' = if (empty(aiExistingProjectConnecti
197
215
? ''
198
216
: !empty (applicationInsightsName ) ? applicationInsightsName : '${abbrs .insightsComponents }${resourceToken }'
199
217
containerRegistryName : containerRegistryResolvedName
200
- searchServiceName : !useSearch
201
- ? ''
202
- : !empty (searchServiceName ) ? searchServiceName : '${abbrs .searchSearchServices }${resourceToken }'
203
- searchConnectionName : !useSearch
218
+ searchServiceName : resolvedSearchServiceName
219
+ searchConnectionName : !useSearchService
204
220
? ''
205
221
: !empty (searchConnectionName ) ? searchConnectionName : 'search-service-connection'
206
222
}
207
223
}
208
224
225
+ var searchServiceEndpoint = !useSearchService
226
+ ? ''
227
+ : ai .outputs .searchServiceEndpoint
228
+
209
229
// If bringing an existing AI project, set up the log analytics workspace here
210
230
module logAnalytics 'core/monitor/loganalytics.bicep' = if (!empty (aiExistingProjectConnectionString )) {
211
231
name : 'logAnalytics'
@@ -222,6 +242,75 @@ var projectConnectionString = empty(hostName)
222
242
? aiExistingProjectConnectionString
223
243
: '${hostName };${subscription ().subscriptionId };${rg .name };${projectName }'
224
244
245
+ var resolvedApplicationInsightsName = !useApplicationInsights || !empty (aiExistingProjectConnectionString )
246
+ ? ''
247
+ : !empty (applicationInsightsName ) ? applicationInsightsName : '${abbrs .insightsComponents }${resourceToken }'
248
+
249
+ module monitoringMetricsContribuitorRoleAzureAIDeveloperRG 'core/security/appinsights-access.bicep' = if (!empty (resolvedApplicationInsightsName )) {
250
+ name : 'monitoringmetricscontributor-role-azureai-developer-rg'
251
+ scope : rg
252
+ params : {
253
+ appInsightsName : resolvedApplicationInsightsName
254
+ principalId : api .outputs .SERVICE_API_IDENTITY_PRINCIPAL_ID
255
+ }
256
+ }
257
+
258
+ resource existingProjectRG 'Microsoft.Resources/resourceGroups@2021-04-01' existing = if (!empty (aiExistingProjectConnectionString )) {
259
+ name : split (aiExistingProjectConnectionString , ';' )[2 ]
260
+ }
261
+
262
+ module userRoleAzureAIDeveloperBackendExistingProjectRG 'core/security/role.bicep' = if (!empty (aiExistingProjectConnectionString )) {
263
+ name : 'backend-role-azureai-developer-existing-project-rg'
264
+ scope : existingProjectRG
265
+ params : {
266
+ principalId : api .outputs .SERVICE_API_IDENTITY_PRINCIPAL_ID
267
+ roleDefinitionId : '64702f94-c441-49e6-a78b-ef80e0188fee'
268
+ }
269
+ }
270
+
271
+ //Container apps host and api
272
+ // Container apps host (including container registry)
273
+ module containerApps 'core/host/container-apps.bicep' = {
274
+ name : 'container-apps'
275
+ scope : rg
276
+ params : {
277
+ name : 'app'
278
+ location : location
279
+ tags : tags
280
+ containerAppsEnvironmentName : 'containerapps-env-${resourceToken }'
281
+ containerRegistryName : empty (aiExistingProjectConnectionString )
282
+ ? ai .outputs .containerRegistryName
283
+ : containerRegistryResolvedName
284
+ logAnalyticsWorkspaceName : empty (aiExistingProjectConnectionString )
285
+ ? ai .outputs .logAnalyticsWorkspaceName
286
+ : logAnalytics .outputs .name
287
+ }
288
+ }
289
+
290
+ // API app
291
+ module api 'api.bicep' = {
292
+ name : 'api'
293
+ scope : rg
294
+ params : {
295
+ name : 'ca-api-${resourceToken }'
296
+ location : location
297
+ tags : tags
298
+ identityName : '${abbrs .managedIdentityUserAssignedIdentities }api-${resourceToken }'
299
+ containerAppsEnvironmentName : containerApps .outputs .environmentName
300
+ containerRegistryName : containerApps .outputs .registryName
301
+ projectConnectionString : projectConnectionString
302
+ agentDeploymentName : agentDeploymentName
303
+ searchConnectionName : searchConnectionName
304
+ aiSearchIndexName : aiSearchIndexName
305
+ searchServiceEndpoint : searchServiceEndpoint
306
+ embeddingDeploymentName : embeddingDeploymentName
307
+ embeddingDeploymentDimensions : embeddingDeploymentDimensions
308
+ agentName : agentName
309
+ agentID : agentID
310
+ exists : apiAppExists
311
+ }
312
+ }
313
+
225
314
module userAcrRolePush 'core/security/role.bicep' = if (!empty (principalId )) {
226
315
name : 'user-role-acr-push'
227
316
scope : rg
@@ -267,76 +356,66 @@ module userRoleAzureAIDeveloper 'core/security/role.bicep' = if (!empty(principa
267
356
}
268
357
}
269
358
270
- module backendRoleAzureAIDeveloperRG 'core/security/role.bicep' = {
271
- name : 'backend-role-azureai-developer -rg'
359
+ module backendRoleSearchIndexDataContributorRG 'core/security/role.bicep' = if ( useSearchService ) {
360
+ name : 'backend-role-azure-index-data-contributor -rg'
272
361
scope : rg
273
362
params : {
274
363
principalId : api .outputs .SERVICE_API_IDENTITY_PRINCIPAL_ID
275
- roleDefinitionId : '64702f94-c441-49e6-a78b-ef80e0188fee '
364
+ roleDefinitionId : '8ebe5a00-799e-43f5-93ac-243d3dce84a7 '
276
365
}
277
366
}
278
367
279
- var resolvedApplicationInsightsName = !useApplicationInsights || !empty (aiExistingProjectConnectionString )
280
- ? ''
281
- : !empty (applicationInsightsName ) ? applicationInsightsName : '${abbrs .insightsComponents }${resourceToken }'
368
+ module backendRoleSearchIndexDataReaderRG 'core/security/role.bicep' = if (useSearchService ) {
369
+ name : 'backend-role-azure-index-data-reader-rg'
370
+ scope : rg
371
+ params : {
372
+ principalId : api .outputs .SERVICE_API_IDENTITY_PRINCIPAL_ID
373
+ roleDefinitionId : '1407120a-92aa-4202-b7e9-c0e197c71c8f'
374
+ }
375
+ }
282
376
283
- module monitoringMetricsContribuitorRoleAzureAIDeveloperRG 'core/security/appinsights-access .bicep' = if (! empty ( resolvedApplicationInsightsName ) ) {
284
- name : 'monitoringmetricscontributor -role-azureai-developer -rg'
377
+ module backendRoleSearchServiceContributorRG 'core/security/role .bicep' = if (useSearchService ) {
378
+ name : 'backend -role-azure-search-service-contributor -rg'
285
379
scope : rg
286
380
params : {
287
- appInsightsName : resolvedApplicationInsightsName
288
381
principalId : api .outputs .SERVICE_API_IDENTITY_PRINCIPAL_ID
382
+ roleDefinitionId : '7ca78c08-252a-4471-8644-bb5ff32d4ba0'
289
383
}
290
384
}
291
385
292
- resource existingProjectRG 'Microsoft.Resources/resourceGroups@2021-04-01' existing = if (!empty (aiExistingProjectConnectionString )) {
293
- name : split (aiExistingProjectConnectionString , ';' )[2 ]
386
+ module userRoleSearchIndexDataContributorRG 'core/security/role.bicep' = if (useSearchService && !empty (principalId )) {
387
+ name : 'user-role-azure-index-data-contributor-rg'
388
+ scope : rg
389
+ params : {
390
+ principalId : principalId
391
+ roleDefinitionId : '8ebe5a00-799e-43f5-93ac-243d3dce84a7'
392
+ }
294
393
}
295
394
296
- module userRoleAzureAIDeveloperBackendExistingProjectRG 'core/security/role.bicep' = if (!empty (aiExistingProjectConnectionString )) {
297
- name : 'backend -role-azureai-developer-existing-project -rg'
298
- scope : existingProjectRG
395
+ module userRoleSearchIndexDataReaderRG 'core/security/role.bicep' = if (useSearchService && !empty (principalId )) {
396
+ name : 'user -role-azure-index-data-reader -rg'
397
+ scope : rg
299
398
params : {
300
- principalId : api . outputs . SERVICE_API_IDENTITY_PRINCIPAL_ID
301
- roleDefinitionId : '64702f94-c441-49e6-a78b-ef80e0188fee '
399
+ principalId : principalId
400
+ roleDefinitionId : '1407120a-92aa-4202-b7e9-c0e197c71c8f '
302
401
}
303
402
}
304
403
305
- //Container apps host and api
306
- // Container apps host (including container registry)
307
- module containerApps 'core/host/container-apps.bicep' = {
308
- name : 'container-apps'
404
+ module userRoleSearchServiceContributorRG 'core/security/role.bicep' = if (useSearchService && !empty (principalId )) {
405
+ name : 'user-role-azure-search-service-contributor-rg'
309
406
scope : rg
310
407
params : {
311
- name : 'app'
312
- location : location
313
- tags : tags
314
- containerAppsEnvironmentName : 'containerapps-env-${resourceToken }'
315
- containerRegistryName : empty (aiExistingProjectConnectionString )
316
- ? ai .outputs .containerRegistryName
317
- : containerRegistryResolvedName
318
- logAnalyticsWorkspaceName : empty (aiExistingProjectConnectionString )
319
- ? ai .outputs .logAnalyticsWorkspaceName
320
- : logAnalytics .outputs .name
408
+ principalId : principalId
409
+ roleDefinitionId : '7ca78c08-252a-4471-8644-bb5ff32d4ba0'
321
410
}
322
411
}
323
412
324
- // API app
325
- module api 'api.bicep' = {
326
- name : 'api'
413
+ module backendRoleAzureAIDeveloperRG 'core/security/role.bicep' = {
414
+ name : 'backend-role-azureai-developer-rg'
327
415
scope : rg
328
416
params : {
329
- name : 'ca-api-${resourceToken }'
330
- location : location
331
- tags : tags
332
- identityName : '${abbrs .managedIdentityUserAssignedIdentities }api-${resourceToken }'
333
- containerAppsEnvironmentName : containerApps .outputs .environmentName
334
- containerRegistryName : containerApps .outputs .registryName
335
- projectConnectionString : projectConnectionString
336
- agentDeploymentName : agentDeploymentName
337
- agentName : agentName
338
- agentID : agentID
339
- exists : apiAppExists
417
+ principalId : api .outputs .SERVICE_API_IDENTITY_PRINCIPAL_ID
418
+ roleDefinitionId : '64702f94-c441-49e6-a78b-ef80e0188fee'
340
419
}
341
420
}
342
421
@@ -346,6 +425,11 @@ output AZURE_RESOURCE_GROUP string = rg.name
346
425
output AZURE_TENANT_ID string = tenant ().tenantId
347
426
output AZURE_AIPROJECT_CONNECTION_STRING string = projectConnectionString
348
427
output AZURE_AI_AGENT_DEPLOYMENT_NAME string = agentDeploymentName
428
+ output AZURE_AI_SEARCH_CONNECTION_NAME string = searchConnectionName
429
+ output AZURE_AI_EMBED_DEPLOYMENT_NAME string = embeddingDeploymentName
430
+ output AZURE_AI_SEARCH_INDEX_NAME string = aiSearchIndexName
431
+ output AZURE_AI_SEARCH_ENDPOINT string = searchServiceEndpoint
432
+ output AZURE_AI_EMBED_DIMENSIONS string = embeddingDeploymentDimensions
349
433
output AZURE_AI_AGENT_NAME string = agentName
350
434
output AZURE_AI_AGENT_ID string = agentID
351
435
0 commit comments