Skip to content

Commit c616128

Browse files
committed
feat(vertexai): Add support for AbortSignal
1 parent 8a03143 commit c616128

19 files changed

+879
-91
lines changed

.changeset/long-keys-watch.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'firebase': minor
3+
'@firebase/vertexai': minor
4+
---
5+
6+
Add support for `AbortSignal`, allowing requests to be aborted.

common/api-review/vertexai.api.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ export class ChatSession {
5050
params?: StartChatParams | undefined;
5151
// (undocumented)
5252
requestOptions?: RequestOptions | undefined;
53-
sendMessage(request: string | Array<string | Part>): Promise<GenerateContentResult>;
54-
sendMessageStream(request: string | Array<string | Part>): Promise<GenerateContentStreamResult>;
53+
sendMessage(request: string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentResult>;
54+
sendMessageStream(request: string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentStreamResult>;
5555
}
5656

5757
// @public
@@ -328,9 +328,9 @@ export interface GenerativeContentBlob {
328328
// @public
329329
export class GenerativeModel extends VertexAIModel {
330330
constructor(vertexAI: VertexAI, modelParams: ModelParams, requestOptions?: RequestOptions);
331-
countTokens(request: CountTokensRequest | string | Array<string | Part>): Promise<CountTokensResponse>;
332-
generateContent(request: GenerateContentRequest | string | Array<string | Part>): Promise<GenerateContentResult>;
333-
generateContentStream(request: GenerateContentRequest | string | Array<string | Part>): Promise<GenerateContentStreamResult>;
331+
countTokens(request: CountTokensRequest | string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<CountTokensResponse>;
332+
generateContent(request: GenerateContentRequest | string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentResult>;
333+
generateContentStream(request: GenerateContentRequest | string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentStreamResult>;
334334
// (undocumented)
335335
generationConfig: GenerationConfig;
336336
// (undocumented)
@@ -466,9 +466,9 @@ export interface ImagenInlineImage {
466466
// @beta
467467
export class ImagenModel extends VertexAIModel {
468468
constructor(vertexAI: VertexAI, modelParams: ImagenModelParams, requestOptions?: RequestOptions | undefined);
469-
generateImages(prompt: string): Promise<ImagenGenerationResponse<ImagenInlineImage>>;
469+
generateImages(prompt: string, singleRequestOptions?: SingleRequestOptions): Promise<ImagenGenerationResponse<ImagenInlineImage>>;
470470
// @internal
471-
generateImagesGCS(prompt: string, gcsURI: string): Promise<ImagenGenerationResponse<ImagenGCSImage>>;
471+
generateImagesGCS(prompt: string, gcsURI: string, singleRequestOptions?: SingleRequestOptions): Promise<ImagenGenerationResponse<ImagenGCSImage>>;
472472
generationConfig?: ImagenGenerationConfig;
473473
// (undocumented)
474474
requestOptions?: RequestOptions | undefined;
@@ -731,6 +731,11 @@ export interface Segment {
731731
startIndex: number;
732732
}
733733

734+
// @public
735+
export interface SingleRequestOptions extends RequestOptions {
736+
signal?: AbortSignal;
737+
}
738+
734739
// @public
735740
export interface StartChatParams extends BaseParams {
736741
// (undocumented)

docs-devsite/_toc.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,8 @@ toc:
588588
path: /docs/reference/js/vertexai.schemashared.md
589589
- title: Segment
590590
path: /docs/reference/js/vertexai.segment.md
591+
- title: SingleRequestOptions
592+
path: /docs/reference/js/vertexai.singlerequestoptions.md
591593
- title: StartChatParams
592594
path: /docs/reference/js/vertexai.startchatparams.md
593595
- title: StringSchema

docs-devsite/vertexai.chatsession.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ export declare class ChatSession
3737
| Method | Modifiers | Description |
3838
| --- | --- | --- |
3939
| [getHistory()](./vertexai.chatsession.md#chatsessiongethistory) | | Gets the chat history so far. Blocked prompts are not added to history. Neither blocked candidates nor the prompts that generated them are added to history. |
40-
| [sendMessage(request)](./vertexai.chatsession.md#chatsessionsendmessage) | | Sends a chat message and receives a non-streaming [GenerateContentResult](./vertexai.generatecontentresult.md#generatecontentresult_interface) |
41-
| [sendMessageStream(request)](./vertexai.chatsession.md#chatsessionsendmessagestream) | | Sends a chat message and receives the response as a [GenerateContentStreamResult](./vertexai.generatecontentstreamresult.md#generatecontentstreamresult_interface) containing an iterable stream and a response promise. |
40+
| [sendMessage(request, singleRequestOptions)](./vertexai.chatsession.md#chatsessionsendmessage) | | Sends a chat message and receives a non-streaming [GenerateContentResult](./vertexai.generatecontentresult.md#generatecontentresult_interface) |
41+
| [sendMessageStream(request, singleRequestOptions)](./vertexai.chatsession.md#chatsessionsendmessagestream) | | Sends a chat message and receives the response as a [GenerateContentStreamResult](./vertexai.generatecontentstreamresult.md#generatecontentstreamresult_interface) containing an iterable stream and a response promise. |
4242

4343
## ChatSession.(constructor)
4444

@@ -103,14 +103,15 @@ Sends a chat message and receives a non-streaming [GenerateContentResult](./vert
103103
<b>Signature:</b>
104104

105105
```typescript
106-
sendMessage(request: string | Array<string | Part>): Promise<GenerateContentResult>;
106+
sendMessage(request: string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentResult>;
107107
```
108108

109109
#### Parameters
110110

111111
| Parameter | Type | Description |
112112
| --- | --- | --- |
113113
| request | string \| Array&lt;string \| [Part](./vertexai.md#part)<!-- -->&gt; | |
114+
| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | |
114115

115116
<b>Returns:</b>
116117

@@ -123,14 +124,15 @@ Sends a chat message and receives the response as a [GenerateContentStreamResult
123124
<b>Signature:</b>
124125

125126
```typescript
126-
sendMessageStream(request: string | Array<string | Part>): Promise<GenerateContentStreamResult>;
127+
sendMessageStream(request: string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentStreamResult>;
127128
```
128129

129130
#### Parameters
130131

131132
| Parameter | Type | Description |
132133
| --- | --- | --- |
133134
| request | string \| Array&lt;string \| [Part](./vertexai.md#part)<!-- -->&gt; | |
135+
| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | |
134136

135137
<b>Returns:</b>
136138

docs-devsite/vertexai.generativemodel.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ export declare class GenerativeModel extends VertexAIModel
4040
4141
| Method | Modifiers | Description |
4242
| --- | --- | --- |
43-
| [countTokens(request)](./vertexai.generativemodel.md#generativemodelcounttokens) | | Counts the tokens in the provided request. |
44-
| [generateContent(request)](./vertexai.generativemodel.md#generativemodelgeneratecontent) | | Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./vertexai.generatecontentresponse.md#generatecontentresponse_interface)<!-- -->. |
45-
| [generateContentStream(request)](./vertexai.generativemodel.md#generativemodelgeneratecontentstream) | | Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. |
43+
| [countTokens(request, singleRequestOptions)](./vertexai.generativemodel.md#generativemodelcounttokens) | | Counts the tokens in the provided request. |
44+
| [generateContent(request, singleRequestOptions)](./vertexai.generativemodel.md#generativemodelgeneratecontent) | | Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./vertexai.generatecontentresponse.md#generatecontentresponse_interface)<!-- -->. |
45+
| [generateContentStream(request, singleRequestOptions)](./vertexai.generativemodel.md#generativemodelgeneratecontentstream) | | Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. |
4646
| [startChat(startChatParams)](./vertexai.generativemodel.md#generativemodelstartchat) | | Gets a new [ChatSession](./vertexai.chatsession.md#chatsession_class) instance which can be used for multi-turn chats. |
4747
4848
## GenerativeModel.(constructor)
@@ -118,14 +118,15 @@ Counts the tokens in the provided request.
118118
<b>Signature:</b>
119119
120120
```typescript
121-
countTokens(request: CountTokensRequest | string | Array<string | Part>): Promise<CountTokensResponse>;
121+
countTokens(request: CountTokensRequest | string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<CountTokensResponse>;
122122
```
123123
124124
#### Parameters
125125
126126
| Parameter | Type | Description |
127127
| --- | --- | --- |
128128
| request | [CountTokensRequest](./vertexai.counttokensrequest.md#counttokensrequest_interface) \| string \| Array&lt;string \| [Part](./vertexai.md#part)<!-- -->&gt; | |
129+
| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | |
129130
130131
<b>Returns:</b>
131132
@@ -138,14 +139,15 @@ Makes a single non-streaming call to the model and returns an object containing
138139
<b>Signature:</b>
139140
140141
```typescript
141-
generateContent(request: GenerateContentRequest | string | Array<string | Part>): Promise<GenerateContentResult>;
142+
generateContent(request: GenerateContentRequest | string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentResult>;
142143
```
143144
144145
#### Parameters
145146
146147
| Parameter | Type | Description |
147148
| --- | --- | --- |
148149
| request | [GenerateContentRequest](./vertexai.generatecontentrequest.md#generatecontentrequest_interface) \| string \| Array&lt;string \| [Part](./vertexai.md#part)<!-- -->&gt; | |
150+
| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | |
149151
150152
<b>Returns:</b>
151153
@@ -158,14 +160,15 @@ Makes a single streaming call to the model and returns an object containing an i
158160
<b>Signature:</b>
159161
160162
```typescript
161-
generateContentStream(request: GenerateContentRequest | string | Array<string | Part>): Promise<GenerateContentStreamResult>;
163+
generateContentStream(request: GenerateContentRequest | string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentStreamResult>;
162164
```
163165
164166
#### Parameters
165167
166168
| Parameter | Type | Description |
167169
| --- | --- | --- |
168170
| request | [GenerateContentRequest](./vertexai.generatecontentrequest.md#generatecontentrequest_interface) \| string \| Array&lt;string \| [Part](./vertexai.md#part)<!-- -->&gt; | |
171+
| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | |
169172
170173
<b>Returns:</b>
171174

docs-devsite/vertexai.imagenmodel.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export declare class ImagenModel extends VertexAIModel
4242
4343
| Method | Modifiers | Description |
4444
| --- | --- | --- |
45-
| [generateImages(prompt)](./vertexai.imagenmodel.md#imagenmodelgenerateimages) | | <b><i>(Public Preview)</i></b> Generates images using the Imagen model and returns them as base64-encoded strings. |
45+
| [generateImages(prompt, singleRequestOptions)](./vertexai.imagenmodel.md#imagenmodelgenerateimages) | | <b><i>(Public Preview)</i></b> Generates images using the Imagen model and returns them as base64-encoded strings. |
4646
4747
## ImagenModel.(constructor)
4848
@@ -118,14 +118,15 @@ If the prompt was not blocked, but one or more of the generated images were filt
118118
<b>Signature:</b>
119119
120120
```typescript
121-
generateImages(prompt: string): Promise<ImagenGenerationResponse<ImagenInlineImage>>;
121+
generateImages(prompt: string, singleRequestOptions?: SingleRequestOptions): Promise<ImagenGenerationResponse<ImagenInlineImage>>;
122122
```
123123
124124
#### Parameters
125125
126126
| Parameter | Type | Description |
127127
| --- | --- | --- |
128128
| prompt | string | A text prompt describing the image(s) to generate. |
129+
| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | |
129130
130131
<b>Returns:</b>
131132

docs-devsite/vertexai.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ The Vertex AI in Firebase Web SDK.
111111
| [SchemaRequest](./vertexai.schemarequest.md#schemarequest_interface) | Final format for [Schema](./vertexai.schema.md#schema_class) params passed to backend requests. |
112112
| [SchemaShared](./vertexai.schemashared.md#schemashared_interface) | Basic [Schema](./vertexai.schema.md#schema_class) properties shared across several Schema-related types. |
113113
| [Segment](./vertexai.segment.md#segment_interface) | |
114+
| [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | Options that can be provided per-request. Extends the base [RequestOptions](./vertexai.requestoptions.md#requestoptions_interface) (like <code>timeout</code> and <code>baseUrl</code>) with request-specific controls like cancellation via <code>AbortSignal</code>.<!-- -->Options specified here will override any default [RequestOptions](./vertexai.requestoptions.md#requestoptions_interface) configured on a model (e.g. [GenerativeModel](./vertexai.generativemodel.md#generativemodel_class)<!-- -->). |
114115
| [StartChatParams](./vertexai.startchatparams.md#startchatparams_interface) | Params for [GenerativeModel.startChat()](./vertexai.generativemodel.md#generativemodelstartchat)<!-- -->. |
115116
| [TextPart](./vertexai.textpart.md#textpart_interface) | Content part interface if the part represents a text string. |
116117
| [ToolConfig](./vertexai.toolconfig.md#toolconfig_interface) | Tool config. This config is shared for all tools provided in the request. |
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
Project: /docs/reference/js/_project.yaml
2+
Book: /docs/reference/_book.yaml
3+
page_type: reference
4+
5+
{% comment %}
6+
DO NOT EDIT THIS FILE!
7+
This is generated by the JS SDK team, and any local changes will be
8+
overwritten. Changes should be made in the source code at
9+
https://github.com/firebase/firebase-js-sdk
10+
{% endcomment %}
11+
12+
# SingleRequestOptions interface
13+
Options that can be provided per-request. Extends the base [RequestOptions](./vertexai.requestoptions.md#requestoptions_interface) (like `timeout` and `baseUrl`<!-- -->) with request-specific controls like cancellation via `AbortSignal`<!-- -->.
14+
15+
Options specified here will override any default [RequestOptions](./vertexai.requestoptions.md#requestoptions_interface) configured on a model (e.g. [GenerativeModel](./vertexai.generativemodel.md#generativemodel_class)<!-- -->).
16+
17+
<b>Signature:</b>
18+
19+
```typescript
20+
export interface SingleRequestOptions extends RequestOptions
21+
```
22+
<b>Extends:</b> [RequestOptions](./vertexai.requestoptions.md#requestoptions_interface)
23+
24+
## Properties
25+
26+
| Property | Type | Description |
27+
| --- | --- | --- |
28+
| [signal](./vertexai.singlerequestoptions.md#singlerequestoptionssignal) | AbortSignal | An <code>AbortSignal</code> instance that allows cancelling ongoing requests (like <code>generateContent</code> or <code>generateImages</code>).<!-- -->If provided, calling <code>abort()</code> on the corresponding <code>AbortController</code> will attempt to cancel the underlying HTTP request. An <code>AbortError</code> will be thrown if cancellation is successful.<!-- -->Note that this will not cancel the request in the backend, so billing will still be applied despite cancellation. |
29+
30+
## SingleRequestOptions.signal
31+
32+
An `AbortSignal` instance that allows cancelling ongoing requests (like `generateContent` or `generateImages`<!-- -->).
33+
34+
If provided, calling `abort()` on the corresponding `AbortController` will attempt to cancel the underlying HTTP request. An `AbortError` will be thrown if cancellation is successful.
35+
36+
Note that this will not cancel the request in the backend, so billing will still be applied despite cancellation.
37+
38+
<b>Signature:</b>
39+
40+
```typescript
41+
signal?: AbortSignal;
42+
```
43+
44+
### Example
45+
46+
47+
```javascript
48+
const controller = new AbortController();
49+
const model = getGenerativeModel({
50+
// ...
51+
});
52+
53+
// To cancel request:
54+
controller.abort();
55+
56+
```
57+

packages/vertexai/src/methods/chat-session.test.ts

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,64 @@ describe('ChatSession', () => {
5252
match.any
5353
);
5454
});
55+
it('singleRequestOptions overrides requestOptions', async () => {
56+
const generateContentStub = stub(
57+
generateContentMethods,
58+
'generateContent'
59+
).rejects('generateContent failed'); // not important
60+
const requestOptions = {
61+
timeout: 1000
62+
};
63+
const singleRequestOptions = {
64+
timeout: 2000
65+
};
66+
const chatSession = new ChatSession(
67+
fakeApiSettings,
68+
'a-model',
69+
undefined,
70+
requestOptions
71+
);
72+
await expect(chatSession.sendMessage('hello', singleRequestOptions)).to.be
73+
.rejected;
74+
expect(generateContentStub).to.be.calledWith(
75+
fakeApiSettings,
76+
'a-model',
77+
match.any,
78+
match({
79+
timeout: singleRequestOptions.timeout
80+
})
81+
);
82+
});
83+
it('singleRequestOptions is merged with requestOptions', async () => {
84+
const generateContentStub = stub(
85+
generateContentMethods,
86+
'generateContent'
87+
).rejects('generateContent failed'); // not important
88+
const abortController = new AbortController();
89+
const requestOptions = {
90+
timeout: 1000
91+
};
92+
const singleRequestOptions = {
93+
signal: abortController.signal
94+
};
95+
const chatSession = new ChatSession(
96+
fakeApiSettings,
97+
'a-model',
98+
undefined,
99+
requestOptions
100+
);
101+
await expect(chatSession.sendMessage('hello', singleRequestOptions)).to.be
102+
.rejected;
103+
expect(generateContentStub).to.be.calledWith(
104+
fakeApiSettings,
105+
'a-model',
106+
match.any,
107+
match({
108+
timeout: requestOptions.timeout,
109+
signal: singleRequestOptions.signal
110+
})
111+
);
112+
});
55113
});
56114
describe('sendMessageStream()', () => {
57115
it('generateContentStream errors should be catchable', async () => {
@@ -94,5 +152,63 @@ describe('ChatSession', () => {
94152
);
95153
clock.restore();
96154
});
155+
it('singleRequestOptions overrides requestOptions', async () => {
156+
const generateContentStub = stub(
157+
generateContentMethods,
158+
'generateContent'
159+
).rejects('generateContent failed'); // not important
160+
const requestOptions = {
161+
timeout: 1000
162+
};
163+
const singleRequestOptions = {
164+
timeout: 2000
165+
};
166+
const chatSession = new ChatSession(
167+
fakeApiSettings,
168+
'a-model',
169+
undefined,
170+
requestOptions
171+
);
172+
await expect(chatSession.sendMessage('hello', singleRequestOptions)).to.be
173+
.rejected;
174+
expect(generateContentStub).to.be.calledWith(
175+
fakeApiSettings,
176+
'a-model',
177+
match.any,
178+
match({
179+
timeout: singleRequestOptions.timeout
180+
})
181+
);
182+
});
183+
it('singleRequestOptions is merged with requestOptions', async () => {
184+
const generateContentStub = stub(
185+
generateContentMethods,
186+
'generateContent'
187+
).rejects('generateContent failed'); // not important
188+
const abortController = new AbortController();
189+
const requestOptions = {
190+
timeout: 1000
191+
};
192+
const singleRequestOptions = {
193+
signal: abortController.signal
194+
};
195+
const chatSession = new ChatSession(
196+
fakeApiSettings,
197+
'a-model',
198+
undefined,
199+
requestOptions
200+
);
201+
await expect(chatSession.sendMessage('hello', singleRequestOptions)).to.be
202+
.rejected;
203+
expect(generateContentStub).to.be.calledWith(
204+
fakeApiSettings,
205+
'a-model',
206+
match.any,
207+
match({
208+
timeout: requestOptions.timeout,
209+
signal: singleRequestOptions.signal
210+
})
211+
);
212+
});
97213
});
98214
});

0 commit comments

Comments
 (0)