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; + } +} + +}