Skip to content

Commit 1a2b4d8

Browse files
Merge branch 'main' into PSL-BUG-17858
2 parents 9b1797b + 3bb2512 commit 1a2b4d8

15 files changed

+620
-334
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,7 @@ Here are some example regions where the services are available: East US, East US
9595

9696
Pricing varies per region and usage, so it isn't possible to predict exact costs for your usage. The majority of the Azure resources used in this infrastructure are on usage-based pricing tiers. However, Azure Container Registry has a fixed cost per registry per day.
9797

98-
Use the [Azure pricing calculator](https://azure.microsoft.com/en-us/pricing/calculator) to calculate the cost of this solution in your subscription.
99-
98+
Use the [Azure pricing calculator](https://azure.microsoft.com/en-us/pricing/calculator) to calculate the cost of this solution in your subscription. [Review a sample pricing sheet for the achitecture](https://azure.com/e/86d0eefbe4dd4a23981c1d3d4f6fe7ed).
10099
| Product | Description | Cost |
101100
|---|---|---|
102101
| [Azure OpenAI Service](https://learn.microsoft.com/azure/ai-services/openai/) | Powers the AI agents for task automation | [Pricing](https://azure.microsoft.com/pricing/details/cognitive-services/openai-service/) |

infra/main.bicep

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ var modelVersion = '2024-08-06'
6565
var aiServicesName = '${solutionPrefix}-aiservices'
6666
var deploymentType = 'GlobalStandard'
6767
var gptModelVersion = 'gpt-4o'
68-
var appVersion = 'fnd01'
68+
var appVersion = 'latest'
6969
var resgistryName = 'biabcontainerreg'
7070
var dockerRegistryUrl = 'https://${resgistryName}.azurecr.io'
7171

infra/main.json

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
"metadata": {
66
"_generator": {
77
"name": "bicep",
8-
"version": "0.34.44.8038",
9-
"templateHash": "7719893060553487435"
8+
"version": "0.35.1.17967",
9+
"templateHash": "6559422175999367984"
1010
}
1111
},
1212
"parameters": {
@@ -48,13 +48,12 @@
4848
"description": "Location for all Ai services resources. This location can be different from the resource group location."
4949
}
5050
},
51-
"prefix": {
51+
"environmentName": {
5252
"type": "string",
53-
"defaultValue": "macae",
5453
"minLength": 3,
5554
"maxLength": 20,
5655
"metadata": {
57-
"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."
56+
"description": "A unique prefix for all resources in this deployment. This should be 3-20 characters long:"
5857
}
5958
},
6059
"tags": {
@@ -107,16 +106,18 @@
107106
}
108107
},
109108
"variables": {
109+
"uniqueId": "[toLower(uniqueString(subscription().id, parameters('environmentName'), resourceGroup().location))]",
110+
"solutionPrefix": "[format('ma{0}', padLeft(take(variables('uniqueId'), 12), 12, '0'))]",
110111
"modelVersion": "2024-08-06",
111-
"aiServicesName": "[format('{0}-aiservices', parameters('prefix'))]",
112+
"aiServicesName": "[format('{0}-aiservices', variables('solutionPrefix'))]",
112113
"deploymentType": "GlobalStandard",
113114
"gptModelVersion": "gpt-4o",
114-
"appVersion": "fnd01",
115+
"appVersion": "latest",
115116
"resgistryName": "biabcontainerreg",
116117
"dockerRegistryUrl": "[format('https://{0}.azurecr.io', variables('resgistryName'))]",
117118
"backendDockerImageURL": "[format('{0}.azurecr.io/macaebackend:{1}', variables('resgistryName'), variables('appVersion'))]",
118119
"frontendDockerImageURL": "[format('{0}.azurecr.io/macaefrontend:{1}', variables('resgistryName'), variables('appVersion'))]",
119-
"uniqueNameFormat": "[format('{0}-{{0}}-{1}', parameters('prefix'), uniqueString(resourceGroup().id, parameters('prefix')))]",
120+
"uniqueNameFormat": "[format('{0}-{{0}}-{1}', variables('solutionPrefix'), uniqueString(resourceGroup().id, variables('solutionPrefix')))]",
120121
"aoaiApiVersion": "2025-01-01-preview",
121122
"aiModelDeployments": [
122123
{
@@ -224,8 +225,7 @@
224225
"kind": "AIServices",
225226
"properties": {
226227
"customSubDomainName": "[variables('aiServicesName')]",
227-
"apiProperties": {},
228-
"disableLocalAuth": true
228+
"apiProperties": {}
229229
}
230230
},
231231
"aiServicesDeployments": {
@@ -262,7 +262,7 @@
262262
"type": "Microsoft.Authorization/roleAssignments",
263263
"apiVersion": "2022-04-01",
264264
"scope": "[format('Microsoft.CognitiveServices/accounts/{0}', variables('aiServicesName'))]",
265-
"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'))]",
265+
"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'))]",
266266
"properties": {
267267
"principalId": "[reference('containerApp', '2024-03-01', 'full').identity.principalId]",
268268
"roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd')]",
@@ -315,7 +315,7 @@
315315
"destination": "log-analytics",
316316
"logAnalyticsConfiguration": {
317317
"customerId": "[reference('logAnalytics').customerId]",
318-
"sharedKey": "[listKeys(resourceId('Microsoft.OperationalInsights/workspaces', format(variables('uniqueNameFormat'), 'logs')), '2023-09-01').primarySharedKey]"
318+
"sharedKey": "[listKeys('logAnalytics', '2023-09-01').primarySharedKey]"
319319
}
320320
}
321321
},
@@ -327,7 +327,7 @@
327327
"acaCosomsRoleAssignment": {
328328
"type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments",
329329
"apiVersion": "2024-05-15",
330-
"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')))]",
330+
"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')))]",
331331
"properties": {
332332
"principalId": "[reference('containerApp', '2024-03-01', 'full').identity.principalId]",
333333
"roleDefinitionId": "[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions', format(variables('uniqueNameFormat'), 'cosmos'), '00000000-0000-0000-0000-000000000002')]",
@@ -341,7 +341,7 @@
341341
"containerApp": {
342342
"type": "Microsoft.App/containerApps",
343343
"apiVersion": "2024-03-01",
344-
"name": "[format('{0}-backend', parameters('prefix'))]",
344+
"name": "[format('{0}-backend', variables('solutionPrefix'))]",
345345
"location": "[parameters('location')]",
346346
"tags": "[parameters('tags')]",
347347
"identity": {
@@ -532,7 +532,7 @@
532532
"existing": true,
533533
"type": "Microsoft.MachineLearningServices/workspaces",
534534
"apiVersion": "2024-01-01-preview",
535-
"name": "[format('{0}-aiproject', parameters('prefix'))]"
535+
"name": "[format('{0}-aiproject', variables('solutionPrefix'))]"
536536
},
537537
"aiDeveloper": {
538538
"existing": true,
@@ -543,8 +543,8 @@
543543
"aiDeveloperAccessProj": {
544544
"type": "Microsoft.Authorization/roleAssignments",
545545
"apiVersion": "2022-04-01",
546-
"scope": "[format('Microsoft.MachineLearningServices/workspaces/{0}', format('{0}-aiproject', parameters('prefix')))]",
547-
"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'))]",
546+
"scope": "[format('Microsoft.MachineLearningServices/workspaces/{0}', format('{0}-aiproject', variables('solutionPrefix')))]",
547+
"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'))]",
548548
"properties": {
549549
"roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', '64702f94-c441-49e6-a78b-ef80e0188fee')]",
550550
"principalId": "[reference('containerApp', '2024-03-01', 'full').identity.principalId]"
@@ -565,7 +565,7 @@
565565
"mode": "Incremental",
566566
"parameters": {
567567
"solutionName": {
568-
"value": "[parameters('prefix')]"
568+
"value": "[variables('solutionPrefix')]"
569569
},
570570
"solutionLocation": {
571571
"value": "[parameters('location')]"
@@ -580,8 +580,8 @@
580580
"metadata": {
581581
"_generator": {
582582
"name": "bicep",
583-
"version": "0.34.44.8038",
584-
"templateHash": "10664495342911727649"
583+
"version": "0.35.1.17967",
584+
"templateHash": "5761607453167859573"
585585
}
586586
},
587587
"parameters": {
@@ -685,7 +685,7 @@
685685
"mode": "Incremental",
686686
"parameters": {
687687
"solutionName": {
688-
"value": "[parameters('prefix')]"
688+
"value": "[variables('solutionPrefix')]"
689689
},
690690
"solutionLocation": {
691691
"value": "[parameters('azureOpenAILocation')]"
@@ -706,7 +706,7 @@
706706
"value": "[reference('aiServices').endpoint]"
707707
},
708708
"aiServicesKey": {
709-
"value": "[listKeys(resourceId('Microsoft.CognitiveServices/accounts', variables('aiServicesName')), '2024-04-01-preview').key1]"
709+
"value": "[listKeys('aiServices', '2024-04-01-preview').key1]"
710710
},
711711
"aiServicesId": {
712712
"value": "[resourceId('Microsoft.CognitiveServices/accounts', variables('aiServicesName'))]"
@@ -718,8 +718,8 @@
718718
"metadata": {
719719
"_generator": {
720720
"name": "bicep",
721-
"version": "0.34.44.8038",
722-
"templateHash": "8087543237770345715"
721+
"version": "0.35.1.17967",
722+
"templateHash": "9490638595753234802"
723723
}
724724
},
725725
"parameters": {
@@ -1094,7 +1094,7 @@
10941094
"mode": "Incremental",
10951095
"parameters": {
10961096
"solutionName": {
1097-
"value": "[parameters('prefix')]"
1097+
"value": "[variables('solutionPrefix')]"
10981098
},
10991099
"managedIdentityId": {
11001100
"value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', format(variables('uniqueNameFormat'), 'containerapp-pull'))]"
@@ -1112,8 +1112,8 @@
11121112
"metadata": {
11131113
"_generator": {
11141114
"name": "bicep",
1115-
"version": "0.34.44.8038",
1116-
"templateHash": "11364190519186458619"
1115+
"version": "0.35.1.17967",
1116+
"templateHash": "12327197428621494853"
11171117
}
11181118
},
11191119
"parameters": {

src/backend/app_config.py

Lines changed: 8 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
# app_config.py
2-
import os
32
import logging
4-
from typing import Optional, List, Dict, Any
5-
from dotenv import load_dotenv
6-
from azure.identity import DefaultAzureCredential, ClientSecretCredential
7-
from azure.cosmos.aio import CosmosClient
3+
import os
4+
from typing import Any, Dict, List, Optional
5+
86
from azure.ai.projects.aio import AIProjectClient
9-
from semantic_kernel.kernel import Kernel
10-
from semantic_kernel.contents import ChatHistory
7+
from azure.cosmos.aio import CosmosClient
8+
from azure.identity import ClientSecretCredential, DefaultAzureCredential
9+
from dotenv import load_dotenv
1110
from semantic_kernel.agents.azure_ai.azure_ai_agent import AzureAIAgent
11+
from semantic_kernel.contents import ChatHistory
1212
from semantic_kernel.functions import KernelFunction
13+
from semantic_kernel.kernel import Kernel
1314

1415
# Load environment variables from .env file
1516
load_dotenv()
@@ -189,94 +190,6 @@ def get_ai_project_client(self):
189190
logging.error("Failed to create AIProjectClient: %s", exc)
190191
raise
191192

192-
async def create_azure_ai_agent(
193-
self,
194-
agent_name: str,
195-
instructions: str,
196-
tools: Optional[List[KernelFunction]] = None,
197-
client=None,
198-
response_format=None,
199-
temperature: float = 0.0,
200-
):
201-
"""
202-
Creates a new Azure AI Agent with the specified name and instructions using AIProjectClient.
203-
If an agent with the given name (assistant_id) already exists, it tries to retrieve it first.
204-
205-
Args:
206-
kernel: The Semantic Kernel instance
207-
agent_name: The name of the agent (will be used as assistant_id)
208-
instructions: The system message / instructions for the agent
209-
agent_type: The type of agent (defaults to "assistant")
210-
tools: Optional tool definitions for the agent
211-
tool_resources: Optional tool resources required by the tools
212-
response_format: Optional response format to control structured output
213-
temperature: The temperature setting for the agent (defaults to 0.0)
214-
215-
Returns:
216-
A new AzureAIAgent instance
217-
"""
218-
try:
219-
# Get the AIProjectClient
220-
if client is None:
221-
client = self.get_ai_project_client()
222-
223-
# # ToDo: This is the fixed code but commenting it out as agent clean up is no happening yet
224-
# # and there are multiple versions of agents due to testing
225-
# # First try to get an existing agent with this name as assistant_id
226-
# try:
227-
# agent_id = None
228-
# agent_list = await client.agents.list_agents()
229-
# for agent in agent_list.data:
230-
# if agent.name == agent_name:
231-
# agent_id = agent.id
232-
# break
233-
# # If the agent already exists, we can use it directly
234-
# # Get the existing agent definition
235-
# existing_definition = await client.agents.get_agent(agent_id)
236-
# # Create the agent instance directly with project_client and existing definition
237-
# agent = AzureAIAgent(
238-
# client=client,
239-
# definition=existing_definition,
240-
# plugins=tools,
241-
# )
242-
243-
# client.agents.list_agents()
244-
245-
# return agent
246-
# except Exception as e:
247-
# # The Azure AI Projects SDK throws an exception when the agent doesn't exist
248-
# # (not returning None), so we catch it and proceed to create a new agent
249-
# if "ResourceNotFound" in str(e) or "404" in str(e):
250-
# logging.info(
251-
# f"Agent with ID {agent_name} not found. Will create a new one."
252-
# )
253-
# else:
254-
# # Log unexpected errors but still try to create a new agent
255-
# logging.warning(
256-
# f"Unexpected error while retrieving agent {agent_name}: {str(e)}. Attempting to create new agent."
257-
# )
258-
259-
# Create the agent using the project client with the agent_name as both name and assistantId
260-
agent_definition = await client.agents.create_agent(
261-
model=self.AZURE_OPENAI_DEPLOYMENT_NAME,
262-
name=agent_name,
263-
instructions=instructions,
264-
temperature=temperature,
265-
response_format=response_format,
266-
)
267-
268-
# Create the agent instance directly with project_client and definition
269-
agent = AzureAIAgent(
270-
client=client,
271-
definition=agent_definition,
272-
plugins=tools,
273-
)
274-
275-
return agent
276-
except Exception as exc:
277-
logging.error("Failed to create Azure AI Agent: %s", exc)
278-
raise
279-
280193

281194
# Create a global instance of AppConfig
282195
config = AppConfig()

0 commit comments

Comments
 (0)