@firebase/ai 2.4.0-canary.261508183 → 2.4.0-canary.c8263c471

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,7 +14,11 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */
17
- import { GenerateContentRequest, ChromeAdapter } from '../types';
17
+ import { GenerateContentRequest, ChromeAdapter, InferenceSource } from '../types';
18
+ interface CallResult<Response> {
19
+ response: Response;
20
+ inferenceSource: InferenceSource;
21
+ }
18
22
  /**
19
23
  * Dispatches a request to the appropriate backend (on-device or in-cloud)
20
24
  * based on the inference mode.
@@ -25,4 +29,5 @@ import { GenerateContentRequest, ChromeAdapter } from '../types';
25
29
  * @param inCloudCall - The function to call for in-cloud inference.
26
30
  * @returns The response from the backend.
27
31
  */
28
- export declare function callCloudOrDevice<Response>(request: GenerateContentRequest, chromeAdapter: ChromeAdapter | undefined, onDeviceCall: () => Promise<Response>, inCloudCall: () => Promise<Response>): Promise<Response>;
32
+ export declare function callCloudOrDevice<Response>(request: GenerateContentRequest, chromeAdapter: ChromeAdapter | undefined, onDeviceCall: () => Promise<Response>, inCloudCall: () => Promise<Response>): Promise<CallResult<Response>>;
33
+ export {};
@@ -14,12 +14,12 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */
17
- import { EnhancedGenerateContentResponse, FunctionCall, GenerateContentResponse, ImagenGCSImage, ImagenInlineImage, InlineDataPart, Part } from '../types';
17
+ import { EnhancedGenerateContentResponse, FunctionCall, GenerateContentResponse, ImagenGCSImage, ImagenInlineImage, InlineDataPart, Part, InferenceSource } from '../types';
18
18
  /**
19
19
  * Creates an EnhancedGenerateContentResponse object that has helper functions and
20
20
  * other modifications that improve usability.
21
21
  */
22
- export declare function createEnhancedContentResponse(response: GenerateContentResponse): EnhancedGenerateContentResponse;
22
+ export declare function createEnhancedContentResponse(response: GenerateContentResponse, inferenceSource?: InferenceSource): EnhancedGenerateContentResponse;
23
23
  /**
24
24
  * Adds convenience helper methods to a response object, including stream
25
25
  * chunks (as long as each chunk is a complete GenerateContentResponse JSON).
@@ -16,6 +16,7 @@
16
16
  */
17
17
  import { GenerateContentResponse, GenerateContentStreamResult } from '../types';
18
18
  import { ApiSettings } from '../types/internal';
19
+ import { InferenceSource } from '../public-types';
19
20
  /**
20
21
  * Process a response.body stream from the backend and return an
21
22
  * iterator that provides one complete GenerateContentResponse at a time
@@ -24,7 +25,7 @@ import { ApiSettings } from '../types/internal';
24
25
  *
25
26
  * @param response - Response from a fetch call
26
27
  */
27
- export declare function processStream(response: Response, apiSettings: ApiSettings): GenerateContentStreamResult;
28
+ export declare function processStream(response: Response, apiSettings: ApiSettings, inferenceSource?: InferenceSource): GenerateContentStreamResult;
28
29
  /**
29
30
  * Reads a raw stream from the fetch response and join incomplete
30
31
  * chunks, returning a new stream that provides a single complete
@@ -349,6 +349,21 @@ export declare const InferenceMode: {
349
349
  * @beta
350
350
  */
351
351
  export type InferenceMode = (typeof InferenceMode)[keyof typeof InferenceMode];
