Skip to content

[Firebase AI] Add the test json files #1282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace Firebase.Sample.FirebaseAI {
using System.Threading.Tasks;
using Google.MiniJSON;
using UnityEngine;
using UnityEngine.Video;
using UnityEngine.Networking;
using System.IO;
#if INCLUDE_FIREBASE_AUTH
using Firebase.Auth;
Expand Down Expand Up @@ -443,7 +443,7 @@ async Task TestEnumSchemaResponse(Backend backend) {
generationConfig: new GenerationConfig(
responseMimeType: "text/x.enum",
responseSchema: Schema.Enum(new string[] { enumValue })));

var response = await model.GenerateContentAsync(
"Hello, I am testing setting the response schema to an enum.");

Expand All @@ -459,7 +459,7 @@ async Task TestAnyOfSchemaResponse(Backend backend) {
Schema.AnyOf(new[] { Schema.Int(), Schema.String() }),
minItems: 2,
maxItems: 6)));

var response = await model.GenerateContentAsync(
"Hello, I am testing setting the response schema with an array, cause you give me some random values.");

Expand Down Expand Up @@ -658,7 +658,7 @@ async Task TestYoutubeLink(Backend backend) {
async Task TestGenerateImage(Backend backend) {
var model = GetFirebaseAI(backend).GetGenerativeModel("gemini-2.0-flash-exp",
generationConfig: new GenerationConfig(
responseModalities: new [] { ResponseModality.Text, ResponseModality.Image })
responseModalities: new[] { ResponseModality.Text, ResponseModality.Image })
);

GenerateContentResponse response = await model.GenerateContentAsync(
Expand Down Expand Up @@ -737,17 +737,40 @@ async Task TestReadSecureFile() {

// The url prefix to use when fetching test data to use from the separate GitHub repo.
readonly string testDataUrl =
"https://raw.githubusercontent.com/FirebaseExtended/vertexai-sdk-test-data/3737ae1fe9c5ecbd55abdeabc273ef4f392cbf19/mock-responses/";
"https://raw.githubusercontent.com/FirebaseExtended/vertexai-sdk-test-data/47becf9101d11ea3c568bf60b12f1c8ed9fb684e/mock-responses/";
readonly HttpClient httpClient = new();

private Task<string> LoadStreamingAsset(string fullPath) {
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
UnityWebRequest request = UnityWebRequest.Get(fullPath);
request.SendWebRequest().completed += (_) => {
if (request.result == UnityWebRequest.Result.Success) {
tcs.SetResult(request.downloadHandler.text);
} else {
tcs.SetResult(null);
}
};
return tcs.Task;
}

// Gets the Json test data from the given filename, potentially downloading from a GitHub repo.
private async Task<Dictionary<string, object>> GetJsonTestData(string filename) {
// TODO: Check if the file is available locally first
string jsonString = null;
// First, try to load the file from StreamingAssets
string localPath = Path.Combine(Application.streamingAssetsPath, "TestData", filename);
if (localPath.StartsWith("jar") || localPath.StartsWith("http")) {
// Special case to access StreamingAsset content on Android
jsonString = await LoadStreamingAsset(localPath);
} else if (File.Exists(localPath)) {
jsonString = File.ReadAllText(localPath);
}

var response = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, testDataUrl + filename));
response.EnsureSuccessStatusCode();

string jsonString = await response.Content.ReadAsStringAsync();
if (string.IsNullOrEmpty(jsonString)) {
var response = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, testDataUrl + filename));
response.EnsureSuccessStatusCode();

jsonString = await response.Content.ReadAsStringAsync();
}

