diff --git a/src/GenerativeAI.Microsoft/AdditionalPropertyKeys.cs b/src/GenerativeAI.Microsoft/AdditionalPropertyKeys.cs index 674106e8..9eb679fc 100644 --- a/src/GenerativeAI.Microsoft/AdditionalPropertyKeys.cs +++ b/src/GenerativeAI.Microsoft/AdditionalPropertyKeys.cs @@ -14,4 +14,14 @@ public static class AdditionalPropertiesKeys /// Key used to indicate the thinking budget in tokens. /// public const string ThinkingBudget = "ThinkingBudget"; + + /// + /// Key used to specify response modalities (e.g., text, image). + /// + public const string ResponseModalities = "ResponseModalities"; + + /// + /// Key used to specify the aspect ratio for image generation. + /// + public const string ImageConfigAspectRatio = "AspectRatio"; } \ No newline at end of file diff --git a/src/GenerativeAI.Microsoft/Extensions/MicrosoftExtensions.cs b/src/GenerativeAI.Microsoft/Extensions/MicrosoftExtensions.cs index 0e74d70c..b43255c3 100644 --- a/src/GenerativeAI.Microsoft/Extensions/MicrosoftExtensions.cs +++ b/src/GenerativeAI.Microsoft/Extensions/MicrosoftExtensions.cs @@ -337,6 +337,17 @@ private static JsonNode ToJsonNodeResponse(this object? response) config.ThinkingConfig.IncludeThoughts = includeThoughts; } + if (options.AdditionalProperties.TryGetValue(AdditionalPropertiesKeys.ResponseModalities, out List? modalities)) + { + config.ResponseModalities = modalities; + } + + if (options.AdditionalProperties.TryGetValue(AdditionalPropertiesKeys.ImageConfigAspectRatio, out string? aspectRatio)) + { + config.ImageConfig ??= new ImageConfig(); + config.ImageConfig.AspectRatio = aspectRatio; + } + return config; } @@ -394,9 +405,18 @@ public static ChatResponseUpdate ToChatResponseUpdate(this GenerateContentRespon if (response.Candidates != null) { + var contents = response.Candidates.Select(s => s.Content).SelectMany(s => s?.Parts ?? new List()).ToList().ToAiContents(options); + + // Add usage information as UsageContent so it gets aggregated by the framework + var usage = ParseContentResponseUsage(response); + if (usage != null) + { + contents.Add(new UsageContent(usage)); + } + return new ChatResponseUpdate { - Contents = response.Candidates.Select(s => s.Content).SelectMany(s => s?.Parts ?? new List()).ToList().ToAiContents(options), + Contents = contents, AdditionalProperties = null, FinishReason = response?.Candidates?.FirstOrDefault()?.FinishReason == FinishReason.OTHER ? ChatFinishReason.Stop diff --git a/src/GenerativeAI/Types/ContentGeneration/Config/GenerationConfig.cs b/src/GenerativeAI/Types/ContentGeneration/Config/GenerationConfig.cs index 4b206baf..3810833f 100644 --- a/src/GenerativeAI/Types/ContentGeneration/Config/GenerationConfig.cs +++ b/src/GenerativeAI/Types/ContentGeneration/Config/GenerationConfig.cs @@ -209,6 +209,12 @@ public class GenerationConfig /// [JsonPropertyName("responseJsonSchema")] public JsonNode? ResponseJsonSchema { get; set; } + + /// + /// Optional. Image generation configuration for models that support image output. + /// + [JsonPropertyName("imageConfig")] + public ImageConfig? ImageConfig { get; set; } } @@ -321,4 +327,16 @@ public class ManualRoutingMode /// [JsonPropertyName("modelName")] public string? ModelName { get; set; } +} + +/// +/// Configuration for image generation in models that support image output (e.g., gemini-2.5-flash-image). +/// +public class ImageConfig +{ + /// + /// Optional. The aspect ratio for generated images. Common values: "16:9", "9:16", "1:1", "4:3", "3:4". + /// + [JsonPropertyName("aspectRatio")] + public string? AspectRatio { get; set; } } \ No newline at end of file