Skip to content
2 changes: 2 additions & 0 deletions firebase-vertexai/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Unreleased
* [changed] Added new exception type for quota exceeded scenarios.
* [feature] `CountTokenRequest` now includes `GenerationConfig` from the model.


# 16.2.0
* [fixed] Added support for new values sent by the server for `FinishReason` and `BlockReason`.
* [changed] Added support for modality-based token count. (#6658)
Expand Down
3 changes: 3 additions & 0 deletions firebase-vertexai/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,9 @@ package com.google.firebase.vertexai.type {
@kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.ERROR, message="This API is part of an experimental public preview and may change in " + "backwards-incompatible ways without notice.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface PublicPreviewAPI {
}

public final class QuotaExceededException extends com.google.firebase.vertexai.type.FirebaseVertexAIException {
}

public final class RequestOptions {
ctor public RequestOptions();
ctor public RequestOptions(long timeoutInMillis = 180.seconds.inWholeMilliseconds);
Expand Down
2 changes: 1 addition & 1 deletion firebase-vertexai/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.

version=16.2.1
version=16.3.0
latestReleasedVersion=16.2.0
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ internal constructor(message: String, cause: Throwable? = null) : RuntimeExcepti
UnknownException(cause.message ?: "", cause.cause)
is com.google.firebase.vertexai.common.ContentBlockedException ->
ContentBlockedException(cause.message ?: "", cause.cause)
is com.google.firebase.vertexai.common.QuotaExceededException ->
QuotaExceededException(cause.message ?: "", cause.cause)
else -> UnknownException(cause.message ?: "", cause)
}
is TimeoutCancellationException ->
Expand Down Expand Up @@ -165,6 +167,14 @@ public class ServiceDisabledException
internal constructor(message: String, cause: Throwable? = null) :
FirebaseVertexAIException(message, cause)

/**
* The request has hit a quota limit. Learn more about quotas in the
* [Firebase documentation.](https://firebase.google.com/docs/vertex-ai/quotas)
*/
public class QuotaExceededException
internal constructor(message: String, cause: Throwable? = null) :
FirebaseVertexAIException(message, cause)

/** Catch all case for exceptions not explicitly expected. */
public class UnknownException internal constructor(message: String, cause: Throwable? = null) :
FirebaseVertexAIException(message, cause)
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import com.google.firebase.vertexai.type.HarmSeverity
import com.google.firebase.vertexai.type.InvalidAPIKeyException
import com.google.firebase.vertexai.type.PromptBlockedException
import com.google.firebase.vertexai.type.PublicPreviewAPI
import com.google.firebase.vertexai.type.QuotaExceededException
import com.google.firebase.vertexai.type.ResponseStoppedException
import com.google.firebase.vertexai.type.SerializationException
import com.google.firebase.vertexai.type.ServerException
Expand Down Expand Up @@ -72,6 +73,19 @@ internal class UnarySnapshotTests {
}
}

@Test
fun `long reply`() =
goldenUnaryFile("unary-success-basic-reply-long.json") {
withTimeout(testTimeout) {
val response = model.generateContent("prompt")

response.candidates.isEmpty() shouldBe false
response.candidates.first().finishReason shouldBe FinishReason.STOP
response.candidates.first().content.parts.isEmpty() shouldBe false
response.candidates.first().safetyRatings.isEmpty() shouldBe false
}
}

@Test
fun `response with detailed token-based usageMetadata`() =
goldenUnaryFile("unary-success-basic-response-long-usage-metadata.json") {
Expand Down Expand Up @@ -177,6 +191,20 @@ internal class UnarySnapshotTests {
}
}

@Test
fun `function call has no arguments field`() =
goldenUnaryFile("unary-success-function-call-empty-arguments.json") {
withTimeout(testTimeout) {
val response = model.generateContent("prompt")
val content = response.candidates.shouldNotBeNullOrEmpty().first().content
content.shouldNotBeNull()
val callPart = content.parts.shouldNotBeNullOrEmpty().first() as FunctionCallPart

callPart.name shouldBe "current_time"
callPart.args shouldBe emptyMap()
}
}

@Test
fun `prompt blocked for safety`() =
goldenUnaryFile("unary-failure-prompt-blocked-safety.json") {
Expand Down Expand Up @@ -239,6 +267,14 @@ internal class UnarySnapshotTests {
}
}

@Test
fun `quota exceeded`() =
goldenUnaryFile("unary-failure-quota-exceeded.json", HttpStatusCode.BadRequest) {
withTimeout(testTimeout) {
shouldThrow<QuotaExceededException> { model.generateContent("prompt") }
}
}

@Test
fun `stopped for safety with no content`() =
goldenUnaryFile("unary-failure-finish-reason-safety-no-content.json") {
Expand Down

This file was deleted.

Loading
Loading