Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 9 additions & 22 deletions infra/deploy_backend_docker.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ param solutionName string
@secure()
param appSettings object = {}
param appServicePlanId string
@secure()
param azureOpenAIKey string
@secure()
param azureAiProjectConnString string
@secure()
param azureSearchAdminKey string
param userassignedIdentityId string
param keyVaultName string

var imageName = 'DOCKER|kmcontainerreg.azurecr.io/km-api:${imageTag}'
var name = '${solutionName}-api'
Expand Down Expand Up @@ -84,6 +89,9 @@ module appService 'deploy_app_service.bicep' = {
appSettings: union(
appSettings,
{
AZURE_OPENAI_API_KEY: azureOpenAIKey
AZURE_AI_SEARCH_API_KEY: azureSearchAdminKey
AZURE_AI_PROJECT_CONN_STRING:azureAiProjectConnString
APPINSIGHTS_INSTRUMENTATIONKEY: reference(applicationInsightsId, '2015-05-01').InstrumentationKey
REACT_APP_LAYOUT_CONFIG: reactAppLayoutConfig
}
Expand All @@ -110,25 +118,4 @@ resource role 'Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments@2022-05-
}
}

resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' existing = {
name: keyVaultName
}

var keyVaultSecretsOfficerId='b86a8fe4-44ce-4948-aee5-eccb2c155cd7'
@description('The built-in role for Key Vault Secrets Officer.')
resource keyVaultSecretsOfficerRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
scope: subscription()
name: keyVaultSecretsOfficerId
}

resource keyVaultSecretsOfficerRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
scope: keyVault
name: guid(keyVault.id, keyVaultSecretsOfficerRoleDefinition.id)
properties: {
roleDefinitionId: keyVaultSecretsOfficerRoleDefinition.id
principalId: appService.outputs.identityPrincipalId
principalType: 'ServicePrincipal'
}
}

