From c6161281041f661c499d048ff3b868532169f2e3 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Mon, 31 Mar 2025 15:17:43 -0400 Subject: [PATCH 1/7] feat(vertexai): Add support for `AbortSignal` --- .changeset/long-keys-watch.md | 6 + common/api-review/vertexai.api.md | 19 +- docs-devsite/_toc.yaml | 2 + docs-devsite/vertexai.chatsession.md | 10 +- docs-devsite/vertexai.generativemodel.md | 15 +- docs-devsite/vertexai.imagenmodel.md | 5 +- docs-devsite/vertexai.md | 1 + docs-devsite/vertexai.singlerequestoptions.md | 57 ++++ .../vertexai/src/methods/chat-session.test.ts | 116 ++++++++ packages/vertexai/src/methods/chat-session.ts | 19 +- packages/vertexai/src/methods/count-tokens.ts | 6 +- .../vertexai/src/methods/generate-content.ts | 10 +- .../src/models/generative-model.test.ts | 116 ++++++++ .../vertexai/src/models/generative-model.ts | 37 ++- .../vertexai/src/models/imagen-model.test.ts | 143 ++++++++- packages/vertexai/src/models/imagen-model.ts | 20 +- .../vertexai/src/requests/request.test.ts | 275 ++++++++++++++++-- packages/vertexai/src/requests/request.ts | 76 ++++- packages/vertexai/src/types/requests.ts | 37 +++ 19 files changed, 879 insertions(+), 91 deletions(-) create mode 100644 .changeset/long-keys-watch.md create mode 100644 docs-devsite/vertexai.singlerequestoptions.md diff --git a/.changeset/long-keys-watch.md b/.changeset/long-keys-watch.md new file mode 100644 index 00000000000..7cc4d582ff1 --- /dev/null +++ b/.changeset/long-keys-watch.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/vertexai': minor +--- + +Add support for `AbortSignal`, allowing requests to be aborted. diff --git a/common/api-review/vertexai.api.md b/common/api-review/vertexai.api.md index f9cf3dac5bd..0c030c8a78e 100644 --- a/common/api-review/vertexai.api.md +++ b/common/api-review/vertexai.api.md @@ -50,8 +50,8 @@ export class ChatSession { params?: StartChatParams | undefined; // (undocumented) requestOptions?: RequestOptions | undefined; - sendMessage(request: string | Array): Promise; - sendMessageStream(request: string | Array): Promise; + sendMessage(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; + sendMessageStream(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; } // @public @@ -328,9 +328,9 @@ export interface GenerativeContentBlob { // @public export class GenerativeModel extends VertexAIModel { constructor(vertexAI: VertexAI, modelParams: ModelParams, requestOptions?: RequestOptions); - countTokens(request: CountTokensRequest | string | Array): Promise; - generateContent(request: GenerateContentRequest | string | Array): Promise; - generateContentStream(request: GenerateContentRequest | string | Array): Promise; + countTokens(request: CountTokensRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; + generateContent(request: GenerateContentRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; + generateContentStream(request: GenerateContentRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; // (undocumented) generationConfig: GenerationConfig; // (undocumented) @@ -466,9 +466,9 @@ export interface ImagenInlineImage { // @beta export class ImagenModel extends VertexAIModel { constructor(vertexAI: VertexAI, modelParams: ImagenModelParams, requestOptions?: RequestOptions | undefined); - generateImages(prompt: string): Promise>; + generateImages(prompt: string, singleRequestOptions?: SingleRequestOptions): Promise>; // @internal - generateImagesGCS(prompt: string, gcsURI: string): Promise>; + generateImagesGCS(prompt: string, gcsURI: string, singleRequestOptions?: SingleRequestOptions): Promise>; generationConfig?: ImagenGenerationConfig; // (undocumented) requestOptions?: RequestOptions | undefined; @@ -731,6 +731,11 @@ export interface Segment { startIndex: number; } +// @public +export interface SingleRequestOptions extends RequestOptions { + signal?: AbortSignal; +} + // @public export interface StartChatParams extends BaseParams { // (undocumented) diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index 665222edb9d..0f5d51acec6 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -588,6 +588,8 @@ toc: path: /docs/reference/js/vertexai.schemashared.md - title: Segment path: /docs/reference/js/vertexai.segment.md + - title: SingleRequestOptions + path: /docs/reference/js/vertexai.singlerequestoptions.md - title: StartChatParams path: /docs/reference/js/vertexai.startchatparams.md - title: StringSchema diff --git a/docs-devsite/vertexai.chatsession.md b/docs-devsite/vertexai.chatsession.md index ed359f7e08c..409717749ea 100644 --- a/docs-devsite/vertexai.chatsession.md +++ b/docs-devsite/vertexai.chatsession.md @@ -37,8 +37,8 @@ export declare class ChatSession | Method | Modifiers | Description | | --- | --- | --- | | [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. | -| [sendMessage(request)](./vertexai.chatsession.md#chatsessionsendmessage) | | Sends a chat message and receives a non-streaming [GenerateContentResult](./vertexai.generatecontentresult.md#generatecontentresult_interface) | -| [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. | +| [sendMessage(request, singleRequestOptions)](./vertexai.chatsession.md#chatsessionsendmessage) | | Sends a chat message and receives a non-streaming [GenerateContentResult](./vertexai.generatecontentresult.md#generatecontentresult_interface) | +| [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. | ## ChatSession.(constructor) @@ -103,7 +103,7 @@ Sends a chat message and receives a non-streaming [GenerateContentResult](./vert Signature: ```typescript -sendMessage(request: string | Array): Promise; +sendMessage(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -111,6 +111,7 @@ sendMessage(request: string | Array): Promise> | | +| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: @@ -123,7 +124,7 @@ Sends a chat message and receives the response as a [GenerateContentStreamResult Signature: ```typescript -sendMessageStream(request: string | Array): Promise; +sendMessageStream(request: string | Array, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -131,6 +132,7 @@ sendMessageStream(request: string | Array): Promise> | | +| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: diff --git a/docs-devsite/vertexai.generativemodel.md b/docs-devsite/vertexai.generativemodel.md index e4a238b0af5..0b5d0d3ec25 100644 --- a/docs-devsite/vertexai.generativemodel.md +++ b/docs-devsite/vertexai.generativemodel.md @@ -40,9 +40,9 @@ export declare class GenerativeModel extends VertexAIModel | Method | Modifiers | Description | | --- | --- | --- | -| [countTokens(request)](./vertexai.generativemodel.md#generativemodelcounttokens) | | Counts the tokens in the provided request. | -| [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). | -| [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. | +| [countTokens(request, singleRequestOptions)](./vertexai.generativemodel.md#generativemodelcounttokens) | | Counts the tokens in the provided request. | +| [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). | +| [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. | | [startChat(startChatParams)](./vertexai.generativemodel.md#generativemodelstartchat) | | Gets a new [ChatSession](./vertexai.chatsession.md#chatsession_class) instance which can be used for multi-turn chats. | ## GenerativeModel.(constructor) @@ -118,7 +118,7 @@ Counts the tokens in the provided request. Signature: ```typescript -countTokens(request: CountTokensRequest | string | Array): Promise; +countTokens(request: CountTokensRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -126,6 +126,7 @@ countTokens(request: CountTokensRequest | string | Array): Promis | Parameter | Type | Description | | --- | --- | --- | | request | [CountTokensRequest](./vertexai.counttokensrequest.md#counttokensrequest_interface) \| string \| Array<string \| [Part](./vertexai.md#part)> | | +| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: @@ -138,7 +139,7 @@ Makes a single non-streaming call to the model and returns an object containing Signature: ```typescript -generateContent(request: GenerateContentRequest | string | Array): Promise; +generateContent(request: GenerateContentRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -146,6 +147,7 @@ generateContent(request: GenerateContentRequest | string | Array) | Parameter | Type | Description | | --- | --- | --- | | request | [GenerateContentRequest](./vertexai.generatecontentrequest.md#generatecontentrequest_interface) \| string \| Array<string \| [Part](./vertexai.md#part)> | | +| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: @@ -158,7 +160,7 @@ Makes a single streaming call to the model and returns an object containing an i Signature: ```typescript -generateContentStream(request: GenerateContentRequest | string | Array): Promise; +generateContentStream(request: GenerateContentRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -166,6 +168,7 @@ generateContentStream(request: GenerateContentRequest | string | Array> | | +| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: diff --git a/docs-devsite/vertexai.imagenmodel.md b/docs-devsite/vertexai.imagenmodel.md index ed40dc8f578..b3bbc2f0993 100644 --- a/docs-devsite/vertexai.imagenmodel.md +++ b/docs-devsite/vertexai.imagenmodel.md @@ -42,7 +42,7 @@ export declare class ImagenModel extends VertexAIModel | Method | Modifiers | Description | | --- | --- | --- | -| [generateImages(prompt)](./vertexai.imagenmodel.md#imagenmodelgenerateimages) | | (Public Preview) Generates images using the Imagen model and returns them as base64-encoded strings. | +| [generateImages(prompt, singleRequestOptions)](./vertexai.imagenmodel.md#imagenmodelgenerateimages) | | (Public Preview) Generates images using the Imagen model and returns them as base64-encoded strings. | ## ImagenModel.(constructor) @@ -118,7 +118,7 @@ If the prompt was not blocked, but one or more of the generated images were filt Signature: ```typescript -generateImages(prompt: string): Promise>; +generateImages(prompt: string, singleRequestOptions?: SingleRequestOptions): Promise>; ``` #### Parameters @@ -126,6 +126,7 @@ generateImages(prompt: string): PromiseReturns: diff --git a/docs-devsite/vertexai.md b/docs-devsite/vertexai.md index 47d45a492ec..7c61852e484 100644 --- a/docs-devsite/vertexai.md +++ b/docs-devsite/vertexai.md @@ -111,6 +111,7 @@ The Vertex AI in Firebase Web SDK. | [SchemaRequest](./vertexai.schemarequest.md#schemarequest_interface) | Final format for [Schema](./vertexai.schema.md#schema_class) params passed to backend requests. | | [SchemaShared](./vertexai.schemashared.md#schemashared_interface) | Basic [Schema](./vertexai.schema.md#schema_class) properties shared across several Schema-related types. | | [Segment](./vertexai.segment.md#segment_interface) | | +| [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | 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.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)). | | [StartChatParams](./vertexai.startchatparams.md#startchatparams_interface) | Params for [GenerativeModel.startChat()](./vertexai.generativemodel.md#generativemodelstartchat). | | [TextPart](./vertexai.textpart.md#textpart_interface) | Content part interface if the part represents a text string. | | [ToolConfig](./vertexai.toolconfig.md#toolconfig_interface) | Tool config. This config is shared for all tools provided in the request. | diff --git a/docs-devsite/vertexai.singlerequestoptions.md b/docs-devsite/vertexai.singlerequestoptions.md new file mode 100644 index 00000000000..af5d46059fd --- /dev/null +++ b/docs-devsite/vertexai.singlerequestoptions.md @@ -0,0 +1,57 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# SingleRequestOptions interface +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`. + +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)). + +Signature: + +```typescript +export interface SingleRequestOptions extends RequestOptions +``` +Extends: [RequestOptions](./vertexai.requestoptions.md#requestoptions_interface) + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [signal](./vertexai.singlerequestoptions.md#singlerequestoptionssignal) | AbortSignal | An AbortSignal instance that allows cancelling ongoing requests (like generateContent or generateImages).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.Note that this will not cancel the request in the backend, so billing will still be applied despite cancellation. | + +## SingleRequestOptions.signal + +An `AbortSignal` instance that allows cancelling ongoing requests (like `generateContent` or `generateImages`). + +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. + +Note that this will not cancel the request in the backend, so billing will still be applied despite cancellation. + +Signature: + +```typescript +signal?: AbortSignal; +``` + +### Example + + +```javascript +const controller = new AbortController(); +const model = getGenerativeModel({ + // ... +}); + +// To cancel request: +controller.abort(); + +``` + diff --git a/packages/vertexai/src/methods/chat-session.test.ts b/packages/vertexai/src/methods/chat-session.test.ts index bd389a3d778..b4a19538c58 100644 --- a/packages/vertexai/src/methods/chat-session.test.ts +++ b/packages/vertexai/src/methods/chat-session.test.ts @@ -52,6 +52,64 @@ describe('ChatSession', () => { match.any ); }); + it('singleRequestOptions overrides requestOptions', async () => { + const generateContentStub = stub( + generateContentMethods, + 'generateContent' + ).rejects('generateContent failed'); // not important + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + timeout: 2000 + }; + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + undefined, + requestOptions + ); + await expect(chatSession.sendMessage('hello', singleRequestOptions)).to.be + .rejected; + expect(generateContentStub).to.be.calledWith( + fakeApiSettings, + 'a-model', + match.any, + match({ + timeout: singleRequestOptions.timeout + }) + ); + }); + it('singleRequestOptions is merged with requestOptions', async () => { + const generateContentStub = stub( + generateContentMethods, + 'generateContent' + ).rejects('generateContent failed'); // not important + const abortController = new AbortController(); + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + signal: abortController.signal + }; + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + undefined, + requestOptions + ); + await expect(chatSession.sendMessage('hello', singleRequestOptions)).to.be + .rejected; + expect(generateContentStub).to.be.calledWith( + fakeApiSettings, + 'a-model', + match.any, + match({ + timeout: requestOptions.timeout, + signal: singleRequestOptions.signal + }) + ); + }); }); describe('sendMessageStream()', () => { it('generateContentStream errors should be catchable', async () => { @@ -94,5 +152,63 @@ describe('ChatSession', () => { ); clock.restore(); }); + it('singleRequestOptions overrides requestOptions', async () => { + const generateContentStub = stub( + generateContentMethods, + 'generateContent' + ).rejects('generateContent failed'); // not important + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + timeout: 2000 + }; + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + undefined, + requestOptions + ); + await expect(chatSession.sendMessage('hello', singleRequestOptions)).to.be + .rejected; + expect(generateContentStub).to.be.calledWith( + fakeApiSettings, + 'a-model', + match.any, + match({ + timeout: singleRequestOptions.timeout + }) + ); + }); + it('singleRequestOptions is merged with requestOptions', async () => { + const generateContentStub = stub( + generateContentMethods, + 'generateContent' + ).rejects('generateContent failed'); // not important + const abortController = new AbortController(); + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + signal: abortController.signal + }; + const chatSession = new ChatSession( + fakeApiSettings, + 'a-model', + undefined, + requestOptions + ); + await expect(chatSession.sendMessage('hello', singleRequestOptions)).to.be + .rejected; + expect(generateContentStub).to.be.calledWith( + fakeApiSettings, + 'a-model', + match.any, + match({ + timeout: requestOptions.timeout, + signal: singleRequestOptions.signal + }) + ); + }); }); }); diff --git a/packages/vertexai/src/methods/chat-session.ts b/packages/vertexai/src/methods/chat-session.ts index 60794001e37..43ea0afb692 100644 --- a/packages/vertexai/src/methods/chat-session.ts +++ b/packages/vertexai/src/methods/chat-session.ts @@ -22,6 +22,7 @@ import { GenerateContentStreamResult, Part, RequestOptions, + SingleRequestOptions, StartChatParams } from '../types'; import { formatNewContent } from '../requests/request-helpers'; @@ -75,7 +76,8 @@ export class ChatSession { * {@link GenerateContentResult} */ async sendMessage( - request: string | Array + request: string | Array, + singleRequestOptions?: SingleRequestOptions ): Promise { await this._sendPromise; const newContent = formatNewContent(request); @@ -95,7 +97,11 @@ export class ChatSession { this._apiSettings, this.model, generateContentRequest, - this.requestOptions + // Merge requestOptions + { + ...this.requestOptions, + ...singleRequestOptions + } ) ) .then(result => { @@ -130,7 +136,8 @@ export class ChatSession { * and a response promise. */ async sendMessageStream( - request: string | Array + request: string | Array, + singleRequestOptions?: SingleRequestOptions ): Promise { await this._sendPromise; const newContent = formatNewContent(request); @@ -146,7 +153,11 @@ export class ChatSession { this._apiSettings, this.model, generateContentRequest, - this.requestOptions + // Merge requestOptions + { + ...this.requestOptions, + ...singleRequestOptions + } ); // Add onto the chain. diff --git a/packages/vertexai/src/methods/count-tokens.ts b/packages/vertexai/src/methods/count-tokens.ts index c9d43a5b6fd..b89dab44e64 100644 --- a/packages/vertexai/src/methods/count-tokens.ts +++ b/packages/vertexai/src/methods/count-tokens.ts @@ -18,7 +18,7 @@ import { CountTokensRequest, CountTokensResponse, - RequestOptions + SingleRequestOptions } from '../types'; import { Task, makeRequest } from '../requests/request'; import { ApiSettings } from '../types/internal'; @@ -27,7 +27,7 @@ export async function countTokens( apiSettings: ApiSettings, model: string, params: CountTokensRequest, - requestOptions?: RequestOptions + singleRequestOptions?: SingleRequestOptions ): Promise { const response = await makeRequest( model, @@ -35,7 +35,7 @@ export async function countTokens( apiSettings, false, JSON.stringify(params), - requestOptions + singleRequestOptions ); return response.json(); } diff --git a/packages/vertexai/src/methods/generate-content.ts b/packages/vertexai/src/methods/generate-content.ts index 0944b38016a..c67c36ac1d2 100644 --- a/packages/vertexai/src/methods/generate-content.ts +++ b/packages/vertexai/src/methods/generate-content.ts @@ -20,7 +20,7 @@ import { GenerateContentResponse, GenerateContentResult, GenerateContentStreamResult, - RequestOptions + SingleRequestOptions } from '../types'; import { Task, makeRequest } from '../requests/request'; import { createEnhancedContentResponse } from '../requests/response-helpers'; @@ -31,7 +31,7 @@ export async function generateContentStream( apiSettings: ApiSettings, model: string, params: GenerateContentRequest, - requestOptions?: RequestOptions + singleRequestOptions?: SingleRequestOptions ): Promise { const response = await makeRequest( model, @@ -39,7 +39,7 @@ export async function generateContentStream( apiSettings, /* stream */ true, JSON.stringify(params), - requestOptions + singleRequestOptions ); return processStream(response); } @@ -48,7 +48,7 @@ export async function generateContent( apiSettings: ApiSettings, model: string, params: GenerateContentRequest, - requestOptions?: RequestOptions + singleRequestOptions?: SingleRequestOptions ): Promise { const response = await makeRequest( model, @@ -56,7 +56,7 @@ export async function generateContent( apiSettings, /* stream */ false, JSON.stringify(params), - requestOptions + singleRequestOptions ); const responseJson: GenerateContentResponse = await response.json(); const enhancedResponse = createEnhancedContentResponse(responseJson); diff --git a/packages/vertexai/src/models/generative-model.test.ts b/packages/vertexai/src/models/generative-model.test.ts index 51ea8aafead..88ffaa82b1a 100644 --- a/packages/vertexai/src/models/generative-model.test.ts +++ b/packages/vertexai/src/models/generative-model.test.ts @@ -15,14 +15,18 @@ * limitations under the License. */ import { use, expect } from 'chai'; +import chaiAsPromised from 'chai-as-promised'; import { GenerativeModel } from './generative-model'; import { FunctionCallingMode, VertexAI } from '../public-types'; import * as request from '../requests/request'; import { match, restore, stub } from 'sinon'; import { getMockResponse } from '../../test-utils/mock-response'; import sinonChai from 'sinon-chai'; +import * as generateContentMethods from '../methods/generate-content'; +import * as countTokens from '../methods/count-tokens'; use(sinonChai); +use(chaiAsPromised); const fakeVertexAI: VertexAI = { app: { @@ -38,6 +42,9 @@ const fakeVertexAI: VertexAI = { }; describe('GenerativeModel', () => { + afterEach(() => { + restore(); + }); it('passes params through to generateContent', async () => { const genModel = new GenerativeModel(fakeVertexAI, { model: 'my-model', @@ -165,6 +172,62 @@ describe('GenerativeModel', () => { ); restore(); }); + it('generateContent singleRequestOptions overrides requestOptions', async () => { + const generateContentStub = stub( + generateContentMethods, + 'generateContent' + ).rejects('generateContent failed'); // not important + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + timeout: 2000 + }; + const genModel = new GenerativeModel( + fakeVertexAI, + { model: 'my-model' }, + requestOptions + ); + await expect(genModel.generateContent('hello', singleRequestOptions)).to.be + .rejected; + expect(generateContentStub).to.be.calledWith( + match.any, + match.any, + match.any, + match({ + timeout: singleRequestOptions.timeout + }) + ); + }); + it('generateContent singleRequestOptions is merged with requestOptions', async () => { + const generateContentStub = stub( + generateContentMethods, + 'generateContent' + ).rejects('generateContent failed'); // not important + const abortController = new AbortController(); + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + signal: abortController.signal + }; + const genModel = new GenerativeModel( + fakeVertexAI, + { model: 'my-model' }, + requestOptions + ); + await expect(genModel.generateContent('hello', singleRequestOptions)).to.be + .rejected; + expect(generateContentStub).to.be.calledWith( + match.any, + match.any, + match.any, + match({ + timeout: requestOptions.timeout, + signal: singleRequestOptions.signal + }) + ); + }); it('passes params through to chat.sendMessage', async () => { const genModel = new GenerativeModel(fakeVertexAI, { model: 'my-model', @@ -314,4 +377,57 @@ describe('GenerativeModel', () => { ); restore(); }); + it('countTokens singleRequestOptions overrides requestOptions', async () => { + const countTokensStub = stub(countTokens, 'countTokens').rejects( + 'countTokens failed' + ); + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + timeout: 2000 + }; + const genModel = new GenerativeModel( + fakeVertexAI, + { model: 'my-model' }, + requestOptions + ); + await expect(genModel.countTokens('hello', singleRequestOptions)).to.be.rejected; + expect(countTokensStub).to.be.calledWith( + match.any, + match.any, + match.any, + match({ + timeout: singleRequestOptions.timeout + }) + ); + }); + it('countTokens singleRequestOptions is merged with requestOptions', async () => { + const countTokensStub = stub(countTokens, 'countTokens').rejects( + 'countTokens failed' + ); + const abortController = new AbortController(); + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + signal: abortController.signal + }; + const genModel = new GenerativeModel( + fakeVertexAI, + { model: 'my-model' }, + requestOptions + ); + await expect(genModel.countTokens('hello', singleRequestOptions)).to.be + .rejected; + expect(countTokensStub).to.be.calledWith( + match.any, + match.any, + match.any, + match({ + timeout: requestOptions.timeout, + signal: singleRequestOptions.signal + }) + ); + }); }); diff --git a/packages/vertexai/src/models/generative-model.ts b/packages/vertexai/src/models/generative-model.ts index 1af1ee700d5..6d5ae38d967 100644 --- a/packages/vertexai/src/models/generative-model.ts +++ b/packages/vertexai/src/models/generative-model.ts @@ -29,11 +29,12 @@ import { GenerationConfig, ModelParams, Part, - RequestOptions, SafetySetting, + RequestOptions, StartChatParams, Tool, - ToolConfig + ToolConfig, + SingleRequestOptions } from '../types'; import { ChatSession } from '../methods/chat-session'; import { countTokens } from '../methods/count-tokens'; @@ -77,7 +78,8 @@ export class GenerativeModel extends VertexAIModel { * and returns an object containing a single {@link GenerateContentResponse}. */ async generateContent( - request: GenerateContentRequest | string | Array + request: GenerateContentRequest | string | Array, + singleRequestOptions?: SingleRequestOptions ): Promise { const formattedParams = formatGenerateContentInput(request); return generateContent( @@ -91,7 +93,11 @@ export class GenerativeModel extends VertexAIModel { systemInstruction: this.systemInstruction, ...formattedParams }, - this.requestOptions + // Merge request options + { + ...this.requestOptions, + ...singleRequestOptions + } ); } @@ -102,7 +108,8 @@ export class GenerativeModel extends VertexAIModel { * a promise that returns the final aggregated response. */ async generateContentStream( - request: GenerateContentRequest | string | Array + request: GenerateContentRequest | string | Array, + singleRequestOptions?: SingleRequestOptions ): Promise { const formattedParams = formatGenerateContentInput(request); return generateContentStream( @@ -116,7 +123,11 @@ export class GenerativeModel extends VertexAIModel { systemInstruction: this.systemInstruction, ...formattedParams }, - this.requestOptions + // Merge request options + { + ...this.requestOptions, + ...singleRequestOptions + } ); } @@ -149,9 +160,19 @@ export class GenerativeModel extends VertexAIModel { * Counts the tokens in the provided request. */ async countTokens( - request: CountTokensRequest | string | Array + request: CountTokensRequest | string | Array, + singleRequestOptions?: SingleRequestOptions ): Promise { const formattedParams = formatGenerateContentInput(request); - return countTokens(this._apiSettings, this.model, formattedParams); + return countTokens( + this._apiSettings, + this.model, + formattedParams, + // Merge request options + { + ...this.requestOptions, + ...singleRequestOptions + } + ); } } diff --git a/packages/vertexai/src/models/imagen-model.test.ts b/packages/vertexai/src/models/imagen-model.test.ts index 9e534f2195a..10842be800d 100644 --- a/packages/vertexai/src/models/imagen-model.test.ts +++ b/packages/vertexai/src/models/imagen-model.test.ts @@ -45,6 +45,9 @@ const fakeVertexAI: VertexAI = { }; describe('ImagenModel', () => { + afterEach(() => { + restore(); + }); it('generateImages makes a request to predict with default parameters', async () => { const mockResponse = getMockResponse( 'vertexAI', @@ -70,9 +73,8 @@ describe('ImagenModel', () => { value.includes(`"sampleCount":1`) ); }), - undefined + {} ); - restore(); }); it('generateImages makes a request to predict with generation config and safety settings', async () => { const imagenModel = new ImagenModel(fakeVertexAI, { @@ -129,9 +131,74 @@ describe('ImagenModel', () => { ) ); }), - undefined + {} + ); + }); + it('generateImages singleRequestOptions overrides requestOptions', async () => { + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + timeout: 2000 + }; + const imagenModel = new ImagenModel( + fakeVertexAI, + { model: 'my-model' }, + requestOptions + ); + const mockResponse = getMockResponse( + 'vertexAI', + 'unary-success-generate-images-base64.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const prompt = 'A photorealistic image of a toy boat at sea.'; + await imagenModel.generateImages(prompt, singleRequestOptions); + expect(makeRequestStub).to.be.calledWith( + match.any, + request.Task.PREDICT, + match.any, + false, + match.any, + match({ + timeout: singleRequestOptions.timeout + }) + ); + }); + it('generateImages singleRequestOptions is merged with requestOptions', async () => { + const abortController = new AbortController(); + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + signal: abortController.signal + }; + const imagenModel = new ImagenModel( + fakeVertexAI, + { model: 'my-model' }, + requestOptions + ); + const mockResponse = getMockResponse( + 'vertexAI', + 'unary-success-generate-images-base64.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const prompt = 'A photorealistic image of a toy boat at sea.'; + await imagenModel.generateImages(prompt, singleRequestOptions); + expect(makeRequestStub).to.be.calledWith( + match.any, + request.Task.PREDICT, + match.any, + false, + match.any, + match({ + timeout: requestOptions.timeout, + signal: singleRequestOptions.signal + }) ); - restore(); }); it('throws if prompt blocked', async () => { const mockResponse = getMockResponse( @@ -157,8 +224,72 @@ describe('ImagenModel', () => { expect((e as VertexAIError).message).to.include( "Image generation failed with the following error: The prompt could not be submitted. This prompt contains sensitive words that violate Google's Responsible AI practices. Try rephrasing the prompt. If you think this was an error, send feedback." ); - } finally { - restore(); } }); + it('generateImagesGCS singleRequestOptions overrides requestOptions', async () => { + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + timeout: 2000 + }; + const imagenModel = new ImagenModel( + fakeVertexAI, + { model: 'my-model' }, + requestOptions + ); + const mockResponse = getMockResponse( + 'vertexAI', + 'unary-success-generate-images-gcs.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const prompt = 'A photorealistic image of a toy boat at sea.'; + await imagenModel.generateImagesGCS(prompt, '', singleRequestOptions); + expect(makeRequestStub).to.be.calledWith( + match.any, + request.Task.PREDICT, + match.any, + false, + match.any, + match({ + timeout: singleRequestOptions.timeout + }) + ); + }); + it('generateImages singleRequestOptions is merged with requestOptions', async () => { + const abortController = new AbortController(); + const requestOptions = { + timeout: 1000 + }; + const singleRequestOptions = { + signal: abortController.signal + }; + const imagenModel = new ImagenModel( + fakeVertexAI, + { model: 'my-model' }, + requestOptions + ); + const mockResponse = getMockResponse( + 'vertexAI', + 'unary-success-generate-images-gcs.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const prompt = 'A photorealistic image of a toy boat at sea.'; + await imagenModel.generateImagesGCS(prompt, '', singleRequestOptions); + expect(makeRequestStub).to.be.calledWith( + match.any, + request.Task.PREDICT, + match.any, + false, + match.any, + match({ + timeout: requestOptions.timeout, + signal: singleRequestOptions.signal + }) + ); + }); }); diff --git a/packages/vertexai/src/models/imagen-model.ts b/packages/vertexai/src/models/imagen-model.ts index 04514ef6ffd..e74a3b1f2fd 100644 --- a/packages/vertexai/src/models/imagen-model.ts +++ b/packages/vertexai/src/models/imagen-model.ts @@ -26,7 +26,8 @@ import { RequestOptions, ImagenModelParams, ImagenGenerationResponse, - ImagenSafetySettings + ImagenSafetySettings, + SingleRequestOptions } from '../types'; import { VertexAIModel } from './vertexai-model'; @@ -102,7 +103,8 @@ export class ImagenModel extends VertexAIModel { * @beta */ async generateImages( - prompt: string + prompt: string, + singleRequestOptions?: SingleRequestOptions ): Promise> { const body = createPredictRequestBody(prompt, { ...this.generationConfig, @@ -114,7 +116,11 @@ export class ImagenModel extends VertexAIModel { this._apiSettings, /* stream */ false, JSON.stringify(body), - this.requestOptions + // Merge request options + { + ...this.requestOptions, + ...singleRequestOptions + } ); return handlePredictResponse(response); } @@ -140,7 +146,8 @@ export class ImagenModel extends VertexAIModel { */ async generateImagesGCS( prompt: string, - gcsURI: string + gcsURI: string, + singleRequestOptions?: SingleRequestOptions ): Promise> { const body = createPredictRequestBody(prompt, { gcsURI, @@ -153,7 +160,10 @@ export class ImagenModel extends VertexAIModel { this._apiSettings, /* stream */ false, JSON.stringify(body), - this.requestOptions + { + ...this.requestOptions, + ...singleRequestOptions + } ); return handlePredictResponse(response); } diff --git a/packages/vertexai/src/requests/request.test.ts b/packages/vertexai/src/requests/request.test.ts index cd39a0f8ae5..f1835a658db 100644 --- a/packages/vertexai/src/requests/request.test.ts +++ b/packages/vertexai/src/requests/request.test.ts @@ -16,7 +16,7 @@ */ import { expect, use } from 'chai'; -import { match, restore, stub } from 'sinon'; +import Sinon, { match, restore, stub, useFakeTimers } from 'sinon'; import sinonChai from 'sinon-chai'; import chaiAsPromised from 'chai-as-promised'; import { RequestUrl, Task, getHeaders, makeRequest } from './request'; @@ -269,8 +269,37 @@ describe('request methods', () => { }); }); describe('makeRequest', () => { + let fetchStub: Sinon.SinonStub; + let clock: Sinon.SinonFakeTimers; + const fetchAborter = ( + _url: string, + options?: RequestInit + ): Promise => { + expect(options).to.not.be.undefined; + expect(options!.signal).to.not.be.undefined; + const signal = options!.signal; + console.log(signal); + return new Promise((_resolve, reject): void => { + const abortListener = (): void => { + reject(new DOMException(signal?.reason || 'Aborted', 'AbortError')); + }; + + signal?.addEventListener('abort', abortListener, { once: true }); + }); + }; + + beforeEach(() => { + fetchStub = stub(globalThis, 'fetch'); + clock = useFakeTimers(); + }); + + afterEach(() => { + restore(); + clock.restore(); + }); + it('no error', async () => { - const fetchStub = stub(globalThis, 'fetch').resolves({ + fetchStub.resolves({ ok: true } as Response); const response = await makeRequest( @@ -284,7 +313,7 @@ describe('request methods', () => { expect(response.ok).to.be.true; }); it('error with timeout', async () => { - const fetchStub = stub(globalThis, 'fetch').resolves({ + fetchStub.resolves({ ok: false, status: 500, statusText: 'AbortError' @@ -315,7 +344,7 @@ describe('request methods', () => { expect(fetchStub).to.be.calledOnce; }); it('Network error, no response.json()', async () => { - const fetchStub = stub(globalThis, 'fetch').resolves({ + fetchStub.resolves({ ok: false, status: 500, statusText: 'Server Error' @@ -341,7 +370,7 @@ describe('request methods', () => { expect(fetchStub).to.be.calledOnce; }); it('Network error, includes response.json()', async () => { - const fetchStub = stub(globalThis, 'fetch').resolves({ + fetchStub.resolves({ ok: false, status: 500, statusText: 'Server Error', @@ -369,7 +398,7 @@ describe('request methods', () => { expect(fetchStub).to.be.calledOnce; }); it('Network error, includes response.json() and details', async () => { - const fetchStub = stub(globalThis, 'fetch').resolves({ + fetchStub.resolves({ ok: false, status: 500, statusText: 'Server Error', @@ -411,30 +440,226 @@ describe('request methods', () => { } expect(fetchStub).to.be.calledOnce; }); - }); - it('Network error, API not enabled', async () => { - const mockResponse = getMockResponse( - 'vertexAI', - 'unary-failure-firebasevertexai-api-not-enabled.json' - ); - const fetchStub = stub(globalThis, 'fetch').resolves( - mockResponse as Response - ); - try { - await makeRequest( + it('Network error, API not enabled', async () => { + const mockResponse = getMockResponse( + 'vertexAI', + 'unary-failure-firebasevertexai-api-not-enabled.json' + ); + fetchStub.resolves(mockResponse as Response); + try { + await makeRequest( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + '' + ); + } catch (e) { + expect((e as VertexAIError).code).to.equal( + VertexAIErrorCode.API_NOT_ENABLED + ); + expect((e as VertexAIError).message).to.include('my-project'); + expect((e as VertexAIError).message).to.include('googleapis.com'); + } + expect(fetchStub).to.be.calledOnce; + }); + + it('should throw DOMException if external signal is already aborted', async () => { + const controller = new AbortController(); + const abortReason = 'Aborted before request'; + controller.abort(abortReason); + + const requestPromise = makeRequest( 'models/model-name', Task.GENERATE_CONTENT, fakeApiSettings, false, - '' + '{}', + { signal: controller.signal } + ); + + await expect(requestPromise).to.be.rejectedWith( + DOMException, + abortReason + ); + + expect(fetchStub).not.to.have.been.called; + }); + it('should abort fetch if external signal aborts during request', async () => { + fetchStub.callsFake(fetchAborter); + const controller = new AbortController(); + const abortReason = 'Aborted during request'; + + const requestPromise = makeRequest( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + '{}', + { signal: controller.signal } + ); + + await clock.tickAsync(0); + controller.abort(abortReason); + + await expect(requestPromise).to.be.rejectedWith( + VertexAIError, + `VertexAI: Error fetching from https://firebasevertexai.googleapis.com/v1beta/projects/my-project/locations/us-central1/models/model-name:generateContent: ${abortReason} (vertexAI/error)` ); - } catch (e) { - expect((e as VertexAIError).code).to.equal( - VertexAIErrorCode.API_NOT_ENABLED + }); + + it('should abort fetch if timeout expires during request', async () => { + const timeoutDuration = 100; + fetchStub.callsFake(fetchAborter); + + const requestPromise = makeRequest( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + '{}', + { timeout: timeoutDuration } ); - expect((e as VertexAIError).message).to.include('my-project'); - expect((e as VertexAIError).message).to.include('googleapis.com'); - } - expect(fetchStub).to.be.calledOnce; + + await clock.tickAsync(timeoutDuration + 100); + + await expect(requestPromise).to.be.rejectedWith( + VertexAIError, + /Timeout has expired/ + ); + + expect(fetchStub).to.have.been.calledOnce; + const fetchOptions = fetchStub.firstCall.args[1] as RequestInit; + const internalSignal = fetchOptions.signal; + + expect(internalSignal?.aborted).to.be.true; + expect(internalSignal?.reason).to.equal('Timeout has expired.'); + }); + + it('should succeed and clear timeout if fetch completes before timeout', async () => { + const mockResponse = new Response('{}', { + status: 200, + statusText: 'OK' + }); + const fetchPromise = Promise.resolve(mockResponse); + fetchStub.resolves(fetchPromise); + + const requestPromise = makeRequest( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + '{}', + { timeout: 5000 } // Generous timeout + ); + + // Advance time slightly, well within timeout + await clock.tickAsync(10); + + const response = await requestPromise; + expect(response.ok).to.be.true; + + expect(fetchStub).to.have.been.calledOnce; + }); + + it('should succeed and clear timeout/listener if fetch completes with signal provided but not aborted', async () => { + const controller = new AbortController(); + const mockResponse = new Response('{}', { + status: 200, + statusText: 'OK' + }); + const fetchPromise = Promise.resolve(mockResponse); + fetchStub.resolves(fetchPromise); + + const requestPromise = makeRequest( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + '{}', + { signal: controller.signal } + ); + + // Advance time slightly + await clock.tickAsync(10); + + const response = await requestPromise; + expect(response.ok).to.be.true; + expect(fetchStub).to.have.been.calledOnce; + }); + + it('should use external signal abort reason if it occurs before timeout', async () => { + const controller = new AbortController(); + const abortReason = 'External Abort Wins'; + const timeoutDuration = 500; + fetchStub.callsFake(fetchAborter); + + const requestPromise = makeRequest( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + '{}', + { signal: controller.signal, timeout: timeoutDuration } + ); + + // Advance time, but less than the timeout + await clock.tickAsync(timeoutDuration / 2); + controller.abort(abortReason); + + await expect(requestPromise).to.be.rejectedWith( + VertexAIError, + abortReason + ); + }); + + it('should use timeout reason if it occurs before external signal abort', async () => { + const controller = new AbortController(); + const abortReason = 'External Abort Loses'; + const timeoutDuration = 100; + fetchStub.callsFake(fetchAborter); + + const requestPromise = makeRequest( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + '{}', + { signal: controller.signal, timeout: timeoutDuration } + ); + + // Schedule external abort after timeout + setTimeout(() => controller.abort(abortReason), timeoutDuration * 2); + + // Advance time past the timeout + await clock.tickAsync(timeoutDuration + 1); + + await expect(requestPromise).to.be.rejectedWith( + VertexAIError, + /Timeout has expired/ + ); + }); + + it('should pass internal signal to fetch options', async () => { + const mockResponse = new Response('{}', { + status: 200, + statusText: 'OK' + }); + fetchStub.resolves(mockResponse); + + await makeRequest( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + '{}' + ); + + expect(fetchStub).to.have.been.calledOnce; + const fetchOptions = fetchStub.firstCall.args[1] as RequestInit; + expect(fetchOptions.signal).to.exist; + expect(fetchOptions.signal).to.be.instanceOf(AbortSignal); + expect(fetchOptions.signal?.aborted).to.be.false; + }); }); }); diff --git a/packages/vertexai/src/requests/request.ts b/packages/vertexai/src/requests/request.ts index 47e4c6ab446..002930cfbc8 100644 --- a/packages/vertexai/src/requests/request.ts +++ b/packages/vertexai/src/requests/request.ts @@ -15,7 +15,11 @@ * limitations under the License. */ -import { ErrorDetails, RequestOptions, VertexAIErrorCode } from '../types'; +import { + ErrorDetails, + SingleRequestOptions, + VertexAIErrorCode +} from '../types'; import { VertexAIError } from '../errors'; import { ApiSettings } from '../types/internal'; import { @@ -27,6 +31,9 @@ import { } from '../constants'; import { logger } from '../logger'; +const TIMEOUT_EXPIRED_MESSAGE = 'Timeout has expired.'; +const ABORT_ERROR_NAME = 'AbortError'; + export enum Task { GENERATE_CONTENT = 'generateContent', STREAM_GENERATE_CONTENT = 'streamGenerateContent', @@ -40,7 +47,7 @@ export class RequestUrl { public task: Task, public apiSettings: ApiSettings, public stream: boolean, - public requestOptions?: RequestOptions + public requestOptions?: SingleRequestOptions ) {} toString(): string { // TODO: allow user-set option if that feature becomes available @@ -115,9 +122,15 @@ export async function constructRequest( apiSettings: ApiSettings, stream: boolean, body: string, - requestOptions?: RequestOptions + singleRequestOptions?: SingleRequestOptions ): Promise<{ url: string; fetchOptions: RequestInit }> { - const url = new RequestUrl(model, task, apiSettings, stream, requestOptions); + const url = new RequestUrl( + model, + task, + apiSettings, + stream, + singleRequestOptions + ); return { url: url.toString(), fetchOptions: { @@ -134,11 +147,49 @@ export async function makeRequest( apiSettings: ApiSettings, stream: boolean, body: string, - requestOptions?: RequestOptions + singleRequestOptions?: SingleRequestOptions ): Promise { - const url = new RequestUrl(model, task, apiSettings, stream, requestOptions); + const url = new RequestUrl( + model, + task, + apiSettings, + stream, + singleRequestOptions + ); let response; - let fetchTimeoutId: string | number | NodeJS.Timeout | undefined; + + const externalSignal = singleRequestOptions?.signal; + const timeoutMillis = + singleRequestOptions?.timeout != null && singleRequestOptions.timeout >= 0 + ? singleRequestOptions.timeout + : DEFAULT_FETCH_TIMEOUT_MS; + const internalAbortController = new AbortController(); + const fetchTimeoutId = setTimeout(() => { + internalAbortController.abort(TIMEOUT_EXPIRED_MESSAGE); + logger.debug( + `Aborting request to ${url} due to timeout (${timeoutMillis}ms)` + ); + }, timeoutMillis); + + if (externalSignal) { + if (externalSignal.aborted) { + clearTimeout(fetchTimeoutId); + throw new DOMException( + externalSignal.reason ?? 'Aborted externally before fetch', + ABORT_ERROR_NAME + ); + } + + const externalAbortListener = (): void => { + logger.debug(`Aborting request to ${url} due to external abort signal.`); + internalAbortController.abort(externalSignal.reason); + }; + + externalSignal.addEventListener('abort', externalAbortListener, { + once: true + }); + } + try { const request = await constructRequest( model, @@ -146,16 +197,9 @@ export async function makeRequest( apiSettings, stream, body, - requestOptions + singleRequestOptions ); - // Timeout is 180s by default - const timeoutMillis = - requestOptions?.timeout != null && requestOptions.timeout >= 0 - ? requestOptions.timeout - : DEFAULT_FETCH_TIMEOUT_MS; - const abortController = new AbortController(); - fetchTimeoutId = setTimeout(() => abortController.abort(), timeoutMillis); - request.fetchOptions.signal = abortController.signal; + request.fetchOptions.signal = internalAbortController.signal; response = await fetch(request.url, request.fetchOptions); if (!response.ok) { diff --git a/packages/vertexai/src/types/requests.ts b/packages/vertexai/src/types/requests.ts index ee45b636673..d0d62785ad2 100644 --- a/packages/vertexai/src/types/requests.ts +++ b/packages/vertexai/src/types/requests.ts @@ -154,6 +154,43 @@ export interface RequestOptions { baseUrl?: string; } +/** + * Options that can be provided per-request. + * Extends the base {@link RequestOptions} (like `timeout` and `baseUrl`) + * with request-specific controls like cancellation via `AbortSignal`. + * + * Options specified here will override any default {@link RequestOptions} + * configured on a model (e.g. {@link GenerativeModel}). + * + * @public + */ +export interface SingleRequestOptions extends RequestOptions { + /** + * An `AbortSignal` instance that allows cancelling ongoing requests (like `generateContent` or + * `generateImages`). + * + * 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. + * + * Note that this will not cancel the request in the backend, so billing will + * still be applied despite cancellation. + * + * @example + * ```javascript + * const controller = new AbortController(); + * const model = getGenerativeModel({ + * // ... + * }); + * + * // To cancel request: + * controller.abort(); + * ``` + * @see https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal + */ + signal?: AbortSignal; +} + /** * Defines a tool that model can call to access external knowledge. * @public From 54589ad8b8ef198245a899a719ca432aeee61cd9 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Mon, 12 May 2025 13:07:55 -0400 Subject: [PATCH 2/7] Run formatter --- packages/vertexai/src/models/generative-model.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/vertexai/src/models/generative-model.test.ts b/packages/vertexai/src/models/generative-model.test.ts index 88ffaa82b1a..27487d93617 100644 --- a/packages/vertexai/src/models/generative-model.test.ts +++ b/packages/vertexai/src/models/generative-model.test.ts @@ -392,7 +392,8 @@ describe('GenerativeModel', () => { { model: 'my-model' }, requestOptions ); - await expect(genModel.countTokens('hello', singleRequestOptions)).to.be.rejected; + await expect(genModel.countTokens('hello', singleRequestOptions)).to.be + .rejected; expect(countTokensStub).to.be.calledWith( match.any, match.any, From a82a809fc5d9824a87fefff8f87afcbd0acfd7b4 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Thu, 22 May 2025 11:27:25 -0400 Subject: [PATCH 3/7] Fix docs --- docs-devsite/_toc.yaml | 148 +---- docs-devsite/ai.chatsession.md | 22 +- docs-devsite/ai.generativemodel.md | 15 +- docs-devsite/ai.imagenmodel.md | 8 +- docs-devsite/ai.md | 1 + ...toptions.md => ai.singlerequestoptions.md} | 8 +- docs-devsite/vertexai.generativemodel.md | 196 ------ docs-devsite/vertexai.md | 592 ------------------ 8 files changed, 22 insertions(+), 968 deletions(-) rename docs-devsite/{vertexai.singlerequestoptions.md => ai.singlerequestoptions.md} (56%) delete mode 100644 docs-devsite/vertexai.generativemodel.md delete mode 100644 docs-devsite/vertexai.md diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index f5c99e77835..6e07ffa792b 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -132,6 +132,8 @@ toc: path: /docs/reference/js/ai.schemashared.md - title: Segment path: /docs/reference/js/ai.segment.md + - title: SingleRequestOptions + path: /docs/reference/js/ai.singlerequestoptions.md - title: StartChatParams path: /docs/reference/js/ai.startchatparams.md - title: StringSchema @@ -618,149 +620,3 @@ toc: path: /docs/reference/js/storage.uploadtask.md - title: UploadTaskSnapshot path: /docs/reference/js/storage.uploadtasksnapshot.md -<<<<<<< HEAD -- title: vertexai - path: /docs/reference/js/vertexai.md - section: - - title: ArraySchema - path: /docs/reference/js/vertexai.arrayschema.md - - title: BaseParams - path: /docs/reference/js/vertexai.baseparams.md - - title: BooleanSchema - path: /docs/reference/js/vertexai.booleanschema.md - - title: ChatSession - path: /docs/reference/js/vertexai.chatsession.md - - title: Citation - path: /docs/reference/js/vertexai.citation.md - - title: CitationMetadata - path: /docs/reference/js/vertexai.citationmetadata.md - - title: Content - path: /docs/reference/js/vertexai.content.md - - title: CountTokensRequest - path: /docs/reference/js/vertexai.counttokensrequest.md - - title: CountTokensResponse - path: /docs/reference/js/vertexai.counttokensresponse.md - - title: CustomErrorData - path: /docs/reference/js/vertexai.customerrordata.md - - title: Date_2 - path: /docs/reference/js/vertexai.date_2.md - - title: EnhancedGenerateContentResponse - path: /docs/reference/js/vertexai.enhancedgeneratecontentresponse.md - - title: ErrorDetails - path: /docs/reference/js/vertexai.errordetails.md - - title: FileData - path: /docs/reference/js/vertexai.filedata.md - - title: FileDataPart - path: /docs/reference/js/vertexai.filedatapart.md - - title: FunctionCall - path: /docs/reference/js/vertexai.functioncall.md - - title: FunctionCallingConfig - path: /docs/reference/js/vertexai.functioncallingconfig.md - - title: FunctionCallPart - path: /docs/reference/js/vertexai.functioncallpart.md - - title: FunctionDeclaration - path: /docs/reference/js/vertexai.functiondeclaration.md - - title: FunctionDeclarationsTool - path: /docs/reference/js/vertexai.functiondeclarationstool.md - - title: FunctionResponse - path: /docs/reference/js/vertexai.functionresponse.md - - title: FunctionResponsePart - path: /docs/reference/js/vertexai.functionresponsepart.md - - title: GenerateContentCandidate - path: /docs/reference/js/vertexai.generatecontentcandidate.md - - title: GenerateContentRequest - path: /docs/reference/js/vertexai.generatecontentrequest.md - - title: GenerateContentResponse - path: /docs/reference/js/vertexai.generatecontentresponse.md - - title: GenerateContentResult - path: /docs/reference/js/vertexai.generatecontentresult.md - - title: GenerateContentStreamResult - path: /docs/reference/js/vertexai.generatecontentstreamresult.md - - title: GenerationConfig - path: /docs/reference/js/vertexai.generationconfig.md - - title: GenerativeContentBlob - path: /docs/reference/js/vertexai.generativecontentblob.md - - title: GenerativeModel - path: /docs/reference/js/vertexai.generativemodel.md - - title: GroundingAttribution - path: /docs/reference/js/vertexai.groundingattribution.md - - title: GroundingMetadata - path: /docs/reference/js/vertexai.groundingmetadata.md - - title: ImagenGCSImage - path: /docs/reference/js/vertexai.imagengcsimage.md - - title: ImagenGenerationConfig - path: /docs/reference/js/vertexai.imagengenerationconfig.md - - title: ImagenGenerationResponse - path: /docs/reference/js/vertexai.imagengenerationresponse.md - - title: ImagenImageFormat - path: /docs/reference/js/vertexai.imagenimageformat.md - - title: ImagenInlineImage - path: /docs/reference/js/vertexai.imageninlineimage.md - - title: ImagenModel - path: /docs/reference/js/vertexai.imagenmodel.md - - title: ImagenModelParams - path: /docs/reference/js/vertexai.imagenmodelparams.md - - title: ImagenSafetySettings - path: /docs/reference/js/vertexai.imagensafetysettings.md - - title: InlineDataPart - path: /docs/reference/js/vertexai.inlinedatapart.md - - title: IntegerSchema - path: /docs/reference/js/vertexai.integerschema.md - - title: ModalityTokenCount - path: /docs/reference/js/vertexai.modalitytokencount.md - - title: ModelParams - path: /docs/reference/js/vertexai.modelparams.md - - title: NumberSchema - path: /docs/reference/js/vertexai.numberschema.md - - title: ObjectSchema - path: /docs/reference/js/vertexai.objectschema.md - - title: ObjectSchemaInterface - path: /docs/reference/js/vertexai.objectschemainterface.md - - title: PromptFeedback - path: /docs/reference/js/vertexai.promptfeedback.md - - title: RequestOptions - path: /docs/reference/js/vertexai.requestoptions.md - - title: RetrievedContextAttribution - path: /docs/reference/js/vertexai.retrievedcontextattribution.md - - title: SafetyRating - path: /docs/reference/js/vertexai.safetyrating.md - - title: SafetySetting - path: /docs/reference/js/vertexai.safetysetting.md - - title: Schema - path: /docs/reference/js/vertexai.schema.md - - title: SchemaInterface - path: /docs/reference/js/vertexai.schemainterface.md - - title: SchemaParams - path: /docs/reference/js/vertexai.schemaparams.md - - title: SchemaRequest - path: /docs/reference/js/vertexai.schemarequest.md - - title: SchemaShared - path: /docs/reference/js/vertexai.schemashared.md - - title: Segment - path: /docs/reference/js/vertexai.segment.md - - title: SingleRequestOptions - path: /docs/reference/js/vertexai.singlerequestoptions.md - - title: StartChatParams - path: /docs/reference/js/vertexai.startchatparams.md - - title: StringSchema - path: /docs/reference/js/vertexai.stringschema.md - - title: TextPart - path: /docs/reference/js/vertexai.textpart.md - - title: ToolConfig - path: /docs/reference/js/vertexai.toolconfig.md - - title: UsageMetadata - path: /docs/reference/js/vertexai.usagemetadata.md - - title: VertexAI - path: /docs/reference/js/vertexai.vertexai.md - - title: VertexAIError - path: /docs/reference/js/vertexai.vertexaierror.md - - title: VertexAIModel - path: /docs/reference/js/vertexai.vertexaimodel.md - - title: VertexAIOptions - path: /docs/reference/js/vertexai.vertexaioptions.md - - title: VideoMetadata - path: /docs/reference/js/vertexai.videometadata.md - - title: WebAttribution - path: /docs/reference/js/vertexai.webattribution.md -======= ->>>>>>> main diff --git a/docs-devsite/ai.chatsession.md b/docs-devsite/ai.chatsession.md index fc50d4ba920..211502b4076 100644 --- a/docs-devsite/ai.chatsession.md +++ b/docs-devsite/ai.chatsession.md @@ -36,15 +36,9 @@ export declare class ChatSession | Method | Modifiers | Description | | --- | --- | --- | -<<<<<<< HEAD:docs-devsite/vertexai.chatsession.md -| [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. | -| [sendMessage(request, singleRequestOptions)](./vertexai.chatsession.md#chatsessionsendmessage) | | Sends a chat message and receives a non-streaming [GenerateContentResult](./vertexai.generatecontentresult.md#generatecontentresult_interface) | -| [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. | -======= | [getHistory()](./ai.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. | -| [sendMessage(request)](./ai.chatsession.md#chatsessionsendmessage) | | Sends a chat message and receives a non-streaming [GenerateContentResult](./ai.generatecontentresult.md#generatecontentresult_interface) | -| [sendMessageStream(request)](./ai.chatsession.md#chatsessionsendmessagestream) | | Sends a chat message and receives the response as a [GenerateContentStreamResult](./ai.generatecontentstreamresult.md#generatecontentstreamresult_interface) containing an iterable stream and a response promise. | ->>>>>>> main:docs-devsite/ai.chatsession.md +| [sendMessage(request, singleRequestOptions)](./ai.chatsession.md#chatsessionsendmessage) | | Sends a chat message and receives a non-streaming [GenerateContentResult](./ai.generatecontentresult.md#generatecontentresult_interface) | +| [sendMessageStream(request, singleRequestOptions)](./ai.chatsession.md#chatsessionsendmessagestream) | | Sends a chat message and receives the response as a [GenerateContentStreamResult](./ai.generatecontentstreamresult.md#generatecontentstreamresult_interface) containing an iterable stream and a response promise. | ## ChatSession.(constructor) @@ -116,12 +110,8 @@ sendMessage(request: string | Array, singleRequestOptions?: Singl | Parameter | Type | Description | | --- | --- | --- | -<<<<<<< HEAD:docs-devsite/vertexai.chatsession.md -| request | string \| Array<string \| [Part](./vertexai.md#part)> | | -| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | | -======= | request | string \| Array<string \| [Part](./ai.md#part)> | | ->>>>>>> main:docs-devsite/ai.chatsession.md +| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: @@ -141,12 +131,8 @@ sendMessageStream(request: string | Array, singleRequestOptions?: | Parameter | Type | Description | | --- | --- | --- | -<<<<<<< HEAD:docs-devsite/vertexai.chatsession.md -| request | string \| Array<string \| [Part](./vertexai.md#part)> | | -| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | | -======= | request | string \| Array<string \| [Part](./ai.md#part)> | | ->>>>>>> main:docs-devsite/ai.chatsession.md +| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: diff --git a/docs-devsite/ai.generativemodel.md b/docs-devsite/ai.generativemodel.md index d91cf80e881..948251271b9 100644 --- a/docs-devsite/ai.generativemodel.md +++ b/docs-devsite/ai.generativemodel.md @@ -40,9 +40,9 @@ export declare class GenerativeModel extends AIModel | Method | Modifiers | Description | | --- | --- | --- | -| [countTokens(request)](./ai.generativemodel.md#generativemodelcounttokens) | | Counts the tokens in the provided request. | -| [generateContent(request)](./ai.generativemodel.md#generativemodelgeneratecontent) | | Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | -| [generateContentStream(request)](./ai.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. | +| [countTokens(request, singleRequestOptions)](./ai.generativemodel.md#generativemodelcounttokens) | | Counts the tokens in the provided request. | +| [generateContent(request, singleRequestOptions)](./ai.generativemodel.md#generativemodelgeneratecontent) | | Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | +| [generateContentStream(request, singleRequestOptions)](./ai.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. | | [startChat(startChatParams)](./ai.generativemodel.md#generativemodelstartchat) | | Gets a new [ChatSession](./ai.chatsession.md#chatsession_class) instance which can be used for multi-turn chats. | ## GenerativeModel.(constructor) @@ -118,7 +118,7 @@ Counts the tokens in the provided request. Signature: ```typescript -countTokens(request: CountTokensRequest | string | Array): Promise; +countTokens(request: CountTokensRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -126,6 +126,7 @@ countTokens(request: CountTokensRequest | string | Array): Promis | Parameter | Type | Description | | --- | --- | --- | | request | [CountTokensRequest](./ai.counttokensrequest.md#counttokensrequest_interface) \| string \| Array<string \| [Part](./ai.md#part)> | | +| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: @@ -138,7 +139,7 @@ Makes a single non-streaming call to the model and returns an object containing Signature: ```typescript -generateContent(request: GenerateContentRequest | string | Array): Promise; +generateContent(request: GenerateContentRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -146,6 +147,7 @@ generateContent(request: GenerateContentRequest | string | Array) | Parameter | Type | Description | | --- | --- | --- | | request | [GenerateContentRequest](./ai.generatecontentrequest.md#generatecontentrequest_interface) \| string \| Array<string \| [Part](./ai.md#part)> | | +| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: @@ -158,7 +160,7 @@ Makes a single streaming call to the model and returns an object containing an i Signature: ```typescript -generateContentStream(request: GenerateContentRequest | string | Array): Promise; +generateContentStream(request: GenerateContentRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; ``` #### Parameters @@ -166,6 +168,7 @@ generateContentStream(request: GenerateContentRequest | string | Array> | | +| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: diff --git a/docs-devsite/ai.imagenmodel.md b/docs-devsite/ai.imagenmodel.md index a22cec6613d..ae0d4daa2d0 100644 --- a/docs-devsite/ai.imagenmodel.md +++ b/docs-devsite/ai.imagenmodel.md @@ -42,11 +42,7 @@ export declare class ImagenModel extends AIModel | Method | Modifiers | Description | | --- | --- | --- | -<<<<<<< HEAD:docs-devsite/vertexai.imagenmodel.md -| [generateImages(prompt, singleRequestOptions)](./vertexai.imagenmodel.md#imagenmodelgenerateimages) | | (Public Preview) Generates images using the Imagen model and returns them as base64-encoded strings. | -======= -| [generateImages(prompt)](./ai.imagenmodel.md#imagenmodelgenerateimages) | | (Public Preview) Generates images using the Imagen model and returns them as base64-encoded strings. | ->>>>>>> main:docs-devsite/ai.imagenmodel.md +| [generateImages(prompt, singleRequestOptions)](./ai.imagenmodel.md#imagenmodelgenerateimages) | | (Public Preview) Generates images using the Imagen model and returns them as base64-encoded strings. | ## ImagenModel.(constructor) @@ -130,7 +126,7 @@ generateImages(prompt: string, singleRequestOptions?: SingleRequestOptions): Pro | Parameter | Type | Description | | --- | --- | --- | | prompt | string | A text prompt describing the image(s) to generate. | -| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | | +| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | | Returns: diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index c43c0391ba4..fca050e676a 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -117,6 +117,7 @@ The Firebase AI Web SDK. | [SchemaRequest](./ai.schemarequest.md#schemarequest_interface) | Final format for [Schema](./ai.schema.md#schema_class) params passed to backend requests. | | [SchemaShared](./ai.schemashared.md#schemashared_interface) | Basic [Schema](./ai.schema.md#schema_class) properties shared across several Schema-related types. | | [Segment](./ai.segment.md#segment_interface) | | +| [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | Options that can be provided per-request. Extends the base [RequestOptions](./ai.requestoptions.md#requestoptions_interface) (like timeout and baseUrl) with request-specific controls like cancellation via AbortSignal.Options specified here will override any default [RequestOptions](./ai.requestoptions.md#requestoptions_interface) configured on a model (e.g. [GenerativeModel](./ai.generativemodel.md#generativemodel_class)). | | [StartChatParams](./ai.startchatparams.md#startchatparams_interface) | Params for [GenerativeModel.startChat()](./ai.generativemodel.md#generativemodelstartchat). | | [TextPart](./ai.textpart.md#textpart_interface) | Content part interface if the part represents a text string. | | [ToolConfig](./ai.toolconfig.md#toolconfig_interface) | Tool config. This config is shared for all tools provided in the request. | diff --git a/docs-devsite/vertexai.singlerequestoptions.md b/docs-devsite/ai.singlerequestoptions.md similarity index 56% rename from docs-devsite/vertexai.singlerequestoptions.md rename to docs-devsite/ai.singlerequestoptions.md index af5d46059fd..315c99436a4 100644 --- a/docs-devsite/vertexai.singlerequestoptions.md +++ b/docs-devsite/ai.singlerequestoptions.md @@ -10,22 +10,22 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # SingleRequestOptions interface -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`. +Options that can be provided per-request. Extends the base [RequestOptions](./ai.requestoptions.md#requestoptions_interface) (like `timeout` and `baseUrl`) with request-specific controls like cancellation via `AbortSignal`. -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)). +Options specified here will override any default [RequestOptions](./ai.requestoptions.md#requestoptions_interface) configured on a model (e.g. [GenerativeModel](./ai.generativemodel.md#generativemodel_class)). Signature: ```typescript export interface SingleRequestOptions extends RequestOptions ``` -Extends: [RequestOptions](./vertexai.requestoptions.md#requestoptions_interface) +Extends: [RequestOptions](./ai.requestoptions.md#requestoptions_interface) ## Properties | Property | Type | Description | | --- | --- | --- | -| [signal](./vertexai.singlerequestoptions.md#singlerequestoptionssignal) | AbortSignal | An AbortSignal instance that allows cancelling ongoing requests (like generateContent or generateImages).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.Note that this will not cancel the request in the backend, so billing will still be applied despite cancellation. | +| [signal](./ai.singlerequestoptions.md#singlerequestoptionssignal) | AbortSignal | An AbortSignal instance that allows cancelling ongoing requests (like generateContent or generateImages).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.Note that this will not cancel the request in the backend, so billing will still be applied despite cancellation. | ## SingleRequestOptions.signal diff --git a/docs-devsite/vertexai.generativemodel.md b/docs-devsite/vertexai.generativemodel.md deleted file mode 100644 index 0b5d0d3ec25..00000000000 --- a/docs-devsite/vertexai.generativemodel.md +++ /dev/null @@ -1,196 +0,0 @@ -Project: /docs/reference/js/_project.yaml -Book: /docs/reference/_book.yaml -page_type: reference - -{% comment %} -DO NOT EDIT THIS FILE! -This is generated by the JS SDK team, and any local changes will be -overwritten. Changes should be made in the source code at -https://github.com/firebase/firebase-js-sdk -{% endcomment %} - -# GenerativeModel class -Class for generative model APIs. - -Signature: - -```typescript -export declare class GenerativeModel extends VertexAIModel -``` -Extends: [VertexAIModel](./vertexai.vertexaimodel.md#vertexaimodel_class) - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(vertexAI, modelParams, requestOptions)](./vertexai.generativemodel.md#generativemodelconstructor) | | Constructs a new instance of the GenerativeModel class | - -## Properties - -| Property | Modifiers | Type | Description | -| --- | --- | --- | --- | -| [generationConfig](./vertexai.generativemodel.md#generativemodelgenerationconfig) | | [GenerationConfig](./vertexai.generationconfig.md#generationconfig_interface) | | -| [requestOptions](./vertexai.generativemodel.md#generativemodelrequestoptions) | | [RequestOptions](./vertexai.requestoptions.md#requestoptions_interface) | | -| [safetySettings](./vertexai.generativemodel.md#generativemodelsafetysettings) | | [SafetySetting](./vertexai.safetysetting.md#safetysetting_interface)\[\] | | -| [systemInstruction](./vertexai.generativemodel.md#generativemodelsysteminstruction) | | [Content](./vertexai.content.md#content_interface) | | -| [toolConfig](./vertexai.generativemodel.md#generativemodeltoolconfig) | | [ToolConfig](./vertexai.toolconfig.md#toolconfig_interface) | | -| [tools](./vertexai.generativemodel.md#generativemodeltools) | | [Tool](./vertexai.md#tool)\[\] | | - -## Methods - -| Method | Modifiers | Description | -| --- | --- | --- | -| [countTokens(request, singleRequestOptions)](./vertexai.generativemodel.md#generativemodelcounttokens) | | Counts the tokens in the provided request. | -| [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). | -| [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. | -| [startChat(startChatParams)](./vertexai.generativemodel.md#generativemodelstartchat) | | Gets a new [ChatSession](./vertexai.chatsession.md#chatsession_class) instance which can be used for multi-turn chats. | - -## GenerativeModel.(constructor) - -Constructs a new instance of the `GenerativeModel` class - -Signature: - -```typescript -constructor(vertexAI: VertexAI, modelParams: ModelParams, requestOptions?: RequestOptions); -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| vertexAI | [VertexAI](./vertexai.vertexai.md#vertexai_interface) | | -| modelParams | [ModelParams](./vertexai.modelparams.md#modelparams_interface) | | -| requestOptions | [RequestOptions](./vertexai.requestoptions.md#requestoptions_interface) | | - -## GenerativeModel.generationConfig - -Signature: - -```typescript -generationConfig: GenerationConfig; -``` - -## GenerativeModel.requestOptions - -Signature: - -```typescript -requestOptions?: RequestOptions; -``` - -## GenerativeModel.safetySettings - -Signature: - -```typescript -safetySettings: SafetySetting[]; -``` - -## GenerativeModel.systemInstruction - -Signature: - -```typescript -systemInstruction?: Content; -``` - -## GenerativeModel.toolConfig - -Signature: - -```typescript -toolConfig?: ToolConfig; -``` - -## GenerativeModel.tools - -Signature: - -```typescript -tools?: Tool[]; -``` - -## GenerativeModel.countTokens() - -Counts the tokens in the provided request. - -Signature: - -```typescript -countTokens(request: CountTokensRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| request | [CountTokensRequest](./vertexai.counttokensrequest.md#counttokensrequest_interface) \| string \| Array<string \| [Part](./vertexai.md#part)> | | -| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | | - -Returns: - -Promise<[CountTokensResponse](./vertexai.counttokensresponse.md#counttokensresponse_interface)> - -## GenerativeModel.generateContent() - -Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./vertexai.generatecontentresponse.md#generatecontentresponse_interface). - -Signature: - -```typescript -generateContent(request: GenerateContentRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| request | [GenerateContentRequest](./vertexai.generatecontentrequest.md#generatecontentrequest_interface) \| string \| Array<string \| [Part](./vertexai.md#part)> | | -| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | | - -Returns: - -Promise<[GenerateContentResult](./vertexai.generatecontentresult.md#generatecontentresult_interface)> - -## GenerativeModel.generateContentStream() - -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. - -Signature: - -```typescript -generateContentStream(request: GenerateContentRequest | string | Array, singleRequestOptions?: SingleRequestOptions): Promise; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| request | [GenerateContentRequest](./vertexai.generatecontentrequest.md#generatecontentrequest_interface) \| string \| Array<string \| [Part](./vertexai.md#part)> | | -| singleRequestOptions | [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | | - -Returns: - -Promise<[GenerateContentStreamResult](./vertexai.generatecontentstreamresult.md#generatecontentstreamresult_interface)> - -## GenerativeModel.startChat() - -Gets a new [ChatSession](./vertexai.chatsession.md#chatsession_class) instance which can be used for multi-turn chats. - -Signature: - -```typescript -startChat(startChatParams?: StartChatParams): ChatSession; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| startChatParams | [StartChatParams](./vertexai.startchatparams.md#startchatparams_interface) | | - -Returns: - -[ChatSession](./vertexai.chatsession.md#chatsession_class) - diff --git a/docs-devsite/vertexai.md b/docs-devsite/vertexai.md deleted file mode 100644 index 7c61852e484..00000000000 --- a/docs-devsite/vertexai.md +++ /dev/null @@ -1,592 +0,0 @@ -Project: /docs/reference/js/_project.yaml -Book: /docs/reference/_book.yaml -page_type: reference - -{% comment %} -DO NOT EDIT THIS FILE! -This is generated by the JS SDK team, and any local changes will be -overwritten. Changes should be made in the source code at -https://github.com/firebase/firebase-js-sdk -{% endcomment %} - -# vertexai package -The Vertex AI in Firebase Web SDK. - -## Functions - -| Function | Description | -| --- | --- | -| function(app, ...) | -| [getVertexAI(app, options)](./vertexai.md#getvertexai_04094cf) | Returns a [VertexAI](./vertexai.vertexai.md#vertexai_interface) instance for the given app. | -| function(vertexAI, ...) | -| [getGenerativeModel(vertexAI, modelParams, requestOptions)](./vertexai.md#getgenerativemodel_e3037c9) | Returns a [GenerativeModel](./vertexai.generativemodel.md#generativemodel_class) class with methods for inference and other functionality. | -| [getImagenModel(vertexAI, modelParams, requestOptions)](./vertexai.md#getimagenmodel_812c375) | (Public Preview) Returns an [ImagenModel](./vertexai.imagenmodel.md#imagenmodel_class) class with methods for using Imagen.Only Imagen 3 models (named imagen-3.0-*) are supported. | - -## Classes - -| Class | Description | -| --- | --- | -| [ArraySchema](./vertexai.arrayschema.md#arrayschema_class) | Schema class for "array" types. The items param should refer to the type of item that can be a member of the array. | -| [BooleanSchema](./vertexai.booleanschema.md#booleanschema_class) | Schema class for "boolean" types. | -| [ChatSession](./vertexai.chatsession.md#chatsession_class) | ChatSession class that enables sending chat messages and stores history of sent and received messages so far. | -| [GenerativeModel](./vertexai.generativemodel.md#generativemodel_class) | Class for generative model APIs. | -| [ImagenImageFormat](./vertexai.imagenimageformat.md#imagenimageformat_class) | (Public Preview) Defines the image format for images generated by Imagen.Use this class to specify the desired format (JPEG or PNG) and compression quality for images generated by Imagen. This is typically included as part of [ImagenModelParams](./vertexai.imagenmodelparams.md#imagenmodelparams_interface). | -| [ImagenModel](./vertexai.imagenmodel.md#imagenmodel_class) | (Public Preview) Class for Imagen model APIs.This class provides methods for generating images using the Imagen model. | -| [IntegerSchema](./vertexai.integerschema.md#integerschema_class) | Schema class for "integer" types. | -| [NumberSchema](./vertexai.numberschema.md#numberschema_class) | Schema class for "number" types. | -| [ObjectSchema](./vertexai.objectschema.md#objectschema_class) | Schema class for "object" types. The properties param must be a map of Schema objects. | -| [Schema](./vertexai.schema.md#schema_class) | Parent class encompassing all Schema types, with static methods that allow building specific Schema types. This class can be converted with JSON.stringify() into a JSON string accepted by Vertex AI REST endpoints. (This string conversion is automatically done when calling SDK methods.) | -| [StringSchema](./vertexai.stringschema.md#stringschema_class) | Schema class for "string" types. Can be used with or without enum values. | -| [VertexAIError](./vertexai.vertexaierror.md#vertexaierror_class) | Error class for the Vertex AI in Firebase SDK. | -| [VertexAIModel](./vertexai.vertexaimodel.md#vertexaimodel_class) | Base class for Vertex AI in Firebase model APIs. | - -## Enumerations - -| Enumeration | Description | -| --- | --- | -| [BlockReason](./vertexai.md#blockreason) | Reason that a prompt was blocked. | -| [FinishReason](./vertexai.md#finishreason) | Reason that a candidate finished. | -| [FunctionCallingMode](./vertexai.md#functioncallingmode) | | -| [HarmBlockMethod](./vertexai.md#harmblockmethod) | | -| [HarmBlockThreshold](./vertexai.md#harmblockthreshold) | Threshold above which a prompt or candidate will be blocked. | -| [HarmCategory](./vertexai.md#harmcategory) | Harm categories that would cause prompts or candidates to be blocked. | -| [HarmProbability](./vertexai.md#harmprobability) | Probability that a prompt or candidate matches a harm category. | -| [HarmSeverity](./vertexai.md#harmseverity) | Harm severity levels. | -| [ImagenAspectRatio](./vertexai.md#imagenaspectratio) | (Public Preview) Aspect ratios for Imagen images.To specify an aspect ratio for generated images, set the aspectRatio property in your [ImagenGenerationConfig](./vertexai.imagengenerationconfig.md#imagengenerationconfig_interface).See the the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) for more details and examples of the supported aspect ratios. | -| [ImagenPersonFilterLevel](./vertexai.md#imagenpersonfilterlevel) | (Public Preview) A filter level controlling whether generation of images containing people or faces is allowed.See the personGeneration documentation for more details. | -| [ImagenSafetyFilterLevel](./vertexai.md#imagensafetyfilterlevel) | (Public Preview) A filter level controlling how aggressively to filter sensitive content.Text prompts provided as inputs and images (generated or uploaded) through Imagen on Vertex AI are assessed against a list of safety filters, which include 'harmful categories' (for example, violence, sexual, derogatory, and toxic). This filter level controls how aggressively to filter out potentially harmful content from responses. See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) and the [Responsible AI and usage guidelines](https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters) for more details. | -| [Modality](./vertexai.md#modality) | Content part modality. | -| [SchemaType](./vertexai.md#schematype) | Contains the list of OpenAPI data types as defined by the [OpenAPI specification](https://swagger.io/docs/specification/data-models/data-types/) | -| [VertexAIErrorCode](./vertexai.md#vertexaierrorcode) | Standardized error codes that [VertexAIError](./vertexai.vertexaierror.md#vertexaierror_class) can have. | - -## Interfaces - -| Interface | Description | -| --- | --- | -| [BaseParams](./vertexai.baseparams.md#baseparams_interface) | Base parameters for a number of methods. | -| [Citation](./vertexai.citation.md#citation_interface) | A single citation. | -| [CitationMetadata](./vertexai.citationmetadata.md#citationmetadata_interface) | Citation metadata that may be found on a [GenerateContentCandidate](./vertexai.generatecontentcandidate.md#generatecontentcandidate_interface). | -| [Content](./vertexai.content.md#content_interface) | Content type for both prompts and response candidates. | -| [CountTokensRequest](./vertexai.counttokensrequest.md#counttokensrequest_interface) | Params for calling [GenerativeModel.countTokens()](./vertexai.generativemodel.md#generativemodelcounttokens) | -| [CountTokensResponse](./vertexai.counttokensresponse.md#counttokensresponse_interface) | Response from calling [GenerativeModel.countTokens()](./vertexai.generativemodel.md#generativemodelcounttokens). | -| [CustomErrorData](./vertexai.customerrordata.md#customerrordata_interface) | Details object that contains data originating from a bad HTTP response. | -| [Date\_2](./vertexai.date_2.md#date_2_interface) | Protobuf google.type.Date | -| [EnhancedGenerateContentResponse](./vertexai.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponse_interface) | Response object wrapped with helper methods. | -| [ErrorDetails](./vertexai.errordetails.md#errordetails_interface) | Details object that may be included in an error response. | -| [FileData](./vertexai.filedata.md#filedata_interface) | Data pointing to a file uploaded on Google Cloud Storage. | -| [FileDataPart](./vertexai.filedatapart.md#filedatapart_interface) | Content part interface if the part represents [FileData](./vertexai.filedata.md#filedata_interface) | -| [FunctionCall](./vertexai.functioncall.md#functioncall_interface) | A predicted [FunctionCall](./vertexai.functioncall.md#functioncall_interface) returned from the model that contains a string representing the [FunctionDeclaration.name](./vertexai.functiondeclaration.md#functiondeclarationname) and a structured JSON object containing the parameters and their values. | -| [FunctionCallingConfig](./vertexai.functioncallingconfig.md#functioncallingconfig_interface) | | -| [FunctionCallPart](./vertexai.functioncallpart.md#functioncallpart_interface) | Content part interface if the part represents a [FunctionCall](./vertexai.functioncall.md#functioncall_interface). | -| [FunctionDeclaration](./vertexai.functiondeclaration.md#functiondeclaration_interface) | Structured representation of a function declaration as defined by the [OpenAPI 3.0 specification](https://spec.openapis.org/oas/v3.0.3). Included in this declaration are the function name and parameters. This FunctionDeclaration is a representation of a block of code that can be used as a Tool by the model and executed by the client. | -| [FunctionDeclarationsTool](./vertexai.functiondeclarationstool.md#functiondeclarationstool_interface) | A FunctionDeclarationsTool is a piece of code that enables the system to interact with external systems to perform an action, or set of actions, outside of knowledge and scope of the model. | -| [FunctionResponse](./vertexai.functionresponse.md#functionresponse_interface) | The result output from a [FunctionCall](./vertexai.functioncall.md#functioncall_interface) that contains a string representing the [FunctionDeclaration.name](./vertexai.functiondeclaration.md#functiondeclarationname) and a structured JSON object containing any output from the function is used as context to the model. This should contain the result of a [FunctionCall](./vertexai.functioncall.md#functioncall_interface) made based on model prediction. | -| [FunctionResponsePart](./vertexai.functionresponsepart.md#functionresponsepart_interface) | Content part interface if the part represents [FunctionResponse](./vertexai.functionresponse.md#functionresponse_interface). | -| [GenerateContentCandidate](./vertexai.generatecontentcandidate.md#generatecontentcandidate_interface) | A candidate returned as part of a [GenerateContentResponse](./vertexai.generatecontentresponse.md#generatecontentresponse_interface). | -| [GenerateContentRequest](./vertexai.generatecontentrequest.md#generatecontentrequest_interface) | Request sent through [GenerativeModel.generateContent()](./vertexai.generativemodel.md#generativemodelgeneratecontent) | -| [GenerateContentResponse](./vertexai.generatecontentresponse.md#generatecontentresponse_interface) | Individual response from [GenerativeModel.generateContent()](./vertexai.generativemodel.md#generativemodelgeneratecontent) and [GenerativeModel.generateContentStream()](./vertexai.generativemodel.md#generativemodelgeneratecontentstream). generateContentStream() will return one in each chunk until the stream is done. | -| [GenerateContentResult](./vertexai.generatecontentresult.md#generatecontentresult_interface) | Result object returned from [GenerativeModel.generateContent()](./vertexai.generativemodel.md#generativemodelgeneratecontent) call. | -| [GenerateContentStreamResult](./vertexai.generatecontentstreamresult.md#generatecontentstreamresult_interface) | Result object returned from [GenerativeModel.generateContentStream()](./vertexai.generativemodel.md#generativemodelgeneratecontentstream) call. Iterate over stream to get chunks as they come in and/or use the response promise to get the aggregated response when the stream is done. | -| [GenerationConfig](./vertexai.generationconfig.md#generationconfig_interface) | Config options for content-related requests | -| [GenerativeContentBlob](./vertexai.generativecontentblob.md#generativecontentblob_interface) | Interface for sending an image. | -| [GroundingAttribution](./vertexai.groundingattribution.md#groundingattribution_interface) | | -| [GroundingMetadata](./vertexai.groundingmetadata.md#groundingmetadata_interface) | Metadata returned to client when grounding is enabled. | -| [ImagenGCSImage](./vertexai.imagengcsimage.md#imagengcsimage_interface) | An image generated by Imagen, stored in a Cloud Storage for Firebase bucket.This feature is not available yet. | -| [ImagenGenerationConfig](./vertexai.imagengenerationconfig.md#imagengenerationconfig_interface) | (Public Preview) Configuration options for generating images with Imagen.See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images-imagen) for more details. | -| [ImagenGenerationResponse](./vertexai.imagengenerationresponse.md#imagengenerationresponse_interface) | (Public Preview) The response from a request to generate images with Imagen. | -| [ImagenInlineImage](./vertexai.imageninlineimage.md#imageninlineimage_interface) | (Public Preview) An image generated by Imagen, represented as inline data. | -| [ImagenModelParams](./vertexai.imagenmodelparams.md#imagenmodelparams_interface) | (Public Preview) Parameters for configuring an [ImagenModel](./vertexai.imagenmodel.md#imagenmodel_class). | -| [ImagenSafetySettings](./vertexai.imagensafetysettings.md#imagensafetysettings_interface) | (Public Preview) Settings for controlling the aggressiveness of filtering out sensitive content.See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) for more details. | -| [InlineDataPart](./vertexai.inlinedatapart.md#inlinedatapart_interface) | Content part interface if the part represents an image. | -| [ModalityTokenCount](./vertexai.modalitytokencount.md#modalitytokencount_interface) | Represents token counting info for a single modality. | -| [ModelParams](./vertexai.modelparams.md#modelparams_interface) | Params passed to [getGenerativeModel()](./vertexai.md#getgenerativemodel_e3037c9). | -| [ObjectSchemaInterface](./vertexai.objectschemainterface.md#objectschemainterface_interface) | Interface for [ObjectSchema](./vertexai.objectschema.md#objectschema_class) class. | -| [PromptFeedback](./vertexai.promptfeedback.md#promptfeedback_interface) | If the prompt was blocked, this will be populated with blockReason and the relevant safetyRatings. | -| [RequestOptions](./vertexai.requestoptions.md#requestoptions_interface) | Params passed to [getGenerativeModel()](./vertexai.md#getgenerativemodel_e3037c9). | -| [RetrievedContextAttribution](./vertexai.retrievedcontextattribution.md#retrievedcontextattribution_interface) | | -| [SafetyRating](./vertexai.safetyrating.md#safetyrating_interface) | A safety rating associated with a [GenerateContentCandidate](./vertexai.generatecontentcandidate.md#generatecontentcandidate_interface) | -| [SafetySetting](./vertexai.safetysetting.md#safetysetting_interface) | Safety setting that can be sent as part of request parameters. | -| [SchemaInterface](./vertexai.schemainterface.md#schemainterface_interface) | Interface for [Schema](./vertexai.schema.md#schema_class) class. | -| [SchemaParams](./vertexai.schemaparams.md#schemaparams_interface) | Params passed to [Schema](./vertexai.schema.md#schema_class) static methods to create specific [Schema](./vertexai.schema.md#schema_class) classes. | -| [SchemaRequest](./vertexai.schemarequest.md#schemarequest_interface) | Final format for [Schema](./vertexai.schema.md#schema_class) params passed to backend requests. | -| [SchemaShared](./vertexai.schemashared.md#schemashared_interface) | Basic [Schema](./vertexai.schema.md#schema_class) properties shared across several Schema-related types. | -| [Segment](./vertexai.segment.md#segment_interface) | | -| [SingleRequestOptions](./vertexai.singlerequestoptions.md#singlerequestoptions_interface) | 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.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)). | -| [StartChatParams](./vertexai.startchatparams.md#startchatparams_interface) | Params for [GenerativeModel.startChat()](./vertexai.generativemodel.md#generativemodelstartchat). | -| [TextPart](./vertexai.textpart.md#textpart_interface) | Content part interface if the part represents a text string. | -| [ToolConfig](./vertexai.toolconfig.md#toolconfig_interface) | Tool config. This config is shared for all tools provided in the request. | -| [UsageMetadata](./vertexai.usagemetadata.md#usagemetadata_interface) | Usage metadata about a [GenerateContentResponse](./vertexai.generatecontentresponse.md#generatecontentresponse_interface). | -| [VertexAI](./vertexai.vertexai.md#vertexai_interface) | An instance of the Vertex AI in Firebase SDK. | -| [VertexAIOptions](./vertexai.vertexaioptions.md#vertexaioptions_interface) | Options when initializing the Vertex AI in Firebase SDK. | -| [VideoMetadata](./vertexai.videometadata.md#videometadata_interface) | Describes the input video content. | -| [WebAttribution](./vertexai.webattribution.md#webattribution_interface) | | - -## Variables - -| Variable | Description | -| --- | --- | -| [POSSIBLE\_ROLES](./vertexai.md#possible_roles) | Possible roles. | -| [ResponseModality](./vertexai.md#responsemodality) | (Public Preview) Generation modalities to be returned in generation responses. | - -## Type Aliases - -| Type Alias | Description | -| --- | --- | -| [Part](./vertexai.md#part) | Content part - includes text, image/video, or function call/response part types. | -| [ResponseModality](./vertexai.md#responsemodality) | (Public Preview) Generation modalities to be returned in generation responses. | -| [Role](./vertexai.md#role) | Role is the producer of the content. | -| [Tool](./vertexai.md#tool) | Defines a tool that model can call to access external knowledge. | -| [TypedSchema](./vertexai.md#typedschema) | A type that includes all specific Schema types. | - -## function(app, ...) - -### getVertexAI(app, options) {:#getvertexai_04094cf} - -Returns a [VertexAI](./vertexai.vertexai.md#vertexai_interface) instance for the given app. - -Signature: - -```typescript -export declare function getVertexAI(app?: FirebaseApp, options?: VertexAIOptions): VertexAI; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| app | [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) | The [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) to use. | -| options | [VertexAIOptions](./vertexai.vertexaioptions.md#vertexaioptions_interface) | | - -Returns: - -[VertexAI](./vertexai.vertexai.md#vertexai_interface) - -## function(vertexAI, ...) - -### getGenerativeModel(vertexAI, modelParams, requestOptions) {:#getgenerativemodel_e3037c9} - -Returns a [GenerativeModel](./vertexai.generativemodel.md#generativemodel_class) class with methods for inference and other functionality. - -Signature: - -```typescript -export declare function getGenerativeModel(vertexAI: VertexAI, modelParams: ModelParams, requestOptions?: RequestOptions): GenerativeModel; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| vertexAI | [VertexAI](./vertexai.vertexai.md#vertexai_interface) | | -| modelParams | [ModelParams](./vertexai.modelparams.md#modelparams_interface) | | -| requestOptions | [RequestOptions](./vertexai.requestoptions.md#requestoptions_interface) | | - -Returns: - -[GenerativeModel](./vertexai.generativemodel.md#generativemodel_class) - -### getImagenModel(vertexAI, modelParams, requestOptions) {:#getimagenmodel_812c375} - -> 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. -> - -Returns an [ImagenModel](./vertexai.imagenmodel.md#imagenmodel_class) class with methods for using Imagen. - -Only Imagen 3 models (named `imagen-3.0-*`) are supported. - -Signature: - -```typescript -export declare function getImagenModel(vertexAI: VertexAI, modelParams: ImagenModelParams, requestOptions?: RequestOptions): ImagenModel; -``` - -#### Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| vertexAI | [VertexAI](./vertexai.vertexai.md#vertexai_interface) | An instance of the Vertex AI in Firebase SDK. | -| modelParams | [ImagenModelParams](./vertexai.imagenmodelparams.md#imagenmodelparams_interface) | Parameters to use when making Imagen requests. | -| requestOptions | [RequestOptions](./vertexai.requestoptions.md#requestoptions_interface) | Additional options to use when making requests. | - -Returns: - -[ImagenModel](./vertexai.imagenmodel.md#imagenmodel_class) - -#### Exceptions - -If the `apiKey` or `projectId` fields are missing in your Firebase config. - -## POSSIBLE\_ROLES - -Possible roles. - -Signature: - -```typescript -POSSIBLE_ROLES: readonly ["user", "model", "function", "system"] -``` - -## ResponseModality - -> 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. -> - -Generation modalities to be returned in generation responses. - -Signature: - -```typescript -ResponseModality: { - readonly TEXT: "TEXT"; - readonly IMAGE: "IMAGE"; -} -``` - -## Part - -Content part - includes text, image/video, or function call/response part types. - -Signature: - -```typescript -export type Part = TextPart | InlineDataPart | FunctionCallPart | FunctionResponsePart | FileDataPart; -``` - -## ResponseModality - -> 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. -> - -Generation modalities to be returned in generation responses. - -Signature: - -```typescript -export type ResponseModality = (typeof ResponseModality)[keyof typeof ResponseModality]; -``` - -## Role - -Role is the producer of the content. - -Signature: - -```typescript -export type Role = (typeof POSSIBLE_ROLES)[number]; -``` - -## Tool - -Defines a tool that model can call to access external knowledge. - -Signature: - -```typescript -export declare type Tool = FunctionDeclarationsTool; -``` - -## TypedSchema - -A type that includes all specific Schema types. - -Signature: - -```typescript -export type TypedSchema = IntegerSchema | NumberSchema | StringSchema | BooleanSchema | ObjectSchema | ArraySchema; -``` - -## BlockReason - -Reason that a prompt was blocked. - -Signature: - -```typescript -export declare enum BlockReason -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| BLOCKLIST | "BLOCKLIST" | Content was blocked because it contained terms from the terminology blocklist. | -| OTHER | "OTHER" | Content was blocked, but the reason is uncategorized. | -| PROHIBITED\_CONTENT | "PROHIBITED_CONTENT" | Content was blocked due to prohibited content. | -| SAFETY | "SAFETY" | Content was blocked by safety settings. | - -## FinishReason - -Reason that a candidate finished. - -Signature: - -```typescript -export declare enum FinishReason -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| BLOCKLIST | "BLOCKLIST" | The candidate content contained forbidden terms. | -| MALFORMED\_FUNCTION\_CALL | "MALFORMED_FUNCTION_CALL" | The function call generated by the model was invalid. | -| MAX\_TOKENS | "MAX_TOKENS" | The maximum number of tokens as specified in the request was reached. | -| OTHER | "OTHER" | Unknown reason. | -| PROHIBITED\_CONTENT | "PROHIBITED_CONTENT" | The candidate content potentially contained prohibited content. | -| RECITATION | "RECITATION" | The candidate content was flagged for recitation reasons. | -| SAFETY | "SAFETY" | The candidate content was flagged for safety reasons. | -| SPII | "SPII" | The candidate content potentially contained Sensitive Personally Identifiable Information (SPII). | -| STOP | "STOP" | Natural stop point of the model or provided stop sequence. | - -## FunctionCallingMode - - -Signature: - -```typescript -export declare enum FunctionCallingMode -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| ANY | "ANY" | Model is constrained to always predicting a function call only. If allowed_function_names is set, the predicted function call will be limited to any one of allowed_function_names, else the predicted function call will be any one of the provided function_declarations. | -| AUTO | "AUTO" | Default model behavior; model decides to predict either a function call or a natural language response. | -| NONE | "NONE" | Model will not predict any function call. Model behavior is same as when not passing any function declarations. | - -## HarmBlockMethod - - -Signature: - -```typescript -export declare enum HarmBlockMethod -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| PROBABILITY | "PROBABILITY" | The harm block method uses the probability score. | -| SEVERITY | "SEVERITY" | The harm block method uses both probability and severity scores. | - -## HarmBlockThreshold - -Threshold above which a prompt or candidate will be blocked. - -Signature: - -```typescript -export declare enum HarmBlockThreshold -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| BLOCK\_LOW\_AND\_ABOVE | "BLOCK_LOW_AND_ABOVE" | Content with NEGLIGIBLE will be allowed. | -| BLOCK\_MEDIUM\_AND\_ABOVE | "BLOCK_MEDIUM_AND_ABOVE" | Content with NEGLIGIBLE and LOW will be allowed. | -| BLOCK\_NONE | "BLOCK_NONE" | All content will be allowed. | -| BLOCK\_ONLY\_HIGH | "BLOCK_ONLY_HIGH" | Content with NEGLIGIBLE, LOW, and MEDIUM will be allowed. | - -## HarmCategory - -Harm categories that would cause prompts or candidates to be blocked. - -Signature: - -```typescript -export declare enum HarmCategory -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| HARM\_CATEGORY\_DANGEROUS\_CONTENT | "HARM_CATEGORY_DANGEROUS_CONTENT" | | -| HARM\_CATEGORY\_HARASSMENT | "HARM_CATEGORY_HARASSMENT" | | -| HARM\_CATEGORY\_HATE\_SPEECH | "HARM_CATEGORY_HATE_SPEECH" | | -| HARM\_CATEGORY\_SEXUALLY\_EXPLICIT | "HARM_CATEGORY_SEXUALLY_EXPLICIT" | | - -## HarmProbability - -Probability that a prompt or candidate matches a harm category. - -Signature: - -```typescript -export declare enum HarmProbability -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| HIGH | "HIGH" | Content has a high chance of being unsafe. | -| LOW | "LOW" | Content has a low chance of being unsafe. | -| MEDIUM | "MEDIUM" | Content has a medium chance of being unsafe. | -| NEGLIGIBLE | "NEGLIGIBLE" | Content has a negligible chance of being unsafe. | - -## HarmSeverity - -Harm severity levels. - -Signature: - -```typescript -export declare enum HarmSeverity -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| HARM\_SEVERITY\_HIGH | "HARM_SEVERITY_HIGH" | High level of harm severity. | -| HARM\_SEVERITY\_LOW | "HARM_SEVERITY_LOW" | Low level of harm severity. | -| HARM\_SEVERITY\_MEDIUM | "HARM_SEVERITY_MEDIUM" | Medium level of harm severity. | -| HARM\_SEVERITY\_NEGLIGIBLE | "HARM_SEVERITY_NEGLIGIBLE" | Negligible level of harm severity. | - -## ImagenAspectRatio - -> 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. -> - -Aspect ratios for Imagen images. - -To specify an aspect ratio for generated images, set the `aspectRatio` property in your [ImagenGenerationConfig](./vertexai.imagengenerationconfig.md#imagengenerationconfig_interface). - -See the the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) for more details and examples of the supported aspect ratios. - -Signature: - -```typescript -export declare enum ImagenAspectRatio -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| LANDSCAPE\_16x9 | "16:9" | (Public Preview) Landscape (16:9) aspect ratio. | -| LANDSCAPE\_3x4 | "3:4" | (Public Preview) Landscape (3:4) aspect ratio. | -| PORTRAIT\_4x3 | "4:3" | (Public Preview) Portrait (4:3) aspect ratio. | -| PORTRAIT\_9x16 | "9:16" | (Public Preview) Portrait (9:16) aspect ratio. | -| SQUARE | "1:1" | (Public Preview) Square (1:1) aspect ratio. | - -## ImagenPersonFilterLevel - -> 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. -> - -A filter level controlling whether generation of images containing people or faces is allowed. - -See the personGeneration documentation for more details. - -Signature: - -```typescript -export declare enum ImagenPersonFilterLevel -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| ALLOW\_ADULT | "allow_adult" | (Public Preview) Allow generation of images containing adults only; images of children are filtered out.Generation of images containing people or faces may require your use case to be reviewed and approved by Cloud support; see the [Responsible AI and usage guidelines](https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#person-face-gen) for more details. | -| ALLOW\_ALL | "allow_all" | (Public Preview) Allow generation of images containing adults only; images of children are filtered out.Generation of images containing people or faces may require your use case to be reviewed and approved by Cloud support; see the [Responsible AI and usage guidelines](https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#person-face-gen) for more details. | -| BLOCK\_ALL | "dont_allow" | (Public Preview) Disallow generation of images containing people or faces; images of people are filtered out. | - -## ImagenSafetyFilterLevel - -> 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. -> - -A filter level controlling how aggressively to filter sensitive content. - -Text prompts provided as inputs and images (generated or uploaded) through Imagen on Vertex AI are assessed against a list of safety filters, which include 'harmful categories' (for example, `violence`, `sexual`, `derogatory`, and `toxic`). This filter level controls how aggressively to filter out potentially harmful content from responses. See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) and the [Responsible AI and usage guidelines](https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters) for more details. - -Signature: - -```typescript -export declare enum ImagenSafetyFilterLevel -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| BLOCK\_LOW\_AND\_ABOVE | "block_low_and_above" | (Public Preview) The most aggressive filtering level; most strict blocking. | -| BLOCK\_MEDIUM\_AND\_ABOVE | "block_medium_and_above" | (Public Preview) Blocks some sensitive prompts and responses. | -| BLOCK\_NONE | "block_none" | (Public Preview) The least aggressive filtering level; blocks very few sensitive prompts and responses.Access to this feature is restricted and may require your case to be reviewed and approved by Cloud support. | -| BLOCK\_ONLY\_HIGH | "block_only_high" | (Public Preview) Blocks few sensitive prompts and responses. | - -## Modality - -Content part modality. - -Signature: - -```typescript -export declare enum Modality -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| AUDIO | "AUDIO" | Audio. | -| DOCUMENT | "DOCUMENT" | Document (for example, PDF). | -| IMAGE | "IMAGE" | Image. | -| MODALITY\_UNSPECIFIED | "MODALITY_UNSPECIFIED" | Unspecified modality. | -| TEXT | "TEXT" | Plain text. | -| VIDEO | "VIDEO" | Video. | - -## SchemaType - -Contains the list of OpenAPI data types as defined by the [OpenAPI specification](https://swagger.io/docs/specification/data-models/data-types/) - -Signature: - -```typescript -export declare enum SchemaType -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| ARRAY | "array" | Array type. | -| BOOLEAN | "boolean" | Boolean type. | -| INTEGER | "integer" | Integer type. | -| NUMBER | "number" | Number type. | -| OBJECT | "object" | Object type. | -| STRING | "string" | String type. | - -## VertexAIErrorCode - -Standardized error codes that [VertexAIError](./vertexai.vertexaierror.md#vertexaierror_class) can have. - -Signature: - -```typescript -export declare const enum VertexAIErrorCode -``` - -## Enumeration Members - -| Member | Value | Description | -| --- | --- | --- | -| API\_NOT\_ENABLED | "api-not-enabled" | An error due to the Firebase API not being enabled in the Console. | -| ERROR | "error" | A generic error occurred. | -| FETCH\_ERROR | "fetch-error" | An error occurred while performing a fetch. | -| INVALID\_CONTENT | "invalid-content" | An error associated with a Content object. | -| INVALID\_SCHEMA | "invalid-schema" | An error due to invalid Schema input. | -| NO\_API\_KEY | "no-api-key" | An error occurred due to a missing Firebase API key. | -| NO\_APP\_ID | "no-app-id" | An error occured due to a missing Firebase app ID. | -| NO\_MODEL | "no-model" | An error occurred due to a model name not being specified during initialization. | -| NO\_PROJECT\_ID | "no-project-id" | An error occurred due to a missing project ID. | -| PARSE\_FAILED | "parse-failed" | An error occurred while parsing. | -| REQUEST\_ERROR | "request-error" | An error occurred in a request. | -| RESPONSE\_ERROR | "response-error" | An error occurred in a response. | - From f69061167940a71d8a1de2116bc4516d8b145194 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Thu, 22 May 2025 11:27:53 -0400 Subject: [PATCH 4/7] Update changeset to use `@firebase/ai` --- .changeset/long-keys-watch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/long-keys-watch.md b/.changeset/long-keys-watch.md index 7cc4d582ff1..fb13ed74987 100644 --- a/.changeset/long-keys-watch.md +++ b/.changeset/long-keys-watch.md @@ -1,6 +1,6 @@ --- 'firebase': minor -'@firebase/vertexai': minor +'@firebase/ai': minor --- Add support for `AbortSignal`, allowing requests to be aborted. From 821e58093f450c3db7442973addbee545a29d2de Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Thu, 22 May 2025 11:28:48 -0400 Subject: [PATCH 5/7] remove ghost changeset --- .changeset/dirty-crews-cross.md | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 .changeset/dirty-crews-cross.md diff --git a/.changeset/dirty-crews-cross.md b/.changeset/dirty-crews-cross.md deleted file mode 100644 index 08a962670f0..00000000000 --- a/.changeset/dirty-crews-cross.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"@firebase/auth": patch -"@firebase/database": patch -"@firebase/firestore": patch -"@firebase/functions": patch -"@firebase/storage": patch ---- - -Revert "Fixed scroll behavior (#9043)" From 15239fb16874c43ae7994d94d1f578956e0ff6fb Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Thu, 22 May 2025 11:33:10 -0400 Subject: [PATCH 6/7] update example in docs --- docs-devsite/ai.singlerequestoptions.md | 4 ++++ packages/ai/src/types/requests.ts | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/docs-devsite/ai.singlerequestoptions.md b/docs-devsite/ai.singlerequestoptions.md index 315c99436a4..6e7e1f4bf12 100644 --- a/docs-devsite/ai.singlerequestoptions.md +++ b/docs-devsite/ai.singlerequestoptions.md @@ -49,6 +49,10 @@ const controller = new AbortController(); const model = getGenerativeModel({ // ... }); +model.generateContent( + "Write a story about a magic backpack.", + { signal: controller.signal } +); // To cancel request: controller.abort(); diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index 3f6c61add09..0664adf6ecf 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -189,6 +189,10 @@ export interface SingleRequestOptions extends RequestOptions { * const model = getGenerativeModel({ * // ... * }); + * model.generateContent( + * "Write a story about a magic backpack.", + * { signal: controller.signal } + * ); * * // To cancel request: * controller.abort(); From 0096b9a07ddf79f343cc652c580ee33b41546912 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Tue, 27 May 2025 10:47:18 -0400 Subject: [PATCH 7/7] Docs review --- docs-devsite/ai.md | 2 +- docs-devsite/ai.singlerequestoptions.md | 6 +++--- packages/ai/src/types/requests.ts | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index fca050e676a..46b8ae8493a 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -117,7 +117,7 @@ The Firebase AI Web SDK. | [SchemaRequest](./ai.schemarequest.md#schemarequest_interface) | Final format for [Schema](./ai.schema.md#schema_class) params passed to backend requests. | | [SchemaShared](./ai.schemashared.md#schemashared_interface) | Basic [Schema](./ai.schema.md#schema_class) properties shared across several Schema-related types. | | [Segment](./ai.segment.md#segment_interface) | | -| [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | Options that can be provided per-request. Extends the base [RequestOptions](./ai.requestoptions.md#requestoptions_interface) (like timeout and baseUrl) with request-specific controls like cancellation via AbortSignal.Options specified here will override any default [RequestOptions](./ai.requestoptions.md#requestoptions_interface) configured on a model (e.g. [GenerativeModel](./ai.generativemodel.md#generativemodel_class)). | +| [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | Options that can be provided per-request. Extends the base [RequestOptions](./ai.requestoptions.md#requestoptions_interface) (like timeout and baseUrl) with request-specific controls like cancellation via AbortSignal.Options specified here will override any default [RequestOptions](./ai.requestoptions.md#requestoptions_interface) configured on a model (for example, [GenerativeModel](./ai.generativemodel.md#generativemodel_class)). | | [StartChatParams](./ai.startchatparams.md#startchatparams_interface) | Params for [GenerativeModel.startChat()](./ai.generativemodel.md#generativemodelstartchat). | | [TextPart](./ai.textpart.md#textpart_interface) | Content part interface if the part represents a text string. | | [ToolConfig](./ai.toolconfig.md#toolconfig_interface) | Tool config. This config is shared for all tools provided in the request. | diff --git a/docs-devsite/ai.singlerequestoptions.md b/docs-devsite/ai.singlerequestoptions.md index 6e7e1f4bf12..a55bd3c2f3c 100644 --- a/docs-devsite/ai.singlerequestoptions.md +++ b/docs-devsite/ai.singlerequestoptions.md @@ -12,7 +12,7 @@ https://github.com/firebase/firebase-js-sdk # SingleRequestOptions interface Options that can be provided per-request. Extends the base [RequestOptions](./ai.requestoptions.md#requestoptions_interface) (like `timeout` and `baseUrl`) with request-specific controls like cancellation via `AbortSignal`. -Options specified here will override any default [RequestOptions](./ai.requestoptions.md#requestoptions_interface) configured on a model (e.g. [GenerativeModel](./ai.generativemodel.md#generativemodel_class)). +Options specified here will override any default [RequestOptions](./ai.requestoptions.md#requestoptions_interface) configured on a model (for example, [GenerativeModel](./ai.generativemodel.md#generativemodel_class)). Signature: @@ -25,7 +25,7 @@ export interface SingleRequestOptions extends RequestOptions | Property | Type | Description | | --- | --- | --- | -| [signal](./ai.singlerequestoptions.md#singlerequestoptionssignal) | AbortSignal | An AbortSignal instance that allows cancelling ongoing requests (like generateContent or generateImages).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.Note that this will not cancel the request in the backend, so billing will still be applied despite cancellation. | +| [signal](./ai.singlerequestoptions.md#singlerequestoptionssignal) | AbortSignal | An AbortSignal instance that allows cancelling ongoing requests (like generateContent or generateImages).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.Note that this will not cancel the request in the backend, so any applicable billing charges will still be applied despite cancellation. | ## SingleRequestOptions.signal @@ -33,7 +33,7 @@ An `AbortSignal` instance that allows cancelling ongoing requests (like `generat 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. -Note that this will not cancel the request in the backend, so billing will still be applied despite cancellation. +Note that this will not cancel the request in the backend, so any applicable billing charges will still be applied despite cancellation. Signature: diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index 0664adf6ecf..a22508a1d72 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -167,7 +167,7 @@ export interface RequestOptions { * with request-specific controls like cancellation via `AbortSignal`. * * Options specified here will override any default {@link RequestOptions} - * configured on a model (e.g. {@link GenerativeModel}). + * configured on a model (for example, {@link GenerativeModel}). * * @public */ @@ -180,8 +180,8 @@ export interface SingleRequestOptions extends RequestOptions { * will attempt to cancel the underlying HTTP request. An `AbortError` 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. + * Note that this will not cancel the request in the backend, so any applicable billing charges + * will still be applied despite cancellation. * * @example * ```javascript