@@ -33,8 +33,10 @@ import {
33
33
GenerateContentResponse ,
34
34
HarmCategory ,
35
35
HarmProbability ,
36
- SafetyRating
36
+ SafetyRating ,
37
+ VertexAIErrorCode
37
38
} from '../types' ;
39
+ import { VertexAIError } from '../errors' ;
38
40
39
41
use ( sinonChai ) ;
40
42
@@ -220,6 +222,23 @@ describe('processStream', () => {
220
222
}
221
223
expect ( foundCitationMetadata ) . to . be . true ;
222
224
} ) ;
225
+ it ( 'removes empty text parts' , async ( ) => {
226
+ const fakeResponse = getMockResponseStreaming (
227
+ 'streaming-success-empty-text-part.txt'
228
+ ) ;
229
+ const result = processStream ( fakeResponse as Response ) ;
230
+ const aggregatedResponse = await result . response ;
231
+ expect ( aggregatedResponse . text ( ) ) . to . equal ( '1' ) ;
232
+ expect ( aggregatedResponse . candidates ?. length ) . to . equal ( 1 ) ;
233
+ expect ( aggregatedResponse . candidates ?. [ 0 ] . content . parts . length ) . to . equal ( 1 ) ;
234
+
235
+ // The chunk with the empty text part will still go through the stream
236
+ let numChunks = 0 ;
237
+ for await ( const _ of result . stream ) {
238
+ numChunks ++ ;
239
+ }
240
+ expect ( numChunks ) . to . equal ( 2 ) ;
241
+ } ) ;
223
242
} ) ;
224
243
225
244
describe ( 'aggregateResponses' , ( ) => {
@@ -403,4 +422,49 @@ describe('aggregateResponses', () => {
403
422
) . to . equal ( 150 ) ;
404
423
} ) ;
405
424
} ) ;
425
+
426
+ it ( 'throws if a part has no properties' , ( ) => {
427
+ const responsesToAggregate : GenerateContentResponse [ ] = [
428
+ {
429
+ candidates : [
430
+ {
431
+ index : 0 ,
432
+ content : {
433
+ role : 'user' ,
434
+ parts : [ { } as any ] // Empty
435
+ } ,
436
+ finishReason : FinishReason . STOP ,
437
+ finishMessage : 'something' ,
438
+ safetyRatings : [
439
+ {
440
+ category : HarmCategory . HARM_CATEGORY_HARASSMENT ,
441
+ probability : HarmProbability . NEGLIGIBLE
442
+ } as SafetyRating
443
+ ]
444
+ }
445
+ ] ,
446
+ promptFeedback : {
447
+ blockReason : BlockReason . SAFETY ,
448
+ safetyRatings : [
449
+ {
450
+ category : HarmCategory . HARM_CATEGORY_DANGEROUS_CONTENT ,
451
+ probability : HarmProbability . LOW
452
+ } as SafetyRating
453
+ ]
454
+ }
455
+ }
456
+ ] ;
457
+
458
+ try {
459
+ aggregateResponses ( responsesToAggregate ) ;
460
+ } catch ( e ) {
461
+ expect ( ( e as VertexAIError ) . code ) . includes (
462
+ VertexAIErrorCode . INVALID_CONTENT
463
+ ) ;
464
+ expect ( ( e as VertexAIError ) . message ) . to . include (
465
+ 'Part should have at least one property, but there are none. This is likely caused ' +
466
+ 'by a malformed response from the backend.'
467
+ ) ;
468
+ }
469
+ } ) ;
406
470
} ) ;
0 commit comments