From ac5ca77d56f906217dd5e716be5653a35330a94d Mon Sep 17 00:00:00 2001 From: Shreyas-Microsoft Date: Fri, 13 Jun 2025 13:00:10 +0530 Subject: [PATCH 01/11] initial commit & update sk version --- src/backend/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/requirements.txt b/src/backend/requirements.txt index 6234a5b..9dbaff8 100644 --- a/src/backend/requirements.txt +++ b/src/backend/requirements.txt @@ -35,8 +35,8 @@ structlog typing-extensions python-jose[cryptography] passlib[bcrypt] -semantic-kernel[azure]==1.27.2 -openai +semantic-kernel[azure]==1.32.2 +openai==1.84.0 sqlparse sqlglot unittest2 From 8ec88b6a18a56719ca46d0eb131cb199b9aeae0c Mon Sep 17 00:00:00 2001 From: Shreyas-Microsoft Date: Fri, 13 Jun 2025 13:20:31 +0530 Subject: [PATCH 02/11] bicep changes --- infra/deploy_ai_foundry.bicep | 162 +++++++++++++++++++++++----------- src/backend/requirements.txt | 2 +- 2 files changed, 112 insertions(+), 52 deletions(-) diff --git a/infra/deploy_ai_foundry.bicep b/infra/deploy_ai_foundry.bicep index 604966b..b9f365f 100644 --- a/infra/deploy_ai_foundry.bicep +++ b/infra/deploy_ai_foundry.bicep @@ -22,22 +22,16 @@ var existingLawName = useExisting ? split(existingLogAnalyticsWorkspaceId, '/')[ 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' - - resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = { name: keyVaultName } @@ -73,9 +67,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 @@ -128,6 +119,30 @@ resource storage 'Microsoft.Storage/storageAccounts@2022-09-01' = { } } +// Create AI Services resource (pavan approach) +resource aiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = { + name: aiServicesName + location: location + sku: { + name: 'S0' + } + kind: 'AIServices' + identity: { + type: 'SystemAssigned' + } + properties: { + allowProjectManagement: true + customSubDomainName: aiServicesName + networkAcls: { + defaultAction: 'Allow' + virtualNetworkRules: [] + ipRules: [] + } + publicNetworkAccess: 'Enabled' + disableLocalAuth: false //needs to be false to access keys + } +} + @description('This is the built-in Storage Blob Data Contributor.') resource blobDataContributor 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' existing = { scope: subscription() @@ -144,51 +159,93 @@ resource storageroleAssignment 'Microsoft.Authorization/roleAssignments@2022-04- } } -resource aiHub 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = { - name: azureAiHubName - location: location - identity: { - type: 'SystemAssigned' +resource storageroleAiServiceAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(resourceGroup().id, aiServices.id, blobDataContributor.id) + scope: storage + properties: { + principalId: aiServices.identity.principalId + roleDefinitionId: blobDataContributor.id + principalType: 'ServicePrincipal' + } +} + +resource cognitiveServicesUserRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + scope: aiServices + name: 'a97b65f3-24c7-4388-baec-2e87135dc908' +} + +resource cognitiveServicesUserAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(resourceGroup().id, managedIdentityObjectId, cognitiveServicesUserRoleDefinition.id) + scope: aiServices + properties: { + principalId: managedIdentityObjectId + roleDefinitionId: cognitiveServicesUserRoleDefinition.id + principalType: 'ServicePrincipal' } +} + +resource cognitiveServicesUserAiServiceAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(resourceGroup().id, aiServices.id, cognitiveServicesUserRoleDefinition.id) + scope: aiServices 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 - } - } + principalId: aiServices.identity.principalId + roleDefinitionId: cognitiveServicesUserRoleDefinition.id + principalType: 'ServicePrincipal' + } +} + +resource aiDeveloperRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + scope: aiServices + name: '64702f94-c441-49e6-a78b-ef80e0188fee' +} + +resource aiDeveloperAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(resourceGroup().id, managedIdentityObjectId, aiDeveloperRoleDefinition.id) + scope: aiServices + properties: { + principalId: managedIdentityObjectId + roleDefinitionId: aiDeveloperRoleDefinition.id + principalType: 'ServicePrincipal' } } -resource aiHubProject 'Microsoft.MachineLearningServices/workspaces@2024-01-01-preview' = { +resource aiDeveloperAiServiceAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(resourceGroup().id, aiServices.id, aiDeveloperRoleDefinition.id) + scope: aiServices + properties: { + principalId: aiServices.identity.principalId + roleDefinitionId: aiDeveloperRoleDefinition.id + principalType: 'ServicePrincipal' + } +} + +// Create AI Project (pavan approach) +resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' = { + parent: aiServices name: aiProjectName - location: location - kind: 'Project' + location: solutionLocation + kind: 'AIServices' identity: { type: 'SystemAssigned' } + properties: {} +} + +// Create project-level storage connection +resource project_connection_azure_storage 'Microsoft.CognitiveServices/accounts/projects/connections@2025-04-01-preview' = { + name: 'myStorageProjectConnectionName' + parent: aiProject properties: { - friendlyName: aiProjectFriendlyName - hubResourceId: aiHub.id + category: 'AzureBlob' + target: storage.properties.primaryEndpoints.blob + authType: 'AAD' + metadata: { + ApiType: 'Azure' + ResourceId: storage.id + location: storage.location + containerName: 'ai-container' + accountName: storage.name + } } } @@ -220,7 +277,7 @@ resource azureOpenAIApiKeyEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-pr parent: keyVault name: 'AZURE-OPENAI-KEY' properties: { - value: aiServicesKey //aiServices_m.listKeys().key1 + value: aiServices.listKeys().key1 } } @@ -244,7 +301,7 @@ resource azureOpenAIEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01- parent: keyVault name: 'AZURE-OPENAI-ENDPOINT' properties: { - value: aiServicesEndpoint//aiServices_m.properties.endpoint + value: aiServices.properties.endpoints['OpenAI Language Model Instance API'] } } @@ -252,7 +309,7 @@ resource azureAIProjectConnectionStringEntry 'Microsoft.KeyVault/vaults/secrets@ parent: keyVault name: 'AZURE-AI-PROJECT-CONN-STRING' properties: { - value: '${split(aiHubProject.properties.discoveryUrl, '/')[2]};${subscription().subscriptionId};${resourceGroup().name};${aiHubProject.name}' + value: '${aiProjectName};${subscription().subscriptionId};${resourceGroup().name};${aiProject.name}' } } @@ -276,7 +333,7 @@ resource cogServiceEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-p parent: keyVault name: 'COG-SERVICES-ENDPOINT' properties: { - value: aiServicesEndpoint + value: aiServices.properties.endpoints['OpenAI Language Model Instance API'] } } @@ -284,7 +341,7 @@ resource cogServiceKeyEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-previe parent: keyVault name: 'COG-SERVICES-KEY' properties: { - value: aiServicesKey + value: aiServices.listKeys().key1 } } @@ -324,8 +381,10 @@ output keyvaultName string = keyvaultName output keyvaultId string = keyVault.id output aiServicesName string = aiServicesName +output aiServicesTarget string = aiServices.properties.endpoints['OpenAI Language Model Instance API'] +output aiServicesId string = aiServices.id output aiSearchName string = aiSearchName -output aiProjectName string = aiHubProject.name +output aiProjectName string = aiProject.name output storageAccountName string = storageNameCleaned @@ -333,4 +392,5 @@ output logAnalyticsId string = useExisting ? existingLogAnalyticsWorkspace.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}' +output projectConnectionString string = '${aiProjectName};${subscription().subscriptionId};${resourceGroup().name};${aiProject.name}' +output projectEndpoint string = aiProject.properties.endpoints['AI Foundry API'] \ No newline at end of file diff --git a/src/backend/requirements.txt b/src/backend/requirements.txt index 9dbaff8..e16631b 100644 --- a/src/backend/requirements.txt +++ b/src/backend/requirements.txt @@ -52,4 +52,4 @@ opentelemetry-api==1.31.1 opentelemetry-semantic-conventions==0.52b1 opentelemetry-instrumentation==0.52b1 azure-monitor-opentelemetry==1.6.8 -azure-ai-projects==1.0.0b9 +azure-ai-projects==1.0.0b11 From a7d1e12991f06d9fb1b0c5c988388114e5c78ab5 Mon Sep 17 00:00:00 2001 From: Shreyas-Microsoft Date: Fri, 13 Jun 2025 21:13:53 +0530 Subject: [PATCH 03/11] fdp code level changes- hardcoded endpoint --- src/backend/common/config/config.py | 2 ++ src/backend/sql_agents/agents/agent_base.py | 30 ++++++++++++--------- src/backend/sql_agents/process_batch.py | 5 ++-- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/backend/common/config/config.py b/src/backend/common/config/config.py index 24eb2fe..47e4476 100644 --- a/src/backend/common/config/config.py +++ b/src/backend/common/config/config.py @@ -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") @@ -62,3 +63,4 @@ def get_azure_credentials(self): app_config = Config() +print(f"[DEBUG] AI_PROJECT_ENDPOINT: '{os.getenv('AI_PROJECT_ENDPOINT')}'") \ No newline at end of file diff --git a/src/backend/sql_agents/agents/agent_base.py b/src/backend/sql_agents/agents/agent_base.py index 34bb9e8..6d4fca3 100644 --- a/src/backend/sql_agents/agents/agent_base.py +++ b/src/backend/sql_agents/agents/agent_base.py @@ -3,11 +3,10 @@ import logging from abc import ABC, abstractmethod from typing import Any, Generic, List, Optional, TypeVar, Union +import json -from azure.ai.projects.models import ( - ResponseFormatJsonSchema, - ResponseFormatJsonSchemaType, -) +# Removed broken import: +# from azure.ai.projects.models import ResponseFormatJsonSchema, ResponseFormatJsonSchemaType from semantic_kernel.agents.azure_ai.azure_ai_agent import AzureAIAgent from semantic_kernel.functions import KernelArguments @@ -107,23 +106,30 @@ async def setup(self) -> AzureAIAgent: kernel_args = self.get_kernel_arguments() + # Define an agent on the Azure AI agent service + # Construct response_format manually + response_format = None + if self.response_object: + response_format = { + "type": "json_schema", + "json_schema": { + "name": self.response_object.__name__, + "description": f"respond with {self.response_object.__name__.lower()}", + "schema": self.response_object.model_json_schema() + } + } + try: - # Define an agent on the Azure AI agent service agent_definition = await self.config.ai_project_client.agents.create_agent( model=_deployment_name, name=_name, instructions=template_content, temperature=self.temperature, - response_format=ResponseFormatJsonSchemaType( - json_schema=ResponseFormatJsonSchema( - name=self.response_object.__name__, - description=f"respond with {self.response_object.__name__.lower()}", - schema=self.response_object.model_json_schema(), - ) - ), + response_format=response_format, ) except Exception as exc: logger.error("Error creating agent definition: %s", exc) + raise # Set the agent definition with the response format # Create a Semantic Kernel agent based on the agent definition diff --git a/src/backend/sql_agents/process_batch.py b/src/backend/sql_agents/process_batch.py index b7b8401..44c29d6 100644 --- a/src/backend/sql_agents/process_batch.py +++ b/src/backend/sql_agents/process_batch.py @@ -24,7 +24,7 @@ from fastapi import HTTPException -from semantic_kernel.agents.azure_ai.azure_ai_agent import AzureAIAgent # pylint: disable=E0611 +from semantic_kernel.agents.azure_ai.azure_ai_agent import AzureAIAgent, AzureAIAgentSettings # pylint: disable=E0611 from semantic_kernel.contents import AuthorRole from semantic_kernel.exceptions.service_exceptions import ServiceResponseException @@ -57,10 +57,11 @@ async def process_batch_async( except Exception as exc: logger.error("Error updating batch status. %s", exc) + ai_agent_settings = AzureAIAgentSettings() # Add client and auto cleanup async with ( DefaultAzureCredential() as creds, - AzureAIAgent.create_client(credential=creds) as client, + AzureAIAgent.create_client(credential=creds, endpoint="https://fdp-rg-psl-codmod-main-resource.services.ai.azure.com/api/projects/fdp-rg-psl-codmod-main") as client, ): # setup all agent settings and agents per batch From c8da88d5d03477702824cbd50f3bda18049b06a4 Mon Sep 17 00:00:00 2001 From: Shreyas-Microsoft Date: Mon, 16 Jun 2025 16:02:15 +0530 Subject: [PATCH 04/11] Remove hardcoded ai endpoint value --- src/backend/sql_agents/process_batch.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/backend/sql_agents/process_batch.py b/src/backend/sql_agents/process_batch.py index 44c29d6..9e7eb9d 100644 --- a/src/backend/sql_agents/process_batch.py +++ b/src/backend/sql_agents/process_batch.py @@ -20,7 +20,7 @@ ) from common.services.batch_service import BatchService from common.storage.blob_factory import BlobStorageFactory - +from common.config.config import app_config from fastapi import HTTPException @@ -37,7 +37,6 @@ logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) - # Walk through batch structure processing each file async def process_batch_async( batch_id: str, convert_from: str = "informix", convert_to: str = "tsql" @@ -61,7 +60,7 @@ async def process_batch_async( # Add client and auto cleanup async with ( DefaultAzureCredential() as creds, - AzureAIAgent.create_client(credential=creds, endpoint="https://fdp-rg-psl-codmod-main-resource.services.ai.azure.com/api/projects/fdp-rg-psl-codmod-main") as client, + AzureAIAgent.create_client(credential=creds, endpoint=app_config.ai_project_endpoint) as client, ): # setup all agent settings and agents per batch From f2e135104e4479e4267f3e82113e8e0fd481d2ec Mon Sep 17 00:00:00 2001 From: Shreyas-Microsoft Date: Mon, 16 Jun 2025 18:07:54 +0530 Subject: [PATCH 05/11] prashnat changes --- infra/abbreviations.json | 2 + infra/deploy_ai_foundry.bicep | 380 ++++++++++++++++------------------ infra/main.bicep | 4 +- 3 files changed, 185 insertions(+), 201 deletions(-) diff --git a/infra/abbreviations.json b/infra/abbreviations.json index 93b9565..9d232cc 100644 --- a/infra/abbreviations.json +++ b/infra/abbreviations.json @@ -2,6 +2,8 @@ "ai": { "aiSearch": "srch-", "aiServices": "aisa-", + "aiFoundry": "aif-", + "aiFoundryProject": "aifp-", "aiVideoIndexer": "avi-", "machineLearningWorkspace": "mlw-", "openAIService": "oai-", diff --git a/infra/deploy_ai_foundry.bicep b/infra/deploy_ai_foundry.bicep index b9f365f..e6ef636 100644 --- a/infra/deploy_ai_foundry.bicep +++ b/infra/deploy_ai_foundry.bicep @@ -7,10 +7,10 @@ param solutionLocation string param keyVaultName string param gptModelName string param gptModelVersion string -param managedIdentityObjectId string +// param managedIdentityObjectId string param aiServicesEndpoint string param aiServicesKey string -param aiServicesId string +// param aiServicesId string param existingLogAnalyticsWorkspaceId string = '' @@ -22,15 +22,23 @@ var existingLawName = useExisting ? split(existingLogAnalyticsWorkspaceId, '/')[ var abbrs = loadJsonContent('./abbreviations.json') var storageName = '${abbrs.storage.storageAccount}${solutionName}' + var storageSkuName = 'Standard_LRS' -var aiServicesName = '${abbrs.ai.aiServices}${solutionName}' +// var aiServicesName = '${abbrs.ai.aiServices}${solutionName}' +var aiFoundryName = '${abbrs.ai.aiFoundry}${solutionName}' var workspaceName = '${abbrs.managementGovernance.logAnalyticsWorkspace}${solutionName}' var keyvaultName = '${abbrs.security.keyVault}${solutionName}' var location = solutionLocation -var aiProjectName = '${abbrs.ai.aiHubProject}${solutionName}' -var aiProjectFriendlyName = aiProjectName +// var azureAiHubName = '${abbrs.ai.aiHub}${solutionName}' +// var aiHubFriendlyName = azureAiHubName +// var aiHubDescription = 'AI Hub for KM template' +// var aiProjectName = '${abbrs.ai.aiHubProject}${solutionName}' var aiSearchName = '${solutionName}-search' var applicationInsightsName = '${solutionName}-appi' +var aiProjectDescription = 'AI foundary project for CPS template' +var aiProjectName = '${abbrs.ai.aiFoundryProject}${solutionName}' +var aiProjectFriendlyName = aiProjectName + resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = { name: keyVaultName @@ -67,187 +75,124 @@ 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 - } -} - -// Create AI Services resource (pavan approach) -resource aiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = { - name: aiServicesName - location: location - sku: { - name: 'S0' - } - kind: 'AIServices' - identity: { - type: 'SystemAssigned' - } - properties: { - allowProjectManagement: true - customSubDomainName: aiServicesName - networkAcls: { - defaultAction: 'Allow' - virtualNetworkRules: [] - ipRules: [] - } - publicNetworkAccess: 'Enabled' - disableLocalAuth: false //needs to be false to access keys - } -} - -@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 storageroleAiServiceAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(resourceGroup().id, aiServices.id, blobDataContributor.id) - scope: storage - properties: { - principalId: aiServices.identity.principalId - roleDefinitionId: blobDataContributor.id - principalType: 'ServicePrincipal' - } -} - -resource cognitiveServicesUserRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - scope: aiServices - name: 'a97b65f3-24c7-4388-baec-2e87135dc908' -} - -resource cognitiveServicesUserAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(resourceGroup().id, managedIdentityObjectId, cognitiveServicesUserRoleDefinition.id) - scope: aiServices - properties: { - principalId: managedIdentityObjectId - roleDefinitionId: cognitiveServicesUserRoleDefinition.id - principalType: 'ServicePrincipal' - } -} - -resource cognitiveServicesUserAiServiceAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(resourceGroup().id, aiServices.id, cognitiveServicesUserRoleDefinition.id) - scope: aiServices - properties: { - principalId: aiServices.identity.principalId - roleDefinitionId: cognitiveServicesUserRoleDefinition.id - principalType: 'ServicePrincipal' - } -} - -resource aiDeveloperRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - scope: aiServices - name: '64702f94-c441-49e6-a78b-ef80e0188fee' -} -resource aiDeveloperAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(resourceGroup().id, managedIdentityObjectId, aiDeveloperRoleDefinition.id) - scope: aiServices - properties: { - principalId: managedIdentityObjectId - roleDefinitionId: aiDeveloperRoleDefinition.id - principalType: 'ServicePrincipal' - } -} - -resource aiDeveloperAiServiceAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(resourceGroup().id, aiServices.id, aiDeveloperRoleDefinition.id) - scope: aiServices - properties: { - principalId: aiServices.identity.principalId - roleDefinitionId: aiDeveloperRoleDefinition.id - principalType: 'ServicePrincipal' - } -} -// Create AI Project (pavan approach) -resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' = { - parent: aiServices - name: aiProjectName - location: solutionLocation - kind: 'AIServices' - identity: { - type: 'SystemAssigned' - } - properties: {} -} -// Create project-level storage connection -resource project_connection_azure_storage 'Microsoft.CognitiveServices/accounts/projects/connections@2025-04-01-preview' = { - name: 'myStorageProjectConnectionName' - parent: aiProject - properties: { - category: 'AzureBlob' - target: storage.properties.primaryEndpoints.blob - authType: 'AAD' - metadata: { - ApiType: 'Azure' - ResourceId: storage.id - location: storage.location - containerName: 'ai-container' - accountName: storage.name - } - } -} +// 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 @@ -277,7 +222,7 @@ resource azureOpenAIApiKeyEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-pr parent: keyVault name: 'AZURE-OPENAI-KEY' properties: { - value: aiServices.listKeys().key1 + value: aiServicesKey //aiServices_m.listKeys().key1 } } @@ -301,18 +246,56 @@ resource azureOpenAIEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01- parent: keyVault name: 'AZURE-OPENAI-ENDPOINT' properties: { - value: aiServices.properties.endpoints['OpenAI Language Model Instance API'] + value: aiServicesEndpoint//aiServices_m.properties.endpoint } } -resource azureAIProjectConnectionStringEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { - parent: keyVault - name: 'AZURE-AI-PROJECT-CONN-STRING' + +resource aiFoundry 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = { + name: aiFoundryName + location: location + 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: aiFoundry + name: aiProjectName + location: location + identity: { + type: 'SystemAssigned' + } properties: { - value: '${aiProjectName};${subscription().subscriptionId};${resourceGroup().name};${aiProject.name}' + description: aiProjectDescription + displayName: aiProjectFriendlyName } } + +// resource azureAIProjectConnectionStringEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { +// parent: keyVault +// name: 'AZURE-AI-PROJECT-CONN-STRING' +// properties: { +// value: '${split(aiFoundryProject.properties.discoveryUrl, '/')[2]};${subscription().subscriptionId};${resourceGroup().name};${aiFoundryProject.name}' +// } +// } + resource azureOpenAICUApiVersionEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { parent: keyVault name: 'AZURE-OPENAI-CU-VERSION' @@ -333,7 +316,7 @@ resource cogServiceEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-p parent: keyVault name: 'COG-SERVICES-ENDPOINT' properties: { - value: aiServices.properties.endpoints['OpenAI Language Model Instance API'] + value: aiServicesEndpoint } } @@ -341,15 +324,15 @@ resource cogServiceKeyEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-previe parent: keyVault name: 'COG-SERVICES-KEY' properties: { - value: aiServices.listKeys().key1 + value: aiServicesKey } } -resource cogServiceNameEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { +resource cogServiceNameEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { // need to discuss with roopan parent: keyVault name: 'COG-SERVICES-NAME' properties: { - value: aiServicesName + value: aiFoundryName } } @@ -380,17 +363,14 @@ resource azureLocatioEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview output keyvaultName string = keyvaultName output keyvaultId string = keyVault.id -output aiServicesName string = aiServicesName -output aiServicesTarget string = aiServices.properties.endpoints['OpenAI Language Model Instance API'] -output aiServicesId string = aiServices.id +output aiFoundryName string = aiFoundryName output aiSearchName string = aiSearchName -output aiProjectName string = aiProject.name +output aiProjectName string = aiFoundryProject.name output storageAccountName string = storageNameCleaned output logAnalyticsId string = useExisting ? existingLogAnalyticsWorkspace.id : logAnalytics.id -output storageAccountId string = storage.id +// output storageAccountId string = storage.id output applicationInsightsConnectionString string = applicationInsights.properties.ConnectionString -output projectConnectionString string = '${aiProjectName};${subscription().subscriptionId};${resourceGroup().name};${aiProject.name}' -output projectEndpoint string = aiProject.properties.endpoints['AI Foundry API'] \ No newline at end of file +output projectConnectionString string = aiFoundryProject.properties.endpoints['AI Foundry API'] \ No newline at end of file diff --git a/infra/main.bicep b/infra/main.bicep index b746251..a700f60 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -323,7 +323,7 @@ resource containerAppBackend 'Microsoft.App/containerApps@2023-05-01' = { } { name: 'AZURE_OPENAI_ENDPOINT' - value: 'https://${azureAifoundry.outputs.aiServicesName}.openai.azure.com/' + value: 'https://${azureAifoundry.outputs.aiFoundryName}.openai.azure.com/' } { name: 'MIGRATOR_AGENT_MODEL_DEPLOY' @@ -506,3 +506,5 @@ module deploymentScriptCLI 'br/public:avm/res/resources/deployment-script:0.5.1' scriptContent: cosmosAssignCli } } + +output AZURE_AIFOUNDRY_NAME string = azureAiServices.name \ No newline at end of file From f60636678e268cedccbbfc2dddca99ce6f33d7bd Mon Sep 17 00:00:00 2001 From: Shreyas-Microsoft Date: Mon, 16 Jun 2025 22:57:14 +0530 Subject: [PATCH 06/11] bicep changes --- infra/deploy_ai_foundry.bicep | 4 +-- infra/main.bicep | 47 +++++++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/infra/deploy_ai_foundry.bicep b/infra/deploy_ai_foundry.bicep index e6ef636..29d4bfd 100644 --- a/infra/deploy_ai_foundry.bicep +++ b/infra/deploy_ai_foundry.bicep @@ -7,10 +7,10 @@ param solutionLocation string param keyVaultName string param gptModelName string param gptModelVersion string -// param managedIdentityObjectId string +param managedIdentityObjectId string param aiServicesEndpoint string param aiServicesKey string -// param aiServicesId string +param aiServicesId string param existingLogAnalyticsWorkspaceId string = '' diff --git a/infra/main.bicep b/infra/main.bicep index a700f60..d66a334 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -59,6 +59,7 @@ var storageSkuName = 'Standard_LRS' var storageContainerName = replace(replace(replace(replace('${ResourcePrefix}cast', '-', ''), '_', ''), '.', ''),'/', '') var azureAiServicesName = '${abbrs.ai.aiServices}${ResourcePrefix}' +// param aiProjectName string var aiModelDeployments = [ @@ -466,23 +467,59 @@ 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 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' } +// var aiServicesName string=azureAifoundry.outputs.aiFoundryName +// var aiProjectName string=azureAifoundry.outputs.aiProjectName + + +// resource aiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing= { +// name: azureAifoundry.outputs.aiFoundryName +// } + +resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' existing= { + name: azureAifoundry.outputs.aiProjectName +} + + 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 } } + +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 + } +} + +resource aiUserAccessFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(containerAppBackend.name, aiProject.id) + scope: resourceGroup() + properties: { + roleDefinitionId: aiUser.id + principalId: containerAppBackend.identity.principalId + } +} + resource contributorRoleDefinition 'Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions@2021-06-15' existing = { name: '${databaseAccount.name}/00000000-0000-0000-0000-000000000002' } From b46d44f49dd0cc49b247c650180f82fa8f5e4653 Mon Sep 17 00:00:00 2001 From: Shreyas-Microsoft Date: Tue, 17 Jun 2025 12:27:17 +0530 Subject: [PATCH 07/11] changes package for json formatter --- src/backend/sql_agents/agents/agent_base.py | 32 +++++++++------------ 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/backend/sql_agents/agents/agent_base.py b/src/backend/sql_agents/agents/agent_base.py index 6d4fca3..1a29a26 100644 --- a/src/backend/sql_agents/agents/agent_base.py +++ b/src/backend/sql_agents/agents/agent_base.py @@ -3,10 +3,11 @@ import logging from abc import ABC, abstractmethod from typing import Any, Generic, List, Optional, TypeVar, Union -import json -# Removed broken import: -# from azure.ai.projects.models import ResponseFormatJsonSchema, ResponseFormatJsonSchemaType +from azure.ai.agents.models import ( + ResponseFormatJsonSchema, + ResponseFormatJsonSchemaType, +) from semantic_kernel.agents.azure_ai.azure_ai_agent import AzureAIAgent from semantic_kernel.functions import KernelArguments @@ -106,30 +107,23 @@ async def setup(self) -> AzureAIAgent: kernel_args = self.get_kernel_arguments() - # Define an agent on the Azure AI agent service - # Construct response_format manually - response_format = None - if self.response_object: - response_format = { - "type": "json_schema", - "json_schema": { - "name": self.response_object.__name__, - "description": f"respond with {self.response_object.__name__.lower()}", - "schema": self.response_object.model_json_schema() - } - } - try: + # Define an agent on the Azure AI agent service agent_definition = await self.config.ai_project_client.agents.create_agent( model=_deployment_name, name=_name, instructions=template_content, temperature=self.temperature, - response_format=response_format, + response_format=ResponseFormatJsonSchemaType( + json_schema=ResponseFormatJsonSchema( + name=self.response_object.__name__, + description=f"respond with {self.response_object.__name__.lower()}", + schema=self.response_object.model_json_schema(), + ) + ), ) except Exception as exc: logger.error("Error creating agent definition: %s", exc) - raise # Set the agent definition with the response format # Create a Semantic Kernel agent based on the agent definition @@ -157,4 +151,4 @@ async def execute(self, inputs: Any) -> T: """Execute the agent with the given inputs.""" agent = await self.get_agent() response = await agent.invoke(inputs) - return response # Type will be inferred from T + return response # Type will be inferred from T \ No newline at end of file From 51e9ed478d106e87754272e838bbdf2a0161f6d4 Mon Sep 17 00:00:00 2001 From: Prashant-Microsoft Date: Wed, 18 Jun 2025 11:16:47 +0530 Subject: [PATCH 08/11] updated foundry changes --- infra/deploy_ai_foundry.bicep | 58 +++--------------------------- infra/main.bicep | 67 ++++++++++++++++++++++------------- 2 files changed, 48 insertions(+), 77 deletions(-) diff --git a/infra/deploy_ai_foundry.bicep b/infra/deploy_ai_foundry.bicep index 29d4bfd..20b4282 100644 --- a/infra/deploy_ai_foundry.bicep +++ b/infra/deploy_ai_foundry.bicep @@ -12,6 +12,7 @@ param aiServicesEndpoint string param aiServicesKey string param aiServicesId string +param aiFoundryName string param existingLogAnalyticsWorkspaceId string = '' var useExisting = !empty(existingLogAnalyticsWorkspaceId) @@ -24,20 +25,13 @@ var abbrs = loadJsonContent('./abbreviations.json') var storageName = '${abbrs.storage.storageAccount}${solutionName}' var storageSkuName = 'Standard_LRS' -// var aiServicesName = '${abbrs.ai.aiServices}${solutionName}' -var aiFoundryName = '${abbrs.ai.aiFoundry}${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 aiSearchName = '${solutionName}-search' var applicationInsightsName = '${solutionName}-appi' -var aiProjectDescription = 'AI foundary project for CPS template' -var aiProjectName = '${abbrs.ai.aiFoundryProject}${solutionName}' -var aiProjectFriendlyName = aiProjectName + resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = { @@ -250,44 +244,6 @@ resource azureOpenAIEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01- } } - -resource aiFoundry 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = { - name: aiFoundryName - location: location - 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: aiFoundry - name: aiProjectName - location: location - identity: { - type: 'SystemAssigned' - } - properties: { - description: aiProjectDescription - displayName: aiProjectFriendlyName - } -} - - // resource azureAIProjectConnectionStringEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { // parent: keyVault // name: 'AZURE-AI-PROJECT-CONN-STRING' @@ -328,11 +284,11 @@ resource cogServiceKeyEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-previe } } -resource cogServiceNameEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { // need to discuss with roopan +resource cogServiceNameEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { parent: keyVault name: 'COG-SERVICES-NAME' properties: { - value: aiFoundryName + value: aiFoundryName } } @@ -363,14 +319,10 @@ resource azureLocatioEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview output keyvaultName string = keyvaultName output keyvaultId string = keyVault.id -output aiFoundryName string = aiFoundryName output aiSearchName string = aiSearchName -output aiProjectName string = aiFoundryProject.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 = aiFoundryProject.properties.endpoints['AI Foundry API'] \ No newline at end of file diff --git a/infra/main.bicep b/infra/main.bicep index d66a334..d1c8f63 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -57,9 +57,12 @@ var cosmosdbLogContainer = 'cmsalog' var containerName = 'appstorage' var storageSkuName = 'Standard_LRS' var storageContainerName = replace(replace(replace(replace('${ResourcePrefix}cast', '-', ''), '_', ''), '.', ''),'/', '') -var azureAiServicesName = '${abbrs.ai.aiServices}${ResourcePrefix}' -// param aiProjectName string +var aiFoundryName = '${abbrs.ai.aiFoundry}${ResourcePrefix}' +var aiProjectDescription = 'AI foundary project for CPS template' +var aiProjectName = '${abbrs.ai.aiFoundryProject}${ResourcePrefix}' +var aiProjectFriendlyName = aiProjectName +var projectEndpointString ='' var aiModelDeployments = [ @@ -75,15 +78,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 } } @@ -138,6 +165,7 @@ module azureAifoundry 'deploy_ai_foundry.bicep' = { params: { solutionName: ResourcePrefix solutionLocation: AzureAiServiceLocation + aiFoundryName: aiFoundryName keyVaultName: kvault.outputs.keyvaultName gptModelName: llmModel gptModelVersion: gptModelVersion @@ -324,7 +352,7 @@ resource containerAppBackend 'Microsoft.App/containerApps@2023-05-01' = { } { name: 'AZURE_OPENAI_ENDPOINT' - value: 'https://${azureAifoundry.outputs.aiFoundryName}.openai.azure.com/' + value: 'https://${aiFoundryName}.openai.azure.com/' } { name: 'MIGRATOR_AGENT_MODEL_DEPLOY' @@ -360,7 +388,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' @@ -371,8 +399,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: projectEndpointString } ] resources: { @@ -475,19 +503,6 @@ resource aiDeveloper 'Microsoft.Authorization/roleDefinitions@2022-04-01' existi name: '64702f94-c441-49e6-a78b-ef80e0188fee' } -// var aiServicesName string=azureAifoundry.outputs.aiFoundryName -// var aiProjectName string=azureAifoundry.outputs.aiProjectName - - -// resource aiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing= { -// name: azureAifoundry.outputs.aiFoundryName -// } - -resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' existing= { - name: azureAifoundry.outputs.aiProjectName -} - - resource aiDeveloperAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = { name: guid(containerAppBackend.name, aiDeveloper.id) scope: resourceGroup() @@ -512,7 +527,7 @@ resource aiUserAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = } resource aiUserAccessFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(containerAppBackend.name, aiProject.id) + name: guid(containerAppBackend.name, aiFoundryProject.id) scope: resourceGroup() properties: { roleDefinitionId: aiUser.id @@ -544,4 +559,8 @@ module deploymentScriptCLI 'br/public:avm/res/resources/deployment-script:0.5.1' } } -output AZURE_AIFOUNDRY_NAME string = azureAiServices.name \ No newline at end of file +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'] From 762baf22b7bf6ddd8c0922d85ce7dc076dc1e6b8 Mon Sep 17 00:00:00 2001 From: Prashant-Microsoft Date: Wed, 18 Jun 2025 14:12:58 +0530 Subject: [PATCH 09/11] modify code --- infra/main.bicep | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/infra/main.bicep b/infra/main.bicep index d1c8f63..7eb99df 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -62,8 +62,6 @@ var aiFoundryName = '${abbrs.ai.aiFoundry}${ResourcePrefix}' var aiProjectDescription = 'AI foundary project for CPS template' var aiProjectName = '${abbrs.ai.aiFoundryProject}${ResourcePrefix}' var aiProjectFriendlyName = aiProjectName -var projectEndpointString ='' - var aiModelDeployments = [ { @@ -400,7 +398,7 @@ resource containerAppBackend 'Microsoft.App/containerApps@2023-05-01' = { } { name: 'AI_PROJECT_ENDPOINT' - value: projectEndpointString + value: aiFoundryProject.properties.endpoints['AI Foundry API'] } ] resources: { From 15357df8ba4edc805038765e073eca2ac6dedf95 Mon Sep 17 00:00:00 2001 From: Shreyas-Microsoft Date: Wed, 18 Jun 2025 17:03:00 +0530 Subject: [PATCH 10/11] remove commented code --- infra/deploy_ai_foundry.bicep | 135 ++-------------------------------- infra/main.bicep | 10 ++- 2 files changed, 14 insertions(+), 131 deletions(-) diff --git a/infra/deploy_ai_foundry.bicep b/infra/deploy_ai_foundry.bicep index 20b4282..740df33 100644 --- a/infra/deploy_ai_foundry.bicep +++ b/infra/deploy_ai_foundry.bicep @@ -11,6 +11,7 @@ param managedIdentityObjectId string param aiServicesEndpoint string param aiServicesKey string param aiServicesId string +param aureaiFoundryEndpoint string param aiFoundryName string param existingLogAnalyticsWorkspaceId string = '' @@ -69,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' @@ -244,13 +126,13 @@ resource azureOpenAIEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01- } } -// resource azureAIProjectConnectionStringEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { -// parent: keyVault -// name: 'AZURE-AI-PROJECT-CONN-STRING' -// properties: { -// value: '${split(aiFoundryProject.properties.discoveryUrl, '/')[2]};${subscription().subscriptionId};${resourceGroup().name};${aiFoundryProject.name}' -// } -// } +resource azureAIProjectEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { + parent: keyVault + name: 'AI-PROJECT-ENDPOINT' + properties: { + value: aureaiFoundryEndpoint + } +} resource azureOpenAICUApiVersionEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = { parent: keyVault @@ -324,5 +206,4 @@ output aiSearchName string = aiSearchName output storageAccountName string = storageNameCleaned output logAnalyticsId string = useExisting ? existingLogAnalyticsWorkspace.id : logAnalytics.id -// output storageAccountId string = storage.id output applicationInsightsConnectionString string = applicationInsights.properties.ConnectionString diff --git a/infra/main.bicep b/infra/main.bicep index 7eb99df..79933cb 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -172,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) } @@ -467,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 @@ -477,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' } } @@ -493,10 +496,6 @@ 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' } @@ -507,6 +506,7 @@ resource aiDeveloperAccessProj 'Microsoft.Authorization/roleAssignments@2022-04- properties: { roleDefinitionId: aiDeveloper.id principalId: containerAppBackend.identity.principalId + principalType: 'ServicePrincipal' } } @@ -521,6 +521,7 @@ resource aiUserAccessProj 'Microsoft.Authorization/roleAssignments@2022-04-01' = properties: { roleDefinitionId: aiUser.id principalId: containerAppBackend.identity.principalId + principalType: 'ServicePrincipal' } } @@ -530,6 +531,7 @@ resource aiUserAccessFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01 properties: { roleDefinitionId: aiUser.id principalId: containerAppBackend.identity.principalId + principalType: 'ServicePrincipal' } } From eea319d375daa8e03011a3c5290429c760b4737c Mon Sep 17 00:00:00 2001 From: Shreyas-Microsoft Date: Wed, 18 Jun 2025 17:18:30 +0530 Subject: [PATCH 11/11] fix pylint errors --- src/backend/common/config/config.py | 2 +- src/backend/sql_agents/agents/agent_base.py | 2 +- src/backend/sql_agents/process_batch.py | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/backend/common/config/config.py b/src/backend/common/config/config.py index 47e4476..945cc8b 100644 --- a/src/backend/common/config/config.py +++ b/src/backend/common/config/config.py @@ -63,4 +63,4 @@ def get_azure_credentials(self): app_config = Config() -print(f"[DEBUG] AI_PROJECT_ENDPOINT: '{os.getenv('AI_PROJECT_ENDPOINT')}'") \ No newline at end of file +print(f"[DEBUG] AI_PROJECT_ENDPOINT: '{os.getenv('AI_PROJECT_ENDPOINT')}'") diff --git a/src/backend/sql_agents/agents/agent_base.py b/src/backend/sql_agents/agents/agent_base.py index 1a29a26..aec5793 100644 --- a/src/backend/sql_agents/agents/agent_base.py +++ b/src/backend/sql_agents/agents/agent_base.py @@ -151,4 +151,4 @@ async def execute(self, inputs: Any) -> T: """Execute the agent with the given inputs.""" agent = await self.get_agent() response = await agent.invoke(inputs) - return response # Type will be inferred from T \ No newline at end of file + return response # Type will be inferred from T diff --git a/src/backend/sql_agents/process_batch.py b/src/backend/sql_agents/process_batch.py index 9e7eb9d..cb22efe 100644 --- a/src/backend/sql_agents/process_batch.py +++ b/src/backend/sql_agents/process_batch.py @@ -11,6 +11,7 @@ from azure.identity.aio import DefaultAzureCredential +from common.config.config import app_config from common.models.api import ( FileProcessUpdate, FileRecord, @@ -20,11 +21,11 @@ ) from common.services.batch_service import BatchService from common.storage.blob_factory import BlobStorageFactory -from common.config.config import app_config + from fastapi import HTTPException -from semantic_kernel.agents.azure_ai.azure_ai_agent import AzureAIAgent, AzureAIAgentSettings # pylint: disable=E0611 +from semantic_kernel.agents.azure_ai.azure_ai_agent import AzureAIAgent # pylint: disable=E0611 from semantic_kernel.contents import AuthorRole from semantic_kernel.exceptions.service_exceptions import ServiceResponseException @@ -37,6 +38,7 @@ logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) + # Walk through batch structure processing each file async def process_batch_async( batch_id: str, convert_from: str = "informix", convert_to: str = "tsql" @@ -56,7 +58,6 @@ async def process_batch_async( except Exception as exc: logger.error("Error updating batch status. %s", exc) - ai_agent_settings = AzureAIAgentSettings() # Add client and auto cleanup async with ( DefaultAzureCredential() as creds,