352
+ /**
353
+ * Indicates whether inference happened on-device or in-cloud.
354
+ *
355
+ * @beta
356
+ */
357
+ export declare const InferenceSource: {
358
+ readonly ON_DEVICE: "on_device";
359
+ readonly IN_CLOUD: "in_cloud";
360
+ };
361
+ /**
362
+ * Indicates whether inference happened on-device or in-cloud.
363
+ *
364
+ * @beta
365
+ */
366
+ export type InferenceSource = (typeof InferenceSource)[keyof typeof InferenceSource];
352
367
  /**
353
368
  * Represents the result of the code execution.
354
369
  *
@@ -15,7 +15,7 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  import { Content, FunctionCall, InlineDataPart } from './content';
18
- import { BlockReason, FinishReason, HarmCategory, HarmProbability, HarmSeverity, Modality } from './enums';
18
+ import { BlockReason, FinishReason, HarmCategory, HarmProbability, HarmSeverity, InferenceSource, Modality } from './enums';
19
19
  /**
20
20
  * Result object returned from {@link GenerativeModel.generateContent} call.
21
21
  *
@@ -76,6 +76,12 @@ export interface EnhancedGenerateContentResponse extends GenerateContentResponse
76
76
  * set to `true`.
77
77
  */
78
78
  thoughtSummary: () => string | undefined;
79
+ /**
80
+ * Indicates whether inference happened on-device or in-cloud.
81
+ *
82
+ * @beta
83
+ */
84
+ inferenceSource?: InferenceSource;
79
85
  }
80
86
  /**
81
87
  * Individual response from {@link GenerativeModel.generateContent} and
package/dist/index.cjs.js CHANGED
@@ -8,7 +8,7 @@ var util = require('@firebase/util');
8
8
  var logger$1 = require('@firebase/logger');
9
9
 
10
10
  var name = "@firebase/ai";
11
- var version = "2.4.0-canary.261508183";
11
+ var version = "2.4.0-canary.c8263c471";
12
12
 
13
13
  /**
14
14
  * @license
@@ -383,6 +383,15 @@ const InferenceMode = {
383
383
  'ONLY_IN_CLOUD': 'only_in_cloud',
384
384
  'PREFER_IN_CLOUD': 'prefer_in_cloud'
385
385
  };
386
+ /**
387
+ * Indicates whether inference happened on-device or in-cloud.
388
+ *
389
+ * @beta
390
+ */
391
+ const InferenceSource = {
392
+ 'ON_DEVICE': 'on_device',
393
+ 'IN_CLOUD': 'in_cloud'
394
+ };
386
395
  /**
387
396
  * Represents the result of the code execution.
388
397
  *
@@ -1596,7 +1605,7 @@ function hasValidCandidates(response) {
1596
1605
  * Creates an EnhancedGenerateContentResponse object that has helper functions and
1597
1606
  * other modifications that improve usability.
1598
1607
  */