return Json.Deserialize(jsonString) as Dictionary<string, object>;
}
Expand Down Expand Up @@ -862,7 +885,7 @@ async Task InternalTestBasicReplyShort() {
async Task InternalTestCitations() {
Dictionary<string, object> json = await GetVertexJsonTestData("unary-success-citations.json");
GenerateContentResponse response = GenerateContentResponse.FromJson(json, FirebaseAI.Backend.InternalProvider.VertexAI);

ValidateTextPart(response, "Some information cited from an external source");

CitationMetadata? metadata = response.Candidates.First().CitationMetadata;
Expand Down Expand Up @@ -1050,7 +1073,7 @@ async Task InternalTestBasicResponseLongUsageMetadata() {
// Test that parsing a basic short reply from Google AI endpoint works as expected.
// https://github.com/FirebaseExtended/vertexai-sdk-test-data/blob/main/mock-responses/googleai/unary-success-basic-reply-short.txt
async Task InternalTestGoogleAIBasicReplyShort() {
Dictionary<string, object> json = await GetGoogleAIJsonTestData("unary-success-basic-reply-short.txt"); //
Dictionary<string, object> json = await GetGoogleAIJsonTestData("unary-success-basic-reply-short.json"); //
GenerateContentResponse response = GenerateContentResponse.FromJson(json, FirebaseAI.Backend.InternalProvider.GoogleAI);

ValidateTextPart(response, "Google's headquarters, also known as the Googleplex, is located in **Mountain View, California**.\n");
Expand All @@ -1076,12 +1099,12 @@ async Task InternalTestGoogleAIBasicReplyShort() {
// Test parsing a Google AI format response with citations.
// Based on: https://github.com/FirebaseExtended/vertexai-sdk-test-data/blob/main/mock-responses/googleai/unary-success-citations.txt
async Task InternalTestGoogleAICitations() {
Dictionary<string, object> json = await GetGoogleAIJsonTestData("unary-success-citations.txt");
Dictionary<string, object> json = await GetGoogleAIJsonTestData("unary-success-citations.json");
GenerateContentResponse response = GenerateContentResponse.FromJson(json, FirebaseAI.Backend.InternalProvider.GoogleAI);

// Validate Text Part (check start and end)
string expectedStart = "Okay, let's break down quantum mechanics.";
string expectedEnd = "foundation for many technologies, including:\n";
string expectedEnd = "area of physics!";
Assert("Candidate count", response.Candidates.Count() == 1);
Candidate candidate = response.Candidates.First();
AssertEq("Content role", candidate.Content.Role, "model");
Expand Down
8 changes: 8 additions & 0 deletions firebaseai/testapp/Assets/StreamingAssets.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions firebaseai/testapp/Assets/StreamingAssets/TestData.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"candidates": [
{
"content": {
"parts": [
{
"text": "Google's headquarters, also known as the Googleplex, is located in **Mountain View, California**.\n"
}
],
"role": "model"
},
"finishReason": "STOP",
"safetyRatings": [
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_HARASSMENT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
"probability": "NEGLIGIBLE"
}
],
"avgLogprobs": -0.048741644079034981
}
],
"usageMetadata": {
"promptTokenCount": 7,
"candidatesTokenCount": 22,
"totalTokenCount": 29,
"promptTokensDetails": [
{
"modality": "TEXT",
"tokenCount": 7
}
],
"candidatesTokensDetails": [
{
"modality": "TEXT",
"tokenCount": 22
}
]
},
"modelVersion": "gemini-2.0-flash"
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"candidates": [
{
"content": {
"parts": [
{
"text": "Okay, let's break down quantum mechanics. It's a challenging but fascinating area of physics!"
}
],
"role": "model"
},
"finishReason": "STOP",
"safetyRatings": [
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_HARASSMENT",
"probability": "NEGLIGIBLE"
},
{
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
"probability": "NEGLIGIBLE"
}
],
"citationMetadata": {
"citationSources": [
{
"startIndex": 548,
"endIndex": 690,
"uri": "https://www.example.com/some-citation-1",
"license": "mit"
},
{
"startIndex": 1240,
"endIndex": 1407,
"uri": "https://www.example.com/some-citation-1"
},
{
"startIndex": 1942,
"endIndex": 2149
},
{
"startIndex": 2036,
"endIndex": 2175
}
]
},
"avgLogprobs": -0.30887421148582783
}
],
"usageMetadata": {
"promptTokenCount": 15,
"candidatesTokenCount": 1667,
"totalTokenCount": 1682,
"promptTokensDetails": [
{
"modality": "TEXT",
"tokenCount": 15
}
],
"candidatesTokensDetails": [
{
"modality": "TEXT",
"tokenCount": 1667
}
]
},
"modelVersion": "gemini-2.0-flash"
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"candidates": [
{
"finishReason": "SAFETY",
"safetyRatings": [
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"probability": "NEGLIGIBLE",
"probabilityScore": 0.3984375,
"severity": "HARM_SEVERITY_LOW",
"severityScore": 0.21582031
},
{
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
"probability": "NEGLIGIBLE",
"probabilityScore": 0.14941406,
"severity": "HARM_SEVERITY_NEGLIGIBLE",
"severityScore": 0.02331543
},
{
"category": "HARM_CATEGORY_HARASSMENT",
"probability": "LOW",
"blocked": true,
"probabilityScore": 0.61328125,
"severity": "HARM_SEVERITY_LOW",
"severityScore": 0.31835938
},
{
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
"probability": "NEGLIGIBLE",
"probabilityScore": 0.13476563,
"severity": "HARM_SEVERITY_NEGLIGIBLE",
"severityScore": 0.12109375
}
]
}
],
"usageMetadata": {
"promptTokenCount": 8,
"totalTokenCount": 8
},
"modelVersion": "gemini-1.5-flash"
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"predictions": [
{
"raiFilteredReason": "Unable to show generated images. All images were filtered out because they violated Vertex AI's usage guidelines. You will not be charged for blocked images. Try rephrasing the prompt. If you think this was an error, send feedback. Support codes: 39322892, 29310472"
}
]
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading