Skip to content

Commit

Permalink
Merge branch 'feat/ivr-lang' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
clemlesne committed Feb 9, 2024
2 parents 19358ae + 3ad1a7c commit 131e60c
Show file tree
Hide file tree
Showing 22 changed files with 670 additions and 329 deletions.
30 changes: 27 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Extract of the data stored during the call:
- [x] Access the claim on a public website
- [x] Access to customer conversation history
- [x] Allow user to change the language of the conversation
- [x] Bot can be called from a phone number
- [x] Bot use multiple voice tones (e.g. happy, sad, neutral) to keep the conversation engaging
- [x] Company products (= lexicon) can be understood by the bot (e.g. a name of a specific insurance product)
Expand Down Expand Up @@ -106,9 +107,11 @@ graph LR
db[("Conversations and claims\n(Cosmos DB or SQLite)")]
event_grid[("Broker\n(Event Grid)")]
gpt["GPT-4 Turbo\n(OpenAI)"]
translation["Translation\n(Cognitive Services)"]
end
api -- Answer with text --> communication_service
api -- Ask for translation --> translation
api -- Few-shot training --> ai_search
api -- Generate completion --> gpt
api -- Save conversation --> db
Expand Down Expand Up @@ -211,6 +214,7 @@ workflow:
agent_phone_number: "+33612345678"
bot_company: Contoso
bot_name: Robert
lang: {}

