diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index bc2851159..8b1378917 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -1,27 +1 @@ -name: PyLint -on: [push] - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.11"] - steps: - - uses: actions/checkout@v4 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r src/backend/requirements.txt - pip install flake8 # Ensure flake8 is installed explicitly - - - name: Run flake8 and pylint - run: | - flake8 --config=.flake8 src/backend # Specify the directory to lint diff --git a/infra/main.bicep b/infra/main.bicep index bea374423..24d2112ba 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -65,7 +65,7 @@ var modelVersion = '2024-08-06' var aiServicesName = '${solutionPrefix}-aiservices' var deploymentType = 'GlobalStandard' var gptModelVersion = 'gpt-4o' -var appVersion = 'fnd01' +var appVersion = 'auj01' var resgistryName = 'biabcontainerreg' var dockerRegistryUrl = 'https://${resgistryName}.azurecr.io' diff --git a/infra/main.json b/infra/main.json index 6c40552d5..13559457c 100644 --- a/infra/main.json +++ b/infra/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "7719893060553487435" + "templateHash": "8198085377798825433" } }, "parameters": { @@ -48,13 +48,12 @@ "description": "Location for all Ai services resources. This location can be different from the resource group location." } }, - "prefix": { + "environmentName": { "type": "string", - "defaultValue": "macae", "minLength": 3, "maxLength": 20, "metadata": { - "description": "Prefix for all resources created by this template. This prefix will be used to create unique names for all resources. The prefix must be unique within the resource group." + "description": "A unique prefix for all resources in this deployment. This should be 3-20 characters long:" } }, "tags": { @@ -107,16 +106,18 @@ } }, "variables": { + "uniqueId": "[toLower(uniqueString(subscription().id, parameters('environmentName'), resourceGroup().location))]", + "solutionPrefix": "[format('ma{0}', padLeft(take(variables('uniqueId'), 12), 12, '0'))]", "modelVersion": "2024-08-06", - "aiServicesName": "[format('{0}-aiservices', parameters('prefix'))]", + "aiServicesName": "[format('{0}-aiservices', variables('solutionPrefix'))]", "deploymentType": "GlobalStandard", "gptModelVersion": "gpt-4o", - "appVersion": "fnd01", + "appVersion": "auj01", "resgistryName": "biabcontainerreg", "dockerRegistryUrl": "[format('https://{0}.azurecr.io', variables('resgistryName'))]", "backendDockerImageURL": "[format('{0}.azurecr.io/macaebackend:{1}', variables('resgistryName'), variables('appVersion'))]", "frontendDockerImageURL": "[format('{0}.azurecr.io/macaefrontend:{1}', variables('resgistryName'), variables('appVersion'))]", - "uniqueNameFormat": "[format('{0}-{{0}}-{1}', parameters('prefix'), uniqueString(resourceGroup().id, parameters('prefix')))]", + "uniqueNameFormat": "[format('{0}-{{0}}-{1}', variables('solutionPrefix'), uniqueString(resourceGroup().id, variables('solutionPrefix')))]", "aoaiApiVersion": "2025-01-01-preview", "aiModelDeployments": [ { @@ -224,8 +225,7 @@ "kind": "AIServices", "properties": { "customSubDomainName": "[variables('aiServicesName')]", - "apiProperties": {}, - "disableLocalAuth": true + "apiProperties": {} } }, "aiServicesDeployments": { @@ -262,7 +262,7 @@ "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.CognitiveServices/accounts/{0}', variables('aiServicesName'))]", - "name": "[guid(resourceId('Microsoft.App/containerApps', format('{0}-backend', parameters('prefix'))), resourceId('Microsoft.CognitiveServices/accounts', variables('aiServicesName')), resourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd'))]", + "name": "[guid(resourceId('Microsoft.App/containerApps', format('{0}-backend', variables('solutionPrefix'))), resourceId('Microsoft.CognitiveServices/accounts', variables('aiServicesName')), resourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd'))]", "properties": { "principalId": "[reference('containerApp', '2024-03-01', 'full').identity.principalId]", "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd')]", @@ -293,8 +293,7 @@ { "name": "EnableServerless" } - ], - "disableLocalAuth": true + ] } }, "pullIdentity": { @@ -327,7 +326,7 @@ "acaCosomsRoleAssignment": { "type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments", "apiVersion": "2024-05-15", - "name": "[format('{0}/{1}', format(variables('uniqueNameFormat'), 'cosmos'), guid(resourceId('Microsoft.App/containerApps', format('{0}-backend', parameters('prefix'))), resourceId('Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions', format(variables('uniqueNameFormat'), 'cosmos'), '00000000-0000-0000-0000-000000000002')))]", + "name": "[format('{0}/{1}', format(variables('uniqueNameFormat'), 'cosmos'), guid(resourceId('Microsoft.App/containerApps', format('{0}-backend', variables('solutionPrefix'))), resourceId('Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions', format(variables('uniqueNameFormat'), 'cosmos'), '00000000-0000-0000-0000-000000000002')))]", "properties": { "principalId": "[reference('containerApp', '2024-03-01', 'full').identity.principalId]", "roleDefinitionId": "[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions', format(variables('uniqueNameFormat'), 'cosmos'), '00000000-0000-0000-0000-000000000002')]", @@ -341,7 +340,7 @@ "containerApp": { "type": "Microsoft.App/containerApps", "apiVersion": "2024-03-01", - "name": "[format('{0}-backend', parameters('prefix'))]", + "name": "[format('{0}-backend', variables('solutionPrefix'))]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", "identity": { @@ -532,7 +531,7 @@ "existing": true, "type": "Microsoft.MachineLearningServices/workspaces", "apiVersion": "2024-01-01-preview", - "name": "[format('{0}-aiproject', parameters('prefix'))]" + "name": "[format('{0}-aiproject', variables('solutionPrefix'))]" }, "aiDeveloper": { "existing": true, @@ -543,8 +542,8 @@ "aiDeveloperAccessProj": { "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", - "scope": "[format('Microsoft.MachineLearningServices/workspaces/{0}', format('{0}-aiproject', parameters('prefix')))]", - "name": "[guid(format('{0}-backend', parameters('prefix')), resourceId('Microsoft.MachineLearningServices/workspaces', format('{0}-aiproject', parameters('prefix'))), resourceId('Microsoft.Authorization/roleDefinitions', '64702f94-c441-49e6-a78b-ef80e0188fee'))]", + "scope": "[format('Microsoft.MachineLearningServices/workspaces/{0}', format('{0}-aiproject', variables('solutionPrefix')))]", + "name": "[guid(format('{0}-backend', variables('solutionPrefix')), resourceId('Microsoft.MachineLearningServices/workspaces', format('{0}-aiproject', variables('solutionPrefix'))), resourceId('Microsoft.Authorization/roleDefinitions', '64702f94-c441-49e6-a78b-ef80e0188fee'))]", "properties": { "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', '64702f94-c441-49e6-a78b-ef80e0188fee')]", "principalId": "[reference('containerApp', '2024-03-01', 'full').identity.principalId]" @@ -565,7 +564,7 @@ "mode": "Incremental", "parameters": { "solutionName": { - "value": "[parameters('prefix')]" + "value": "[variables('solutionPrefix')]" }, "solutionLocation": { "value": "[parameters('location')]" @@ -685,7 +684,7 @@ "mode": "Incremental", "parameters": { "solutionName": { - "value": "[parameters('prefix')]" + "value": "[variables('solutionPrefix')]" }, "solutionLocation": { "value": "[parameters('azureOpenAILocation')]" @@ -1094,7 +1093,7 @@ "mode": "Incremental", "parameters": { "solutionName": { - "value": "[parameters('prefix')]" + "value": "[variables('solutionPrefix')]" }, "managedIdentityId": { "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format(variables('uniqueNameFormat'), 'containerapp-pull'))]" diff --git a/src/backend/app_config.py b/src/backend/app_config.py index b35732a99..f93e3bdaf 100644 --- a/src/backend/app_config.py +++ b/src/backend/app_config.py @@ -203,12 +203,10 @@ async def create_azure_ai_agent( If an agent with the given name (assistant_id) already exists, it tries to retrieve it first. Args: - kernel: The Semantic Kernel instance agent_name: The name of the agent (will be used as assistant_id) instructions: The system message / instructions for the agent - agent_type: The type of agent (defaults to "assistant") tools: Optional tool definitions for the agent - tool_resources: Optional tool resources required by the tools + client: Optional AIProjectClient instance response_format: Optional response format to control structured output temperature: The temperature setting for the agent (defaults to 0.0) @@ -220,41 +218,38 @@ async def create_azure_ai_agent( if client is None: client = self.get_ai_project_client() - # # ToDo: This is the fixed code but commenting it out as agent clean up is no happening yet - # # and there are multiple versions of agents due to testing - # # First try to get an existing agent with this name as assistant_id - # try: - # agent_id = None - # agent_list = await client.agents.list_agents() - # for agent in agent_list.data: - # if agent.name == agent_name: - # agent_id = agent.id - # break - # # If the agent already exists, we can use it directly - # # Get the existing agent definition - # existing_definition = await client.agents.get_agent(agent_id) - # # Create the agent instance directly with project_client and existing definition - # agent = AzureAIAgent( - # client=client, - # definition=existing_definition, - # plugins=tools, - # ) - - # client.agents.list_agents() - - # return agent - # except Exception as e: - # # The Azure AI Projects SDK throws an exception when the agent doesn't exist - # # (not returning None), so we catch it and proceed to create a new agent - # if "ResourceNotFound" in str(e) or "404" in str(e): - # logging.info( - # f"Agent with ID {agent_name} not found. Will create a new one." - # ) - # else: - # # Log unexpected errors but still try to create a new agent - # logging.warning( - # f"Unexpected error while retrieving agent {agent_name}: {str(e)}. Attempting to create new agent." - # ) + # First try to get an existing agent with this name as assistant_id + try: + agent_id = None + agent_list = await client.agents.list_agents() + for agent in agent_list.data: + if agent.name == agent_name: + agent_id = agent.id + break + + # If the agent already exists, we can use it directly + if agent_id: + # Get the existing agent definition + existing_definition = await client.agents.get_agent(agent_id) + # Create the agent instance directly with project_client and existing definition + agent = AzureAIAgent( + client=client, + definition=existing_definition, + plugins=tools, + ) + return agent + except Exception as e: + # The Azure AI Projects SDK throws an exception when the agent doesn't exist + # (not returning None), so we catch it and proceed to create a new agent + if "ResourceNotFound" in str(e) or "404" in str(e): + logging.info( + f"Agent with ID {agent_name} not found. Will create a new one." + ) + else: + # Log unexpected errors but still try to create a new agent + logging.warning( + f"Unexpected error while retrieving agent {agent_name}: {str(e)}. Attempting to create new agent." + ) # Create the agent using the project client with the agent_name as both name and assistantId agent_definition = await client.agents.create_agent(