From 8b751420ca3d6cb5a19c9a06e90fde0d9ef5b6d1 Mon Sep 17 00:00:00 2001
From: "google-labs-jules[bot]"
<161369871+google-labs-jules[bot]@users.noreply.github.com>
Date: Thu, 2 Oct 2025 14:43:00 +0000
Subject: [PATCH] feat: Add ImageConfig and new FinishReason values
Adds new `FinishReason` values to handle image-specific cases.
Introduces `ImageConfig` to allow specifying image generation parameters like aspect ratio, and integrates it into the `GenerationConfig` struct.
---
firebaseai/src/Candidate.cs | 25 +++++++
firebaseai/src/GenerationConfig.cs | 6 +-
firebaseai/src/ImageConfig.cs | 107 +++++++++++++++++++++++++++++
3 files changed, 137 insertions(+), 1 deletion(-)
create mode 100644 firebaseai/src/ImageConfig.cs
diff --git a/firebaseai/src/Candidate.cs b/firebaseai/src/Candidate.cs
index c3053c95..d3317504 100644
--- a/firebaseai/src/Candidate.cs
+++ b/firebaseai/src/Candidate.cs
@@ -63,6 +63,26 @@ public enum FinishReason {
/// Token generation was stopped because the function call generated by the model was invalid.
///
MalformedFunctionCall,
+ ///
+ /// Image generation stopped because of safety reasons.
+ ///
+ ImageSafety,
+ ///
+ /// Image generation stopped because generated images has other prohibited content.
+ ///
+ ImageProhibitedContent,
+ ///
+ /// Image generation stopped due to recitation.
+ ///
+ ImageRecitation,
+ ///
+ /// Image generation stopped because of other miscellaneous issue.
+ ///
+ ImageOther,
+ ///
+ /// The model was expected to generate an image, but none was generated.
+ ///
+ NoImage,
}
///
@@ -130,6 +150,11 @@ private static FinishReason ParseFinishReason(string str) {
"PROHIBITED_CONTENT" => Firebase.AI.FinishReason.ProhibitedContent,
"SPII" => Firebase.AI.FinishReason.SPII,
"MALFORMED_FUNCTION_CALL" => Firebase.AI.FinishReason.MalformedFunctionCall,
+ "IMAGE_SAFETY" => Firebase.AI.FinishReason.ImageSafety,
+ "IMAGE_PROHIBITED_CONTENT" => Firebase.AI.FinishReason.ImageProhibitedContent,
+ "IMAGE_RECITATION" => Firebase.AI.FinishReason.ImageRecitation,
+ "IMAGE_OTHER" => Firebase.AI.FinishReason.ImageOther,
+ "NO_IMAGE" => Firebase.AI.FinishReason.NoImage,
_ => Firebase.AI.FinishReason.Unknown,
};
}
diff --git a/firebaseai/src/GenerationConfig.cs b/firebaseai/src/GenerationConfig.cs
index e4a0ca97..6f9842f2 100644
--- a/firebaseai/src/GenerationConfig.cs
+++ b/firebaseai/src/GenerationConfig.cs
@@ -38,6 +38,7 @@ public readonly struct GenerationConfig {
private readonly Schema _responseSchema;
private readonly List _responseModalities;
private readonly ThinkingConfig? _thinkingConfig;
+ private readonly ImageConfig? _imageConfig;
///
/// Creates a new `GenerationConfig` value.
@@ -168,7 +169,8 @@ public GenerationConfig(
string responseMimeType = null,
Schema responseSchema = null,
IEnumerable responseModalities = null,
- ThinkingConfig? thinkingConfig = null) {
+ ThinkingConfig? thinkingConfig = null,
+ ImageConfig? imageConfig = null) {
_temperature = temperature;
_topP = topP;
_topK = topK;
@@ -182,6 +184,7 @@ public GenerationConfig(
_responseModalities = responseModalities != null ?
new List(responseModalities) : null;
_thinkingConfig = thinkingConfig;
+ _imageConfig = imageConfig;
}
///
@@ -205,6 +208,7 @@ internal Dictionary ToJson() {
_responseModalities.Select(EnumConverters.ResponseModalityToString).ToList();
}
if (_thinkingConfig != null) jsonDict["thinkingConfig"] = _thinkingConfig?.ToJson();
+ if (_imageConfig != null) jsonDict["imageConfig"] = _imageConfig?.ToJson();
return jsonDict;
}
diff --git a/firebaseai/src/ImageConfig.cs b/firebaseai/src/ImageConfig.cs
new file mode 100644
index 00000000..3a81b2da
--- /dev/null
+++ b/firebaseai/src/ImageConfig.cs
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2025 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may not obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Firebase.AI {
+
+///
+/// An aspect ratio for images.
+///
+public enum AspectRatio {
+ ///
+ /// Square (1:1) aspect ratio.
+ ///
+ SQUARE_1_1,
+ ///
+ /// Portrait (2:3) aspect ratio.
+ ///
+ PORTRAIT_2_3,
+ ///
+ /// Landscape (3:2) aspect ratio.
+ ///
+ LANDSCAPE_3_2,
+ ///
+ /// Portrait (3:4) aspect ratio.
+ ///
+ PORTRAIT_3_4,
+ ///
+ /// Landscape (4:3) aspect ratio.
+ ///
+ LANDSCAPE_4_3,
+ ///
+ /// Portrait (4:5) aspect ratio.
+ ///
+ PORTRAIT_4_5,
+ ///
+ /// Landscape (5:4) aspect ratio.
+ ///
+ LANDSCAPE_5_4,
+ ///
+ /// Portrait (9:16) aspect ratio.
+ ///
+ PORTRAIT_9_16,
+ ///
+ /// Landscape (16:9) aspect ratio.
+ ///
+ LANDSCAPE_16_9,
+ ///
+ /// Landscape (21:9) aspect ratio.
+ ///
+ LANDSCAPE_21_9,
+}
+
+///
+/// Configuration options for generating images.
+///
+public readonly struct ImageConfig {
+ ///
+ /// The aspect ratio of generated images.
+ ///
+ public AspectRatio? AspectRatio { get; }
+
+ ///
+ /// Initializes configuration options for generating images.
+ ///
+ /// The aspect ratio of generated images.
+ public ImageConfig(AspectRatio? aspectRatio = null) {
+ AspectRatio = aspectRatio;
+ }
+
+ private static string ConvertAspectRatio(AspectRatio aspectRatio) {
+ return aspectRatio switch {
+ AspectRatio.SQUARE_1_1 => "1:1",
+ AspectRatio.PORTRAIT_2_3 => "2:3",
+ AspectRatio.LANDSCAPE_3_2 => "3:2",
+ AspectRatio.PORTRAIT_3_4 => "3:4",
+ AspectRatio.LANDSCAPE_4_3 => "4:3",
+ AspectRatio.PORTRAIT_4_5 => "4:5",
+ AspectRatio.LANDSCAPE_5_4 => "5:4",
+ AspectRatio.PORTRAIT_9_16 => "9:16",
+ AspectRatio.LANDSCAPE_16_9 => "16:9",
+ AspectRatio.LANDSCAPE_21_9 => "21:9",
+ _ => aspectRatio.ToString(), // Fallback
+ };
+ }
+
+ internal Dictionary ToJson() {
+ var jsonDict = new System.Collections.Generic.Dictionary();
+ if (AspectRatio.HasValue) {
+ jsonDict["aspectRatio"] = ConvertAspectRatio(AspectRatio.Value);
+ }
+ return jsonDict;
+ }
+}
+
+}