Skip to content

Commit a5981ff

Browse files
authored
Merge 6fc7f7d into e0e995a
2 parents e0e995a + 6fc7f7d commit a5981ff

File tree

7 files changed

+185
-5
lines changed

7 files changed

+185
-5
lines changed

firebase-ai/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
- [changed] Added support for input and output transcription. (#7482)
55
- [feature] Added support for sending realtime audio and video in a `LiveSession`.
66
- [changed] Removed redundant internal exception types. (#7475)
7+
- [feature] Added support for configuring the aspect ratio when generating images with the Gemini
8+
2.5 Flash Image model.
9+
- [feature] Added `FinishReason.IMAGE_PROHIBITED_CONTENT` and `FinishReason.NO_IMAGE`, which can be
10+
returned from Gemini image generation.
711

812
# 17.4.0
913

firebase-ai/api.txt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,23 @@ package com.google.firebase.ai.type {
173173
public final class APINotConfiguredException extends com.google.firebase.ai.type.FirebaseAIException {
174174
}
175175

176+
public final class AspectRatio {
177+
field public static final com.google.firebase.ai.type.AspectRatio.Companion Companion;
178+
field public static final com.google.firebase.ai.type.AspectRatio LANDSCAPE_16x9;
179+
field public static final com.google.firebase.ai.type.AspectRatio LANDSCAPE_21x9;
180+
field public static final com.google.firebase.ai.type.AspectRatio LANDSCAPE_3x2;
181+
field public static final com.google.firebase.ai.type.AspectRatio LANDSCAPE_4x3;
182+
field public static final com.google.firebase.ai.type.AspectRatio LANDSCAPE_5x4;
183+
field public static final com.google.firebase.ai.type.AspectRatio PORTRAIT_2x3;
184+
field public static final com.google.firebase.ai.type.AspectRatio PORTRAIT_3x4;
185+
field public static final com.google.firebase.ai.type.AspectRatio PORTRAIT_4x5;
186+
field public static final com.google.firebase.ai.type.AspectRatio PORTRAIT_9x16;
187+
field public static final com.google.firebase.ai.type.AspectRatio SQUARE_1x1;
188+
}
189+
190+
public static final class AspectRatio.Companion {
191+
}
192+
176193
public final class AudioRecordInitializationFailedException extends com.google.firebase.ai.type.FirebaseAIException {
177194
ctor public AudioRecordInitializationFailedException(String message);
178195
}
@@ -337,8 +354,11 @@ package com.google.firebase.ai.type {
337354
property public final int ordinal;
338355
field public static final com.google.firebase.ai.type.FinishReason BLOCKLIST;
339356
field public static final com.google.firebase.ai.type.FinishReason.Companion Companion;
357+
field public static final com.google.firebase.ai.type.FinishReason IMAGE_PROHIBITED_CONTENT;
358+
field public static final com.google.firebase.ai.type.FinishReason IMAGE_SAFETY;
340359
field public static final com.google.firebase.ai.type.FinishReason MALFORMED_FUNCTION_CALL;
341360
field public static final com.google.firebase.ai.type.FinishReason MAX_TOKENS;
361+
field public static final com.google.firebase.ai.type.FinishReason NO_IMAGE;
342362
field public static final com.google.firebase.ai.type.FinishReason OTHER;
343363
field public static final com.google.firebase.ai.type.FinishReason PROHIBITED_CONTENT;
344364
field public static final com.google.firebase.ai.type.FinishReason RECITATION;
@@ -426,6 +446,7 @@ package com.google.firebase.ai.type {
426446
method public com.google.firebase.ai.type.GenerationConfig build();
427447
method public com.google.firebase.ai.type.GenerationConfig.Builder setCandidateCount(Integer? candidateCount);
428448
method public com.google.firebase.ai.type.GenerationConfig.Builder setFrequencyPenalty(Float? frequencyPenalty);
449+
method public com.google.firebase.ai.type.GenerationConfig.Builder setImageConfig(com.google.firebase.ai.type.ImageConfig? imageConfig);
429450
method public com.google.firebase.ai.type.GenerationConfig.Builder setMaxOutputTokens(Integer? maxOutputTokens);
430451
method public com.google.firebase.ai.type.GenerationConfig.Builder setPresencePenalty(Float? presencePenalty);
431452
method public com.google.firebase.ai.type.GenerationConfig.Builder setResponseMimeType(String? responseMimeType);
@@ -438,6 +459,7 @@ package com.google.firebase.ai.type {
438459
method public com.google.firebase.ai.type.GenerationConfig.Builder setTopP(Float? topP);
439460
field public Integer? candidateCount;
440461
field public Float? frequencyPenalty;
462+
field public com.google.firebase.ai.type.ImageConfig? imageConfig;
441463
field public Integer? maxOutputTokens;
442464
field public Float? presencePenalty;
443465
field public String? responseMimeType;
@@ -585,6 +607,19 @@ package com.google.firebase.ai.type {
585607
public static final class HarmSeverity.Companion {
586608
}
587609

610+
public final class ImageConfig {
611+
}
612+
613+
public static final class ImageConfig.Builder {
614+
ctor public ImageConfig.Builder();
615+
method public com.google.firebase.ai.type.ImageConfig build();
616+
method public com.google.firebase.ai.type.ImageConfig.Builder setAspectRatio(com.google.firebase.ai.type.AspectRatio? aspectRatio);
617+
}
618+
619+
public final class ImageConfigKt {
620+
method public static com.google.firebase.ai.type.ImageConfig imageConfig(kotlin.jvm.functions.Function1<? super com.google.firebase.ai.type.ImageConfig.Builder,kotlin.Unit> init);
621+
}
622+
588623
public final class ImagePart implements com.google.firebase.ai.type.Part {
589624
ctor public ImagePart(android.graphics.Bitmap image);
590625
method public android.graphics.Bitmap getImage();
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.firebase.ai.type
18+
19+
/** Represents the aspect ratio that the generated image should conform to. */
20+
public class AspectRatio private constructor(internal val internalVal: String) {
21+
public companion object {
22+
/** A square image, useful for icons, profile pictures, etc. */
23+
@JvmField public val SQUARE_1x1: AspectRatio = AspectRatio("1:1")
24+
/** A portrait image in 3:4, the aspect ratio of older TVs. */
25+
@JvmField public val PORTRAIT_3x4: AspectRatio = AspectRatio("3:4")
26+
/** A landscape image in 4:3, the aspect ratio of older TVs. */
27+
@JvmField public val LANDSCAPE_4x3: AspectRatio = AspectRatio("4:3")
28+
/** A portrait image in 9:16, the aspect ratio of modern monitors and phone screens. */
29+
@JvmField public val PORTRAIT_9x16: AspectRatio = AspectRatio("9:16")
30+
/** A landscape image in 16:9, the aspect ratio of modern monitors and phone screens. */
31+
@JvmField public val LANDSCAPE_16x9: AspectRatio = AspectRatio("16:9")
32+
/** A portrait image in 4:5, the aspect ratio for prints from digital cameras. */
33+
@JvmField public val PORTRAIT_4x5: AspectRatio = AspectRatio("4:5")
34+
/** A landscape image in 5:4, the aspect ratio for prints from digital cameras. */
35+
@JvmField public val LANDSCAPE_5x4: AspectRatio = AspectRatio("5:4")
36+
/** A portrait image in 4:5, the aspect ratio for prints from 35mm film cameras. */
37+
@JvmField public val PORTRAIT_2x3: AspectRatio = AspectRatio("2:3")
38+
/** A landscape image in 4:5, the aspect ratio for prints from 35mm film cameras. */
39+
@JvmField public val LANDSCAPE_3x2: AspectRatio = AspectRatio("3:2")
40+
/** A ultrawide image in 21:9, an aspect ratio commonly used in modern movies. */
41+
@JvmField public val LANDSCAPE_21x9: AspectRatio = AspectRatio("21:9")
42+
}
43+
}

firebase-ai/src/main/kotlin/com/google/firebase/ai/type/Candidate.kt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,10 @@ public class FinishReason private constructor(public val name: String, public va
247247
BLOCKLIST,
248248
PROHIBITED_CONTENT,
249249
SPII,
250-
MALFORMED_FUNCTION_CALL;
250+
MALFORMED_FUNCTION_CALL,
251+
IMAGE_SAFETY,
252+
IMAGE_PROHIBITED_CONTENT,
253+
NO_IMAGE;
251254

252255
internal object Serializer : KSerializer<Internal> by FirstOrdinalSerializer(Internal::class)
253256

@@ -262,6 +265,9 @@ public class FinishReason private constructor(public val name: String, public va
262265
PROHIBITED_CONTENT -> FinishReason.PROHIBITED_CONTENT
263266
SPII -> FinishReason.SPII
264267
MALFORMED_FUNCTION_CALL -> FinishReason.MALFORMED_FUNCTION_CALL
268+
IMAGE_SAFETY -> FinishReason.IMAGE_SAFETY
269+
IMAGE_PROHIBITED_CONTENT -> FinishReason.IMAGE_PROHIBITED_CONTENT
270+
NO_IMAGE -> FinishReason.NO_IMAGE
265271
else -> FinishReason.UNKNOWN
266272
}
267273
}
@@ -301,6 +307,16 @@ public class FinishReason private constructor(public val name: String, public va
301307
/** The function call generated by the model is invalid. */
302308
@JvmField
303309
public val MALFORMED_FUNCTION_CALL: FinishReason = FinishReason("MALFORMED_FUNCTION_CALL", 9)
310+
311+
/** Token generation stopped because generated images has safety violations. */
312+
@JvmField public val IMAGE_SAFETY: FinishReason = FinishReason("IMAGE_SAFETY", 10)
313+
314+
/** Image generation stopped because generated images has other prohibited content. */
315+
@JvmField
316+
public val IMAGE_PROHIBITED_CONTENT: FinishReason = FinishReason("IMAGE_PROHIBITED_CONTENT", 11)
317+
318+
/** The model was expected to generate an image, but none was generated. */
319+
@JvmField public val NO_IMAGE: FinishReason = FinishReason("NO_IMAGE", 12)
304320
}
305321
}
306322

firebase-ai/src/main/kotlin/com/google/firebase/ai/type/GenerationConfig.kt

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ private constructor(
9292
internal val responseSchema: Schema?,
9393
internal val responseModalities: List<ResponseModality>?,
9494
internal val thinkingConfig: ThinkingConfig?,
95+
internal val imageConfig: ImageConfig?,
9596
) {
9697

9798
/**
@@ -137,6 +138,7 @@ private constructor(
137138
@JvmField public var responseSchema: Schema? = null
138139
@JvmField public var responseModalities: List<ResponseModality>? = null
139140
@JvmField public var thinkingConfig: ThinkingConfig? = null
141+
@JvmField public var imageConfig: ImageConfig? = null
140142

141143
public fun setTemperature(temperature: Float?): Builder = apply {
142144
this.temperature = temperature
@@ -170,6 +172,9 @@ private constructor(
170172
public fun setThinkingConfig(thinkingConfig: ThinkingConfig?): Builder = apply {
171173
this.thinkingConfig = thinkingConfig
172174
}
175+
public fun setImageConfig(imageConfig: ImageConfig?): Builder = apply {
176+
this.imageConfig = imageConfig
177+
}
173178

174179
/** Create a new [GenerationConfig] with the attached arguments. */
175180
public fun build(): GenerationConfig =
@@ -185,7 +190,8 @@ private constructor(
185190
responseMimeType = responseMimeType,
186191
responseSchema = responseSchema,
187192
responseModalities = responseModalities,
188-
thinkingConfig = thinkingConfig
193+
thinkingConfig = thinkingConfig,
194+
imageConfig = imageConfig
189195
)
190196
}
191197

@@ -202,7 +208,8 @@ private constructor(
202208
responseMimeType = responseMimeType,
203209
responseSchema = responseSchema?.toInternalOpenApi(),
204210
responseModalities = responseModalities?.map { it.toInternal() },
205-
thinkingConfig = thinkingConfig?.toInternal()
211+
thinkingConfig = thinkingConfig?.toInternal(),
212+
imageConfig = imageConfig?.toInternal()
206213
)
207214

208215
@Serializable
@@ -218,7 +225,8 @@ private constructor(
218225
@SerialName("frequency_penalty") val frequencyPenalty: Float? = null,
219226
@SerialName("response_schema") val responseSchema: Schema.InternalOpenAPI? = null,
220227
@SerialName("response_modalities") val responseModalities: List<String>? = null,
221-
@SerialName("thinking_config") val thinkingConfig: ThinkingConfig.Internal? = null
228+
@SerialName("thinking_config") val thinkingConfig: ThinkingConfig.Internal? = null,
229+
@SerialName("image_config") val imageConfig: ImageConfig.Internal? = null
222230
)
223231

224232
public companion object {
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.firebase.ai.type
18+
19+
import kotlinx.serialization.Serializable
20+
21+
/**
22+
* Configuration parameters to use for image generation.
23+
*
24+
* @property aspectRatio The aspect ratio of the generated image.
25+
*/
26+
public class ImageConfig internal constructor(internal val aspectRatio: AspectRatio?) {
27+
28+
/**
29+
* Builder for creating an [ImageConfig].
30+
*
31+
* Mainly intended for Java interop. Kotlin consumers should use [imageConfig] for a more
32+
* idiomatic experience.
33+
*
34+
* @property aspectRatio See [ImageConfig.aspectRatio].
35+
* @see [imageConfig]
36+
*/
37+
public class Builder {
38+
@JvmField
39+
@set:JvmSynthetic // hide void setter from Java
40+
public var aspectRatio: AspectRatio? = null
41+
42+
public fun setAspectRatio(aspectRatio: AspectRatio?): Builder = apply {
43+
this.aspectRatio = aspectRatio
44+
}
45+
46+
/** Create a new [ImageConfig] with the attached arguments. */
47+
public fun build(): ImageConfig = ImageConfig(aspectRatio = aspectRatio)
48+
}
49+
50+
internal fun toInternal() = Internal(aspectRatio = aspectRatio?.internalVal)
51+
52+
@Serializable internal data class Internal(val aspectRatio: String?)
53+
}
54+
55+
/**
56+
* Helper method to construct an [ImageConfig] in a DSL-like manner.
57+
*
58+
* Example Usage:
59+
* ```
60+
* imageConfig {
61+
* aspectRatio = AspectRatio.LANDSCAPE_16x9
62+
* }
63+
* ```
64+
*/
65+
public fun imageConfig(init: ImageConfig.Builder.() -> Unit): ImageConfig {
66+
val builder = ImageConfig.Builder()
67+
builder.init()
68+
return builder.build()
69+
}

firebase-ai/src/test/java/com/google/firebase/ai/SerializationTests.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,12 @@ internal class SerializationTests {
151151
"BLOCKLIST",
152152
"PROHIBITED_CONTENT",
153153
"SPII",
154-
"MALFORMED_FUNCTION_CALL"
154+
"MALFORMED_FUNCTION_CALL",
155+
"IMAGE_SAFETY",
156+
"IMAGE_PROHIBITED_CONTENT",
157+
"IMAGE_RECITATION",
158+
"IMAGE_OTHER",
159+
"NO_IMAGE"
155160
]
156161
},
157162
"safetyRatings": {

0 commit comments

Comments
 (0)