Skip to content

Commit

Permalink
Merge branch 'feat/bicep-deploy' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
clemlesne committed Jan 16, 2024
2 parents 83c104a + 664e6c3 commit 92dfc48
Show file tree
Hide file tree
Showing 10 changed files with 462 additions and 115 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ COPY --chown=appuser:appuser . /app

WORKDIR /app

CMD ["bash", "-c", "uvicorn main:api --host 0.0.0.0 --port 8080 --proxy-headers --no-server-header --timeout-keep-alive 60 --header x-version:${VERSION}"]
CMD ["bash", "-c", "WEB_CONCURRENCY=4 uvicorn main:api --host 0.0.0.0 --port 8080 --proxy-headers --no-server-header --timeout-keep-alive 60 --header x-version:${VERSION}"]
69 changes: 66 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,80 @@ build:
--tag $(container_name):latest \
.

run:
start:
@echo "🛠️ Deploying to localhost..."
$(docker) run \
--detach \
--env EVENTS_DOMAIN=$(tunnel_url) \
--env VERSION=$(version_full) \
--mount type=bind,source="$(CURDIR)/.env",target="/app/.env" \
--mount type=bind,source="$(CURDIR)/config.yaml",target="/app/config.yaml" \
--name claim-ai-phone-bot \
--name claim-ai \
--publish 8080:8080 \
--rm \
$(container_name):$(version_small)

$(MAKE) eventgrid-register \
endpoint=$(tunnel_url) \
name=$(tunnel_name) \
phone_number=$(shell cat config.yaml | yq '.communication_service.phone_number') \
source="/subscriptions/2e41c463-3dfb-4760-8161-60e8cefa6d28/resourceGroups/claim-ai/providers/Microsoft.Communication/communicationServices/claim-ai"

@echo "🚀 Claim AI is running on $(tunnel_url)"
$(docker) attach --name claim-ai

stop:
@echo "Stopping container..."
$(docker) stop claim-ai-phone-bot
$(docker) stop claim-ai

deploy:
@echo "🛠️ Deploying to Azure..."
az deployment sub create \
--location westeurope \
--parameters config='$(shell cat config.yaml | yq -o json)' \
--template-file bicep/main.bicep \
--name $(name)

$(MAKE) eventgrid-register \
endpoint=$(shell az deployment sub show --name $(name) | yq '.properties.outputs["appUrl"].value') \
name=$(name) \
phone_number=$(shell cat config.yaml | yq '.communication_service.phone_number') \
source=$(shell az deployment sub show --name $(name) | yq '.properties.outputs["communicationId"].value')

@echo "🚀 Claim AI is running on $(shell az deployment sub show --name $(name) | yq '.properties.outputs["appUrl"].value')"
$(MAKE) logs name=$(name)

destroy:
az deployment sub delete --name $(name)

logs:
az containerapp logs show \
--follow \
--format text \
--name claim-ai \
--resource-group $(name) \
--tail 100

eventgrid-register:
@echo "⚙️ Deleting previous event grid subscription..."
az eventgrid event-subscription delete --name $(name) || true

@echo "⚙️ Creating event grid subscription..."
az eventgrid event-subscription create \
--advanced-filter data.to.PhoneNumber.Value StringBeginsWith $(phone_number) \
--enable-advanced-filtering-on-arrays true \
--endpoint $(endpoint)/call/inbound \
--event-delivery-schema eventgridschema \
--event-ttl 3 \
--included-event-types Microsoft.Communication.IncomingCall \
--max-delivery-attempts 8 \
--name $(name) \
--source-resource-id $(source)

