15
15
* limitations under the License.
16
16
*/
17
17
import { describe , expect , it , jest , afterEach } from '@jest/globals' ;
18
- import { addHelpers , formatBlockErrorMessage } from '../lib/requests/response-helpers' ;
18
+ import {
19
+ addHelpers ,
20
+ formatBlockErrorMessage ,
21
+ handlePredictResponse ,
22
+ } from '../lib/requests/response-helpers' ;
19
23
20
- import { BlockReason , Content , FinishReason , GenerateContentResponse } from '../lib/types' ;
24
+ import {
25
+ BlockReason ,
26
+ Content ,
27
+ FinishReason ,
28
+ GenerateContentResponse ,
29
+ ImagenInlineImage ,
30
+ ImagenGCSImage ,
31
+ } from '../lib/types' ;
32
+ import { getMockResponse , BackendName } from './test-utils/mock-response' ;
21
33
22
34
const fakeResponseText : GenerateContentResponse = {
23
35
candidates : [
@@ -31,6 +43,18 @@ const fakeResponseText: GenerateContentResponse = {
31
43
] ,
32
44
} ;
33
45
46
+ const fakeResponseThoughts : GenerateContentResponse = {
47
+ candidates : [
48
+ {
49
+ index : 0 ,
50
+ content : {
51
+ role : 'model' ,
52
+ parts : [ { text : 'Some text' } , { text : 'and some thoughts' , thought : true } ] ,
53
+ } ,
54
+ } ,
55
+ ] ,
56
+ } ;
57
+
34
58
const functionCallPart1 = {
35
59
functionCall : {
36
60
name : 'find_theaters' ,
@@ -129,12 +153,14 @@ describe('response-helpers methods', () => {
129
153
const enhancedResponse = addHelpers ( fakeResponseText ) ;
130
154
expect ( enhancedResponse . text ( ) ) . toBe ( 'Some text and some more text' ) ;
131
155
expect ( enhancedResponse . functionCalls ( ) ) . toBeUndefined ( ) ;
156
+ expect ( enhancedResponse . thoughtSummary ( ) ) . toBeUndefined ( ) ;
132
157
} ) ;
133
158
134
159
it ( 'good response functionCall' , ( ) => {
135
160
const enhancedResponse = addHelpers ( fakeResponseFunctionCall ) ;
136
161
expect ( enhancedResponse . text ( ) ) . toBe ( '' ) ;
137
162
expect ( enhancedResponse . functionCalls ( ) ) . toEqual ( [ functionCallPart1 . functionCall ] ) ;
163
+ expect ( enhancedResponse . thoughtSummary ( ) ) . toBeUndefined ( ) ;
138
164
} ) ;
139
165
140
166
it ( 'good response functionCalls' , ( ) => {
@@ -144,29 +170,41 @@ describe('response-helpers methods', () => {
144
170
functionCallPart1 . functionCall ,
145
171
functionCallPart2 . functionCall ,
146
172
] ) ;
173
+ expect ( enhancedResponse . thoughtSummary ( ) ) . toBeUndefined ( ) ;
147
174
} ) ;
148
175
149
176
it ( 'good response text/functionCall' , ( ) => {
150
177
const enhancedResponse = addHelpers ( fakeResponseMixed1 ) ;
151
178
expect ( enhancedResponse . functionCalls ( ) ) . toEqual ( [ functionCallPart2 . functionCall ] ) ;
152
179
expect ( enhancedResponse . text ( ) ) . toBe ( 'some text' ) ;
180
+ expect ( enhancedResponse . thoughtSummary ( ) ) . toBeUndefined ( ) ;
153
181
} ) ;
154
182
155
183
it ( 'good response functionCall/text' , ( ) => {
156
184
const enhancedResponse = addHelpers ( fakeResponseMixed2 ) ;
157
185
expect ( enhancedResponse . functionCalls ( ) ) . toEqual ( [ functionCallPart1 . functionCall ] ) ;
158
186
expect ( enhancedResponse . text ( ) ) . toBe ( 'some text' ) ;
187
+ expect ( enhancedResponse . thoughtSummary ( ) ) . toBeUndefined ( ) ;
159
188
} ) ;
160
189
161
190
it ( 'good response text/functionCall/text' , ( ) => {
162
191
const enhancedResponse = addHelpers ( fakeResponseMixed3 ) ;
163
192
expect ( enhancedResponse . functionCalls ( ) ) . toEqual ( [ functionCallPart1 . functionCall ] ) ;
164
193
expect ( enhancedResponse . text ( ) ) . toBe ( 'some text and more text' ) ;
194
+ expect ( enhancedResponse . thoughtSummary ( ) ) . toBeUndefined ( ) ;
195
+ } ) ;
196
+
197
+ it ( 'good response text/thought' , ( ) => {
198
+ const enhancedResponse = addHelpers ( fakeResponseThoughts ) ;
199
+ expect ( enhancedResponse . text ( ) ) . toBe ( 'Some text' ) ;
200
+ expect ( enhancedResponse . thoughtSummary ( ) ) . toBe ( 'and some thoughts' ) ;
201
+ expect ( enhancedResponse . functionCalls ( ) ) . toBeUndefined ( ) ;
165
202
} ) ;
166
203
167
204
it ( 'bad response safety' , ( ) => {
168
205
const enhancedResponse = addHelpers ( badFakeResponse ) ;
169
206
expect ( ( ) => enhancedResponse . text ( ) ) . toThrow ( 'SAFETY' ) ;
207
+ expect ( ( ) => enhancedResponse . thoughtSummary ( ) ) . toThrow ( 'SAFETY' ) ;
170
208
} ) ;
171
209
} ) ;
172
210
@@ -233,4 +271,80 @@ describe('response-helpers methods', () => {
233
271
expect ( message ) . toContain ( 'Candidate was blocked due to SAFETY: unsafe candidate' ) ;
234
272
} ) ;
235
273
} ) ;
274
+
275
+ describe ( 'handlePredictResponse' , ( ) => {
276
+ it ( 'returns base64 images' , async ( ) => {
277
+ const mockResponse = getMockResponse (
278
+ BackendName . VertexAI ,
279
+ 'unary-success-generate-images-base64.json' ,
280
+ ) as Response ;
281
+ const res = await handlePredictResponse < ImagenInlineImage > ( mockResponse ) ;
282
+ expect ( res . filteredReason ) . toBeUndefined ( ) ;
283
+ expect ( res . images . length ) . toBe ( 4 ) ;
284
+ res . images . forEach ( image => {
285
+ expect ( image . mimeType ) . toBe ( 'image/png' ) ;
286
+ expect ( image . bytesBase64Encoded . length ) . toBeGreaterThan ( 0 ) ;
287
+ } ) ;
288
+ } ) ;
289
+
290
+ it ( 'returns GCS images' , async ( ) => {
291
+ const mockResponse = getMockResponse (
292
+ BackendName . VertexAI ,
293
+ 'unary-success-generate-images-gcs.json' ,
294
+ ) as Response ;
295
+ const res = await handlePredictResponse < ImagenGCSImage > ( mockResponse ) ;
296
+ expect ( res . filteredReason ) . toBeUndefined ( ) ;
297
+ expect ( res . images . length ) . toBe ( 4 ) ;
298
+ res . images . forEach ( ( image , i ) => {
299
+ expect ( image . mimeType ) . toBe ( 'image/jpeg' ) ;
300
+ expect ( image . gcsURI ) . toBe (
301
+ `gs://test-project-id-1234.firebasestorage.app/images/1234567890123/sample_${ i } .jpg` ,
302
+ ) ;
303
+ } ) ;
304
+ } ) ;
305
+
306
+ it ( 'has filtered reason and no images if all images were filtered' , async ( ) => {
307
+ const mockResponse = getMockResponse (
308
+ BackendName . VertexAI ,
309
+ 'unary-failure-generate-images-all-filtered.json' ,
310
+ ) as Response ;
311
+ const res = await handlePredictResponse < ImagenInlineImage > ( mockResponse ) ;
312
+ expect ( res . filteredReason ) . toBe (
313
+ "Unable to show generated images. All images were filtered out because they violated Vertex AI's usage guidelines. You will not be charged for blocked images. Try rephrasing the prompt. If you think this was an error, send feedback. Support codes: 39322892, 29310472" ,
314
+ ) ;
315
+ expect ( res . images . length ) . toBe ( 0 ) ;
316
+ } ) ;
317
+
318
+ it ( 'has filtered reason and no images if all base64 images were filtered' , async ( ) => {
319
+ const mockResponse = getMockResponse (
320
+ BackendName . VertexAI ,
321
+ 'unary-failure-generate-images-base64-some-filtered.json' ,
322
+ ) as Response ;
323
+ const res = await handlePredictResponse < ImagenInlineImage > ( mockResponse ) ;
324
+ expect ( res . filteredReason ) . toBe (
325
+ 'Your current safety filter threshold filtered out 2 generated images. You will not be charged for blocked images. Try rephrasing the prompt. If you think this was an error, send feedback.' ,
326
+ ) ;
327
+ expect ( res . images . length ) . toBe ( 2 ) ;
328
+ res . images . forEach ( image => {
329
+ expect ( image . mimeType ) . toBe ( 'image/png' ) ;
330
+ expect ( image . bytesBase64Encoded . length ) . toBeGreaterThan ( 0 ) ;
331
+ } ) ;
332
+ } ) ;
333
+
334
+ it ( 'has filtered reason and no images if all GCS images were filtered' , async ( ) => {
335
+ const mockResponse = getMockResponse (
336
+ BackendName . VertexAI ,
337
+ 'unary-failure-generate-images-gcs-some-filtered.json' ,
338
+ ) as Response ;
339
+ const res = await handlePredictResponse < ImagenGCSImage > ( mockResponse ) ;
340
+ expect ( res . filteredReason ) . toBe (
341
+ 'Your current safety filter threshold filtered out 2 generated images. You will not be charged for blocked images. Try rephrasing the prompt. If you think this was an error, send feedback.' ,
342
+ ) ;
343
+ expect ( res . images . length ) . toBe ( 2 ) ;
344
+ res . images . forEach ( image => {
345
+ expect ( image . mimeType ) . toBe ( 'image/jpeg' ) ;
346
+ expect ( image . gcsURI . length ) . toBeGreaterThan ( 0 ) ;
347
+ } ) ;
348
+ } ) ;
349
+ } ) ;
236
350
} ) ;
0 commit comments