15
15
* limitations under the License.
16
16
*/
17
17
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' ;
20
20
import { ApiSettings } from '../types/internal' ;
21
21
import {
22
22
DEFAULT_API_VERSION ,
@@ -26,11 +26,13 @@ import {
26
26
PACKAGE_VERSION ,
27
27
} from '../constants' ;
28
28
import { logger } from '../logger' ;
29
+ import { GoogleAIBackend , VertexAIBackend } from '../backend' ;
29
30
30
31
export enum Task {
31
32
GENERATE_CONTENT = 'generateContent' ,
32
33
STREAM_GENERATE_CONTENT = 'streamGenerateContent' ,
33
34
COUNT_TOKENS = 'countTokens' ,
35
+ PREDICT = 'predict' ,
34
36
}
35
37
36
38
export class RequestUrl {
@@ -58,29 +60,40 @@ export class RequestUrl {
58
60
}
59
61
return emulatorUrl ;
60
62
}
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
+ }
61
68
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
+ ) ;
71
87
}
72
- return url ;
73
88
}
74
89
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 ;
84
97
}
85
98
}
86
99
@@ -99,6 +112,9 @@ export async function getHeaders(url: RequestUrl): Promise<Headers> {
99
112
headers . append ( 'Content-Type' , 'application/json' ) ;
100
113
headers . append ( 'x-goog-api-client' , getClientHeaders ( ) ) ;
101
114
headers . append ( 'x-goog-api-key' , url . apiSettings . apiKey ) ;
115
+ if ( url . apiSettings . automaticDataCollectionEnabled ) {
116
+ headers . append ( 'X-Firebase-Appid' , url . apiSettings . appId ) ;
117
+ }
102
118
if ( url . apiSettings . getAppCheckToken ) {
103
119
let appCheckToken ;
104
120
@@ -154,6 +170,7 @@ export async function makeRequest(
154
170
let fetchTimeoutId : string | number | NodeJS . Timeout | undefined ;
155
171
try {
156
172
const request = await constructRequest ( model , task , apiSettings , stream , body , requestOptions ) ;
173
+ // Timeout is 180s by default
157
174
const timeoutMillis =
158
175
requestOptions ?. timeout != null && requestOptions . timeout >= 0
159
176
? requestOptions . timeout
@@ -192,9 +209,9 @@ export async function makeRequest(
192
209
) ,
193
210
)
194
211
) {
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 ` +
198
215
`API ('firebasevertexai.googleapis.com') to be enabled in your ` +
199
216
`Firebase project. Enable this API by visiting the Firebase Console ` +
200
217
`at https://console.firebase.google.com/project/${ url . apiSettings . project } /genai/ ` +
@@ -208,8 +225,8 @@ export async function makeRequest(
208
225
} ,
209
226
) ;
210
227
}
211
- throw new VertexAIError (
212
- VertexAIErrorCode . FETCH_ERROR ,
228
+ throw new AIError (
229
+ AIErrorCode . FETCH_ERROR ,
213
230
`Error fetching from ${ url } : [${ response . status } ${ response . statusText } ] ${ message } ` ,
214
231
{
215
232
status : response . status ,
@@ -221,14 +238,11 @@ export async function makeRequest(
221
238
} catch ( e ) {
222
239
let err = e as Error ;
223
240
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 &&
226
243
e instanceof Error
227
244
) {
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 } ` ) ;
232
246
err . stack = e . stack ;
233
247
}
234
248
0 commit comments