watch-call:
@echo "👀 Watching status of $(phone_number)..."
while true; do \
clear; \
curl -s "$(endpoint)/call?phone_number=%2B$(phone_number)" | yq --prettyPrint '.[0] | {"phone_number": .phone_number, "claim": .claim, "reminders": .reminders}'; \
sleep 3; \
done
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ AI-powered call center solution with Azure and OpenAI GPT.
[![Last release date](https://img.shields.io/github/release-date/clemlesne/claim-ai-phone-bot)](https://github.com/clemlesne/claim-ai-phone-bot/releases)
[![Project license](https://img.shields.io/github/license/clemlesne/claim-ai-phone-bot)](https://github.com/clemlesne/claim-ai-phone-bot/blob/main/LICENSE)

[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fclemlesne%2Fclaim-ai-phone-bot%2Fmain%2Fbicep%2Fmain.bicep)

## Overview

A French demo is avaialble on YouTube. Do not hesitate to watch the demo in x1.5 speed to get a quick overview of the project.
Expand Down Expand Up @@ -125,6 +127,8 @@ Place a file called `config.yaml` in the root of the project with the following
api:
root_path: "/"

database: {}

monitoring:
logging:
app_level: INFO
Expand Down
254 changes: 254 additions & 0 deletions bicep/app.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
param config string
param imageVersion string
param instance string = deployment().name
param location string = resourceGroup().location
param openaiLocation string
param tags object

var prefix = instance
var appUrl = 'https://claim-ai.${acaEnv.properties.defaultDomain}'

output appUrl string = appUrl
output communicationId string = communication.id

resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
name: prefix
location: location
tags: tags
properties: {
retentionInDays: 30
sku: {
name: 'PerGB2018'
}
}
}

resource acaEnv 'Microsoft.App/managedEnvironments@2023-05-01' = {
name: prefix
location: location
tags: tags
properties: {
appLogsConfiguration: {
destination: 'log-analytics'
logAnalyticsConfiguration: {
customerId: logAnalyticsWorkspace.properties.customerId
sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey
}
}
workloadProfiles: [
{
// Consumption workload profile name must be 'Consumption'
name: 'Consumption'
workloadProfileType: 'Consumption'
}
]
}
}

resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {
name: 'claim-ai'
location: location
tags: tags
identity: {
type: 'SystemAssigned'
}
properties: {
configuration: {
activeRevisionsMode: 'Single'
ingress: {
external: true
targetPort: 8080
}
}
environmentId: acaEnv.id
template: {
scale: {
maxReplicas: 1
}
containers: [
{
image: 'ghcr.io/clemlesne/claim-ai-phone-bot:${imageVersion}'
name: 'claim-ai'
env: [
{
name: 'CONFIG_JSON'
value: config
}
{
name: 'EVENTS_DOMAIN'
value: appUrl
}
{
name: 'SQLITE_PATH'
value: '/app/data/.default.sqlite'
}
]
resources: {
cpu: 1
memory: '2Gi'
}
probes: [
{
type: 'Liveness'
httpGet: {
path: '/health/liveness'
port: 8080
}
}
]
}
]
}
}
}

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: replace(prefix, '-', '')
location: location
tags: tags
sku: {
name: 'Standard_ZRS'
}
kind: 'StorageV2'
}

resource blobService 'Microsoft.Storage/storageAccounts/blobServices@2023-01-01' = {
parent: storageAccount
name: 'default'
}

resource blobContainer 'Microsoft.Storage/storageAccounts/blobServices/containers@2023-01-01' = {
parent: blobService
name: '$web'
}

resource roleCommunicationContributor 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' existing = {
name: 'b24988ac-6180-42a0-ab88-20f7382dd24c'
}

resource appContributeCommunication 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(subscription().id, deployment().name, 'appContributeCommunication')
scope: communication
properties: {
principalId: containerApp.identity.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: roleCommunicationContributor.id
}
}

resource communication 'Microsoft.Communication/CommunicationServices@2023-06-01-preview' existing = {
name: prefix
}

resource eventgridTopic 'Microsoft.EventGrid/systemTopics@2023-12-15-preview' = {
name: prefix
location: 'global'
tags: tags
properties: {
source: communication.id
topicType: 'Microsoft.Communication.CommunicationServices'
}
}

resource roleOpenaiContributor 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' existing = {
name: 'a001fd3d-188f-4b5d-821b-7da978bf7442'
}

resource appAccessOpenai 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(subscription().id, deployment().name, 'appAccessOpenai')
scope: cognitiveOpenai
properties: {
principalId: containerApp.identity.principalId
principalType: 'ServicePrincipal'
roleDefinitionId: roleOpenaiContributor.id
}
}

resource cognitiveOpenai 'Microsoft.CognitiveServices/accounts@2023-10-01-preview' = {
name: '${prefix}-openai'
location: openaiLocation
tags: tags
sku: {
name: 'S0'
}
kind: 'OpenAI'
properties: {
customSubDomainName: '${prefix}-openai'
}
}

resource gpt 'Microsoft.CognitiveServices/accounts/deployments@2023-10-01-preview' = {
parent: cognitiveOpenai
name: 'gpt'
sku: {
capacity: 50
name: 'Standard'
}
properties: {
raiPolicyName: contentfilter.name
model: {
format: 'OpenAI'
name: 'gpt-4'
version: '1106-Preview'
}
}
}

resource contentfilter 'Microsoft.CognitiveServices/accounts/raiPolicies@2023-06-01-preview' = {
parent: cognitiveOpenai
name: 'gpt'
properties: {
basePolicyName: 'Microsoft.Default'
mode: 'Default'
contentFilters: [
{
blocking: false
enabled: false
name: 'hate'
source: 'Prompt'
}
{
blocking: false
enabled: false
name: 'sexual'
source: 'Prompt'
}
{
blocking: false
enabled: false
name: 'selfharm'
source: 'Prompt'
}
{
blocking: false
enabled: false
name: 'violence'
source: 'Prompt'
}
{
blocking: false
enabled: false
name: 'hate'
source: 'Completion'
}
{
blocking: false
enabled: false
name: 'sexual'
source: 'Completion'
}
{
blocking: false
enabled: false
name: 'selfharm'
source: 'Completion'
}
{
blocking: false
enabled: false
name: 'violence'
source: 'Completion'
}
]
}
}
36 changes: 36 additions & 0 deletions bicep/main.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
param config string
param imageVersion string = 'feat-bicep-deploy'
param instance string = deployment().name
param location string = 'westeurope'
param openaiLocation string = 'swedencentral'

targetScope = 'subscription'

output appUrl string = app.outputs.appUrl
output communicationId string = app.outputs.communicationId

var tags = {
application: 'claim-ai'
instance: instance
managed_by: 'Bicep'
sources: 'https://github.com/clemlesne/claim-ai-phone-bot'
version: imageVersion
}

resource sub 'Microsoft.Resources/resourceGroups@2021-04-01' = {
location: location
name: instance
tags: tags
}

module app 'app.bicep' = {
name: instance
scope: sub
params: {
config: config
imageVersion: imageVersion
location: location
openaiLocation: openaiLocation
tags: tags
}
}
Loading

0 comments on commit 92dfc48

Please sign in to comment.