communication_service:
phone_number: "+33612345678"
Expand Down Expand Up @@ -264,11 +268,9 @@ communication_service:
access_key: xxx
endpoint: https://xxx.france.communication.azure.com
phone_number: "+33612345678"
voice_name: fr-FR-DeniseNeural
cognitive_service:
# Must be of type "AI services multi-service account"
# See: https://learn.microsoft.com/en-us/azure/ai-services/multi-service-resource?tabs=macos&pivots=azportal#create-a-new-multi-service-resource
endpoint: https://xxx.cognitiveservices.azure.com
openai:
Expand Down Expand Up @@ -373,7 +375,7 @@ prompts:
Assistant will provide internal IT support to employees. Assistant requires data from the employee to provide IT support. The assistant's role is not over until the issue is resolved or the request is fulfilled.
# Rules
- Answers in {conversation_lang}, even if the employee speaks in a different language
- Answers in {default_lang}, even if the customer speaks another language
- Cannot talk about any topic other than IT support
- Is polite, helpful, and professional
- Rephrase the employee's questions as statements and answer them
Expand Down Expand Up @@ -401,6 +403,28 @@ prompts:
{reminders}
```

### Customize the languages

The bot can be used in multiple languages. It can understand the language the user chose.

See the [list of supported languages](https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support?tabs=tts#supported-languages) for the Text-to-Speech service.

```yaml
# config.yaml
[...]
workflow:
lang:
default_short_code: "fr-FR"
availables:
- pronunciations_en: ["French", "FR", "France"]
short_code: "fr-FR"
voice_name: "fr-FR-DeniseNeural"
- pronunciations_en: ["Chinese", "ZH", "China"]
short_code: "zh-CN"
voice_name: "zh-CN-XiaoxiaoNeural"
```

### Customize the moderation levels

Levels are defined for each category of Content Safety. The higher the score, the more strict the moderation is, from 0 to 7.
Expand Down
36 changes: 26 additions & 10 deletions bicep/app.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ param agentPhoneNumber string
param botCompany string
param botName string
param botPhoneNumber string
param botVoiceName string
param gptModel string
param gptVersion string
param imageVersion string
Expand Down Expand Up @@ -38,12 +37,12 @@ var config = {
agent_phone_number: agentPhoneNumber
bot_company: botCompany
bot_name: botName
lang: loadYamlContent('../config.yaml').workflow.lang
}
communication_service: {
access_key: communication.listKeys().primaryKey
endpoint: communication.properties.hostName
phone_number: botPhoneNumber
voice_name: botVoiceName
}
cognitive_service: {
endpoint: cognitiveCommunication.properties.endpoint
Expand All @@ -68,6 +67,10 @@ var config = {
llm: loadYamlContent('../config.yaml').prompts.llm
tts: loadYamlContent('../config.yaml').prompts.tts
}
ai_translation: {
access_key: translate.listKeys().key1
endpoint: 'https://${translate.name}.cognitiveservices.azure.com/'
}
}

output appUrl string = appUrl
Expand All @@ -81,7 +84,7 @@ resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10
properties: {
retentionInDays: 30
sku: {
name: 'PerGB2018'
name: 'PerGB2018' // Pay-as-you-go
}
}
}
Expand Down Expand Up @@ -221,7 +224,7 @@ resource cognitiveCommunication 'Microsoft.CognitiveServices/accounts@2023-10-01
location: location
tags: tags
sku: {
name: 'S0'
name: 'S0' // Only one available
}
kind: 'CognitiveServices'
properties: {
Expand All @@ -234,7 +237,7 @@ resource cognitiveDocument 'Microsoft.CognitiveServices/accounts@2023-10-01-prev
location: location
tags: tags
sku: {
name: 'S0'
name: 'S0' // Pay-as-you-go
}
kind: 'FormRecognizer'
properties: {
Expand All @@ -247,7 +250,7 @@ resource cognitiveContentsafety 'Microsoft.CognitiveServices/accounts@2023-10-01
location: location
tags: tags
sku: {
name: 'S0'
name: 'S0' // Pay-as-you-go
}
kind: 'ContentSafety'
properties: {
Expand Down Expand Up @@ -278,7 +281,7 @@ resource cognitiveOpenai 'Microsoft.CognitiveServices/accounts@2023-10-01-previe
location: openaiLocation
tags: tags
sku: {
name: 'S0'
name: 'S0' // Pay-as-you-go
}
kind: 'OpenAI'
properties: {
Expand All @@ -291,7 +294,7 @@ resource gpt 'Microsoft.CognitiveServices/accounts/deployments@2023-10-01-previe
name: gptModelFullName
sku: {
capacity: 50
name: 'Standard'
name: 'Standard' // Pay-as-you-go
}
properties: {
// raiPolicyName: contentfilter.name
Expand Down Expand Up @@ -367,7 +370,7 @@ resource ada 'Microsoft.CognitiveServices/accounts/deployments@2023-10-01-previe
name: adaModelFullName
sku: {
capacity: 50
name: 'Standard'
name: 'Standard' // Pay-as-you-go
}
properties: {
// raiPolicyName: contentfilter.name
Expand Down Expand Up @@ -460,7 +463,7 @@ resource search 'Microsoft.Search/searchServices@2023-11-01' = {
location: searchLocation
tags: tags
sku: {
name: 'basic'
name: 'basic' // Smallest with semantic search
}
identity: {
type: 'SystemAssigned'
Expand All @@ -469,3 +472,16 @@ resource search 'Microsoft.Search/searchServices@2023-11-01' = {
semanticSearch: 'standard'
}
}

resource translate 'Microsoft.CognitiveServices/accounts@2023-10-01-preview' = {
name: '${prefix}-translate'
location: location
tags: tags
sku: {
name: 'S1' // Pay-as-you-go
}
kind: 'TextTranslation'
properties: {
customSubDomainName: '${prefix}-translate'
}
}
1 change: 0 additions & 1 deletion bicep/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ module app 'app.bicep' = {
botCompany: botCompany
botName: botName
botPhoneNumber: botPhoneNumber
botVoiceName: 'fr-FR-DeniseNeural'
gptModel: gptModel
gptVersion: gptVersion
imageVersion: imageVersion
Expand Down
7 changes: 7 additions & 0 deletions helpers/config_models/ai_translation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from pydantic import SecretStr
from pydantic_settings import BaseSettings


class AiTranslationModel(BaseSettings):
access_key: SecretStr
endpoint: str
1 change: 0 additions & 1 deletion helpers/config_models/communication_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@ class CommunicationServiceModel(BaseSettings):
access_key: SecretStr
endpoint: str
phone_number: PhoneNumber
voice_name: str
8 changes: 4 additions & 4 deletions helpers/config_models/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from typing import Optional


class Mode(str, Enum):
class ModeEnum(str, Enum):
COSMOS_DB = "cosmos_db"
SQLITE = "sqlite"

Expand Down Expand Up @@ -32,17 +32,17 @@ def full_path(self) -> str:

class DatabaseModel(BaseSettings):
cosmos_db: Optional[CosmosDbModel] = None
mode: Mode = Mode.SQLITE
mode: ModeEnum = ModeEnum.SQLITE
sqlite: Optional[SqliteModel] = None

@validator("cosmos_db", always=True)
def check_cosmos_db(cls, v, values, **kwargs):
if not v and values.get("mode", None) == Mode.COSMOS_DB:
if not v and values.get("mode", None) == ModeEnum.COSMOS_DB:
raise ValueError("Cosmos DB config required")
return v

@validator("sqlite", always=True)
def check_sqlite(cls, v, values, **kwargs):
if not v and values.get("mode", None) == Mode.SQLITE:
if not v and values.get("mode", None) == ModeEnum.SQLITE:
raise ValueError("Sqlite config required")
return v
6 changes: 3 additions & 3 deletions helpers/config_models/monitoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from pydantic_settings import BaseSettings


class LoggingLevel(str, Enum):
class LoggingLevelEnum(str, Enum):
# Copied from https://docs.python.org/3.12/library/logging.html#logging-levels
CRITICAL = "CRITICAL"
DEBUG = "DEBUG"
Expand All @@ -13,8 +13,8 @@ class LoggingLevel(str, Enum):


class LoggingMonitoringModel(BaseSettings):
app_level: LoggingLevel = LoggingLevel.INFO
sys_level: LoggingLevel = LoggingLevel.WARNING
app_level: LoggingLevelEnum = LoggingLevelEnum.INFO
sys_level: LoggingLevelEnum = LoggingLevelEnum.WARNING


class MonitoringModel(BaseSettings):
Expand Down
Loading

0 comments on commit 131e60c

Please sign in to comment.