Skip to content

Commit 69fe6f9

Browse files
authored
[VertexAI] Add response modality to GenerateContent (#1237)
* [VertexAI] Add multi-modalities to GenerationConfig * Add integration test
1 parent c536e96 commit 69fe6f9

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

vertexai/src/GenerationConfig.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
using System;
1818
using System.Collections.Generic;
19+
using System.Linq;
20+
using Firebase.VertexAI.Internal;
1921

2022
namespace Firebase.VertexAI {
2123

@@ -34,6 +36,7 @@ public readonly struct GenerationConfig {
3436
private readonly string[] _stopSequences;
3537
private readonly string _responseMimeType;
3638
private readonly Schema _responseSchema;
39+
private readonly List<ResponseModality> _responseModalities;
3740

3841
/// <summary>
3942
/// Creates a new `GenerationConfig` value.
@@ -146,7 +149,8 @@ public GenerationConfig(
146149
float? frequencyPenalty = null,
147150
string[] stopSequences = null,
148151
string responseMimeType = null,
149-
Schema responseSchema = null) {
152+
Schema responseSchema = null,
153+
IEnumerable<ResponseModality> responseModalities = null) {
150154
_temperature = temperature;
151155
_topP = topP;
152156
_topK = topK;
@@ -157,6 +161,8 @@ public GenerationConfig(
157161
_stopSequences = stopSequences;
158162
_responseMimeType = responseMimeType;
159163
_responseSchema = responseSchema;
164+
_responseModalities = responseModalities != null ?
165+
new List<ResponseModality>(responseModalities) : null;
160166
}
161167

162168
/// <summary>
@@ -175,6 +181,10 @@ internal Dictionary<string, object> ToJson() {
175181
if (_stopSequences != null && _stopSequences.Length > 0) jsonDict["stopSequences"] = _stopSequences;
176182
if (!string.IsNullOrWhiteSpace(_responseMimeType)) jsonDict["responseMimeType"] = _responseMimeType;
177183
if (_responseSchema != null) jsonDict["responseSchema"] = _responseSchema.ToJson();
184+
if (_responseModalities != null && _responseModalities.Count > 0) {
185+
jsonDict["responseModalities"] =
186+
_responseModalities.Select(EnumConverters.ResponseModalityToString).ToList();
187+
}
178188

179189
return jsonDict;
180190
}

vertexai/testapp/Assets/Firebase/Sample/VertexAI/UIHandlerAutomated.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ protected override void Start() {
6565
TestChatBasicTextStream,
6666
TestCountTokens,
6767
TestYoutubeLink,
68+
TestGenerateImage,
6869
};
6970
// Set of tests that only run the single time.
7071
Func<Task>[] singleTests = {
@@ -632,6 +633,35 @@ async Task TestYoutubeLink(Backend backend) {
632633
response.Text.Contains("Firebase", StringComparison.OrdinalIgnoreCase));
633634
}
634635

636+
// Test being able to generate an image with GenerateContent.
637+
async Task TestGenerateImage(Backend backend) {
638+
var model = GetFirebaseAI(backend).GetGenerativeModel("gemini-2.0-flash-exp",
639+
generationConfig: new GenerationConfig(
640+
responseModalities: new [] { ResponseModality.Text, ResponseModality.Image })
641+
);
642+
643+
GenerateContentResponse response = await model.GenerateContentAsync(
644+
ModelContent.Text("Can you give me a picture of a cartoon dog, and a couple of sentences about him?")
645+
);
646+
647+
Assert("Response missing candidates.", response.Candidates.Any());
648+
649+
// We don't care much about the response, just that there is an image, and text.
650+
bool foundText = false;
651+
bool foundImage = false;
652+
var candidate = response.Candidates.First();
653+
foreach (var part in candidate.Content.Parts) {
654+
if (part is ModelContent.TextPart) {
655+
foundText = true;
656+
} else if (part is ModelContent.InlineDataPart dataPart) {
657+
if (dataPart.MimeType.Contains("image")) {
658+
foundImage = true;
659+
}
660+
}
661+
}
662+
Assert($"Missing expected modalities. Text: {foundText}, Image: {foundImage}", foundText && foundImage);
663+
}
664+
635665
// Test providing a file from a GCS bucket (Firebase Storage) to the model.
636666
async Task TestReadFile() {
637667
// GCS is currently only supported with VertexAI.

0 commit comments

Comments
 (0)