Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/set asr properties #263

Merged
merged 8 commits into from
Oct 3, 2024
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
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {

allprojects {
group = "com.just-ai.jaicf"
version = "1.3.6"
version = "1.3.7"

repositories {
mavenCentral()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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(
Expand All @@ -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 {
Expand Down Expand Up @@ -71,58 +76,68 @@ 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
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
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()
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 = "."
}
Expand Down Expand Up @@ -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<String, String>) {
asrConfig = setAsrPropertiesHandler.handle(
properties,
mergeAsrConfigs(asrConfig, (executionContext.request as TelephonyBotRequest).asrConfig)
)
}

/**
* Schedules a redial in outbound call campaign.
*
Expand Down Expand Up @@ -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
)
}
}
Original file line number Diff line number Diff line change
@@ -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<SetAsrPropertiesHandlerAbstract>
) {

fun handle(properties: Map<String, String>, 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
)
}
}
Loading