diff --git a/vertexai/app/build.gradle.kts b/vertexai/app/build.gradle.kts index 44d1836748..ca501905cb 100644 --- a/vertexai/app/build.gradle.kts +++ b/vertexai/app/build.gradle.kts @@ -56,16 +56,17 @@ dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.6") implementation("androidx.activity:activity-compose:1.9.3") implementation("androidx.navigation:navigation-compose:2.8.3") - + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3") implementation(platform("androidx.compose:compose-bom:2024.10.00")) + implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.material3:material3") implementation("io.coil-kt:coil-compose:2.7.0") - - implementation("com.google.firebase:firebase-analytics:22.1.2") - implementation("com.google.firebase:firebase-vertexai:16.0.0-beta06") + + implementation(platform("com.google.firebase:firebase-bom:33.5.1")) + implementation("com.google.firebase:firebase-vertexai") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.2.1") diff --git a/vertexai/app/src/main/kotlin/com/google/firebase/quickstart/vertexai/GenerativeAiViewModelFactory.kt b/vertexai/app/src/main/kotlin/com/google/firebase/quickstart/vertexai/GenerativeAiViewModelFactory.kt index 41eae68e00..77af5cc57b 100644 --- a/vertexai/app/src/main/kotlin/com/google/firebase/quickstart/vertexai/GenerativeAiViewModelFactory.kt +++ b/vertexai/app/src/main/kotlin/com/google/firebase/quickstart/vertexai/GenerativeAiViewModelFactory.kt @@ -27,10 +27,9 @@ import com.google.firebase.quickstart.vertexai.feature.multimodal.PhotoReasoning import com.google.firebase.quickstart.vertexai.feature.text.SummarizeViewModel import com.google.firebase.vertexai.type.Schema import com.google.firebase.vertexai.type.Tool -import com.google.firebase.vertexai.type.defineFunction +import com.google.firebase.vertexai.type.FunctionDeclaration import com.google.firebase.vertexai.type.generationConfig import com.google.firebase.vertexai.vertexAI -import org.json.JSONObject val GenerativeViewModelFactory = object : ViewModelProvider.Factory { override fun create( @@ -47,7 +46,7 @@ val GenerativeViewModelFactory = object : ViewModelProvider.Factory { // Initialize a GenerativeModel with the `gemini-flash` AI model // for text generation val generativeModel = Firebase.vertexAI.generativeModel( - modelName = "gemini-1.5-flash-preview-0514", + modelName = "gemini-1.5-flash", generationConfig = config ) SummarizeViewModel(generativeModel) @@ -57,7 +56,7 @@ val GenerativeViewModelFactory = object : ViewModelProvider.Factory { // Initialize a GenerativeModel with the `gemini-flash` AI model // for multimodal text generation val generativeModel = Firebase.vertexAI.generativeModel( - modelName = "gemini-1.5-flash-preview-0514", + modelName = "gemini-1.5-flash", generationConfig = config ) PhotoReasoningViewModel(generativeModel) @@ -66,7 +65,7 @@ val GenerativeViewModelFactory = object : ViewModelProvider.Factory { isAssignableFrom(ChatViewModel::class.java) -> { // Initialize a GenerativeModel with the `gemini-flash` AI model for chat val generativeModel = Firebase.vertexAI.generativeModel( - modelName = "gemini-1.5-flash-preview-0514", + modelName = "gemini-1.5-flash", generationConfig = config ) ChatViewModel(generativeModel) @@ -74,23 +73,24 @@ val GenerativeViewModelFactory = object : ViewModelProvider.Factory { isAssignableFrom(FunctionsChatViewModel::class.java) -> { // Declare the functions you want to make available to the model + val functionDeclaration = FunctionDeclaration( + name = "upperCase", + description = "Returns the upper case version of the input string", + parameters = mapOf( + "input" to Schema.string( "Text to transform")) + ) val tools = listOf( - Tool( + Tool.functionDeclarations( listOf( - defineFunction( - "upperCase", - "Returns the upper case version of the input string", - Schema.str("input", "Text to transform") - ) { input -> - JSONObject("{\"response\": \"${input.uppercase()}\"}") - } + functionDeclaration ) ) ) + // Initialize a GenerativeModel with the `gemini-pro` AI model for function calling chat val generativeModel = Firebase.vertexAI.generativeModel( - modelName = "gemini-1.5-pro-preview-0514", + modelName = "gemini-1.5-flash", generationConfig = config, tools = tools ) diff --git a/vertexai/app/src/main/kotlin/com/google/firebase/quickstart/vertexai/feature/audio/AudioViewModel.kt b/vertexai/app/src/main/kotlin/com/google/firebase/quickstart/vertexai/feature/audio/AudioViewModel.kt index a17a0201c5..7108ed589f 100644 --- a/vertexai/app/src/main/kotlin/com/google/firebase/quickstart/vertexai/feature/audio/AudioViewModel.kt +++ b/vertexai/app/src/main/kotlin/com/google/firebase/quickstart/vertexai/feature/audio/AudioViewModel.kt @@ -47,7 +47,7 @@ class AudioViewModel( viewModelScope.launch(Dispatchers.IO) { try { val inputContent = content { - blob("audio/aac", audioBytes) + inlineData(audioBytes, "audio/aac") text(prompt) } diff --git a/vertexai/app/src/main/kotlin/com/google/firebase/quickstart/vertexai/feature/functioncalling/FunctionsChatViewModel.kt b/vertexai/app/src/main/kotlin/com/google/firebase/quickstart/vertexai/feature/functioncalling/FunctionsChatViewModel.kt index eb2c50dae9..c5309e1408 100644 --- a/vertexai/app/src/main/kotlin/com/google/firebase/quickstart/vertexai/feature/functioncalling/FunctionsChatViewModel.kt +++ b/vertexai/app/src/main/kotlin/com/google/firebase/quickstart/vertexai/feature/functioncalling/FunctionsChatViewModel.kt @@ -27,6 +27,9 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.buildJsonObject +import java.lang.IllegalArgumentException class FunctionsChatViewModel( private val generativeModel: GenerativeModel @@ -77,18 +80,23 @@ class FunctionsChatViewModel( val firstFunctionCall = response.functionCalls.firstOrNull() if (firstFunctionCall != null) { - val matchingFunction = - generativeModel.tools?.flatMap { it.functionDeclarations } - ?.first { it.name == firstFunctionCall.name } - ?: throw InvalidStateException( - "Model requested nonexistent function \"${firstFunctionCall.name}\" " + val functionCall = firstFunctionCall + val result = when (functionCall.name) { + "upperCase" -> buildJsonObject { + put( + "result", + JsonPrimitive(functionCall.args["text"].toString().uppercase() ?: "") ) + } - val funResult = matchingFunction.execute(firstFunctionCall) + else -> throw IllegalArgumentException( + "Model requested nonexistent function \"${firstFunctionCall.name}\" " + ) + } response = chat.sendMessage( content(role = "function") { - part(FunctionResponsePart("output", funResult)) + part(FunctionResponsePart("upperCase", result)) } ) } diff --git a/vertexai/build.gradle.kts b/vertexai/build.gradle.kts index 414f9349db..b182c2d5af 100644 --- a/vertexai/build.gradle.kts +++ b/vertexai/build.gradle.kts @@ -20,4 +20,5 @@ plugins { id("org.jetbrains.kotlin.android") version "2.0.21" apply false id("org.jetbrains.kotlin.plugin.compose") version "2.0.21" apply false id("com.google.gms.google-services") version "4.4.2" apply false + kotlin("plugin.serialization") version "2.0.20" } diff --git a/vertexai/gradle/wrapper/gradle-wrapper.properties b/vertexai/gradle/wrapper/gradle-wrapper.properties index 17655d0ef2..1a2bf629f8 100644 --- a/vertexai/gradle/wrapper/gradle-wrapper.properties +++ b/vertexai/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Mon Sep 30 15:29:58 EDT 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists