Skip to content

Commit 9bff00f

Browse files
committed
Filter empty text parts when streaming
1 parent dafae52 commit 9bff00f

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

packages/vertexai/src/requests/stream-reader.test.ts

+28-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
import {
1919
aggregateResponses,
2020
getResponseStream,
21-
processStream
21+
processStream,
22+
filterEmptyTextParts
2223
} from './stream-reader';
2324
import { expect, use } from 'chai';
2425
import { restore } from 'sinon';
@@ -404,3 +405,29 @@ describe('aggregateResponses', () => {
404405
});
405406
});
406407
});
408+
409+
describe('filterEmptyTextParts', () => {
410+
it('Removes only empty text parts', () => {
411+
const parts = [
412+
{
413+
text: 'foo'
414+
},
415+
{
416+
text: ''
417+
},
418+
{
419+
text: 'bar'
420+
}
421+
];
422+
423+
const filteredParts = filterEmptyTextParts(parts);
424+
expect(filteredParts).to.deep.equal([
425+
{
426+
text: 'foo'
427+
},
428+
{
429+
text: 'bar'
430+
}
431+
]);
432+
});
433+
});

packages/vertexai/src/requests/stream-reader.ts

+29
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ async function getResponsePromise(
6262
);
6363
return enhancedResponse;
6464
}
65+
66+
// The backend can send empty text parts, but if they are sent back (e.g. in a chat history) there
67+
// will be an error. To prevent this, filter out the empty text part from responses.
68+
if (value.candidates && value.candidates.length > 0) {
69+
value.candidates.forEach(candidate => {
70+
if (candidate.content) {
71+
candidate.content.parts = candidate.content.parts.filter(part => part.text !== '');
72+
}
73+
});
74+
}
6575
allResponses.push(value);
6676
}
6777
}
@@ -76,6 +86,15 @@ async function* generateResponseSequence(
7686
break;
7787
}
7888

89+
// The backend can send empty text parts, but if they are sent back (e.g. in a chat history) there
90+
// will be an error. To prevent this, filter out the empty text part from responses.
91+
if (value.candidates && value.candidates.length > 0) {
92+
value.candidates.forEach(candidate => {
93+
if (candidate.content) {
94+
candidate.content.parts = candidate.content.parts.filter(part => part.text !== '');
95+
}
96+
});
97+
}
7998
const enhancedResponse = createEnhancedContentResponse(value);
8099
yield enhancedResponse;
81100
}
@@ -203,3 +222,13 @@ export function aggregateResponses(
203222
}
204223
return aggregatedResponse;
205224
}
225+
226+
/**
227+
* The backend can send empty text parts, but if they are sent back (e.g. in a chat history) there
228+
* will be an error. To prevent this, filter out the empty text part from responses.
229+
*
230+
* @internal
231+
*/
232+
export function filterEmptyTextParts(parts: Part[]): Part[] {
233+
return parts?.filter(part => part.text !== '');
234+
}

0 commit comments

Comments
 (0)