output appUrl string = appService.outputs.appUrl
8 changes: 3 additions & 5 deletions infra/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -194,16 +194,16 @@ module backend_docker 'deploy_backend_docker.bicep'= {
imageTag: imageTag
appServicePlanId: hostingplan.outputs.name
applicationInsightsId: aifoundry.outputs.applicationInsightsId
azureOpenAIKey:keyVault.getSecret('AZURE-OPENAI-KEY')
azureAiProjectConnString:keyVault.getSecret('AZURE-AI-PROJECT-CONN-STRING')
azureSearchAdminKey:keyVault.getSecret('AZURE-SEARCH-KEY')
solutionName: solutionPrefix
userassignedIdentityId: managedIdentityModule.outputs.managedIdentityBackendAppOutput.id
keyVaultName:aifoundry.outputs.keyvaultName
appSettings:{
AZURE_OPEN_AI_DEPLOYMENT_MODEL:gptModelName
AZURE_OPEN_AI_ENDPOINT:aifoundry.outputs.aiServicesTarget
AZURE_OPENAI_API_VERSION: azureOpenAIApiVersion
AZURE_OPENAI_RESOURCE:aifoundry.outputs.aiServicesName
AZURE_OPENAI_API_KEY:'AZURE-OPENAI-KEY'
AZURE_KEY_VAULT_URL: kvault.outputs.keyvaultUri
USE_CHAT_HISTORY_ENABLED:'True'
AZURE_COSMOSDB_ACCOUNT: cosmosDBModule.outputs.cosmosAccountName
AZURE_COSMOSDB_CONVERSATIONS_CONTAINER: cosmosDBModule.outputs.cosmosContainerName
Expand All @@ -217,9 +217,7 @@ module backend_docker 'deploy_backend_docker.bicep'= {
OPENAI_API_VERSION: azureOpenAIApiVersion
AZURE_AI_SEARCH_ENDPOINT: aifoundry.outputs.aiSearchTarget
AZURE_AI_SEARCH_INDEX: 'call_transcripts_index'
AZURE_AI_SEARCH_API_KEY:'AZURE-SEARCH-KEY'
USE_AI_PROJECT_CLIENT:'False'
AZURE_AI_PROJECT_CONN_STRING:'AZURE-AI-PROJECT-CONN-STRING'
DISPLAY_CHART_DEFAULT:'True'
}
}
Expand Down
67 changes: 37 additions & 30 deletions infra/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"_generator": {
"name": "bicep",
"version": "0.34.44.8038",
"templateHash": "11969070936051168983"
"templateHash": "1028263065130624134"
}
},
"parameters": {
Expand Down Expand Up @@ -1961,23 +1961,42 @@
"applicationInsightsId": {
"value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_ai_foundry'), '2022-09-01').outputs.applicationInsightsId.value]"
},
"azureOpenAIKey": {
"reference": {
"keyVault": {
"id": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.KeyVault/vaults', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_ai_foundry'), '2022-09-01').outputs.keyvaultName.value)]"
},
"secretName": "AZURE-OPENAI-KEY"
}
},
"azureAiProjectConnString": {
"reference": {
"keyVault": {
"id": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.KeyVault/vaults', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_ai_foundry'), '2022-09-01').outputs.keyvaultName.value)]"
},
"secretName": "AZURE-AI-PROJECT-CONN-STRING"
}
},
"azureSearchAdminKey": {
"reference": {
"keyVault": {
"id": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.KeyVault/vaults', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_ai_foundry'), '2022-09-01').outputs.keyvaultName.value)]"
},
"secretName": "AZURE-SEARCH-KEY"
}
},
"solutionName": {
"value": "[variables('solutionPrefix')]"
},
"userassignedIdentityId": {
"value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_managed_identity'), '2022-09-01').outputs.managedIdentityBackendAppOutput.value.id]"
},
"keyVaultName": {
"value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_ai_foundry'), '2022-09-01').outputs.keyvaultName.value]"
},
"appSettings": {
"value": {
"AZURE_OPEN_AI_DEPLOYMENT_MODEL": "[parameters('gptModelName')]",
"AZURE_OPEN_AI_ENDPOINT": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_ai_foundry'), '2022-09-01').outputs.aiServicesTarget.value]",
"AZURE_OPENAI_API_VERSION": "[variables('azureOpenAIApiVersion')]",
"AZURE_OPENAI_RESOURCE": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_ai_foundry'), '2022-09-01').outputs.aiServicesName.value]",
"AZURE_OPENAI_API_KEY": "AZURE-OPENAI-KEY",
"AZURE_KEY_VAULT_URL": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_keyvault'), '2022-09-01').outputs.keyvaultUri.value]",
"USE_CHAT_HISTORY_ENABLED": "True",
"AZURE_COSMOSDB_ACCOUNT": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_cosmos_db'), '2022-09-01').outputs.cosmosAccountName.value]",
"AZURE_COSMOSDB_CONVERSATIONS_CONTAINER": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_cosmos_db'), '2022-09-01').outputs.cosmosContainerName.value]",
Expand All @@ -1990,9 +2009,7 @@
"OPENAI_API_VERSION": "[variables('azureOpenAIApiVersion')]",
"AZURE_AI_SEARCH_ENDPOINT": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_ai_foundry'), '2022-09-01').outputs.aiSearchTarget.value]",
"AZURE_AI_SEARCH_INDEX": "call_transcripts_index",
"AZURE_AI_SEARCH_API_KEY": "AZURE-SEARCH-KEY",
"USE_AI_PROJECT_CLIENT": "False",
"AZURE_AI_PROJECT_CONN_STRING": "AZURE-AI-PROJECT-CONN-STRING",
"DISPLAY_CHART_DEFAULT": "True"
}
}
Expand All @@ -2004,7 +2021,7 @@
"_generator": {
"name": "bicep",
"version": "0.34.44.8038",
"templateHash": "3648197818087330444"
"templateHash": "445807380408189331"
}
},
"parameters": {
Expand All @@ -2024,18 +2041,23 @@
"appServicePlanId": {
"type": "string"
},
"userassignedIdentityId": {
"type": "string"
"azureOpenAIKey": {
"type": "securestring"
},
"keyVaultName": {
"azureAiProjectConnString": {
"type": "securestring"
},
"azureSearchAdminKey": {
"type": "securestring"
},
"userassignedIdentityId": {
"type": "string"
}
},
"variables": {
"imageName": "[format('DOCKER|kmcontainerreg.azurecr.io/km-api:{0}', parameters('imageTag'))]",
"name": "[format('{0}-api', parameters('solutionName'))]",
"reactAppLayoutConfig": "{\r\n \"appConfig\": {\r\n \"THREE_COLUMN\": {\r\n \"DASHBOARD\": 50,\r\n \"CHAT\": 33,\r\n \"CHATHISTORY\": 17\r\n },\r\n \"TWO_COLUMN\": {\r\n \"DASHBOARD_CHAT\": {\r\n \"DASHBOARD\": 65,\r\n \"CHAT\": 35\r\n },\r\n \"CHAT_CHATHISTORY\": {\r\n \"CHAT\": 80,\r\n \"CHATHISTORY\": 20\r\n }\r\n }\r\n },\r\n \"charts\": [\r\n {\r\n \"id\": \"SATISFIED\",\r\n \"name\": \"Satisfied\",\r\n \"type\": \"card\",\r\n \"layout\": { \"row\": 1, \"column\": 1, \"height\": 11 }\r\n },\r\n {\r\n \"id\": \"TOTAL_CALLS\",\r\n \"name\": \"Total Calls\",\r\n \"type\": \"card\",\r\n \"layout\": { \"row\": 1, \"column\": 2, \"span\": 1 }\r\n },\r\n {\r\n \"id\": \"AVG_HANDLING_TIME\",\r\n \"name\": \"Average Handling Time\",\r\n \"type\": \"card\",\r\n \"layout\": { \"row\": 1, \"column\": 3, \"span\": 1 }\r\n },\r\n {\r\n \"id\": \"SENTIMENT\",\r\n \"name\": \"Topics Overview\",\r\n \"type\": \"donutchart\",\r\n \"layout\": { \"row\": 2, \"column\": 1, \"width\": 40, \"height\": 44.5 }\r\n },\r\n {\r\n \"id\": \"AVG_HANDLING_TIME_BY_TOPIC\",\r\n \"name\": \"Average Handling Time By Topic\",\r\n \"type\": \"bar\",\r\n \"layout\": { \"row\": 2, \"column\": 2, \"row-span\": 2, \"width\": 60 }\r\n },\r\n {\r\n \"id\": \"TOPICS\",\r\n \"name\": \"Trending Topics\",\r\n \"type\": \"table\",\r\n \"layout\": { \"row\": 3, \"column\": 1, \"span\": 2 }\r\n },\r\n {\r\n \"id\": \"KEY_PHRASES\",\r\n \"name\": \"Key Phrases\",\r\n \"type\": \"wordcloud\",\r\n \"layout\": { \"row\": 3, \"column\": 2, \"height\": 44.5 }\r\n }\r\n ]\r\n}",
"keyVaultSecretsOfficerId": "b86a8fe4-44ce-4948-aee5-eccb2c155cd7"
"reactAppLayoutConfig": "{\r\n \"appConfig\": {\r\n \"THREE_COLUMN\": {\r\n \"DASHBOARD\": 50,\r\n \"CHAT\": 33,\r\n \"CHATHISTORY\": 17\r\n },\r\n \"TWO_COLUMN\": {\r\n \"DASHBOARD_CHAT\": {\r\n \"DASHBOARD\": 65,\r\n \"CHAT\": 35\r\n },\r\n \"CHAT_CHATHISTORY\": {\r\n \"CHAT\": 80,\r\n \"CHATHISTORY\": 20\r\n }\r\n }\r\n },\r\n \"charts\": [\r\n {\r\n \"id\": \"SATISFIED\",\r\n \"name\": \"Satisfied\",\r\n \"type\": \"card\",\r\n \"layout\": { \"row\": 1, \"column\": 1, \"height\": 11 }\r\n },\r\n {\r\n \"id\": \"TOTAL_CALLS\",\r\n \"name\": \"Total Calls\",\r\n \"type\": \"card\",\r\n \"layout\": { \"row\": 1, \"column\": 2, \"span\": 1 }\r\n },\r\n {\r\n \"id\": \"AVG_HANDLING_TIME\",\r\n \"name\": \"Average Handling Time\",\r\n \"type\": \"card\",\r\n \"layout\": { \"row\": 1, \"column\": 3, \"span\": 1 }\r\n },\r\n {\r\n \"id\": \"SENTIMENT\",\r\n \"name\": \"Topics Overview\",\r\n \"type\": \"donutchart\",\r\n \"layout\": { \"row\": 2, \"column\": 1, \"width\": 40, \"height\": 44.5 }\r\n },\r\n {\r\n \"id\": \"AVG_HANDLING_TIME_BY_TOPIC\",\r\n \"name\": \"Average Handling Time By Topic\",\r\n \"type\": \"bar\",\r\n \"layout\": { \"row\": 2, \"column\": 2, \"row-span\": 2, \"width\": 60 }\r\n },\r\n {\r\n \"id\": \"TOPICS\",\r\n \"name\": \"Trending Topics\",\r\n \"type\": \"table\",\r\n \"layout\": { \"row\": 3, \"column\": 1, \"span\": 2 }\r\n },\r\n {\r\n \"id\": \"KEY_PHRASES\",\r\n \"name\": \"Key Phrases\",\r\n \"type\": \"wordcloud\",\r\n \"layout\": { \"row\": 3, \"column\": 2, \"height\": 44.5 }\r\n }\r\n ]\r\n}"
},
"resources": [
{
Expand All @@ -2051,20 +2073,6 @@
"[resourceId('Microsoft.Resources/deployments', format('{0}-app-module', variables('name')))]"
]
},
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2022-04-01",
"scope": "[format('Microsoft.KeyVault/vaults/{0}', parameters('keyVaultName'))]",
"name": "[guid(resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName')), subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('keyVaultSecretsOfficerId')))]",
"properties": {
"roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', variables('keyVaultSecretsOfficerId'))]",
"principalId": "[reference(resourceId('Microsoft.Resources/deployments', format('{0}-app-module', variables('name'))), '2022-09-01').outputs.identityPrincipalId.value]",
"principalType": "ServicePrincipal"
},
"dependsOn": [
"[resourceId('Microsoft.Resources/deployments', format('{0}-app-module', variables('name')))]"
]
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2022-09-01",
Expand All @@ -2088,7 +2096,7 @@
"value": "[parameters('userassignedIdentityId')]"
},
"appSettings": {
"value": "[union(parameters('appSettings'), createObject('APPINSIGHTS_INSTRUMENTATIONKEY', reference(parameters('applicationInsightsId'), '2015-05-01').InstrumentationKey, 'REACT_APP_LAYOUT_CONFIG', variables('reactAppLayoutConfig')))]"
"value": "[union(parameters('appSettings'), createObject('AZURE_OPENAI_API_KEY', parameters('azureOpenAIKey'), 'AZURE_AI_SEARCH_API_KEY', parameters('azureSearchAdminKey'), 'AZURE_AI_PROJECT_CONN_STRING', parameters('azureAiProjectConnString'), 'APPINSIGHTS_INSTRUMENTATIONKEY', reference(parameters('applicationInsightsId'), '2015-05-01').InstrumentationKey, 'REACT_APP_LAYOUT_CONFIG', variables('reactAppLayoutConfig')))]"
}
},
"template": {
Expand Down Expand Up @@ -2273,7 +2281,6 @@
"[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_ai_foundry')]",
"[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_cosmos_db')]",
"[resourceId('Microsoft.Resources/deployments', 'deploy_app_service_plan')]",
"[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_keyvault')]",
"[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_managed_identity')]",
"[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, resourceGroup().name), 'Microsoft.Resources/deployments', 'deploy_sql_db')]"
]
Expand Down
19 changes: 11 additions & 8 deletions src/api/ApiApp.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
FROM python:3.11-alpine

# Install system dependencies required for building and running the application
RUN apk add --no-cache --virtual .build-deps \
build-base \
libffi-dev \
openssl-dev \
RUN apk add --no-cache --virtual .build-deps \
build-base \
libffi-dev \
openssl-dev \
curl \
unixodbc-dev \
libpq
unixodbc-dev \
libpq \
opus-dev \
libvpx-dev

# Download and install Microsoft ODBC Driver and MSSQL tools
RUN curl -O https://download.microsoft.com/download/e/4/e/e4e67866-dffd-428c-aac7-8d28ddafb39b/msodbcsql17_17.10.6.1-1_amd64.apk \
Expand All @@ -23,7 +25,8 @@ WORKDIR /app
COPY ./requirements.txt .

# Install Python dependencies
RUN pip install --no-cache-dir -r requirements.txt && rm -rf /root/.cache
RUN pip install --upgrade pip setuptools wheel \
&& pip install --no-cache-dir -r requirements.txt && rm -rf /root/.cache

# Copy the backend application code into the container
COPY ./ .
Expand All @@ -32,4 +35,4 @@ COPY ./ .
EXPOSE 80

# Start the application using Uvicorn
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "80"]
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "80"]
Loading
Loading