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

RTVI 0.2.0 #13

Merged
merged 3 commits into from
Oct 17, 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
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,14 @@ object ConfigConstants {
listOf(
BotProfile(
name = "Voice only",
id = "voice_2024_08",
id = "voice_2024_10",
llmProviders = NamedOptionList(listOf(Anthropic, Together), default = Together),
ttsProviders = NamedOptionList(listOf(Cartesia)),
sttProviders = NamedOptionList(listOf(Deepgram))
),
BotProfile(
name = "Voice and vision",
id = "vision_2024_08",
id = "vision_2024_10",
llmProviders = NamedOptionList(listOf(Anthropic)),
ttsProviders = NamedOptionList(listOf(Cartesia)),
sttProviders = NamedOptionList(listOf(Deepgram))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
package co.daily.bots.demo

import co.daily.bots.demo.ui.InCallLayout
import co.daily.bots.demo.ui.Logo
import co.daily.bots.demo.ui.PermissionScreen
import co.daily.bots.demo.ui.VoiceClientSettingsPanel
import co.daily.bots.demo.ui.theme.Colors
import co.daily.bots.demo.ui.theme.RTVIClientTheme
import co.daily.bots.demo.ui.theme.TextStyles
import co.daily.bots.demo.ui.theme.textFieldColors
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
Expand Down Expand Up @@ -58,9 +50,17 @@ import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import co.daily.bots.demo.ui.InCallLayout
import co.daily.bots.demo.ui.Logo
import co.daily.bots.demo.ui.PermissionScreen
import co.daily.bots.demo.ui.VoiceClientSettingsPanel
import co.daily.bots.demo.ui.theme.Colors
import co.daily.bots.demo.ui.theme.RTVIClientTheme
import co.daily.bots.demo.ui.theme.TextStyles
import co.daily.bots.demo.ui.theme.textFieldColors


private const val DEFAULT_BACKEND = "https://api.daily.co/v1/bots/start"
private const val DEFAULT_BACKEND = "https://api.daily.co/v1/bots"

class MainActivity : ComponentActivity() {

Expand Down Expand Up @@ -91,7 +91,7 @@ class MainActivity : ComponentActivity() {

voiceClientManager.errors.firstOrNull()?.let { errorText ->

val dismiss: () -> Unit = { voiceClientManager.errors.removeFirst() }
val dismiss: () -> Unit = { voiceClientManager.errors.removeAt(0) }

AlertDialog(
onDismissRequest = dismiss,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package co.daily.bots.demo

import ai.rtvi.client.VoiceClient
import ai.rtvi.client.VoiceClientOptions
import ai.rtvi.client.VoiceEventCallbacks
import co.daily.bots.demo.utils.Timestamp
import ai.rtvi.client.RTVIClient
import ai.rtvi.client.RTVIClientOptions
import ai.rtvi.client.RTVIClientParams
import ai.rtvi.client.RTVIEventCallbacks
import ai.rtvi.client.daily.DailyVoiceClient
import ai.rtvi.client.result.Future
import ai.rtvi.client.result.RTVIError
import ai.rtvi.client.result.Result
import ai.rtvi.client.result.VoiceError
import ai.rtvi.client.types.ActionDescription
import ai.rtvi.client.types.Option
import ai.rtvi.client.types.Participant
import ai.rtvi.client.types.PipecatMetrics
import ai.rtvi.client.types.RTVIURLEndpoints
import ai.rtvi.client.types.ServiceConfig
import ai.rtvi.client.types.ServiceRegistration
import ai.rtvi.client.types.Tracks
Expand All @@ -25,6 +26,7 @@ import androidx.compose.runtime.Stable
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import co.daily.bots.demo.utils.Timestamp

@Immutable
data class Error(val message: String)
Expand Down Expand Up @@ -74,14 +76,14 @@ class VoiceClientManager(private val context: Context) {
}
}

private val client = mutableStateOf<VoiceClient?>(null)
private val client = mutableStateOf<RTVIClient?>(null)

val state = mutableStateOf<TransportState?>(null)

val errors = mutableStateListOf<Error>()

val actionDescriptions =
mutableStateOf<Result<List<ActionDescription>, VoiceError>?>(null)
mutableStateOf<Result<List<ActionDescription>, RTVIError>?>(null)

val expiryTime = mutableStateOf<Timestamp?>(null)

Expand All @@ -95,7 +97,7 @@ class VoiceClientManager(private val context: Context) {
val camera = mutableStateOf(false)
val tracks = mutableStateOf<Tracks?>(null)

private fun <E> Future<E, VoiceError>.displayErrors() = withErrorCallback {
private fun <E> Future<E, RTVIError>.displayErrors() = withErrorCallback {
Log.e(TAG, "Future resolved with error: ${it.description}", it.exception)
errors.add(Error(it.description))
}
Expand All @@ -111,54 +113,58 @@ class VoiceClientManager(private val context: Context) {
return
}

val options = VoiceClientOptions(
services = listOf(
ServiceRegistration("tts", initOptions.ttsProvider.id),
ServiceRegistration("llm", initOptions.llmProvider.id),
ServiceRegistration("stt", initOptions.sttProvider.id),
),
config = listOf(
ServiceConfig(
"tts", listOf(
Option("voice", runtimeOptions.ttsVoice.id)
)
val options = RTVIClientOptions(
params = RTVIClientParams(
baseUrl = baseUrl,
endpoints = RTVIURLEndpoints(connect = "/start"),
// Note: For security reasons, don't include your API key in a production
// client app. See: https://docs.dailybots.ai/architecture
headers = apiKey
?.takeUnless { it.isEmpty() }
?.let { listOf("Authorization" to "Bearer $it") }
?: emptyList(),
requestData = listOf(
"bot_profile" to Value.Str(initOptions.botProfile.id),
"max_duration" to Value.Number(600.0)
),
ServiceConfig(
"llm", listOf(
Option("model", runtimeOptions.llmModel.id),
Option(
"initial_messages", Value.Array(
Value.Object(
"role" to Value.Str("system"),
"content" to Value.Str("You are a helpful voice assistant. Keep answers brief, and do not include markdown or other formatting in your responses, as they will be read out using TTS. Please greet the user and offer to assist them.")
config = listOf(
ServiceConfig(
"tts", listOf(
Option("voice", runtimeOptions.ttsVoice.id)
)
),
ServiceConfig(
"llm", listOf(
Option("model", runtimeOptions.llmModel.id),
Option(
"initial_messages", Value.Array(
Value.Object(
"role" to Value.Str("system"),
"content" to Value.Str("You are a helpful voice assistant. Keep answers brief, and do not include markdown or other formatting in your responses, as they will be read out using TTS. Please greet the user and offer to assist them.")
)
)
)
),
Option("run_on_config", true),
)
),
ServiceConfig(
"stt", listOf(
Option("model", runtimeOptions.sttModel.id),
Option("language", runtimeOptions.sttLanguage.id),
),
Option("run_on_config", true),
)
),
ServiceConfig(
"stt", listOf(
Option("model", runtimeOptions.sttModel.id),
Option("language", runtimeOptions.sttLanguage.id),
)
)
)
),
// Note: For security reasons, don't include your API key in a production
// client app. See: https://docs.dailybots.ai/architecture
customHeaders = apiKey
?.takeUnless { it.isEmpty() }
?.let { listOf("Authorization" to "Bearer $it") }
?: emptyList(),
customBodyParams = listOf(
"bot_profile" to Value.Str(initOptions.botProfile.id),
"max_duration" to Value.Number(600.0)
services = listOf(
ServiceRegistration("tts", initOptions.ttsProvider.id),
ServiceRegistration("llm", initOptions.llmProvider.id),
ServiceRegistration("stt", initOptions.sttProvider.id),
)
)

state.value = TransportState.Idle
state.value = TransportState.Disconnected

val callbacks = object : VoiceEventCallbacks() {
val callbacks = object : RTVIEventCallbacks() {
override fun onTransportStateChanged(state: TransportState) {
[email protected] = state
}
Expand Down Expand Up @@ -249,9 +255,9 @@ class VoiceClientManager(private val context: Context) {
}
}

val client = DailyVoiceClient(context, baseUrl, callbacks, options)
val client = DailyVoiceClient(context, callbacks, options)

client.start().displayErrors().withErrorCallback {
client.connect().displayErrors().withErrorCallback {
callbacks.onDisconnected()
}

Expand Down
14 changes: 7 additions & 7 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[versions]
accompanistPermissions = "0.34.0"
agp = "8.5.1"
agp = "8.5.2"
constraintlayoutCompose = "1.0.1"
rtviClientDaily = "0.1.5"
kotlin = "2.0.0"
rtviClientDaily = "0.2.1"
kotlin = "2.0.20"
coreKtx = "1.13.1"
lifecycleRuntimeKtx = "2.8.4"
activityCompose = "1.9.1"
composeBom = "2024.06.00"
lifecycleRuntimeKtx = "2.8.6"
activityCompose = "1.9.2"
composeBom = "2024.09.03"
kotlinxSerializationJson = "1.7.1"
kotlinxSerializationPlugin = "2.0.0"
kotlinxSerializationPlugin = "2.0.20"

[libraries]
accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanistPermissions" }
Expand Down