diff --git a/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/README.md b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/README.md new file mode 100644 index 000000000000..8c933598c2b3 --- /dev/null +++ b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/README.md @@ -0,0 +1,51 @@ +--- +description: This set of templates demonstrates how to set up Azure AI Agent Service with the standard setup and bing, meaning with managed identity authentication of each project connection and public internet access enabled. The bing project connection uses api keys for authentication. Agents use customer-owned, single-tenant search and storage resources. With this setup, you have full control and visibility over these resources, but you will incur costs based on your usage. +page_type: sample +products: +- azure +- azure-resource-manager +- azure-ai-agent-service +urlFragment: standard-agent-bing +languages: +- bicep +- json +--- +# Standard Agent Setup with Bing + +Resources for the hub, project, storage account, key vault, AI Services, and Azure AI Search will be created for you. The AI Services, AI Search, and Azure Blob Storage account will be connected to your project/hub using managed identity for authentication and a gpt-4o-mini model will be deployed in the eastus region. A bing resource will be created and connected to your hub/project using an api key for authentication. + +Optional use an existing AI Services, AI Search, Azure Blob Storage, and/or Bing resource by providing the full arm resource id in the parameters file: + +- aiServiceAccountResourceId +- aiSearchServiceResourceId +- aiStorageAccountResourceId +- bingSearchResourceID + +![Azure Public Test Date](https://azurequickstartsservice.blob.core.windows.net/badges/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/PublicLastTestDate.svg) +![Azure Public Test Result](https://azurequickstartsservice.blob.core.windows.net/badges/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/PublicDeployment.svg) + +![Azure US Gov Last Test Date](https://azurequickstartsservice.blob.core.windows.net/badges/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/FairfaxLastTestDate.svg) +![Azure US Gov Last Test Result](https://azurequickstartsservice.blob.core.windows.net/badges/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/FairfaxDeployment.svg) + +![Best Practice Check](https://azurequickstartsservice.blob.core.windows.net/badges/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/BestPracticeResult.svg) +![Cred Scan Check](https://azurequickstartsservice.blob.core.windows.net/badges/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/CredScanResult.svg) + +![Bicep Version](https://azurequickstartsservice.blob.core.windows.net/badges/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/BicepVersion.svg) + +[![Deploy To Azure](https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/1-CONTRIBUTION-GUIDE/images/deploytoazure.svg?sanitize=true)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-quickstart-templates%2Fmaster%2Fquickstarts%2Fmicrosoft.azure-ai-agent-service%2Fstandard-agent-bing%2Fazuredeploy.json) + +[![Visualize](https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/1-CONTRIBUTION-GUIDE/images/visualizebutton.svg?sanitize=true)](http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-quickstart-templates%2Fmaster%2Fquickstarts%2Fmicrosoft.azure-ai-agent-service%2Fstandard-agent-bing%2Fazuredeploy.json) + +## Resources + +| Provider and type | Description | +| - | - | +| `Microsoft.Resources/resourceGroups` | The resource group all resources get deployed into | +| `Microsoft.KeyVault/vaults` | An Azure Key Vault instance associated to the Azure Machine Learning workspace | +| `Microsoft.Storage/storageAccounts` | An Azure Storage instance associated to the Azure Machine Learning workspace | +| `Microsoft.MachineLearningServices/workspaces` | An Azure AI hub (Azure Machine Learning RP workspace of kind 'hub') | +| `Microsoft.MachineLearningServices/workspaces` | An Azure AI project (Azure Machine Learning RP workspace of kind 'project') | +| `Microsoft.CognitiveServices/accounts` | An Azure AI Services as the model-as-a-service endpoint provider (allowed kinds: 'AIServices' and 'OpenAI') | +| `Microsoft.CognitiveServices/accounts/deployments` | A gpt-4o-mini model is deployed | +| `Microsoft.Search/searchServices` | An Azure AI Search account | +| `Microsoft.Bing/accounts` | A Bing Resource | diff --git a/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/azuredeploy.parameters.json b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/azuredeploy.parameters.json new file mode 100644 index 000000000000..bb3c965db57c --- /dev/null +++ b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/azuredeploy.parameters.json @@ -0,0 +1,72 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "aiHubName": { + "value": "hub-demo" + }, + "aiHubFriendlyName": { + "value": "Agents Hub resource" + }, + "aiHubDescription": { + "value": "This is an example AI resource for use in Azure AI Studio." + }, + "aiProjectName": { + "value": "project-demo" + }, + "aiProjectFriendlyName": { + "value": "Agents Project resource" + }, + "aiProjectDescription": { + "value": "This is an example AI Project resource for use in Azure AI Studio." + }, + "tags": { + "value": {} + }, + "aiSearchName": { + "value": "agent-ai-search" + }, + "capabilityHostName": { + "value": "caphost1" + }, + "storageName": { + "value": "agent-storage" + }, + "aiServicesName": { + "value": "agent-ai-services" + }, + "modelName": { + "value": "gpt-4o-mini" + }, + "modelFormat": { + "value": "OpenAI" + }, + "modelVersion": { + "value": "2024-07-18" + }, + "modelSkuName": { + "value": "GlobalStandard" + }, + "modelCapacity": { + "value": 50 + }, + "modelLocation": { + "value": "eastus" + }, + "aiServiceAccountResourceId": { + "value": "" + }, + "aiSearchServiceResourceId": { + "value": "" + }, + "aiStorageAccountResourceId":{ + "value": "" + }, + "bingSearchResourceID" : { + "value": "" + }, + "bingName" : { + "value": "agent-bing-search" + } + } + } \ No newline at end of file diff --git a/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/main.bicep b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/main.bicep new file mode 100644 index 000000000000..01cc865f4a2c --- /dev/null +++ b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/main.bicep @@ -0,0 +1,193 @@ +// Execute this main file to deploy Standard Agent setup resources + +// Parameters +@minLength(2) +@maxLength(12) +@description('Name for the AI resource and used to derive name of dependent resources.') +param aiHubName string = 'hub-demo' + +@description('Friendly name for your Hub resource') +param aiHubFriendlyName string = 'Agents Hub resource' + +@description('Description of your Azure AI resource displayed in AI studio') +param aiHubDescription string = 'This is an example AI resource for use in Azure AI Studio.' + +@description('Name for the AI project resources.') +param aiProjectName string = 'project-demo' + +@description('Friendly name for your Azure AI resource') +param aiProjectFriendlyName string = 'Agents Project resource' + +@description('Description of your Azure AI resource displayed in AI studio') +param aiProjectDescription string = 'This is an example AI Project resource for use in Azure AI Studio.' + +@description('Azure region used for the deployment of all resources.') +param location string = resourceGroup().location + +@description('Set of tags to apply to all resources.') +param tags object = {} + +@description('Name of the Azure AI Search account') +param aiSearchName string = 'agent-ai-search' + +@description('Name for capabilityHost.') +param capabilityHostName string = 'caphost1' + +@description('Name of the storage account') +param storageName string = 'agent-storage' + +@description('Name of the Azure AI Services account') +param aiServicesName string = 'agent-ai-services' + +@description('Model name for deployment') +param modelName string = 'gpt-4o-mini' + +@description('Model format for deployment') +param modelFormat string = 'OpenAI' + +@description('Model version for deployment') +param modelVersion string = '2024-07-18' + +@description('Model deployment SKU name') +param modelSkuName string = 'GlobalStandard' + +@description('Model deployment capacity') +param modelCapacity int = 50 + +@description('Model deployment location. If you want to deploy an Azure AI resource/model in different location than the rest of the resources created.') +param modelLocation string = 'eastus' + +@description('The AI Service Account full ARM Resource ID. This is an optional field, and if not provided, the resource will be created.') +param aiServiceAccountResourceId string = '' + +@description('The AI Search Service full ARM Resource ID. This is an optional field, and if not provided, the resource will be created.') +param aiSearchServiceResourceId string = '' + +@description('The AI Storage Account full ARM Resource ID. This is an optional field, and if not provided, the resource will be created.') +param aiStorageAccountResourceId string = '' + +@description('The full ARM Bing Resource ID. This is an optional field, and if not provided, the resource will be created.') +param bingSearchResourceID string = '' + +@description('The Bing Search resource name') +param bingName string = 'agent-bing-search' + +// Variables +var name = toLower('${aiHubName}') +var projectName = toLower('${aiProjectName}') + +// Create a short, unique suffix, that will be unique to each resource group +// var uniqueSuffix = substring(uniqueString(resourceGroup().id), 0, 4) +param deploymentTimestamp string = utcNow('yyyyMMddHHmmss') +var uniqueSuffix = substring(uniqueString('${resourceGroup().id}-${deploymentTimestamp}'), 0, 4) + +var aiServiceExists = aiServiceAccountResourceId != '' +var acsExists = aiSearchServiceResourceId != '' + +var aiServiceParts = split(aiServiceAccountResourceId, '/') +var aiServiceAccountSubscriptionId = aiServiceExists ? aiServiceParts[2] : subscription().subscriptionId +var aiServiceAccountResourceGroupName = aiServiceExists ? aiServiceParts[4] : resourceGroup().name + +var acsParts = split(aiSearchServiceResourceId, '/') +var aiSearchServiceSubscriptionId = acsExists ? acsParts[2] : subscription().subscriptionId +var aiSearchServiceResourceGroupName = acsExists ? acsParts[4] : resourceGroup().name + +// Dependent resources for the Azure Machine Learning workspace +module aiDependencies 'modules-standard-bing/standard-dependent-resources-bing.bicep' = { + name: 'dependencies-${name}-${uniqueSuffix}-deployment' + params: { + location: location + storageName: '${storageName}${uniqueSuffix}' + keyvaultName: 'kv-${name}-${uniqueSuffix}' + aiServicesName: '${aiServicesName}${uniqueSuffix}' + aiSearchName: '${aiSearchName}-${uniqueSuffix}' + bingName: '${bingName}-${uniqueSuffix}' + tags: tags + + // Model deployment parameters + modelName: modelName + modelFormat: modelFormat + modelVersion: modelVersion + modelSkuName: modelSkuName + modelCapacity: modelCapacity + modelLocation: modelLocation + + aiServiceAccountResourceId: aiServiceAccountResourceId + aiSearchServiceResourceId: aiSearchServiceResourceId + aiStorageAccountResourceId: aiStorageAccountResourceId + bingSearchResourceID: bingSearchResourceID + } +} + +module aiHub 'modules-standard-bing/standard-ai-hub-bing.bicep' = { + name: '${name}-${uniqueSuffix}-deployment' + params: { + // workspace organization + aiHubName: '${name}-${uniqueSuffix}' + aiHubFriendlyName: aiHubFriendlyName + aiHubDescription: aiHubDescription + location: location + tags: tags + capabilityHostName: '${name}-${uniqueSuffix}-${capabilityHostName}' + + aiSearchName: aiDependencies.outputs.aiSearchName + aiSearchId: aiDependencies.outputs.aisearchID + aiSearchServiceResourceGroupName: aiDependencies.outputs.aiSearchServiceResourceGroupName + aiSearchServiceSubscriptionId: aiDependencies.outputs.aiSearchServiceSubscriptionId + + aiServicesName: aiDependencies.outputs.aiServicesName + aiServicesId: aiDependencies.outputs.aiservicesID + aiServicesTarget: aiDependencies.outputs.aiservicesTarget + aiServiceAccountResourceGroupName:aiDependencies.outputs.aiServiceAccountResourceGroupName + aiServiceAccountSubscriptionId:aiDependencies.outputs.aiServiceAccountSubscriptionId + + bingName: aiDependencies.outputs.bingName + bingId: aiDependencies.outputs.bingId + bingResourceGroupName: aiDependencies.outputs.bingResourceGroupName + bingSubscriptionId: aiDependencies.outputs.bingSubscriptionId + + keyVaultId: aiDependencies.outputs.keyvaultId + storageAccountId: aiDependencies.outputs.storageId + } +} + +module aiProject 'modules-standard-bing/standard-ai-project-bing.bicep' = { + name: '${projectName}-${uniqueSuffix}-deployment' + params: { + // workspace organization + aiProjectName: '${projectName}-${uniqueSuffix}' + aiProjectFriendlyName: aiProjectFriendlyName + aiProjectDescription: aiProjectDescription + location: location + tags: tags + + // dependent resources + capabilityHostName: '${projectName}-${uniqueSuffix}-${capabilityHostName}' + + aiHubId: aiHub.outputs.aiHubID + acsConnectionName: aiHub.outputs.acsConnectionName + aoaiConnectionName: aiHub.outputs.aoaiConnectionName + } +} + +module aiServiceRoleAssignments 'modules-standard-bing/ai-service-role-assignments-bing.bicep' = { + name: 'ai-service-role-assignments-${projectName}-${uniqueSuffix}-deployment' + scope: resourceGroup(aiServiceAccountSubscriptionId, aiServiceAccountResourceGroupName) + params: { + aiServicesName: aiDependencies.outputs.aiServicesName + aiProjectPrincipalId: aiProject.outputs.aiProjectPrincipalId + aiProjectId: aiProject.outputs.aiProjectResourceId + } +} + +module aiSearchRoleAssignments 'modules-standard-bing/ai-search-role-assignments-bing.bicep' = { + name: 'ai-search-role-assignments-${projectName}-${uniqueSuffix}-deployment' + scope: resourceGroup(aiSearchServiceSubscriptionId, aiSearchServiceResourceGroupName) + params: { + aiSearchName: aiDependencies.outputs.aiSearchName + aiProjectPrincipalId: aiProject.outputs.aiProjectPrincipalId + aiProjectId: aiProject.outputs.aiProjectResourceId + } +} + +output PROJECT_CONNECTION_STRING string = aiProject.outputs.projectConnectionString diff --git a/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/metadata.json b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/metadata.json new file mode 100644 index 000000000000..adc1bc143512 --- /dev/null +++ b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/metadata.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://aka.ms/azure-quickstart-templates-metadata-schema#", + "type": "QuickStart", + "itemDisplayName": "Standard Agent Setup with Bing", + "description": "This set of templates demonstrates how to set up Azure AI Agent Service with the standard setup and bing, meaning with managed identity authentication and public internet access enabled. Agents use customer-owned, single-tenant search and storage resources. With this setup, you have full control and visibility over these resources, but you will incur costs based on your usage.", + "summary": "This set of templates demonstrates how to use Azure AI Agent Service with the standard setup and bing.", + "githubUsername": "fosteramanda", + "dateUpdated": "2024-12-06", + "environments": [ + "AzureCloud" + ] + } \ No newline at end of file diff --git a/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/modules-standard-bing/ai-search-role-assignments-bing.bicep b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/modules-standard-bing/ai-search-role-assignments-bing.bicep new file mode 100644 index 000000000000..eb8e8b5e70ac --- /dev/null +++ b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/modules-standard-bing/ai-search-role-assignments-bing.bicep @@ -0,0 +1,46 @@ +// Assigns the necessary roles to the AI project + +@description('Name of the AI Search resource') +param aiSearchName string + +@description('Principal ID of the AI project') +param aiProjectPrincipalId string + +@description('Resource ID of the AI project') +param aiProjectId string + +resource searchService 'Microsoft.Search/searchServices@2024-06-01-preview' existing = { + name: aiSearchName + scope: resourceGroup() +} + +// search roles +resource searchIndexDataContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '8ebe5a00-799e-43f5-93ac-243d3dce84a7' + scope: resourceGroup() +} + +resource searchIndexDataContributorAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: searchService + name: guid(aiProjectId, searchIndexDataContributorRole.id, searchService.id) + properties: { + principalId: aiProjectPrincipalId + roleDefinitionId: searchIndexDataContributorRole.id + principalType: 'ServicePrincipal' + } +} + +resource searchServiceContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '7ca78c08-252a-4471-8644-bb5ff32d4ba0' + scope: resourceGroup() +} + +resource searchServiceContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: searchService + name: guid(aiProjectId, searchServiceContributorRole.id, searchService.id) + properties: { + principalId: aiProjectPrincipalId + roleDefinitionId: searchServiceContributorRole.id + principalType: 'ServicePrincipal' + } +} diff --git a/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/modules-standard-bing/ai-service-role-assignments-bing.bicep b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/modules-standard-bing/ai-service-role-assignments-bing.bicep new file mode 100644 index 000000000000..f22ad548aeec --- /dev/null +++ b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/modules-standard-bing/ai-service-role-assignments-bing.bicep @@ -0,0 +1,56 @@ +// Assigns the necessary roles to the AI project + +param aiServicesName string +param aiProjectPrincipalId string +param aiProjectId string + +resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' existing = { + name: aiServicesName + scope: resourceGroup() +} + +resource cognitiveServicesContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + scope: resourceGroup() + +} + +resource cognitiveServicesContributorAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01'= { + scope: aiServices + name: guid(aiServices.id, cognitiveServicesContributorRole.id, aiProjectId) + properties: { + principalId: aiProjectPrincipalId + roleDefinitionId: cognitiveServicesContributorRole.id + principalType: 'ServicePrincipal' + } +} + + +resource cognitiveServicesOpenAIUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' + scope: resourceGroup() +} +resource cognitiveServicesOpenAIUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: aiServices + name: guid(aiProjectId, cognitiveServicesOpenAIUserRole.id, aiServices.id) + properties: { + principalId: aiProjectPrincipalId + roleDefinitionId: cognitiveServicesOpenAIUserRole.id + principalType: 'ServicePrincipal' + } +} + +resource cognitiveServicesUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: 'a97b65f3-24c7-4388-baec-2e87135dc908' + scope: resourceGroup() +} + +resource cognitiveServicesUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: aiServices + name: guid(aiProjectId, cognitiveServicesUserRole.id, aiServices.id) + properties: { + principalId: aiProjectPrincipalId + roleDefinitionId: cognitiveServicesUserRole.id + principalType: 'ServicePrincipal' + } +} diff --git a/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/modules-standard-bing/standard-ai-hub-bing.bicep b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/modules-standard-bing/standard-ai-hub-bing.bicep new file mode 100644 index 000000000000..b1f4bb60d2cc --- /dev/null +++ b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/modules-standard-bing/standard-ai-hub-bing.bicep @@ -0,0 +1,153 @@ +// Creates an Azure AI resource with proxied endpoints for the Azure AI services provider + +@description('Azure region of the deployment') +param location string + +@description('Tags to add to the resources') +param tags object + +@description('AI hub name') +param aiHubName string + +@description('AI hub display name') +param aiHubFriendlyName string = aiHubName + +@description('AI hub description') +param aiHubDescription string + +@description('Resource ID of the key vault resource for storing connection strings') +param keyVaultId string + +@description('Resource ID of the storage account resource for storing experimentation outputs') +param storageAccountId string + +@description('Resource ID of the AI Services resource') +param aiServicesId string +@description('Resource ID of the AI Services endpoint') +param aiServicesTarget string +@description('Name AI Services resource') +param aiServicesName string +@description('Resource Group name of the AI Services resource') +param aiServiceAccountResourceGroupName string +@description('Subscription ID of the AI Services resource') +param aiServiceAccountSubscriptionId string + +@description('Name AI Search resource') +param aiSearchName string +@description('Resource ID of the AI Search resource') +param aiSearchId string +param aiSearchServiceResourceGroupName string +param aiSearchServiceSubscriptionId string + +param bingName string +param bingId string +param bingResourceGroupName string +param bingSubscriptionId string + + +@description('Name for capabilityHost.') +param capabilityHostName string = 'caphost1' + +var acsConnectionName = '${aiHubName}-connection-AISearch' + +var bingConnectionName = '${aiHubName}-connection-Bing' + +var aoaiConnection = '${aiHubName}-connection-AIServices_aoai' + + +resource aiServices 'Microsoft.CognitiveServices/accounts@2023-05-01' existing = { + name: aiServicesName + scope: resourceGroup(aiServiceAccountSubscriptionId, aiServiceAccountResourceGroupName) +} + +resource searchService 'Microsoft.Search/searchServices@2023-11-01' existing = { + name: aiSearchName + scope: resourceGroup(aiSearchServiceSubscriptionId, aiSearchServiceResourceGroupName) +} + +#disable-next-line BCP081 +resource bingSearch 'Microsoft.Bing/accounts@2020-06-10' existing = { + name: bingName + scope: resourceGroup(bingSubscriptionId, bingResourceGroupName) +} + +resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' = { + name: aiHubName + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + // organization + friendlyName: aiHubFriendlyName + description: aiHubDescription + + // dependent resources + keyVault: keyVaultId + storageAccount: storageAccountId + } + kind: 'hub' + + resource aiServicesConnection 'connections@2024-07-01-preview' = { + name: '${aiHubName}-connection-AIServices' + properties: { + category: 'AIServices' + target: aiServicesTarget + authType: 'AAD' + isSharedToAll: true + metadata: { + ApiType: 'Azure' + ResourceId: aiServicesId + location: aiServices.location + } + } + } + resource hub_connection_azureai_search 'connections@2024-07-01-preview' = { + name: acsConnectionName + properties: { + category: 'CognitiveSearch' + target: 'https://${aiSearchName}.search.windows.net' + authType: 'AAD' + //useWorkspaceManagedIdentity: false + isSharedToAll: true + metadata: { + ApiType: 'Azure' + ResourceId: aiSearchId + location: searchService.location + } + } + } + + resource hub_connection_bing 'connections@2024-07-01-preview' = { + name: bingConnectionName + properties: { + category: 'ApiKey' + target: 'https://api.bing.microsoft.com/' + authType: 'ApiKey' + isSharedToAll: true + credentials: { + key: '${listKeys(bingId, '2020-06-10').key1}' + } + metadata: { + ApiType: 'Azure' + ResourceId: bingId + location: bingSearch.location + } + } + } + + // Resource definition for the capability host + #disable-next-line BCP081 + resource capabilityHost 'capabilityHosts@2024-10-01-preview' = { + name: '${aiHubName}-${capabilityHostName}' + properties: { + capabilityHostKind: 'Agents' + } + } + +} + +output aiHubID string = aiHub.id +output aoaiConnectionName string = aoaiConnection +output acsConnectionName string = acsConnectionName diff --git a/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/modules-standard-bing/standard-ai-project-bing.bicep b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/modules-standard-bing/standard-ai-project-bing.bicep new file mode 100644 index 000000000000..c2b579dfc26f --- /dev/null +++ b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/modules-standard-bing/standard-ai-project-bing.bicep @@ -0,0 +1,79 @@ +// Creates an Azure AI resource with proxied endpoints for the Azure AI services provider + +@description('Azure region of the deployment') +param location string + +@description('Tags to add to the resources') +param tags object + +@description('AI Project name') +param aiProjectName string + +@description('AI Project display name') +param aiProjectFriendlyName string = aiProjectName + +@description('AI Project description') +param aiProjectDescription string + +@description('Resource ID of the AI Hub resource') +param aiHubId string + +@description('Name for capabilityHost.') +param capabilityHostName string = 'caphost1' + +@description('Name for ACS connection.') +param acsConnectionName string + +@description('Name for ACS connection.') +param aoaiConnectionName string + +//for constructing endpoint +var subscriptionId = subscription().subscriptionId +var resourceGroupName = resourceGroup().name + +var projectConnectionString = '${location}.api.azureml.ms;${subscriptionId};${resourceGroupName};${aiProjectName}' + + +var storageConnections = ['${aiProjectName}/workspaceblobstore'] +var aiSearchConnection = ['${acsConnectionName}'] +var aiServiceConnections = ['${aoaiConnectionName}'] + + +resource aiProject 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = { + name: aiProjectName + location: location + tags: union(tags, { + ProjectConnectionString: projectConnectionString + }) + identity: { + type: 'SystemAssigned' + } + properties: { + // organization + friendlyName: aiProjectFriendlyName + description: aiProjectDescription + + // dependent resources + hubResourceId: aiHubId + + } + kind: 'project' + + // Resource definition for the capability host + #disable-next-line BCP081 + resource capabilityHost 'capabilityHosts@2024-10-01-preview' = { + name: '${aiProjectName}-${capabilityHostName}' + properties: { + capabilityHostKind: 'Agents' + aiServicesConnections: aiServiceConnections + vectorStoreConnections: aiSearchConnection + storageConnections: storageConnections + } + } +} + +output aiProjectName string = aiProject.name +output aiProjectResourceId string = aiProject.id +output aiProjectPrincipalId string = aiProject.identity.principalId +output aiProjectWorkspaceId string = aiProject.properties.workspaceId +output projectConnectionString string = aiProject.tags.ProjectConnectionString diff --git a/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/modules-standard-bing/standard-dependent-resources-bing.bicep b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/modules-standard-bing/standard-dependent-resources-bing.bicep new file mode 100644 index 000000000000..db656e70f3fe --- /dev/null +++ b/quickstarts/microsoft.azure-ai-agent-service/standard-agent-bing/modules-standard-bing/standard-dependent-resources-bing.bicep @@ -0,0 +1,224 @@ +// Creates Azure dependent resources for the Azure AI Agent setup + +@description('Azure region of the deployment') +param location string = resourceGroup().location + +@description('Tags to add to the resources') +param tags object = {} + +@description('AI services name') +param aiServicesName string + +@description('The name of the Key Vault') +param keyvaultName string + +@description('The name of the AI Search resource') +param aiSearchName string + +@description('Name of the storage account') +param storageName string + +var storageNameCleaned = replace(storageName, '-', '') + +@description('Model name for deployment') +param modelName string + +@description('Model format for deployment') +param modelFormat string + +@description('Model version for deployment') +param modelVersion string + +@description('Model deployment SKU name') +param modelSkuName string + +@description('Model deployment capacity') +param modelCapacity int + +@description('Model/AI Resource deployment location') +param modelLocation string + +@description('The AI Service Account full ARM Resource ID. This is an optional field, and if not provided, the resource will be created.') +param aiServiceAccountResourceId string + +@description('The AI Search Service full ARM Resource ID. This is an optional field, and if not provided, the resource will be created.') +param aiSearchServiceResourceId string + +@description('The AI Storage Account full ARM Resource ID. This is an optional field, and if not provided, the resource will be created.') +param aiStorageAccountResourceId string + +@description('The full ARM Bing Resource ID. This is an optional field, and if not provided, the resource will be created.') +param bingSearchResourceID string + +@description('The Bing Search resource name') +param bingName string = 'agent-bing-search' + +var aiServiceExists = aiServiceAccountResourceId != '' +var acsExists = aiSearchServiceResourceId != '' +var aiStorageExists = aiStorageAccountResourceId != '' +var bingExists = bingSearchResourceID != '' + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyvaultName + location: location + tags: tags + properties: { + createMode: 'default' + enabledForDeployment: false + enabledForDiskEncryption: false + enabledForTemplateDeployment: false + enableSoftDelete: true + enableRbacAuthorization: true + enablePurgeProtection: true + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' + } + sku: { + family: 'A' + name: 'standard' + } + softDeleteRetentionInDays: 7 + tenantId: subscription().tenantId + } +} + +var bingParts = split(bingSearchResourceID, '/') +#disable-next-line BCP081 +resource existingBingResource 'Microsoft.Bing/accounts@2020-06-10' existing = if (bingExists) { + name: bingParts[8] + scope: resourceGroup(bingParts[2], bingParts[4]) +} + +#disable-next-line BCP081 +resource bingSearch 'Microsoft.Bing/accounts@2020-06-10' = if (!bingExists) { + name: bingName + location: 'global' + sku: { + name: 'G1' + } + kind: 'Bing.Search.v7' +} + +var aiServiceParts = split(aiServiceAccountResourceId, '/') + +resource existingAIServiceAccount 'Microsoft.CognitiveServices/accounts@2023-05-01' existing = if (aiServiceExists) { + name: aiServiceParts[8] + scope: resourceGroup(aiServiceParts[2], aiServiceParts[4]) +} + +resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = if(!aiServiceExists) { + name: aiServicesName + location: modelLocation + sku: { + name: 'S0' + } + kind: 'AIServices' // or 'OpenAI' + identity: { + type: 'SystemAssigned' + } + properties: { + customSubDomainName: toLower('${(aiServicesName)}') + apiProperties: { + statisticsEnabled: false + } + publicNetworkAccess: 'Enabled' + } +} +resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-06-01-preview'= if(!aiServiceExists){ + parent: aiServices + name: modelName + sku : { + capacity: modelCapacity + name: modelSkuName + } + properties: { + model:{ + name: modelName + format: modelFormat + version: modelVersion + } + } +} + +var acsParts = split(aiSearchServiceResourceId, '/') + +resource existingSearchService 'Microsoft.Search/searchServices@2023-11-01' existing = if (acsExists) { + name: acsParts[8] + scope: resourceGroup(acsParts[2], acsParts[4]) +} +resource aiSearch 'Microsoft.Search/searchServices@2024-06-01-preview' = if(!acsExists) { + name: aiSearchName + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + disableLocalAuth: false + authOptions: { aadOrApiKey: { aadAuthFailureMode: 'http401WithBearerChallenge'}} + encryptionWithCmk: { + enforcement: 'Unspecified' + } + hostingMode: 'default' + partitionCount: 1 + publicNetworkAccess: 'enabled' + replicaCount: 1 + semanticSearch: 'disabled' + } + sku: { + name: 'standard' + } +} + +var aiStorageParts = split(aiStorageAccountResourceId, '/') + +resource existingAIStorageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' existing = if (aiStorageExists) { + name: aiStorageParts[8] + scope: resourceGroup(aiStorageParts[2], aiStorageParts[4]) +} + +// Some regions doesn't support Standard Zone-Redundant storage, need to use Geo-redundant storage +param noZRSRegions array = ['southindia', 'westus'] +param sku object = contains(noZRSRegions, location) ? { name: 'Standard_GRS' } : { name: 'Standard_ZRS' } + +resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' = if(!aiStorageExists) { + name: storageNameCleaned + location: location + kind: 'StorageV2' + sku: sku + properties: { + minimumTlsVersion: 'TLS1_2' + allowBlobPublicAccess: false + publicNetworkAccess: 'Enabled' + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Allow' + virtualNetworkRules: [] + } + allowSharedKeyAccess: false + } +} + +output aiServicesName string = aiServiceExists ? existingAIServiceAccount.name : aiServicesName +output aiservicesID string = aiServiceExists ? existingAIServiceAccount.id : aiServices.id +output aiservicesTarget string = aiServiceExists ? existingAIServiceAccount.properties.endpoint : aiServices.properties.endpoint +output aiServiceAccountResourceGroupName string = aiServiceExists ? aiServiceParts[4] : resourceGroup().name +output aiServiceAccountSubscriptionId string = aiServiceExists ? aiServiceParts[2] : subscription().subscriptionId + +output aiSearchName string = acsExists ? existingSearchService.name : aiSearch.name +output aisearchID string = acsExists ? existingSearchService.id : aiSearch.id +output aiSearchServiceResourceGroupName string = acsExists ? acsParts[4] : resourceGroup().name +output aiSearchServiceSubscriptionId string = acsExists ? acsParts[2] : subscription().subscriptionId + +output storageAccountName string = aiStorageExists ? existingAIStorageAccount.name : storage.name +output storageId string = aiStorageExists ? existingAIStorageAccount.id : storage.id +output storageAccountResourceGroupName string = aiStorageExists ? aiStorageParts[4] : resourceGroup().name +output storageAccountSubscriptionId string = aiStorageExists ? aiStorageParts[2] : subscription().subscriptionId + +output bingName string = bingExists ? existingBingResource.name : bingSearch.name +output bingId string = bingExists ? existingBingResource.id : bingSearch.id +output bingResourceGroupName string = bingExists ? bingParts[4] : resourceGroup().name +output bingSubscriptionId string = bingExists ? bingParts[2] : subscription().subscriptionId + +output keyvaultId string = keyVault.id