1599
- function createEnhancedContentResponse(response) {
1608
+ function createEnhancedContentResponse(response, inferenceSource = InferenceSource.IN_CLOUD) {
1600
1609
  /**
1601
1610
  * The Vertex AI backend omits default values.
1602
1611
  * This causes the `index` property to be omitted from the first candidate in the
@@ -1607,6 +1616,7 @@ function createEnhancedContentResponse(response) {
1607
1616
  response.candidates[0].index = 0;
1608
1617
  }
1609
1618
  const responseWithHelpers = addHelpers(response);
1619
+ responseWithHelpers.inferenceSource = inferenceSource;
1610
1620
  return responseWithHelpers;
1611
1621
  }
1612
1622
  /**
@@ -1983,16 +1993,16 @@ const responseLineRE = /^data\: (.*)(?:\n\n|\r\r|\r\n\r\n)/;
1983
1993
  *
1984
1994
  * @param response - Response from a fetch call
1985
1995
  */
1986
- function processStream(response, apiSettings) {
1996
+ function processStream(response, apiSettings, inferenceSource) {
1987
1997
  const inputStream = response.body.pipeThrough(new TextDecoderStream('utf8', { fatal: true }));
1988
1998
  const responseStream = getResponseStream(inputStream);
1989
1999
  const [stream1, stream2] = responseStream.tee();
1990
2000
  return {
1991
- stream: generateResponseSequence(stream1, apiSettings),
1992
- response: getResponsePromise(stream2, apiSettings)
2001
+ stream: generateResponseSequence(stream1, apiSettings, inferenceSource),
2002
+ response: getResponsePromise(stream2, apiSettings, inferenceSource)
1993
2003
  };
1994
2004
  }
1995
- async function getResponsePromise(stream, apiSettings) {
2005
+ async function getResponsePromise(stream, apiSettings, inferenceSource) {
1996
2006
  const allResponses = [];
1997
2007
  const reader = stream.getReader();
1998
2008
  while (true) {
@@ -2002,12 +2012,12 @@ async function getResponsePromise(stream, apiSettings) {
2002
2012
  if (apiSettings.backend.backendType === BackendType.GOOGLE_AI) {
2003
2013
  generateContentResponse = mapGenerateContentResponse(generateContentResponse);
2004
2014
  }
2005
- return createEnhancedContentResponse(generateContentResponse);
2015
+ return createEnhancedContentResponse(generateContentResponse, inferenceSource);
2006
2016
  }
2007
2017
  allResponses.push(value);
2008
2018
  }
2009
2019
  }
2010
- async function* generateResponseSequence(stream, apiSettings) {
2020
+ async function* generateResponseSequence(stream, apiSettings, inferenceSource) {
2011
2021
  const reader = stream.getReader();
2012
2022
  while (true) {
2013
2023
  const { value, done } = await reader.read();
@@ -2016,10 +2026,10 @@ async function* generateResponseSequence(stream, apiSettings) {
2016
2026
  }
2017
2027
  let enhancedResponse;
2018
2028
  if (apiSettings.backend.backendType === BackendType.GOOGLE_AI) {
2019
- enhancedResponse = createEnhancedContentResponse(mapGenerateContentResponse(value));
2029
+ enhancedResponse = createEnhancedContentResponse(mapGenerateContentResponse(value), inferenceSource);
2020
2030
  }
2021
2031
  else {
2022
- enhancedResponse = createEnhancedContentResponse(value);
2032
+ enhancedResponse = createEnhancedContentResponse(value, inferenceSource);
2023
2033
  }
2024
2034
  const firstCandidate = enhancedResponse.candidates?.[0];
2025
2035
  // Don't yield a response with no useful data for the developer.
@@ -2189,31 +2199,52 @@ const errorsCausingFallback = [
2189
2199
  */
2190
2200
  async function callCloudOrDevice(request, chromeAdapter, onDeviceCall, inCloudCall) {
2191
2201
  if (!chromeAdapter) {
2192
- return inCloudCall();
2202
+ return {
2203
+ response: await inCloudCall(),
2204
+ inferenceSource: InferenceSource.IN_CLOUD
2205
+ };
2193
2206
  }
2194
2207
  switch (chromeAdapter.mode) {
2195
2208
  case InferenceMode.ONLY_ON_DEVICE:
2196
2209
  if (await chromeAdapter.isAvailable(request)) {
2197
- return onDeviceCall();
2210
+ return {
2211
+ response: await onDeviceCall(),
2212
+ inferenceSource: InferenceSource.ON_DEVICE
2213
+ };
2198
2214
  }
2199
2215
  throw new AIError(AIErrorCode.UNSUPPORTED, 'Inference mode is ONLY_ON_DEVICE, but an on-device model is not available.');
2200
2216
  case InferenceMode.ONLY_IN_CLOUD:
2201
- return inCloudCall();
2217
+ return {
2218
+ response: await inCloudCall(),
2219
+ inferenceSource: InferenceSource.IN_CLOUD
2220
+ };
2202
2221
  case InferenceMode.PREFER_IN_CLOUD:
2203
2222
  try {
2204
- return await inCloudCall();
2223
+ return {
2224
+ response: await inCloudCall(),
2225
+ inferenceSource: InferenceSource.IN_CLOUD
2226
+ };
2205
2227
  }
2206
2228
  catch (e) {
2207
2229
  if (e instanceof AIError && errorsCausingFallback.includes(e.code)) {
2208
- return onDeviceCall();
2230
+ return {
2231
+ response: await onDeviceCall(),
2232
+ inferenceSource: InferenceSource.ON_DEVICE
2233
+ };
2209
2234
  }
2210
2235
  throw e;
2211
2236
  }
2212
2237
  case InferenceMode.PREFER_ON_DEVICE:
2213
2238
  if (await chromeAdapter.isAvailable(request)) {
2214
- return onDeviceCall();
2239
+ return {
2240
+ response: await onDeviceCall(),
2241
+ inferenceSource: InferenceSource.ON_DEVICE
2242
+ };
2215
2243
  }
2216
- return inCloudCall();
2244
+ return {
2245
+ response: await inCloudCall(),
2246
+ inferenceSource: InferenceSource.IN_CLOUD
2247
+ };
2217
2248
  default:
2218
2249
  throw new AIError(AIErrorCode.ERROR, `Unexpected infererence mode: ${chromeAdapter.mode}`);
2219
2250
  }
@@ -2243,8 +2274,8 @@ async function generateContentStreamOnCloud(apiSettings, model, params, requestO
2243
2274
  /* stream */ true, JSON.stringify(params), requestOptions);
2244
2275
  }
2245
2276
  async function generateContentStream(apiSettings, model, params, chromeAdapter, requestOptions) {
2246
- const response = await callCloudOrDevice(params, chromeAdapter, () => chromeAdapter.generateContentStream(params), () => generateContentStreamOnCloud(apiSettings, model, params, requestOptions));
2247
- return processStream(response, apiSettings); // TODO: Map streaming responses
2277
+ const callResult = await callCloudOrDevice(params, chromeAdapter, () => chromeAdapter.generateContentStream(params), () => generateContentStreamOnCloud(apiSettings, model, params, requestOptions));
2278
+ return processStream(callResult.response, apiSettings); // TODO: Map streaming responses
2248
2279
  }
2249
2280
  async function generateContentOnCloud(apiSettings, model, params, requestOptions) {
2250
2281
  if (apiSettings.backend.backendType === BackendType.GOOGLE_AI) {
@@ -2254,9 +2285,9 @@ async function generateContentOnCloud(apiSettings, model, params, requestOptions
2254
2285
  /* stream */ false, JSON.stringify(params), requestOptions);
2255
2286
  }
2256
2287
  async function generateContent(apiSettings, model, params, chromeAdapter, requestOptions) {
2257
- const response = await callCloudOrDevice(params, chromeAdapter, () => chromeAdapter.generateContent(params), () => generateContentOnCloud(apiSettings, model, params, requestOptions));
2258
- const generateContentResponse = await processGenerateContentResponse(response, apiSettings);
2259
- const enhancedResponse = createEnhancedContentResponse(generateContentResponse);
2288
+ const callResult = await callCloudOrDevice(params, chromeAdapter, () => chromeAdapter.generateContent(params), () => generateContentOnCloud(apiSettings, model, params, requestOptions));
2289
+ const generateContentResponse = await processGenerateContentResponse(callResult.response, apiSettings);
2290
+ const enhancedResponse = createEnhancedContentResponse(generateContentResponse, callResult.inferenceSource);
2260
2291
  return {
2261
2292
  response: enhancedResponse
2262
2293
  };
@@ -4138,6 +4169,7 @@ exports.ImagenModel = ImagenModel;
4138
4169
  exports.ImagenPersonFilterLevel = ImagenPersonFilterLevel;
4139
4170
  exports.ImagenSafetyFilterLevel = ImagenSafetyFilterLevel;
4140
4171
  exports.InferenceMode = InferenceMode;
4172
+ exports.InferenceSource = InferenceSource;
4141
4173
  exports.IntegerSchema = IntegerSchema;
4142
4174
  exports.Language = Language;
4143
4175
  exports.LiveGenerativeModel = LiveGenerativeModel;