diff --git a/firebase-vertexai/CHANGELOG.md b/firebase-vertexai/CHANGELOG.md index 4293874a293..0969016889c 100644 --- a/firebase-vertexai/CHANGELOG.md +++ b/firebase-vertexai/CHANGELOG.md @@ -1,4 +1,11 @@ # Unreleased +* [changed] **Breaking Change**: `LiveModelFutures.connect` now returns `ListenableFuture` instead of `ListenableFuture`. + * **Action Required:** Remove any transformations from LiveSession object to LiveSessionFutures object. + * **Action Required:** Change type of variable handling `LiveModelFutures.connect` to `ListenableFuture` +* [changed] **Breaking Change**: Removed `UNSPECIFIED` value for enum class `ResponseModality` + * **Action Required:** Remove all references to `ResponseModality.UNSPECIFIED` +* [changed] **Breaking Change**: Renamed `LiveGenerationConfig.setResponseModalities` to `LiveGenerationConfig.setResponseModality` + * **Action Required:** Replace all references of `LiveGenerationConfig.setResponseModalities` with `LiveGenerationConfig.setResponseModality` * [feature] Added support for `HarmBlockThreshold.OFF`. See the [model documentation](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/configure-safety-filters#how_to_configure_content_filters){: .external} for more information. diff --git a/firebase-vertexai/api.txt b/firebase-vertexai/api.txt index 137d49f490c..1ea9d432305 100644 --- a/firebase-vertexai/api.txt +++ b/firebase-vertexai/api.txt @@ -115,7 +115,7 @@ package com.google.firebase.vertexai.java { } @com.google.firebase.vertexai.type.PublicPreviewAPI public abstract class LiveModelFutures { - method public abstract com.google.common.util.concurrent.ListenableFuture connect(); + method public abstract com.google.common.util.concurrent.ListenableFuture connect(); method public static final com.google.firebase.vertexai.java.LiveModelFutures from(com.google.firebase.vertexai.LiveGenerativeModel model); field public static final com.google.firebase.vertexai.java.LiveModelFutures.Companion Companion; } @@ -132,6 +132,7 @@ package com.google.firebase.vertexai.java { method public abstract com.google.common.util.concurrent.ListenableFuture send(String text); method public abstract com.google.common.util.concurrent.ListenableFuture sendFunctionResponse(java.util.List functionList); method public abstract com.google.common.util.concurrent.ListenableFuture sendMediaStream(java.util.List mediaChunks); + method public abstract com.google.common.util.concurrent.ListenableFuture startAudioConversation(); method public abstract com.google.common.util.concurrent.ListenableFuture startAudioConversation(kotlin.jvm.functions.Function1? functionCallHandler); method public abstract com.google.common.util.concurrent.ListenableFuture stopAudioConversation(); method public abstract void stopReceiving(); @@ -597,7 +598,7 @@ package com.google.firebase.vertexai.type { method public com.google.firebase.vertexai.type.LiveGenerationConfig.Builder setFrequencyPenalty(Float? frequencyPenalty); method public com.google.firebase.vertexai.type.LiveGenerationConfig.Builder setMaxOutputTokens(Integer? maxOutputTokens); method public com.google.firebase.vertexai.type.LiveGenerationConfig.Builder setPresencePenalty(Float? presencePenalty); - method public com.google.firebase.vertexai.type.LiveGenerationConfig.Builder setResponseModalities(com.google.firebase.vertexai.type.ResponseModality? responseModalities); + method public com.google.firebase.vertexai.type.LiveGenerationConfig.Builder setResponseModality(com.google.firebase.vertexai.type.ResponseModality? responseModality); method public com.google.firebase.vertexai.type.LiveGenerationConfig.Builder setSpeechConfig(com.google.firebase.vertexai.type.SpeechConfig? speechConfig); method public com.google.firebase.vertexai.type.LiveGenerationConfig.Builder setTemperature(Float? temperature); method public com.google.firebase.vertexai.type.LiveGenerationConfig.Builder setTopK(Integer? topK); @@ -696,7 +697,6 @@ package com.google.firebase.vertexai.type { field public static final com.google.firebase.vertexai.type.ResponseModality.Companion Companion; field public static final com.google.firebase.vertexai.type.ResponseModality IMAGE; field public static final com.google.firebase.vertexai.type.ResponseModality TEXT; - field public static final com.google.firebase.vertexai.type.ResponseModality UNSPECIFIED; } public static final class ResponseModality.Companion { diff --git a/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/java/LiveModelFutures.kt b/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/java/LiveModelFutures.kt index c167e700a5e..cc8fb8893d7 100644 --- a/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/java/LiveModelFutures.kt +++ b/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/java/LiveModelFutures.kt @@ -19,7 +19,6 @@ package com.google.firebase.vertexai.java import androidx.concurrent.futures.SuspendToFutureAdapter import com.google.common.util.concurrent.ListenableFuture import com.google.firebase.vertexai.LiveGenerativeModel -import com.google.firebase.vertexai.type.LiveSession import com.google.firebase.vertexai.type.PublicPreviewAPI import com.google.firebase.vertexai.type.ServiceConnectionHandshakeFailedException @@ -32,16 +31,16 @@ import com.google.firebase.vertexai.type.ServiceConnectionHandshakeFailedExcepti public abstract class LiveModelFutures internal constructor() { /** - * Start a [LiveSession] with the server for bidirectional streaming. - * @return A [LiveSession] that you can use to stream messages to and from the server. + * Start a [LiveSessionFutures] with the server for bidirectional streaming. + * @return A [LiveSessionFutures] that you can use to stream messages to and from the server. * @throws [ServiceConnectionHandshakeFailedException] If the client was not able to establish a * connection with the server. */ - public abstract fun connect(): ListenableFuture + public abstract fun connect(): ListenableFuture private class FuturesImpl(private val model: LiveGenerativeModel) : LiveModelFutures() { - override fun connect(): ListenableFuture { - return SuspendToFutureAdapter.launchFuture { model.connect() } + override fun connect(): ListenableFuture { + return SuspendToFutureAdapter.launchFuture { LiveSessionFutures.from(model.connect()) } } } diff --git a/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/java/LiveSessionFutures.kt b/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/java/LiveSessionFutures.kt index 044f83e8cc1..f5b56758d19 100644 --- a/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/java/LiveSessionFutures.kt +++ b/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/java/LiveSessionFutures.kt @@ -48,6 +48,12 @@ public abstract class LiveSessionFutures internal constructor() { functionCallHandler: ((FunctionCallPart) -> FunctionResponsePart)? ): ListenableFuture + /** + * Starts an audio conversation with the Gemini server, which can only be stopped using + * [stopAudioConversation]. + */ + public abstract fun startAudioConversation(): ListenableFuture + /** * Stops the audio conversation with the Gemini Server. * @@ -124,6 +130,9 @@ public abstract class LiveSessionFutures internal constructor() { functionCallHandler: ((FunctionCallPart) -> FunctionResponsePart)? ) = SuspendToFutureAdapter.launchFuture { session.startAudioConversation(functionCallHandler) } + override fun startAudioConversation() = + SuspendToFutureAdapter.launchFuture { session.startAudioConversation() } + override fun stopAudioConversation() = SuspendToFutureAdapter.launchFuture { session.stopAudioConversation() } diff --git a/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/type/LiveGenerationConfig.kt b/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/type/LiveGenerationConfig.kt index 55e789fd14f..2f8f39a3afc 100644 --- a/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/type/LiveGenerationConfig.kt +++ b/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/type/LiveGenerationConfig.kt @@ -130,8 +130,8 @@ private constructor( public fun setFrequencyPenalty(frequencyPenalty: Float?): Builder = apply { this.frequencyPenalty = frequencyPenalty } - public fun setResponseModalities(responseModalities: ResponseModality?): Builder = apply { - this.responseModality = responseModalities + public fun setResponseModality(responseModality: ResponseModality?): Builder = apply { + this.responseModality = responseModality } public fun setSpeechConfig(speechConfig: SpeechConfig?): Builder = apply { this.speechConfig = speechConfig diff --git a/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/type/ResponseModality.kt b/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/type/ResponseModality.kt index c9abb9f21f3..e6be477f845 100644 --- a/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/type/ResponseModality.kt +++ b/firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/type/ResponseModality.kt @@ -18,7 +18,6 @@ package com.google.firebase.vertexai.type import com.google.firebase.vertexai.common.util.FirstOrdinalSerializer import kotlinx.serialization.KSerializer -import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable /** Represents the type of content present in a response (e.g., text, image, audio). */ @@ -27,7 +26,6 @@ public class ResponseModality private constructor(public val ordinal: Int) { @Serializable(Internal.Serializer::class) internal enum class Internal { - @SerialName("MODALITY_UNSPECIFIED") UNSPECIFIED, TEXT, IMAGE, AUDIO; @@ -38,8 +36,7 @@ public class ResponseModality private constructor(public val ordinal: Int) { when (this) { TEXT -> ResponseModality.TEXT IMAGE -> ResponseModality.IMAGE - AUDIO -> ResponseModality.AUDIO - else -> ResponseModality.UNSPECIFIED + else -> ResponseModality.AUDIO } } @@ -47,12 +44,9 @@ public class ResponseModality private constructor(public val ordinal: Int) { when (this) { TEXT -> "TEXT" IMAGE -> "IMAGE" - AUDIO -> "AUDIO" - else -> "UNSPECIFIED" + else -> "AUDIO" } public companion object { - /** Unspecified modality. */ - @JvmField public val UNSPECIFIED: ResponseModality = ResponseModality(0) /** Represents a plain text response modality. */ @JvmField public val TEXT: ResponseModality = ResponseModality(1)