diff --git a/build.gradle.kts b/build.gradle.kts index 06352597..a4aa9b17 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { allprojects { group = "com.just-ai.jaicf" - version = "1.3.6" + version = "1.3.7" repositories { mavenCentral() diff --git a/channels/jaicp/src/main/kotlin/com/justai/jaicf/channel/jaicp/dto/config/AsrConfig.kt b/channels/jaicp/src/main/kotlin/com/justai/jaicf/channel/jaicp/dto/config/AsrConfig.kt index da49afaa..270e3a37 100644 --- a/channels/jaicp/src/main/kotlin/com/justai/jaicf/channel/jaicp/dto/config/AsrConfig.kt +++ b/channels/jaicp/src/main/kotlin/com/justai/jaicf/channel/jaicp/dto/config/AsrConfig.kt @@ -2,6 +2,7 @@ package com.justai.jaicf.channel.jaicp.dto.config import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonObject /** * Configuration parameters for the automatic speech recognition (ASR) provider used in a telephone channel. @@ -18,6 +19,8 @@ import kotlinx.serialization.Serializable * @param azure configuration options for the Azure ASR provider, if used. * @param asm configuration options for the ASM ASR provider, if used. * @param sber configuration options for the Sber ASR provider, if used. + * @param asrProperties special properties used with selected ASR, if used. + * @param tokenData data used for ASR auth, if used. **/ @Serializable data class AsrConfig( @@ -30,7 +33,9 @@ data class AsrConfig( val mts: AsrMtsConfig? = null, val azure: AsrAzureConfig? = null, val asm: AsrAsmConfig? = null, - val sber: AsrSberConfig? = null + val sber: AsrSberConfig? = null, + val asrProperties: JsonObject? = null, + val tokenData: JsonObject? = null ) { @Serializable enum class AsrProviderType { @@ -71,18 +76,22 @@ data class AsrConfig( * Subclasses contain provider-specific settings that are used to configure the ASR provider for the current session. **/ @Serializable -sealed class AsrProviderConfig +sealed class AsrProviderConfig{ + abstract val asrProperties: JsonObject? +} @Serializable data class AsrGoogleConfig( val model: String? = null, - val lang: String? = null + val lang: String? = null, + override val asrProperties: JsonObject? = null ) : AsrProviderConfig() @Serializable data class AsrZitechConfig( val model: String? = null, - val lang: String? = null + val lang: String? = null, + override val asrProperties: JsonObject? = null ) : AsrProviderConfig() @Serializable @@ -90,21 +99,24 @@ data class AsrYandexConfig( val model: String? = null, val lang: String? = null, val numbersAsWords: Boolean? = null, - val sensitivityReduction: Boolean? = null + val sensitivityReduction: Boolean? = null, + override val asrProperties: JsonObject? = null ) : AsrProviderConfig() @Serializable data class AsrMtsConfig( val model: String? = null, val lang: String? = null, - val transferType: String? = null + val transferType: String? = null, + override val asrProperties: JsonObject? = null ) : AsrProviderConfig() @Serializable data class AsrAimyvoiceConfig( val codec: String? = null, val mode: String? = null, - val grammarFileNames: String? = null + val grammarFileNames: String? = null, + override val asrProperties: JsonObject? = null ) : AsrProviderConfig() @Serializable @@ -112,17 +124,20 @@ data class AsrAzureConfig( val language: String? = null, val outputFormat: String? = null, val profanityOption: String? = null, - val enableDictation: Boolean? = null + val enableDictation: Boolean? = null, + override val asrProperties: JsonObject? = null ) : AsrProviderConfig() @Serializable data class AsrAsmConfig( val sampleRate: Long? = null, val model: String? = null, + override val asrProperties: JsonObject? = null ) : AsrProviderConfig() @Serializable data class AsrSberConfig( val language: String? = null, - val model: String? = null + val model: String? = null, + override val asrProperties: JsonObject? = null ) : AsrProviderConfig() \ No newline at end of file diff --git a/channels/jaicp/src/main/kotlin/com/justai/jaicf/channel/jaicp/reactions/TelephonyReactions.kt b/channels/jaicp/src/main/kotlin/com/justai/jaicf/channel/jaicp/reactions/TelephonyReactions.kt index 276bda16..e6365de5 100755 --- a/channels/jaicp/src/main/kotlin/com/justai/jaicf/channel/jaicp/reactions/TelephonyReactions.kt +++ b/channels/jaicp/src/main/kotlin/com/justai/jaicf/channel/jaicp/reactions/TelephonyReactions.kt @@ -4,6 +4,7 @@ import com.justai.jaicf.channel.jaicp.channels.TelephonyChannel import com.justai.jaicf.channel.jaicp.dto.* import com.justai.jaicf.channel.jaicp.dto.bargein.* import com.justai.jaicf.channel.jaicp.dto.config.* +import com.justai.jaicf.channel.jaicp.reactions.handlers.* import com.justai.jaicf.helpers.http.toUrl import com.justai.jaicf.logging.AudioReaction import com.justai.jaicf.logging.SayReaction @@ -28,6 +29,21 @@ class TelephonyReactions(private val bargeInDefaultProps: BargeInProperties) : J internal var asrConfig: AsrConfig? = null + private val setAsrPropertiesHandler = SetAsrPropertiesHandler( + listOf( + SetAsrPropertiesHandlerSber(), + SetAsrPropertiesHandlerYandex(), + SetAsrPropertiesHandlerGoogle(), + SetAsrPropertiesHandlerMts(), + SetAsrPropertiesHandlerZitech(), + SetAsrPropertiesHandlerAimyvoice(), + SetAsrPropertiesHandlerAzure(), + SetAsrPropertiesHandlerAsm(), + SetAsrPropertiesHandlerKaldi(), + SetAsrPropertiesHandlerTinkoff(), + ) + ) + companion object { private const val CURRENT_CONTEXT_PATH = "." } @@ -201,6 +217,27 @@ class TelephonyReactions(private val bargeInDefaultProps: BargeInProperties) : J ) } + /** + * This method overrides the ASR properties of the ASR used for the current call. + * example usage: + * ``` + * state("asr") { + * action { + * reactions.telephony?.setAsrProperties( + * mapOf("enable_profanity_filter" to "true") + * ) + * } + * } + * ``` + * @param properties map of properties names with its assigned values. + * */ + fun setAsrProperties(properties: Map) { + asrConfig = setAsrPropertiesHandler.handle( + properties, + mergeAsrConfigs(asrConfig, (executionContext.request as TelephonyBotRequest).asrConfig) + ) + } + /** * Schedules a redial in outbound call campaign. * @@ -460,4 +497,20 @@ class TelephonyReactions(private val bargeInDefaultProps: BargeInProperties) : J private fun ensureBargeInProps() { bargeIn = bargeIn ?: bargeInDefaultProps } + + private fun mergeAsrConfigs(firstAsrConfig: AsrConfig?, secondAsrConfig: AsrConfig?): AsrConfig { + return AsrConfig( + type = firstAsrConfig?.type ?: secondAsrConfig?.type, + yandex = firstAsrConfig?.yandex ?: secondAsrConfig?.yandex, + zitech = firstAsrConfig?.zitech ?: secondAsrConfig?.zitech, + google = firstAsrConfig?.google ?: secondAsrConfig?.google, + aimyvoice = firstAsrConfig?.aimyvoice ?: secondAsrConfig?.aimyvoice, + mts = firstAsrConfig?.mts ?: secondAsrConfig?.mts, + azure = firstAsrConfig?.azure ?: secondAsrConfig?.azure, + asm = firstAsrConfig?.asm ?: secondAsrConfig?.asm, + sber = firstAsrConfig?.sber ?: secondAsrConfig?.sber, + asrProperties = firstAsrConfig?.asrProperties ?: secondAsrConfig?.asrProperties, + tokenData = firstAsrConfig?.tokenData ?: secondAsrConfig?.tokenData + ) + } } diff --git a/channels/jaicp/src/main/kotlin/com/justai/jaicf/channel/jaicp/reactions/handlers/SetAsrPropertiesHandler.kt b/channels/jaicp/src/main/kotlin/com/justai/jaicf/channel/jaicp/reactions/handlers/SetAsrPropertiesHandler.kt new file mode 100644 index 00000000..b5f73ecf --- /dev/null +++ b/channels/jaicp/src/main/kotlin/com/justai/jaicf/channel/jaicp/reactions/handlers/SetAsrPropertiesHandler.kt @@ -0,0 +1,147 @@ +package com.justai.jaicf.channel.jaicp.reactions.handlers + +import com.justai.jaicf.channel.jaicp.dto.config.* +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive + +class SetAsrPropertiesHandler( + private val listOfActualHandlers: List +) { + + fun handle(properties: Map, asrConfig: AsrConfig): AsrConfig { + val propertiesJson = JsonObject(properties.toMutableMap().mapValues { entry -> JsonPrimitive(entry.value) }) + return listOfActualHandlers.first { it.canHandle(checkNotNull(asrConfig.type)) } + .handle(asrConfig, propertiesJson) + } +} + +interface SetAsrPropertiesHandlerAbstract { + fun canHandle(type: AsrConfig.AsrProviderType): Boolean + fun handle(asrConfig: AsrConfig, propertiesJson: JsonObject): AsrConfig +} + +class SetAsrPropertiesHandlerSber() : SetAsrPropertiesHandlerAbstract { + override fun canHandle(type: AsrConfig.AsrProviderType): Boolean = + type == AsrConfig.AsrProviderType.SBER + + override fun handle(asrConfig: AsrConfig, propertiesJson: JsonObject): AsrConfig { + val asrProviderConfig: AsrSberConfig = checkNotNull(asrConfig.sber) + return asrConfig.copy( + asrProperties = propertiesJson, + sber = asrProviderConfig.copy(asrProperties = propertiesJson) + ) + } +} + +class SetAsrPropertiesHandlerYandex() : SetAsrPropertiesHandlerAbstract { + override fun canHandle(type: AsrConfig.AsrProviderType): Boolean = + type == AsrConfig.AsrProviderType.YANDEX + + override fun handle(asrConfig: AsrConfig, propertiesJson: JsonObject): AsrConfig { + val asrProviderConfig: AsrYandexConfig = checkNotNull(asrConfig.yandex) + return asrConfig.copy( + asrProperties = propertiesJson, + yandex = asrProviderConfig.copy(asrProperties = propertiesJson) + ) + } +} + +class SetAsrPropertiesHandlerGoogle() : SetAsrPropertiesHandlerAbstract { + override fun canHandle(type: AsrConfig.AsrProviderType): Boolean = + type == AsrConfig.AsrProviderType.GOOGLE + + override fun handle(asrConfig: AsrConfig, propertiesJson: JsonObject): AsrConfig { + val asrProviderConfig: AsrGoogleConfig = checkNotNull(asrConfig.google) + return asrConfig.copy( + asrProperties = propertiesJson, + google = asrProviderConfig.copy(asrProperties = propertiesJson) + ) + } +} + +class SetAsrPropertiesHandlerMts() : SetAsrPropertiesHandlerAbstract { + override fun canHandle(type: AsrConfig.AsrProviderType): Boolean = + type == AsrConfig.AsrProviderType.MTS + + override fun handle(asrConfig: AsrConfig, propertiesJson: JsonObject): AsrConfig { + val asrProviderConfig: AsrMtsConfig = checkNotNull(asrConfig.mts) + return asrConfig.copy( + asrProperties = propertiesJson, + mts = asrProviderConfig.copy(asrProperties = propertiesJson) + ) + } +} + +class SetAsrPropertiesHandlerZitech() : SetAsrPropertiesHandlerAbstract { + override fun canHandle(type: AsrConfig.AsrProviderType): Boolean = + type == AsrConfig.AsrProviderType.ZITECH + + override fun handle(asrConfig: AsrConfig, propertiesJson: JsonObject): AsrConfig { + val asrProviderConfig: AsrZitechConfig = checkNotNull(asrConfig.zitech) + return asrConfig.copy( + asrProperties = propertiesJson, + zitech = asrProviderConfig.copy(asrProperties = propertiesJson) + ) + } +} + +class SetAsrPropertiesHandlerAimyvoice() : SetAsrPropertiesHandlerAbstract { + override fun canHandle(type: AsrConfig.AsrProviderType): Boolean = + type == AsrConfig.AsrProviderType.AIMYVOICE + + override fun handle(asrConfig: AsrConfig, propertiesJson: JsonObject): AsrConfig { + val asrProviderConfig: AsrAimyvoiceConfig = checkNotNull(asrConfig.aimyvoice) + return asrConfig.copy( + asrProperties = propertiesJson, + aimyvoice = asrProviderConfig.copy(asrProperties = propertiesJson) + ) + } +} + +class SetAsrPropertiesHandlerAzure() : SetAsrPropertiesHandlerAbstract { + override fun canHandle(type: AsrConfig.AsrProviderType): Boolean = + type == AsrConfig.AsrProviderType.AZURE + + override fun handle(asrConfig: AsrConfig, propertiesJson: JsonObject): AsrConfig { + val asrProviderConfig: AsrAzureConfig = checkNotNull(asrConfig.azure) + return asrConfig.copy( + asrProperties = propertiesJson, + azure = asrProviderConfig.copy(asrProperties = propertiesJson) + ) + } +} + +class SetAsrPropertiesHandlerAsm() : SetAsrPropertiesHandlerAbstract { + override fun canHandle(type: AsrConfig.AsrProviderType): Boolean = + type == AsrConfig.AsrProviderType.ASM + + override fun handle(asrConfig: AsrConfig, propertiesJson: JsonObject): AsrConfig { + val asrProviderConfig: AsrAsmConfig = checkNotNull(asrConfig.asm) + return asrConfig.copy( + asrProperties = propertiesJson, + asm = asrProviderConfig.copy(asrProperties = propertiesJson) + ) + } +} + +class SetAsrPropertiesHandlerKaldi() : SetAsrPropertiesHandlerAbstract { + override fun canHandle(type: AsrConfig.AsrProviderType): Boolean = + type == AsrConfig.AsrProviderType.KALDI + + override fun handle(asrConfig: AsrConfig, propertiesJson: JsonObject): AsrConfig { + return asrConfig.copy( + asrProperties = propertiesJson + ) + } +} + +class SetAsrPropertiesHandlerTinkoff() : SetAsrPropertiesHandlerAbstract { + override fun canHandle(type: AsrConfig.AsrProviderType): Boolean = + type == AsrConfig.AsrProviderType.TINKOFF + + override fun handle(asrConfig: AsrConfig, propertiesJson: JsonObject): AsrConfig { + return asrConfig.copy( + asrProperties = propertiesJson + ) + } +} \ No newline at end of file