From 95c617dafbae6714056adc04eeb7578bf7aa3333 Mon Sep 17 00:00:00 2001 From: Greg Spencer Date: Thu, 24 Jul 2025 18:16:02 -0700 Subject: [PATCH 1/7] add responseJsonSchema to GenerationConfig --- packages/firebase_ai/firebase_ai/CHANGELOG.md | 4 ++++ .../firebase_ai/firebase_ai/lib/src/api.dart | 17 +++++++++++++- .../firebase_ai/test/api_test.dart | 23 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/packages/firebase_ai/firebase_ai/CHANGELOG.md b/packages/firebase_ai/firebase_ai/CHANGELOG.md index ac6b077646fc..deea82bb0d76 100644 --- a/packages/firebase_ai/firebase_ai/CHANGELOG.md +++ b/packages/firebase_ai/firebase_ai/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.3.1 + + - **FEAT**(firebase_ai): Add support for `responseJsonSchema` in the [GenerationConfig]. + ## 2.3.0 - **FEAT**(firebase_ai): Add support for Grounding with Google Search ([#17468](https://github.com/firebase/flutterfire/issues/17468)). ([2aaf5af0](https://github.com/firebase/flutterfire/commit/2aaf5af08d46d90bd723997b20109362d9f18d32)) diff --git a/packages/firebase_ai/firebase_ai/lib/src/api.dart b/packages/firebase_ai/firebase_ai/lib/src/api.dart index 7a482c087f1d..6da9cd3eb796 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/api.dart @@ -998,8 +998,10 @@ final class GenerationConfig extends BaseGenerationConfig { super.responseModalities, this.responseMimeType, this.responseSchema, + this.responseJsonSchema, this.thinkingConfig, - }); + }) : assert(responseSchema == null || responseJsonSchema == null, + 'responseSchema and responseJsonSchema cannot both be set.'); /// The set of character sequences (up to 5) that will stop output generation. /// @@ -1020,6 +1022,17 @@ final class GenerationConfig extends BaseGenerationConfig { /// a schema; currently this is limited to `application/json`. final Schema? responseSchema; + /// The response schema as a JSON string. + /// + /// - Note: This only applies when the [responseMimeType] supports a schema; + /// currently this is limited to `application/json`. + /// + /// This schema can include more advanced features of JSON than the [Schema] + /// class supports. See [the Gemini + /// documentation](https://ai.google.dev/gemini-api/docs/structured-output#json-schema) + /// about the limitations of this feature. + final String? responseJsonSchema; + /// Config for thinking features. /// /// An error will be returned if this field is set for models that don't @@ -1036,6 +1049,8 @@ final class GenerationConfig extends BaseGenerationConfig { 'responseMimeType': responseMimeType, if (responseSchema case final responseSchema?) 'responseSchema': responseSchema.toJson(), + if (responseJsonSchema case final responseJsonSchema?) + 'responseSchema': responseJsonSchema, if (thinkingConfig case final thinkingConfig?) 'thinkingConfig': thinkingConfig.toJson(), }; diff --git a/packages/firebase_ai/firebase_ai/test/api_test.dart b/packages/firebase_ai/firebase_ai/test/api_test.dart index a21b17a0ee56..a0017bc36570 100644 --- a/packages/firebase_ai/firebase_ai/test/api_test.dart +++ b/packages/firebase_ai/firebase_ai/test/api_test.dart @@ -442,6 +442,29 @@ void main() { }); }); + test('GenerationConfig toJson with responseJsonSchema', () { + const jsonSchema = '{"type": "string", "title": "MyString"}'; + final config = GenerationConfig( + responseMimeType: 'application/json', + responseJsonSchema: jsonSchema, + ); + expect(config.toJson(), { + 'responseMimeType': 'application/json', + 'responseSchema': jsonSchema, + }); + }); + + test( + 'throws assertion if both responseSchema and responseJsonSchema are provided', + () { + final schema = Schema.object(properties: {}); + const jsonSchema = '{"type": "string", "title": "MyString"}'; + expect( + () => GenerationConfig( + responseSchema: schema, responseJsonSchema: jsonSchema), + throwsA(isA())); + }); + test('GenerationConfig toJson with empty stopSequences (omitted)', () { final config = GenerationConfig(stopSequences: []); expect(config.toJson(), {}); // Empty list for stopSequences is omitted From bc56c2274a13ce37133181fd4b51e1aebf004a0d Mon Sep 17 00:00:00 2001 From: Greg Spencer Date: Fri, 25 Jul 2025 09:18:29 -0700 Subject: [PATCH 2/7] Bump version in pubspec --- packages/firebase_ai/firebase_ai/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/firebase_ai/firebase_ai/pubspec.yaml b/packages/firebase_ai/firebase_ai/pubspec.yaml index 2dd52dede1cc..801f8cbb79f6 100644 --- a/packages/firebase_ai/firebase_ai/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ai description: Firebase AI SDK. -version: 2.3.0 +version: 2.3.1 homepage: https://firebase.google.com/docs/vertex-ai/get-started?platform=flutter topics: - firebase @@ -17,7 +17,7 @@ platforms: environment: sdk: '>=3.2.0 <4.0.0' - flutter: ">=3.16.0" + flutter: '>=3.16.0' dependencies: firebase_app_check: ^0.3.2+10 From 1da68aefdc63d3f5f5a22fed7c28216d8aaa6348 Mon Sep 17 00:00:00 2001 From: Greg Spencer Date: Tue, 29 Jul 2025 12:41:54 -0700 Subject: [PATCH 3/7] Fix typo --- packages/firebase_ai/firebase_ai/lib/src/api.dart | 2 +- packages/firebase_ai/firebase_ai/test/api_test.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/firebase_ai/firebase_ai/lib/src/api.dart b/packages/firebase_ai/firebase_ai/lib/src/api.dart index 6da9cd3eb796..3f037024bad8 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/api.dart @@ -1050,7 +1050,7 @@ final class GenerationConfig extends BaseGenerationConfig { if (responseSchema case final responseSchema?) 'responseSchema': responseSchema.toJson(), if (responseJsonSchema case final responseJsonSchema?) - 'responseSchema': responseJsonSchema, + 'responseJsonSchema': responseJsonSchema, if (thinkingConfig case final thinkingConfig?) 'thinkingConfig': thinkingConfig.toJson(), }; diff --git a/packages/firebase_ai/firebase_ai/test/api_test.dart b/packages/firebase_ai/firebase_ai/test/api_test.dart index a0017bc36570..53353614d346 100644 --- a/packages/firebase_ai/firebase_ai/test/api_test.dart +++ b/packages/firebase_ai/firebase_ai/test/api_test.dart @@ -450,7 +450,7 @@ void main() { ); expect(config.toJson(), { 'responseMimeType': 'application/json', - 'responseSchema': jsonSchema, + 'responseJsonSchema': jsonSchema, }); }); From 8ff84b6c5379e702f91baa03a648c6f4f98b350a Mon Sep 17 00:00:00 2001 From: Greg Spencer Date: Wed, 30 Jul 2025 11:59:03 -0700 Subject: [PATCH 4/7] Review changes --- packages/firebase_ai/firebase_ai/CHANGELOG.md | 4 ---- .../firebase_ai/firebase_ai/lib/src/api.dart | 21 ++++++++++++++----- packages/firebase_ai/firebase_ai/pubspec.yaml | 4 ++-- .../firebase_ai/test/api_test.dart | 13 +++++++++--- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/packages/firebase_ai/firebase_ai/CHANGELOG.md b/packages/firebase_ai/firebase_ai/CHANGELOG.md index 07a42be25e7e..6b3c82bd2a30 100644 --- a/packages/firebase_ai/firebase_ai/CHANGELOG.md +++ b/packages/firebase_ai/firebase_ai/CHANGELOG.md @@ -1,7 +1,3 @@ -## 3.1.0 - - - **FEAT**(firebase_ai): Add support for `responseJsonSchema` in the [GenerationConfig]. - ## 3.0.0 > Note: This release has breaking changes. diff --git a/packages/firebase_ai/firebase_ai/lib/src/api.dart b/packages/firebase_ai/firebase_ai/lib/src/api.dart index 3f037024bad8..ad5e0bd754fe 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/api.dart @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +import 'dart:convert'; + import 'content.dart'; import 'error.dart'; import 'schema.dart'; @@ -1020,18 +1022,27 @@ final class GenerationConfig extends BaseGenerationConfig { /// /// - Note: This only applies when the [responseMimeType] supports /// a schema; currently this is limited to `application/json`. + /// + /// Only one of [responseSchema] or [responseJsonSchema] may be specified at + /// the same time. final Schema? responseSchema; - /// The response schema as a JSON string. + /// The response schema as a JSON-compatible map. /// /// - Note: This only applies when the [responseMimeType] supports a schema; /// currently this is limited to `application/json`. /// /// This schema can include more advanced features of JSON than the [Schema] - /// class supports. See [the Gemini - /// documentation](https://ai.google.dev/gemini-api/docs/structured-output#json-schema) + /// class taken by [responseSchema] supports. See the [Gemini + /// documentation](https://ai.google.dev/api/generate-content#FIELDS.response_json_schema) /// about the limitations of this feature. - final String? responseJsonSchema; + /// + /// Notably, this feature is only supported on Gemini 2.5 and later. Use + /// [responseSchema] for earlier models. + /// + /// Only one of [responseSchema] or [responseJsonSchema] may be specified at + /// the same time. + final Map? responseJsonSchema; /// Config for thinking features. /// @@ -1050,7 +1061,7 @@ final class GenerationConfig extends BaseGenerationConfig { if (responseSchema case final responseSchema?) 'responseSchema': responseSchema.toJson(), if (responseJsonSchema case final responseJsonSchema?) - 'responseJsonSchema': responseJsonSchema, + 'responseJsonSchema': json.encode(responseJsonSchema), if (thinkingConfig case final thinkingConfig?) 'thinkingConfig': thinkingConfig.toJson(), }; diff --git a/packages/firebase_ai/firebase_ai/pubspec.yaml b/packages/firebase_ai/firebase_ai/pubspec.yaml index 6570a8cccfa8..89d92429ea9d 100644 --- a/packages/firebase_ai/firebase_ai/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ai description: Firebase AI SDK. -version: 3.1.0 +version: 3.0.0 homepage: https://firebase.google.com/docs/vertex-ai/get-started?platform=flutter topics: - firebase @@ -17,7 +17,7 @@ platforms: environment: sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.16.0' + flutter: ">=3.16.0" dependencies: firebase_app_check: ^0.4.0 diff --git a/packages/firebase_ai/firebase_ai/test/api_test.dart b/packages/firebase_ai/firebase_ai/test/api_test.dart index 53353614d346..2972c5af05e2 100644 --- a/packages/firebase_ai/firebase_ai/test/api_test.dart +++ b/packages/firebase_ai/firebase_ai/test/api_test.dart @@ -11,6 +11,9 @@ // 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. + +import 'dart:convert'; + import 'package:firebase_ai/firebase_ai.dart'; import 'package:firebase_ai/src/api.dart'; @@ -443,14 +446,16 @@ void main() { }); test('GenerationConfig toJson with responseJsonSchema', () { - const jsonSchema = '{"type": "string", "title": "MyString"}'; + final jsonSchema = + (json.decode('{"type": "string", "title": "MyString"}') as Map) + .cast(); final config = GenerationConfig( responseMimeType: 'application/json', responseJsonSchema: jsonSchema, ); expect(config.toJson(), { 'responseMimeType': 'application/json', - 'responseJsonSchema': jsonSchema, + 'responseJsonSchema': json.encode(jsonSchema), }); }); @@ -458,7 +463,9 @@ void main() { 'throws assertion if both responseSchema and responseJsonSchema are provided', () { final schema = Schema.object(properties: {}); - const jsonSchema = '{"type": "string", "title": "MyString"}'; + final jsonSchema = + (json.decode('{"type": "string", "title": "MyString"}') as Map) + .cast(); expect( () => GenerationConfig( responseSchema: schema, responseJsonSchema: jsonSchema), From 37cbc3c18dcf84c64dd4d3f4b074a3682c1e0ff6 Mon Sep 17 00:00:00 2001 From: Greg Spencer Date: Wed, 30 Jul 2025 17:16:13 -0700 Subject: [PATCH 5/7] Remove string encoding. --- packages/firebase_ai/firebase_ai/lib/src/api.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_ai/firebase_ai/lib/src/api.dart b/packages/firebase_ai/firebase_ai/lib/src/api.dart index ad5e0bd754fe..07fc9a16ed5d 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/api.dart @@ -1061,7 +1061,7 @@ final class GenerationConfig extends BaseGenerationConfig { if (responseSchema case final responseSchema?) 'responseSchema': responseSchema.toJson(), if (responseJsonSchema case final responseJsonSchema?) - 'responseJsonSchema': json.encode(responseJsonSchema), + 'responseJsonSchema': responseJsonSchema, if (thinkingConfig case final thinkingConfig?) 'thinkingConfig': thinkingConfig.toJson(), }; From 0f578e4ddab8f6e8cfad881acc0e6f28b6fb540e Mon Sep 17 00:00:00 2001 From: Greg Spencer Date: Wed, 30 Jul 2025 17:23:12 -0700 Subject: [PATCH 6/7] Update test. --- .../firebase_ai/test/api_test.dart | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/firebase_ai/firebase_ai/test/api_test.dart b/packages/firebase_ai/firebase_ai/test/api_test.dart index 2972c5af05e2..72a4e8536f23 100644 --- a/packages/firebase_ai/firebase_ai/test/api_test.dart +++ b/packages/firebase_ai/firebase_ai/test/api_test.dart @@ -446,17 +446,22 @@ void main() { }); test('GenerationConfig toJson with responseJsonSchema', () { - final jsonSchema = - (json.decode('{"type": "string", "title": "MyString"}') as Map) - .cast(); + final jsonSchema = { + 'type': 'object', + 'properties': { + 'recipeName': {'type': 'string'} + }, + 'required': ['recipeName'] + }; final config = GenerationConfig( responseMimeType: 'application/json', responseJsonSchema: jsonSchema, ); - expect(config.toJson(), { - 'responseMimeType': 'application/json', - 'responseJsonSchema': json.encode(jsonSchema), - }); + final json = config.toJson(); + expect(json['responseMimeType'], 'application/json'); + final dynamic responseSchema = json['responseJsonSchema']; + expect(responseSchema, isA>()); + expect(responseSchema, equals(jsonSchema)); }); test( From 3ccc4515fe82060921b41c92660828fd12da56b7 Mon Sep 17 00:00:00 2001 From: Greg Spencer Date: Thu, 31 Jul 2025 09:11:09 -0700 Subject: [PATCH 7/7] Fix analyzer warning --- packages/firebase_ai/firebase_ai/lib/src/api.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/firebase_ai/firebase_ai/lib/src/api.dart b/packages/firebase_ai/firebase_ai/lib/src/api.dart index 07fc9a16ed5d..f669446c7629 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/api.dart @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -import 'dart:convert'; - import 'content.dart'; import 'error.dart'; import 'schema.dart';