Skip to content

Commit 889af7c

Browse files
authored
feat(ai): add missing enum types (#18198)
1 parent 90d2e1f commit 889af7c

File tree

3 files changed

+110
-4
lines changed

3 files changed

+110
-4
lines changed

packages/firebase_ai/firebase_ai/lib/src/api.dart

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,19 @@ enum HarmCategory {
626626
sexuallyExplicit('HARM_CATEGORY_SEXUALLY_EXPLICIT'),
627627

628628
/// Promotes or enables access to harmful goods, services, and activities.
629-
dangerousContent('HARM_CATEGORY_DANGEROUS_CONTENT');
629+
dangerousContent('HARM_CATEGORY_DANGEROUS_CONTENT'),
630+
631+
/// Image content containing hate speech.
632+
imageHate('HARM_CATEGORY_IMAGE_HATE'),
633+
634+
/// Image content that is dangerous.
635+
imageDangerousContent('HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT'),
636+
637+
/// Image content containing harassment.
638+
imageHarassment('HARM_CATEGORY_IMAGE_HARASSMENT'),
639+
640+
/// Image content that is sexually explicit.
641+
imageSexuallyExplicit('HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT');
630642

631643
const HarmCategory(this._jsonString);
632644

@@ -638,7 +650,13 @@ enum HarmCategory {
638650
'HARM_CATEGORY_HATE_SPEECH' => HarmCategory.hateSpeech,
639651
'HARM_CATEGORY_SEXUALLY_EXPLICIT' => HarmCategory.sexuallyExplicit,
640652
'HARM_CATEGORY_DANGEROUS_CONTENT' => HarmCategory.dangerousContent,
641-
_ => throw FormatException('Unhandled HarmCategory format', jsonObject),
653+
'HARM_CATEGORY_IMAGE_HATE' => HarmCategory.imageHate,
654+
'HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT' =>
655+
HarmCategory.imageDangerousContent,
656+
'HARM_CATEGORY_IMAGE_HARASSMENT' => HarmCategory.imageHarassment,
657+
'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT' =>
658+
HarmCategory.imageSexuallyExplicit,
659+
_ => HarmCategory.unknown,
642660
};
643661
}
644662

packages/firebase_ai/firebase_ai/lib/src/developer/api.dart

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,13 @@ String _harmCategoryToJson(HarmCategory harmCategory) => switch (harmCategory) {
4949
HarmCategory.harassment => 'HARM_CATEGORY_HARASSMENT',
5050
HarmCategory.hateSpeech => 'HARM_CATEGORY_HATE_SPEECH',
5151
HarmCategory.sexuallyExplicit => 'HARM_CATEGORY_SEXUALLY_EXPLICIT',
52-
HarmCategory.dangerousContent => 'HARM_CATEGORY_DANGEROUS_CONTENT'
52+
HarmCategory.dangerousContent => 'HARM_CATEGORY_DANGEROUS_CONTENT',
53+
HarmCategory.imageHate => 'HARM_CATEGORY_IMAGE_HATE',
54+
HarmCategory.imageDangerousContent =>
55+
'HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT',
56+
HarmCategory.imageHarassment => 'HARM_CATEGORY_IMAGE_HARASSMENT',
57+
HarmCategory.imageSexuallyExplicit =>
58+
'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT',
5359
};
5460

5561
Object _safetySettingToJson(SafetySetting safetySetting) {
@@ -241,5 +247,11 @@ HarmCategory _parseHarmCategory(Object jsonObject) => switch (jsonObject) {
241247
'HARM_CATEGORY_HATE_SPEECH' => HarmCategory.hateSpeech,
242248
'HARM_CATEGORY_SEXUALLY_EXPLICIT' => HarmCategory.sexuallyExplicit,
243249
'HARM_CATEGORY_DANGEROUS_CONTENT' => HarmCategory.dangerousContent,
244-
_ => throw unhandledFormat('HarmCategory', jsonObject),
250+
'HARM_CATEGORY_IMAGE_HATE' => HarmCategory.imageHate,
251+
'HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT' =>
252+
HarmCategory.imageDangerousContent,
253+
'HARM_CATEGORY_IMAGE_HARASSMENT' => HarmCategory.imageHarassment,
254+
'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT' =>
255+
HarmCategory.imageSexuallyExplicit,
256+
_ => HarmCategory.unknown,
245257
};

packages/firebase_ai/firebase_ai/test/api_test.dart

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,13 @@ void main() {
289289
'HARM_CATEGORY_SEXUALLY_EXPLICIT');
290290
expect(HarmCategory.dangerousContent.toJson(),
291291
'HARM_CATEGORY_DANGEROUS_CONTENT');
292+
expect(HarmCategory.imageHate.toJson(), 'HARM_CATEGORY_IMAGE_HATE');
293+
expect(HarmCategory.imageDangerousContent.toJson(),
294+
'HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT');
295+
expect(HarmCategory.imageHarassment.toJson(),
296+
'HARM_CATEGORY_IMAGE_HARASSMENT');
297+
expect(HarmCategory.imageSexuallyExplicit.toJson(),
298+
'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT');
292299
});
293300

294301
test('HarmProbability toJson and toString', () {
@@ -736,6 +743,75 @@ void main() {
736743
expect(response.usageMetadata!.candidatesTokensDetails, hasLength(1));
737744
});
738745

746+
test('parses image harm categories in safetyRatings', () {
747+
final json = {
748+
'candidates': [
749+
{
750+
'content': {
751+
'role': 'model',
752+
'parts': [
753+
{'text': ''}
754+
]
755+
},
756+
'finishReason': 'STOP',
757+
'safetyRatings': [
758+
{
759+
'category': 'HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT',
760+
'probability': 'NEGLIGIBLE'
761+
},
762+
{
763+
'category': 'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT',
764+
'probability': 'NEGLIGIBLE'
765+
},
766+
{
767+
'category': 'HARM_CATEGORY_IMAGE_HATE',
768+
'probability': 'NEGLIGIBLE'
769+
},
770+
{
771+
'category': 'HARM_CATEGORY_IMAGE_HARASSMENT',
772+
'probability': 'NEGLIGIBLE'
773+
},
774+
]
775+
}
776+
]
777+
};
778+
final response =
779+
VertexSerialization().parseGenerateContentResponse(json);
780+
final ratings = response.candidates.first.safetyRatings!;
781+
expect(ratings.map((r) => r.category), [
782+
HarmCategory.imageDangerousContent,
783+
HarmCategory.imageSexuallyExplicit,
784+
HarmCategory.imageHate,
785+
HarmCategory.imageHarassment,
786+
]);
787+
});
788+
789+
test('falls back to HarmCategory.unknown for unrecognized values', () {
790+
final json = {
791+
'candidates': [
792+
{
793+
'content': {
794+
'role': 'model',
795+
'parts': [
796+
{'text': ''}
797+
]
798+
},
799+
'finishReason': 'STOP',
800+
'safetyRatings': [
801+
{
802+
'category': 'HARM_CATEGORY_SOMETHING_NEW',
803+
'probability': 'NEGLIGIBLE'
804+
}
805+
]
806+
}
807+
]
808+
};
809+
final response =
810+
VertexSerialization().parseGenerateContentResponse(json);
811+
expect(response.candidates.first.safetyRatings!.first.category,
812+
HarmCategory.unknown);
813+
});
814+
739815
group('usageMetadata parsing', () {
740816
test('parses usageMetadata when thoughtsTokenCount is set', () {
741817
final json = {

0 commit comments

Comments
 (0)