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

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 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.SetAsrPropertiesHandler
import com.justai.jaicf.helpers.http.toUrl
import com.justai.jaicf.logging.AudioReaction
import com.justai.jaicf.logging.SayReaction
Expand All @@ -28,6 +29,8 @@ class TelephonyReactions(private val bargeInDefaultProps: BargeInProperties) : J

internal var asrConfig: AsrConfig? = null

private val setAsrPropertiesHandler = SetAsrPropertiesHandler()

companion object {
private const val CURRENT_CONTEXT_PATH = "."
}
Expand Down Expand Up @@ -201,6 +204,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 +484,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,164 @@
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 setAsrPropertiesHandlerSber = SetAsrPropertiesHandlerSber()
private val setAsrPropertiesHandlerYandex = SetAsrPropertiesHandlerYandex()
private val setAsrPropertiesHandlerGoogle = SetAsrPropertiesHandlerGoogle()
private val setAsrPropertiesHandlerMts = SetAsrPropertiesHandlerMts()
private val setAsrPropertiesHandlerZitech = SetAsrPropertiesHandlerZitech()
private val setAsrPropertiesHandlerAimyvoice = SetAsrPropertiesHandlerAimyvoice()
private val setAsrPropertiesHandlerAzure = SetAsrPropertiesHandlerAzure()
private val setAsrPropertiesHandlerAsm = SetAsrPropertiesHandlerAsm()
private val setAsrPropertiesHandlerKaldi = SetAsrPropertiesHandlerKaldi()
private val setAsrPropertiesHandlerTinkoff = SetAsrPropertiesHandlerTinkoff()

fun handle(properties: Map<String, String>, asrConfig: AsrConfig): AsrConfig {
val propertiesJson = JsonObject(properties.toMutableMap().mapValues { entry -> JsonPrimitive(entry.value) })
return when (checkNotNull(asrConfig.type)) {
AsrConfig.AsrProviderType.SBER -> {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Главная идея - избавиться от этого when.

Условно нужно несколько моментов:

  1. Вынести конфигурацию списка хендлеров вне этого класса, т.е. будет что-то вида SetAsrPropertiesHandler(listOfActualHandlers)
  2. Сделать общий интерфейс хендлера с методами canHandle(...) и handle(...)
  3. Центральный хендлер (этот класс) делегирует canHandle() и handle() в лежащие внутри него хендлеры - кто первый ответит, что может захендлить, тот и хендлит.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Реализовал как описано выше

setAsrPropertiesHandlerSber.handle(asrConfig, propertiesJson)
}

AsrConfig.AsrProviderType.YANDEX -> {
setAsrPropertiesHandlerYandex.handle(asrConfig, propertiesJson)
}

AsrConfig.AsrProviderType.GOOGLE -> {
setAsrPropertiesHandlerGoogle.handle(asrConfig, propertiesJson)
}

AsrConfig.AsrProviderType.MTS -> {
setAsrPropertiesHandlerMts.handle(asrConfig, propertiesJson)
}

AsrConfig.AsrProviderType.ZITECH -> {
setAsrPropertiesHandlerZitech.handle(asrConfig, propertiesJson)
}

AsrConfig.AsrProviderType.AIMYVOICE -> {
setAsrPropertiesHandlerAimyvoice.handle(asrConfig, propertiesJson)
}

AsrConfig.AsrProviderType.AZURE -> {
setAsrPropertiesHandlerAzure.handle(asrConfig, propertiesJson)
}

AsrConfig.AsrProviderType.ASM -> {
setAsrPropertiesHandlerAsm.handle(asrConfig, propertiesJson)
}

AsrConfig.AsrProviderType.TINKOFF -> {
setAsrPropertiesHandlerTinkoff.handle(asrConfig, propertiesJson)
}

AsrConfig.AsrProviderType.KALDI -> {
setAsrPropertiesHandlerKaldi.handle(asrConfig, propertiesJson)
}
}
}
}

abstract class SetAsrPropertiesHandlerAbstract {
abstract fun handle(asrConfig: AsrConfig, propertiesJson: JsonObject): AsrConfig
}

class SetAsrPropertiesHandlerSber() : SetAsrPropertiesHandlerAbstract() {
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 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 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 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 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 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 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 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 handle(asrConfig: AsrConfig, propertiesJson: JsonObject): AsrConfig {
return asrConfig.copy(
asrProperties = propertiesJson
)
}
}

class SetAsrPropertiesHandlerTinkoff() : SetAsrPropertiesHandlerAbstract() {
override fun handle(asrConfig: AsrConfig, propertiesJson: JsonObject): AsrConfig {
return asrConfig.copy(
asrProperties = propertiesJson
)
}
}
Loading