Skip to content

Commit 4f7f1ec

Browse files
committed
feat(vertexai): Gemini multimodal output
1 parent 4e0f630 commit 4f7f1ec

File tree

8 files changed

+177
-2
lines changed

8 files changed

+177
-2
lines changed

common/api-review/vertexai.api.md

+12
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ export { Date_2 as Date }
124124
export interface EnhancedGenerateContentResponse extends GenerateContentResponse {
125125
// (undocumented)
126126
functionCalls: () => FunctionCall[] | undefined;
127+
inlineData: () => GenerativeContentBlob[] | undefined;
127128
text: () => string;
128129
}
129130

@@ -304,6 +305,8 @@ export interface GenerationConfig {
304305
// (undocumented)
305306
presencePenalty?: number;
306307
responseMimeType?: string;
308+
// @beta
309+
responseModalities?: ResponseModality[];
307310
responseSchema?: TypedSchema | SchemaRequest;
308311
// (undocumented)
309312
stopSequences?: string[];
@@ -596,6 +599,15 @@ export interface RequestOptions {
596599
timeout?: number;
597600
}
598601

602+
// @beta
603+
export const ResponseModality: {
604+
readonly TEXT: "TEXT";
605+
readonly IMAGE: "IMAGE";
606+
};
607+
608+
// @beta
609+
export type ResponseModality = (typeof ResponseModality)[keyof typeof ResponseModality];
610+
599611
// @public (undocumented)
600612
export interface RetrievedContextAttribution {
601613
// (undocumented)

docs-devsite/vertexai.enhancedgeneratecontentresponse.md

+11
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export interface EnhancedGenerateContentResponse extends GenerateContentResponse
2424
| Property | Type | Description |
2525
| --- | --- | --- |
2626
| [functionCalls](./vertexai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponsefunctioncalls) | () =&gt; [FunctionCall](./vertexai.functioncall.md#functioncall_interface)<!-- -->\[\] \| undefined | |
27+
| [inlineData](./vertexai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponseinlinedata) | () =&gt; [GenerativeContentBlob](./vertexai.generativecontentblob.md#generativecontentblob_interface)<!-- -->\[\] \| undefined | Aggregates and returns all [InlineDataPart](./vertexai.inlinedatapart.md#inlinedatapart_interface) from the [GenerateContentResponse](./vertexai.generatecontentresponse.md#generatecontentresponse_interface)<!-- -->'s first candidate. |
2728
| [text](./vertexai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponsetext) | () =&gt; string | Returns the text string from the response, if available. Throws if the prompt or candidate was blocked. |
2829
2930
## EnhancedGenerateContentResponse.functionCalls
@@ -34,6 +35,16 @@ export interface EnhancedGenerateContentResponse extends GenerateContentResponse
3435
functionCalls: () => FunctionCall[] | undefined;
3536
```
3637
38+
## EnhancedGenerateContentResponse.inlineData
39+
40+
Aggregates and returns all [InlineDataPart](./vertexai.inlinedatapart.md#inlinedatapart_interface) from the [GenerateContentResponse](./vertexai.generatecontentresponse.md#generatecontentresponse_interface)<!-- -->'s first candidate.
41+
42+
<b>Signature:</b>
43+
44+
```typescript
45+
inlineData: () => GenerativeContentBlob[] | undefined;
46+
```
47+
3748
## EnhancedGenerateContentResponse.text
3849
3950
Returns the text string from the response, if available. Throws if the prompt or candidate was blocked.

docs-devsite/vertexai.generationconfig.md

+16
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export interface GenerationConfig
2727
| [maxOutputTokens](./vertexai.generationconfig.md#generationconfigmaxoutputtokens) | number | |
2828
| [presencePenalty](./vertexai.generationconfig.md#generationconfigpresencepenalty) | number | |
2929
| [responseMimeType](./vertexai.generationconfig.md#generationconfigresponsemimetype) | string | Output response MIME type of the generated candidate text. Supported MIME types are <code>text/plain</code> (default, text output), <code>application/json</code> (JSON response in the candidates), and <code>text/x.enum</code>. |
30+
| [responseModalities](./vertexai.generationconfig.md#generationconfigresponsemodalities) | [ResponseModality](./vertexai.md#responsemodality)<!-- -->\[\] | <b><i>(Public Preview)</i></b> Generation modalities to be returned in generation responses. |
3031
| [responseSchema](./vertexai.generationconfig.md#generationconfigresponseschema) | [TypedSchema](./vertexai.md#typedschema) \| [SchemaRequest](./vertexai.schemarequest.md#schemarequest_interface) | Output response schema of the generated candidate text. This value can be a class generated with a <code>[Schema](./vertexai.schema.md#schema_class)</code> static method like <code>Schema.string()</code> or <code>Schema.object()</code> or it can be a plain JS object matching the <code>[SchemaRequest](./vertexai.schemarequest.md#schemarequest_interface)</code> interface. <br/>Note: This only applies when the specified <code>responseMIMEType</code> supports a schema; currently this is limited to <code>application/json</code> and <code>text/x.enum</code>. |
3132
| [stopSequences](./vertexai.generationconfig.md#generationconfigstopsequences) | string\[\] | |
3233
| [temperature](./vertexai.generationconfig.md#generationconfigtemperature) | number | |
@@ -75,6 +76,21 @@ Output response MIME type of the generated candidate text. Supported MIME types
7576
responseMimeType?: string;
7677
```
7778

79+
## GenerationConfig.responseModalities
80+
81+
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
82+
>
83+
84+
Generation modalities to be returned in generation responses.
85+
86+
- Multimodal response generation is only supported in `gemini-2.0-flash-exp`<!-- -->, not `gemini-2.0-flash`<!-- -->. - Only image generation (`ResponseModality.IMAGE`<!-- -->) is supported.
87+
88+
<b>Signature:</b>
89+
90+
```typescript
91+
responseModalities?: ResponseModality[];
92+
```
93+
7894
## GenerationConfig.responseSchema
7995

8096
Output response schema of the generated candidate text. This value can be a class generated with a <code>[Schema](./vertexai.schema.md#schema_class)</code> static method like `Schema.string()` or `Schema.object()` or it can be a plain JS object matching the <code>[SchemaRequest](./vertexai.schemarequest.md#schemarequest_interface)</code> interface. <br/>Note: This only applies when the specified `responseMIMEType` supports a schema; currently this is limited to `application/json` and `text/x.enum`<!-- -->.

docs-devsite/vertexai.md

+31
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,14 @@ The Vertex AI in Firebase Web SDK.
125125
| Variable | Description |
126126
| --- | --- |
127127
| [POSSIBLE\_ROLES](./vertexai.md#possible_roles) | Possible roles. |
128+
| [ResponseModality](./vertexai.md#responsemodality) | <b><i>(Public Preview)</i></b> Generation modalities to be returned in generation responses. |
128129

129130
## Type Aliases
130131

131132
| Type Alias | Description |
132133
| --- | --- |
133134
| [Part](./vertexai.md#part) | Content part - includes text, image/video, or function call/response part types. |
135+
| [ResponseModality](./vertexai.md#responsemodality) | <b><i>(Public Preview)</i></b> Generation modalities to be returned in generation responses. |
134136
| [Role](./vertexai.md#role) | Role is the producer of the content. |
135137
| [Tool](./vertexai.md#tool) | Defines a tool that model can call to access external knowledge. |
136138
| [TypedSchema](./vertexai.md#typedschema) | A type that includes all specific Schema types. |
@@ -223,6 +225,22 @@ Possible roles.
223225
POSSIBLE_ROLES: readonly ["user", "model", "function", "system"]
224226
```
225227

228+
## ResponseModality
229+
230+
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
231+
>
232+
233+
Generation modalities to be returned in generation responses.
234+
235+
<b>Signature:</b>
236+
237+
```typescript
238+
ResponseModality: {
239+
readonly TEXT: "TEXT";
240+
readonly IMAGE: "IMAGE";
241+
}
242+
```
243+
226244
## Part
227245

228246
Content part - includes text, image/video, or function call/response part types.
@@ -233,6 +251,19 @@ Content part - includes text, image/video, or function call/response part types.
233251
export type Part = TextPart | InlineDataPart | FunctionCallPart | FunctionResponsePart | FileDataPart;
234252
```
235253

254+
## ResponseModality
255+
256+
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
257+
>
258+
259+
Generation modalities to be returned in generation responses.
260+
261+
<b>Signature:</b>
262+
263+
```typescript
264+
export type ResponseModality = (typeof ResponseModality)[keyof typeof ResponseModality];
265+
```
266+
236267
## Role
237268

238269
Role is the producer of the content.

packages/vertexai/src/requests/response-helpers.ts

+58
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
FunctionCall,
2222
GenerateContentCandidate,
2323
GenerateContentResponse,
24+
GenerativeContentBlob,
2425
ImagenGCSImage,
2526
ImagenInlineImage,
2627
VertexAIErrorCode
@@ -89,6 +90,38 @@ export function addHelpers(
8990
}
9091
return '';
9192
};
93+
(response as EnhancedGenerateContentResponse).inlineData = () => {
94+
if (response.candidates && response.candidates.length > 0) {
95+
if (response.candidates.length > 1) {
96+
logger.warn(
97+
`This response had ${response.candidates.length} ` +
98+
`candidates. Returning data from the first candidate only. ` +
99+
`Access response.candidates directly to use the other candidates.`
100+
);
101+
}
102+
if (hadBadFinishReason(response.candidates[0])) {
103+
throw new VertexAIError(
104+
VertexAIErrorCode.RESPONSE_ERROR,
105+
`Response error: ${formatBlockErrorMessage(
106+
response
107+
)}. Response body stored in error.response`,
108+
{
109+
response
110+
}
111+
);
112+
}
113+
return getInlineData(response);
114+
} else if (response.promptFeedback) {
115+
throw new VertexAIError(
116+
VertexAIErrorCode.RESPONSE_ERROR,
117+
`Data not available. ${formatBlockErrorMessage(response)}`,
118+
{
119+
response
120+
}
121+
);
122+
}
123+
return undefined;
124+
};
92125
(response as EnhancedGenerateContentResponse).functionCalls = () => {
93126
if (response.candidates && response.candidates.length > 0) {
94127
if (response.candidates.length > 1) {
@@ -164,6 +197,31 @@ export function getFunctionCalls(
164197
}
165198
}
166199

200+
/**
201+
* Returns {@link GenerativeContentBlob}s in the first candidate if present.
202+
*
203+
* @internal
204+
*/
205+
export function getInlineData(
206+
response: GenerateContentResponse
207+
): GenerativeContentBlob[] | undefined {
208+
const data: GenerativeContentBlob[] = [];
209+
210+
if (response.candidates?.[0].content?.parts) {
211+
for (const part of response.candidates?.[0].content?.parts) {
212+
if (part.inlineData) {
213+
data.push(part.inlineData);
214+
}
215+
}
216+
}
217+
218+
if (data.length > 0) {
219+
return data;
220+
} else {
221+
return undefined;
222+
}
223+
}
224+
167225
const badFinishReasons = [FinishReason.RECITATION, FinishReason.SAFETY];
168226

169227
function hadBadFinishReason(candidate: GenerateContentCandidate): boolean {

packages/vertexai/src/types/enums.ts

+26
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,29 @@ export enum Modality {
240240
*/
241241
DOCUMENT = 'DOCUMENT'
242242
}
243+
244+
/**
245+
* Generation modalities to be returned in generation responses.
246+
*
247+
* @beta
248+
*/
249+
export const ResponseModality = {
250+
/**
251+
* Text.
252+
* @beta
253+
*/
254+
TEXT: 'TEXT',
255+
/**
256+
* Image.
257+
* @beta
258+
*/
259+
IMAGE: 'IMAGE'
260+
} as const;
261+
262+
/**
263+
* Generation modalities to be returned in generation responses.
264+
*
265+
* @beta
266+
*/
267+
export type ResponseModality =
268+
(typeof ResponseModality)[keyof typeof ResponseModality];

packages/vertexai/src/types/requests.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ import {
2121
FunctionCallingMode,
2222
HarmBlockMethod,
2323
HarmBlockThreshold,
24-
HarmCategory
24+
HarmCategory,
25+
Modality,
26+
ResponseModality
2527
} from './enums';
2628
import { ObjectSchemaInterface, SchemaRequest } from './schema';
2729

@@ -95,6 +97,16 @@ export interface GenerationConfig {
9597
* this is limited to `application/json` and `text/x.enum`.
9698
*/
9799
responseSchema?: TypedSchema | SchemaRequest;
100+
/**
101+
* Generation modalities to be returned in generation responses.
102+
*
103+
* @remarks
104+
* - Multimodal response generation is only supported in `gemini-2.0-flash-exp`, not `gemini-2.0-flash`.
105+
* - Only image generation (`ResponseModality.IMAGE`) is supported.
106+
*
107+
* @beta
108+
*/
109+
responseModalities?: ResponseModality[];
98110
}
99111

100112
/**

packages/vertexai/src/types/responses.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { Content, FunctionCall } from './content';
18+
import { Content, FunctionCall, GenerativeContentBlob } from './content';
1919
import {
2020
BlockReason,
2121
FinishReason,
@@ -59,6 +59,15 @@ export interface EnhancedGenerateContentResponse
5959
* Throws if the prompt or candidate was blocked.
6060
*/
6161
text: () => string;
62+
/**
63+
* Aggregates and returns all {@link InlineDataPart} from the {@link GenerateContentResponse}'s
64+
* first candidate.
65+
*
66+
* @returns An array of {@link GenerativeContentBlob} containing data from the response, if available.
67+
*
68+
* @throws If the prompt or candidate was blocked.
69+
*/
70+
inlineData: () => GenerativeContentBlob[] | undefined;
6271
functionCalls: () => FunctionCall[] | undefined;
6372
}
6473

0 commit comments

Comments
 (0)