Skip to content

Commit 7894526

Browse files
authored
handle omit tokenCount nicely (#17336)
1 parent 0b98669 commit 7894526

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

packages/firebase_vertexai/firebase_vertexai/lib/src/api.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,8 +1023,13 @@ ModalityTokenCount _parseModalityTokenCount(Object? jsonObject) {
10231023
if (jsonObject is! Map) {
10241024
throw unhandledFormat('ModalityTokenCount', jsonObject);
10251025
}
1026-
return ModalityTokenCount(ContentModality._parseValue(jsonObject['modality']),
1027-
jsonObject['tokenCount'] as int);
1026+
var modality = ContentModality._parseValue(jsonObject['modality']);
1027+
1028+
if (jsonObject.containsKey('tokenCount')) {
1029+
return ModalityTokenCount(modality, jsonObject['tokenCount'] as int);
1030+
} else {
1031+
return ModalityTokenCount(modality, 0);
1032+
}
10281033
}
10291034

10301035
SafetyRating _parseSafetyRating(Object? jsonObject) {

packages/firebase_vertexai/firebase_vertexai/test/api_test.dart

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,9 @@ void main() {
437437
'totalTokens': 120,
438438
'totalBillableCharacters': 240,
439439
'promptTokensDetails': [
440-
{'modality': 'TEXT', 'tokenCount': 100},
440+
{
441+
'modality': 'TEXT',
442+
},
441443
{'modality': 'IMAGE', 'tokenCount': 20}
442444
]
443445
};
@@ -447,7 +449,7 @@ void main() {
447449
expect(response.promptTokensDetails, isNotNull);
448450
expect(response.promptTokensDetails, hasLength(2));
449451
expect(response.promptTokensDetails![0].modality, ContentModality.text);
450-
expect(response.promptTokensDetails![0].tokenCount, 100);
452+
expect(response.promptTokensDetails![0].tokenCount, 0);
451453
expect(
452454
response.promptTokensDetails![1].modality, ContentModality.image);
453455
expect(response.promptTokensDetails![1].tokenCount, 20);
@@ -597,6 +599,47 @@ void main() {
597599
expect(response.candidates.first.finishMessage, isNull);
598600
});
599601

602+
test('parses usageMetadata for no tokenCount', () {
603+
final json = {
604+
'candidates': [basicCandidateJson],
605+
'usageMetadata': {
606+
'promptTokenCount': 10,
607+
'candidatesTokenCount': 20,
608+
'totalTokenCount': 30,
609+
'promptTokensDetails': [
610+
{'modality': 'TEXT', 'tokenCount': 10}
611+
],
612+
'candidatesTokensDetails': [
613+
{
614+
'modality': 'TEXT',
615+
}
616+
],
617+
}
618+
};
619+
final response = parseGenerateContentResponse(json);
620+
expect(response.candidates, hasLength(1));
621+
expect(response.candidates.first.text, 'Hello world');
622+
expect(response.candidates.first.finishReason, FinishReason.stop);
623+
expect(response.candidates.first.safetyRatings, isNotNull);
624+
expect(response.candidates.first.safetyRatings, hasLength(1));
625+
626+
expect(response.usageMetadata, isNotNull);
627+
expect(response.usageMetadata!.promptTokenCount, 10);
628+
expect(response.usageMetadata!.candidatesTokenCount, 20);
629+
expect(response.usageMetadata!.totalTokenCount, 30);
630+
expect(response.usageMetadata!.promptTokensDetails, hasLength(1));
631+
expect(response.usageMetadata!.promptTokensDetails!.first.modality,
632+
ContentModality.text);
633+
expect(
634+
response.usageMetadata!.promptTokensDetails!.first.tokenCount, 10);
635+
expect(response.usageMetadata!.candidatesTokensDetails, hasLength(1));
636+
expect(response.usageMetadata!.candidatesTokensDetails!.first.modality,
637+
ContentModality.text);
638+
expect(
639+
response.usageMetadata!.candidatesTokensDetails!.first.tokenCount,
640+
0);
641+
});
642+
600643
test('parses citationMetadata with "citationSources"', () {
601644
final json = {
602645
'candidates': [

0 commit comments

Comments
 (0)