Skip to content

Commit 0077c64

Browse files
russellwheatleymikehardy
authored andcommitted
request.ts
1 parent 1921c7f commit 0077c64

File tree

1 file changed

+46
-32
lines changed

1 file changed

+46
-32
lines changed

packages/ai/lib/requests/request.ts

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
* limitations under the License.
1616
*/
1717
import { Platform } from 'react-native';
18-
import { ErrorDetails, RequestOptions, VertexAIErrorCode } from '../types';
19-
import { VertexAIError } from '../errors';
18+
import { AIErrorCode, ErrorDetails, RequestOptions } from '../types';
19+
import { AIError } from '../errors';
2020
import { ApiSettings } from '../types/internal';
2121
import {
2222
DEFAULT_API_VERSION,
@@ -26,11 +26,13 @@ import {
2626
PACKAGE_VERSION,
2727
} from '../constants';
2828
import { logger } from '../logger';
29+
import { GoogleAIBackend, VertexAIBackend } from '../backend';
2930

3031
export enum Task {
3132
GENERATE_CONTENT = 'generateContent',
3233
STREAM_GENERATE_CONTENT = 'streamGenerateContent',
3334
COUNT_TOKENS = 'countTokens',
35+
PREDICT = 'predict',
3436
}
3537

3638
export class RequestUrl {
@@ -58,29 +60,40 @@ export class RequestUrl {
5860
}
5961
return emulatorUrl;
6062
}
63+
const url = new URL(this.baseUrl); // Throws if the URL is invalid
64+
url.pathname = `/${this.apiVersion}/${this.modelPath}:${this.task}`;
65+
url.search = this.queryParams.toString();
66+
return url.toString();
67+
}
6168

62-
const apiVersion = DEFAULT_API_VERSION;
63-
const baseUrl = this.requestOptions?.baseUrl || DEFAULT_BASE_URL;
64-
let url = `${baseUrl}/${apiVersion}`;
65-
url += `/projects/${this.apiSettings.project}`;
66-
url += `/locations/${this.apiSettings.location}`;
67-
url += `/${this.model}`;
68-
url += `:${this.task}`;
69-
if (this.stream) {
70-
url += '?alt=sse';
69+
private get baseUrl(): string {
70+
return this.requestOptions?.baseUrl || DEFAULT_BASE_URL;
71+
}
72+
73+
private get apiVersion(): string {
74+
return DEFAULT_API_VERSION; // TODO: allow user-set options if that feature becomes available
75+
}
76+
77+
private get modelPath(): string {
78+
if (this.apiSettings.backend instanceof GoogleAIBackend) {
79+
return `projects/${this.apiSettings.project}/${this.model}`;
80+
} else if (this.apiSettings.backend instanceof VertexAIBackend) {
81+
return `projects/${this.apiSettings.project}/locations/${this.apiSettings.backend.location}/${this.model}`;
82+
} else {
83+
throw new AIError(
84+
AIErrorCode.ERROR,
85+
`Invalid backend: ${JSON.stringify(this.apiSettings.backend)}`,
86+
);
7187
}
72-
return url;
7388
}
7489

75-
/**
76-
* If the model needs to be passed to the backend, it needs to
77-
* include project and location path.
78-
*/
79-
get fullModelString(): string {
80-
let modelString = `projects/${this.apiSettings.project}`;
81-
modelString += `/locations/${this.apiSettings.location}`;
82-
modelString += `/${this.model}`;
83-
return modelString;
90+
private get queryParams(): URLSearchParams {
91+
const params = new URLSearchParams();
92+
if (this.stream) {
93+
params.set('alt', 'sse');
94+
}
95+
96+
return params;
8497
}
8598
}
8699

@@ -99,6 +112,9 @@ export async function getHeaders(url: RequestUrl): Promise<Headers> {
99112
headers.append('Content-Type', 'application/json');
100113
headers.append('x-goog-api-client', getClientHeaders());
101114
headers.append('x-goog-api-key', url.apiSettings.apiKey);
115+
if (url.apiSettings.automaticDataCollectionEnabled) {
116+
headers.append('X-Firebase-Appid', url.apiSettings.appId);
117+
}
102118
if (url.apiSettings.getAppCheckToken) {
103119
let appCheckToken;
104120

@@ -154,6 +170,7 @@ export async function makeRequest(
154170
let fetchTimeoutId: string | number | NodeJS.Timeout | undefined;
155171
try {
156172
const request = await constructRequest(model, task, apiSettings, stream, body, requestOptions);
173+
// Timeout is 180s by default
157174
const timeoutMillis =
158175
requestOptions?.timeout != null && requestOptions.timeout >= 0
159176
? requestOptions.timeout
@@ -192,9 +209,9 @@ export async function makeRequest(
192209
),
193210
)
194211
) {
195-
throw new VertexAIError(
196-
VertexAIErrorCode.API_NOT_ENABLED,
197-
`The Vertex AI in Firebase SDK requires the Vertex AI in Firebase ` +
212+
throw new AIError(
213+
AIErrorCode.API_NOT_ENABLED,
214+
`The Firebase AI SDK requires the Firebase AI ` +
198215
`API ('firebasevertexai.googleapis.com') to be enabled in your ` +
199216
`Firebase project. Enable this API by visiting the Firebase Console ` +
200217
`at https://console.firebase.google.com/project/${url.apiSettings.project}/genai/ ` +
@@ -208,8 +225,8 @@ export async function makeRequest(
208225
},
209226
);
210227
}
211-
throw new VertexAIError(
212-
VertexAIErrorCode.FETCH_ERROR,
228+
throw new AIError(
229+
AIErrorCode.FETCH_ERROR,
213230
`Error fetching from ${url}: [${response.status} ${response.statusText}] ${message}`,
214231
{
215232
status: response.status,
@@ -221,14 +238,11 @@ export async function makeRequest(
221238
} catch (e) {
222239
let err = e as Error;
223240
if (
224-
(e as VertexAIError).code !== VertexAIErrorCode.FETCH_ERROR &&
225-
(e as VertexAIError).code !== VertexAIErrorCode.API_NOT_ENABLED &&
241+
(e as AIError).code !== AIErrorCode.FETCH_ERROR &&
242+
(e as AIError).code !== AIErrorCode.API_NOT_ENABLED &&
226243
e instanceof Error
227244
) {
228-
err = new VertexAIError(
229-
VertexAIErrorCode.ERROR,
230-
`Error fetching from ${url.toString()}: ${e.message}`,
231-
);
245+
err = new AIError(AIErrorCode.ERROR, `Error fetching from ${url.toString()}: ${e.message}`);
232246
err.stack = e.stack;
233247
}
234248

0 commit comments

Comments
 (0)