@langchain/google-common 0.0.9 → 0.0.11

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.
@@ -15,10 +15,73 @@ const auth_js_1 = require("./auth.cjs");
15
15
  const failed_handler_js_1 = require("./utils/failed_handler.cjs");
16
16
  const zod_to_gemini_parameters_js_1 = require("./utils/zod_to_gemini_parameters.cjs");
17
17
  class ChatConnection extends connection_js_1.AbstractGoogleLLMConnection {
18
+ constructor(fields, caller, client, streaming) {
19
+ super(fields, caller, client, streaming);
20
+ Object.defineProperty(this, "convertSystemMessageToHumanContent", {
21
+ enumerable: true,
22
+ configurable: true,
23
+ writable: true,
24
+ value: void 0
25
+ });
26
+ this.convertSystemMessageToHumanContent =
27
+ fields?.convertSystemMessageToHumanContent;
28
+ }
29
+ get useSystemInstruction() {
30
+ return typeof this.convertSystemMessageToHumanContent === "boolean"
31
+ ? !this.convertSystemMessageToHumanContent
32
+ : this.computeUseSystemInstruction;
33
+ }
34
+ get computeUseSystemInstruction() {
35
+ // This works on models from April 2024 and later
36
+ // Vertex AI: gemini-1.5-pro and gemini-1.0-002 and later
37
+ // AI Studio: gemini-1.5-pro-latest
38
+ if (this.modelFamily === "palm") {
39
+ return false;
40
+ }
41
+ else if (this.modelName === "gemini-1.0-pro-001") {
42
+ return false;
43
+ }
44
+ else if (this.modelName.startsWith("gemini-pro-vision")) {
45
+ return false;
46
+ }
47
+ else if (this.modelName.startsWith("gemini-1.0-pro-vision")) {
48
+ return false;
49
+ }
50
+ else if (this.modelName === "gemini-pro" && this.platform === "gai") {
51
+ // on AI Studio gemini-pro is still pointing at gemini-1.0-pro-001
52
+ return false;
53
+ }
54
+ return true;
55
+ }
18
56
  formatContents(input, _parameters) {
19
57
  return input
20
- .map((msg, i) => (0, gemini_js_1.baseMessageToContent)(msg, input[i - 1]))
21
- .reduce((acc, cur) => [...acc, ...cur]);
58
+ .map((msg, i) => (0, gemini_js_1.baseMessageToContent)(msg, input[i - 1], this.useSystemInstruction))
59
+ .reduce((acc, cur) => {
60
+ // Filter out the system content, since those don't belong
61
+ // in the actual content.
62
+ const hasNoSystem = cur.every((content) => content.role !== "system");
63
+ return hasNoSystem ? [...acc, ...cur] : acc;
64
+ }, []);
65
+ }
66
+ formatSystemInstruction(input, _parameters) {
67
+ if (!this.useSystemInstruction) {
68
+ return {};
69
+ }
70
+ let ret = {};
71
+ input.forEach((message, index) => {
72
+ if (message._getType() === "system") {
73
+ // For system types, we only want it if it is the first message,
74
+ // if it appears anywhere else, it should be an error.
75
+ if (index === 0) {
76
+ // eslint-disable-next-line prefer-destructuring
77
+ ret = (0, gemini_js_1.baseMessageToContent)(message, undefined, true)[0];
78
+ }
79
+ else {
80
+ throw new Error("System messages are only permitted as the first passed message.");
81
+ }
82
+ }
83
+ });
84
+ return ret;
22
85
  }
23
86
  }
24
87
  function convertToGeminiTools(structuredTools) {
@@ -54,11 +117,12 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
54
117
  writable: true,
55
118
  value: true
56
119
  });
120
+ // Set based on modelName
57
121
  Object.defineProperty(this, "model", {
58
122
  enumerable: true,
59
123
  configurable: true,
60
124
  writable: true,
61
- value: "gemini-pro"
125
+ value: void 0
62
126
  });
63
127
  Object.defineProperty(this, "modelName", {
64
128
  enumerable: true,
@@ -102,6 +166,13 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
102
166
  writable: true,
103
167
  value: []
104
168
  });
169
+ // May intentionally be undefined, meaning to compute this.
170
+ Object.defineProperty(this, "convertSystemMessageToHumanContent", {
171
+ enumerable: true,
172
+ configurable: true,
173
+ writable: true,
174
+ value: void 0
175
+ });
105
176
  Object.defineProperty(this, "safetyHandler", {
106
177
  enumerable: true,
107
178
  configurable: true,
@@ -6,13 +6,19 @@ import { AIMessageChunk } from "@langchain/core/messages";
6
6
  import { BaseLanguageModelInput, StructuredOutputMethodOptions } from "@langchain/core/language_models/base";
7
7
  import type { z } from "zod";
8
8
  import { Runnable, RunnableInterface } from "@langchain/core/runnables";
9
+ import { AsyncCaller } from "@langchain/core/utils/async_caller";
9
10
  import { StructuredToolInterface } from "@langchain/core/tools";
10
11
  import { GoogleAIBaseLLMInput, GoogleAIModelParams, GoogleAISafetySetting, GoogleConnectionParams, GooglePlatformType, GeminiContent, GoogleAIBaseLanguageModelCallOptions } from "./types.js";
11
12
  import { AbstractGoogleLLMConnection } from "./connection.js";
12
13
  import { GoogleAbstractedClient } from "./auth.js";
13
14
  import type { GoogleBaseLLMInput, GoogleAISafetyHandler, GoogleAISafetyParams } from "./types.js";
14
15
  declare class ChatConnection<AuthOptions> extends AbstractGoogleLLMConnection<BaseMessage[], AuthOptions> {
16
+ convertSystemMessageToHumanContent: boolean | undefined;
17
+ constructor(fields: GoogleAIBaseLLMInput<AuthOptions> | undefined, caller: AsyncCaller, client: GoogleAbstractedClient, streaming: boolean);
18
+ get useSystemInstruction(): boolean;
19
+ get computeUseSystemInstruction(): boolean;
15
20
  formatContents(input: BaseMessage[], _parameters: GoogleAIModelParams): GeminiContent[];
21
+ formatSystemInstruction(input: BaseMessage[], _parameters: GoogleAIModelParams): GeminiContent;
16
22
  }
17
23
  /**
18
24
  * Input to chat model class.
@@ -33,6 +39,7 @@ export declare abstract class ChatGoogleBase<AuthOptions> extends BaseChatModel<
33
39
  topK: number;
34
40
  stopSequences: string[];
35
41
  safetySettings: GoogleAISafetySetting[];
42
+ convertSystemMessageToHumanContent: boolean | undefined;
36
43
  safetyHandler: GoogleAISafetyHandler;
37
44
  protected connection: ChatConnection<AuthOptions>;
38
45
  protected streamedConnection: ChatConnection<AuthOptions>;
@@ -12,10 +12,73 @@ import { ApiKeyGoogleAuth } from "./auth.js";
12
12
  import { ensureParams } from "./utils/failed_handler.js";
13
13
  import { zodToGeminiParameters } from "./utils/zod_to_gemini_parameters.js";
14
14
  class ChatConnection extends AbstractGoogleLLMConnection {
15
+ constructor(fields, caller, client, streaming) {
16
+ super(fields, caller, client, streaming);
17
+ Object.defineProperty(this, "convertSystemMessageToHumanContent", {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value: void 0
22
+ });
23
+ this.convertSystemMessageToHumanContent =
24
+ fields?.convertSystemMessageToHumanContent;
25
+ }
26
+ get useSystemInstruction() {
27
+ return typeof this.convertSystemMessageToHumanContent === "boolean"
28
+ ? !this.convertSystemMessageToHumanContent
29
+ : this.computeUseSystemInstruction;
30
+ }
31
+ get computeUseSystemInstruction() {
32
+ // This works on models from April 2024 and later
33
+ // Vertex AI: gemini-1.5-pro and gemini-1.0-002 and later
34
+ // AI Studio: gemini-1.5-pro-latest
35
+ if (this.modelFamily === "palm") {
36
+ return false;
37
+ }
38
+ else if (this.modelName === "gemini-1.0-pro-001") {
39
+ return false;
40
+ }
41
+ else if (this.modelName.startsWith("gemini-pro-vision")) {
42
+ return false;
43
+ }
44
+ else if (this.modelName.startsWith("gemini-1.0-pro-vision")) {
45
+ return false;
46
+ }
47
+ else if (this.modelName === "gemini-pro" && this.platform === "gai") {
48
+ // on AI Studio gemini-pro is still pointing at gemini-1.0-pro-001
49
+ return false;
50
+ }
51
+ return true;
52
+ }
15
53
  formatContents(input, _parameters) {
16
54
  return input
17
- .map((msg, i) => baseMessageToContent(msg, input[i - 1]))
18
- .reduce((acc, cur) => [...acc, ...cur]);
55
+ .map((msg, i) => baseMessageToContent(msg, input[i - 1], this.useSystemInstruction))
56
+ .reduce((acc, cur) => {
57
+ // Filter out the system content, since those don't belong
58
+ // in the actual content.
59
+ const hasNoSystem = cur.every((content) => content.role !== "system");
60
+ return hasNoSystem ? [...acc, ...cur] : acc;
61
+ }, []);
62
+ }
63
+ formatSystemInstruction(input, _parameters) {
64
+ if (!this.useSystemInstruction) {
65
+ return {};
66
+ }
67
+ let ret = {};
68
+ input.forEach((message, index) => {
69
+ if (message._getType() === "system") {
70
+ // For system types, we only want it if it is the first message,
71
+ // if it appears anywhere else, it should be an error.
72
+ if (index === 0) {
73
+ // eslint-disable-next-line prefer-destructuring
74
+ ret = baseMessageToContent(message, undefined, true)[0];
75
+ }
76
+ else {
77
+ throw new Error("System messages are only permitted as the first passed message.");
78
+ }
79
+ }
80
+ });
81
+ return ret;
19
82
  }
20
83
  }
21
84
  function convertToGeminiTools(structuredTools) {
@@ -51,11 +114,12 @@ export class ChatGoogleBase extends BaseChatModel {
51
114
  writable: true,
52
115
  value: true
53
116
  });
117
+ // Set based on modelName
54
118
  Object.defineProperty(this, "model", {
55
119
  enumerable: true,
56
120
  configurable: true,
57
121
  writable: true,
58
- value: "gemini-pro"
122
+ value: void 0
59
123
  });
60
124
  Object.defineProperty(this, "modelName", {
61
125
  enumerable: true,
@@ -99,6 +163,13 @@ export class ChatGoogleBase extends BaseChatModel {
99
163
  writable: true,
100
164
  value: []
101
165
  });
166
+ // May intentionally be undefined, meaning to compute this.
167
+ Object.defineProperty(this, "convertSystemMessageToHumanContent", {
168
+ enumerable: true,
169
+ configurable: true,
170
+ writable: true,
171
+ value: void 0
172
+ });
102
173
  Object.defineProperty(this, "safetyHandler", {
103
174
  enumerable: true,
104
175
  configurable: true,
@@ -213,6 +213,9 @@ class AbstractGoogleLLMConnection extends GoogleAIConnection {
213
213
  formatSafetySettings(_input, parameters) {
214
214
  return parameters.safetySettings ?? [];
215
215
  }
216
+ formatSystemInstruction(_input, _parameters) {
217
+ return {};
218
+ }
216
219
  // Borrowed from the OpenAI invocation params test
217
220
  isStructuredToolArray(tools) {
218
221
  return (tools !== undefined &&
@@ -242,23 +245,18 @@ class AbstractGoogleLLMConnection extends GoogleAIConnection {
242
245
  return this.structuredToolsToGeminiTools(tools);
243
246
  }
244
247
  else {
248
+ if (tools.length === 1 && !tools[0].functionDeclarations?.length) {
249
+ return [];
250
+ }
245
251
  return tools;
246
252
  }
247
253
  }
248
254
  formatData(input, parameters) {
249
- /*
250
- const parts = messageContentToParts(input);
251
- const contents: GeminiContent[] = [
252
- {
253
- role: "user", // Required by Vertex AI
254
- parts,
255
- }
256
- ]
257
- */
258
255
  const contents = this.formatContents(input, parameters);
259
256
  const generationConfig = this.formatGenerationConfig(input, parameters);
260
257
  const tools = this.formatTools(input, parameters);
261
258
  const safetySettings = this.formatSafetySettings(input, parameters);
259
+ const systemInstruction = this.formatSystemInstruction(input, parameters);
262
260
  const ret = {
263
261
  contents,
264
262
  generationConfig,
@@ -269,6 +267,11 @@ class AbstractGoogleLLMConnection extends GoogleAIConnection {
269
267
  if (safetySettings && safetySettings.length) {
270
268
  ret.safetySettings = safetySettings;
271
269
  }
270
+ if (systemInstruction?.role &&
271
+ systemInstruction?.parts &&
272
+ systemInstruction?.parts?.length) {
273
+ ret.systemInstruction = systemInstruction;
274
+ }
272
275
  return ret;
273
276
  }
274
277
  }
@@ -45,6 +45,7 @@ export declare abstract class AbstractGoogleLLMConnection<MessageType, AuthOptio
45
45
  abstract formatContents(input: MessageType, parameters: GoogleAIModelRequestParams): GeminiContent[];
46
46
  formatGenerationConfig(_input: MessageType, parameters: GoogleAIModelRequestParams): GeminiGenerationConfig;
47
47
  formatSafetySettings(_input: MessageType, parameters: GoogleAIModelRequestParams): GeminiSafetySetting[];
48
+ formatSystemInstruction(_input: MessageType, _parameters: GoogleAIModelRequestParams): GeminiContent;
48
49
  isStructuredToolArray(tools?: unknown[]): tools is StructuredToolInterface[];
49
50
  structuredToolToFunctionDeclaration(tool: StructuredToolInterface): GeminiFunctionDeclaration;
50
51
  structuredToolsToGeminiTools(tools: StructuredToolInterface[]): GeminiTool[];
@@ -207,6 +207,9 @@ export class AbstractGoogleLLMConnection extends GoogleAIConnection {
207
207
  formatSafetySettings(_input, parameters) {
208
208
  return parameters.safetySettings ?? [];
209
209
  }
210
+ formatSystemInstruction(_input, _parameters) {
211
+ return {};
212
+ }
210
213
  // Borrowed from the OpenAI invocation params test
211
214
  isStructuredToolArray(tools) {
212
215
  return (tools !== undefined &&
@@ -236,23 +239,18 @@ export class AbstractGoogleLLMConnection extends GoogleAIConnection {
236
239
  return this.structuredToolsToGeminiTools(tools);
237
240
  }
238
241
  else {
242
+ if (tools.length === 1 && !tools[0].functionDeclarations?.length) {
243
+ return [];
244
+ }
239
245
  return tools;
240
246
  }
241
247
  }
242
248
  formatData(input, parameters) {
243
- /*
244
- const parts = messageContentToParts(input);
245
- const contents: GeminiContent[] = [
246
- {
247
- role: "user", // Required by Vertex AI
248
- parts,
249
- }
250
- ]
251
- */
252
249
  const contents = this.formatContents(input, parameters);
253
250
  const generationConfig = this.formatGenerationConfig(input, parameters);
254
251
  const tools = this.formatTools(input, parameters);
255
252
  const safetySettings = this.formatSafetySettings(input, parameters);
253
+ const systemInstruction = this.formatSystemInstruction(input, parameters);
256
254
  const ret = {
257
255
  contents,
258
256
  generationConfig,
@@ -263,6 +261,11 @@ export class AbstractGoogleLLMConnection extends GoogleAIConnection {
263
261
  if (safetySettings && safetySettings.length) {
264
262
  ret.safetySettings = safetySettings;
265
263
  }
264
+ if (systemInstruction?.role &&
265
+ systemInstruction?.parts &&
266
+ systemInstruction?.parts?.length) {
267
+ ret.systemInstruction = systemInstruction;
268
+ }
266
269
  return ret;
267
270
  }
268
271
  }
package/dist/types.d.ts CHANGED
@@ -73,6 +73,7 @@ export interface GoogleAIModelParams {
73
73
  topK?: number;
74
74
  stopSequences?: string[];
75
75
  safetySettings?: GoogleAISafetySetting[];
76
+ convertSystemMessageToHumanContent?: boolean;
76
77
  }
77
78
  /**
78
79
  * The params which can be passed to the API at request time.
@@ -124,11 +125,11 @@ export interface GeminiSafetySetting {
124
125
  category: string;
125
126
  threshold: string;
126
127
  }
127
- export interface GeminiSafetyRating {
128
+ export type GeminiSafetyRating = {
128
129
  category: string;
129
130
  probability: string;
130
- }
131
- export type GeminiRole = "user" | "model" | "function";
131
+ } & Record<string, unknown>;
132
+ export type GeminiRole = "system" | "user" | "model" | "function";
132
133
  export interface GeminiContent {
133
134
  parts: GeminiPart[];
134
135
  role: GeminiRole;
@@ -162,6 +163,7 @@ export interface GeminiGenerationConfig {
162
163
  }
163
164
  export interface GeminiRequest {
164
165
  contents?: GeminiContent[];
166
+ systemInstruction?: GeminiContent;
165
167
  tools?: GeminiTool[];
166
168
  safetySettings?: GeminiSafetySetting[];
167
169
  generationConfig?: GeminiGenerationConfig;
@@ -183,6 +185,7 @@ interface GeminiResponsePromptFeedback {
183
185
  export interface GenerateContentResponseData {
184
186
  candidates: GeminiResponseCandidate[];
185
187
  promptFeedback: GeminiResponsePromptFeedback;
188
+ usageMetadata: Record<string, unknown>;
186
189
  }
187
190
  export type GoogleLLMModelFamily = null | "palm" | "gemini";
188
191
  export type GoogleLLMResponseData = JsonStream | GenerateContentResponseData | GenerateContentResponseData[];
@@ -24,6 +24,10 @@ function copyAIModelParamsInto(params, options, target) {
24
24
  options?.stopSequences ?? params?.stopSequences ?? target.stopSequences;
25
25
  ret.safetySettings =
26
26
  options?.safetySettings ?? params?.safetySettings ?? target.safetySettings;
27
+ ret.convertSystemMessageToHumanContent =
28
+ options?.convertSystemMessageToHumanContent ??
29
+ params?.convertSystemMessageToHumanContent ??
30
+ target?.convertSystemMessageToHumanContent;
27
31
  ret.tools = options?.tools;
28
32
  // Ensure tools are formatted properly for Gemini
29
33
  const geminiTools = options?.tools
@@ -20,6 +20,10 @@ export function copyAIModelParamsInto(params, options, target) {
20
20
  options?.stopSequences ?? params?.stopSequences ?? target.stopSequences;
21
21
  ret.safetySettings =
22
22
  options?.safetySettings ?? params?.safetySettings ?? target.safetySettings;
23
+ ret.convertSystemMessageToHumanContent =
24
+ options?.convertSystemMessageToHumanContent ??
25
+ params?.convertSystemMessageToHumanContent ??
26
+ target?.convertSystemMessageToHumanContent;
23
27
  ret.tools = options?.tools;
24
28
  // Ensure tools are formatted properly for Gemini
25
29
  const geminiTools = options?.tools
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MessageGeminiSafetyHandler = exports.DefaultGeminiSafetyHandler = exports.isModelGemini = exports.validateGeminiParams = exports.safeResponseToChatResult = exports.responseToChatResult = exports.safeResponseToBaseMessage = exports.responseToBaseMessage = exports.partsToBaseMessageFields = exports.responseToBaseMessageFields = exports.responseToChatGenerations = exports.partToChatGeneration = exports.partToMessageChunk = exports.chunkToString = exports.safeResponseToChatGeneration = exports.responseToChatGeneration = exports.safeResponseToGeneration = exports.responseToGeneration = exports.safeResponseToString = exports.responseToString = exports.partToText = exports.responseToParts = exports.responseToGenerateContentResponseData = exports.toolsRawToTools = exports.partsToToolsRaw = exports.partsToMessageContent = exports.baseMessageToContent = exports.messageContentToParts = void 0;
3
+ exports.MessageGeminiSafetyHandler = exports.DefaultGeminiSafetyHandler = exports.isModelGemini = exports.validateGeminiParams = exports.safeResponseToChatResult = exports.responseToChatResult = exports.safeResponseToBaseMessage = exports.responseToBaseMessage = exports.partsToBaseMessageFields = exports.responseToBaseMessageFields = exports.responseToChatGenerations = exports.partToChatGeneration = exports.partToMessageChunk = exports.chunkToString = exports.safeResponseToChatGeneration = exports.responseToChatGeneration = exports.safeResponseToGeneration = exports.responseToGeneration = exports.responseToGenerationInfo = exports.safeResponseToString = exports.responseToString = exports.partToText = exports.responseToParts = exports.responseToGenerateContentResponseData = exports.toolsRawToTools = exports.partsToToolsRaw = exports.partsToMessageContent = exports.baseMessageToContent = exports.messageContentToParts = void 0;
4
4
  const uuid_1 = require("uuid");
5
5
  const messages_1 = require("@langchain/core/messages");
6
6
  const outputs_1 = require("@langchain/core/outputs");
@@ -158,11 +158,13 @@ function roleMessageToContent(role, message) {
158
158
  },
159
159
  ];
160
160
  }
161
- function systemMessageToContent(message) {
162
- return [
163
- ...roleMessageToContent("user", message),
164
- ...roleMessageToContent("model", new messages_1.AIMessage("Ok")),
165
- ];
161
+ function systemMessageToContent(message, useSystemInstruction) {
162
+ return useSystemInstruction
163
+ ? roleMessageToContent("system", message)
164
+ : [
165
+ ...roleMessageToContent("user", message),
166
+ ...roleMessageToContent("model", new messages_1.AIMessage("Ok")),
167
+ ];
166
168
  }
167
169
  function toolMessageToContent(message, prevMessage) {
168
170
  const contentStr = typeof message.content === "string"
@@ -211,11 +213,11 @@ function toolMessageToContent(message, prevMessage) {
211
213
  ];
212
214
  }
213
215
  }
214
- function baseMessageToContent(message, prevMessage) {
216
+ function baseMessageToContent(message, prevMessage, useSystemInstruction) {
215
217
  const type = message._getType();
216
218
  switch (type) {
217
219
  case "system":
218
- return systemMessageToContent(message);
220
+ return systemMessageToContent(message, useSystemInstruction);
219
221
  case "human":
220
222
  return roleMessageToContent("user", message);
221
223
  case "ai":
@@ -379,10 +381,32 @@ function safeResponseToString(response, safetyHandler) {
379
381
  return safeResponseTo(response, safetyHandler, responseToString);
380
382
  }
381
383
  exports.safeResponseToString = safeResponseToString;
384
+ function responseToGenerationInfo(response) {
385
+ if (!Array.isArray(response.data)) {
386
+ return {};
387
+ }
388
+ const data = response.data[0];
389
+ return {
390
+ usage_metadata: {
391
+ prompt_token_count: data.usageMetadata?.promptTokenCount,
392
+ candidates_token_count: data.usageMetadata?.candidatesTokenCount,
393
+ total_token_count: data.usageMetadata?.totalTokenCount,
394
+ },
395
+ safety_ratings: data.candidates[0]?.safetyRatings?.map((rating) => ({
396
+ category: rating.category,
397
+ probability: rating.probability,
398
+ probability_score: rating.probabilityScore,
399
+ severity: rating.severity,
400
+ severity_score: rating.severityScore,
401
+ })),
402
+ finish_reason: data.candidates[0]?.finishReason,
403
+ };
404
+ }
405
+ exports.responseToGenerationInfo = responseToGenerationInfo;
382
406
  function responseToGeneration(response) {
383
407
  return {
384
408
  text: responseToString(response),
385
- generationInfo: response,
409
+ generationInfo: responseToGenerationInfo(response),
386
410
  };
387
411
  }
388
412
  exports.responseToGeneration = responseToGeneration;
@@ -394,7 +418,7 @@ function responseToChatGeneration(response) {
394
418
  return new outputs_1.ChatGenerationChunk({
395
419
  text: responseToString(response),
396
420
  message: partToMessageChunk(responseToParts(response)[0]),
397
- generationInfo: response,
421
+ generationInfo: responseToGenerationInfo(response),
398
422
  });
399
423
  }
400
424
  exports.responseToChatGeneration = responseToChatGeneration;
@@ -452,7 +476,7 @@ function responseToChatGenerations(response) {
452
476
  if (ret.every((item) => typeof item.message.content === "string")) {
453
477
  const combinedContent = ret.map((item) => item.message.content).join("");
454
478
  const combinedText = ret.map((item) => item.text).join("");
455
- const toolCallChunks = ret[ret.length - 1].message.additional_kwargs?.tool_calls?.map((toolCall, i) => ({
479
+ const toolCallChunks = ret[ret.length - 1]?.message.additional_kwargs?.tool_calls?.map((toolCall, i) => ({
456
480
  name: toolCall.function.name,
457
481
  args: toolCall.function.arguments,
458
482
  id: toolCall.id,
@@ -462,7 +486,7 @@ function responseToChatGenerations(response) {
462
486
  new outputs_1.ChatGenerationChunk({
463
487
  message: new messages_1.AIMessageChunk({
464
488
  content: combinedContent,
465
- additional_kwargs: ret[ret.length - 1].message.additional_kwargs,
489
+ additional_kwargs: ret[ret.length - 1]?.message.additional_kwargs,
466
490
  tool_call_chunks: toolCallChunks,
467
491
  }),
468
492
  text: combinedText,
@@ -525,7 +549,7 @@ function responseToChatResult(response) {
525
549
  const generations = responseToChatGenerations(response);
526
550
  return {
527
551
  generations,
528
- llmOutput: response,
552
+ llmOutput: responseToGenerationInfo(response),
529
553
  };
530
554
  }
531
555
  exports.responseToChatResult = responseToChatResult;
@@ -2,7 +2,7 @@ import { AIMessageFields, BaseMessage, BaseMessageChunk, BaseMessageFields, Mess
2
2
  import { ChatGeneration, ChatGenerationChunk, ChatResult, Generation } from "@langchain/core/outputs";
3
3
  import type { GoogleLLMResponse, GoogleAIModelParams, GeminiPart, GeminiContent, GenerateContentResponseData, GoogleAISafetyHandler } from "../types.js";
4
4
  export declare function messageContentToParts(content: MessageContent): GeminiPart[];
5
- export declare function baseMessageToContent(message: BaseMessage, prevMessage?: BaseMessage): GeminiContent[];
5
+ export declare function baseMessageToContent(message: BaseMessage, prevMessage: BaseMessage | undefined, useSystemInstruction: boolean): GeminiContent[];
6
6
  export declare function partsToMessageContent(parts: GeminiPart[]): MessageContent;
7
7
  interface FunctionCall {
8
8
  name: string;
@@ -29,6 +29,25 @@ export declare function responseToParts(response: GoogleLLMResponse): GeminiPart
29
29
  export declare function partToText(part: GeminiPart): string;
30
30
  export declare function responseToString(response: GoogleLLMResponse): string;
31
31
  export declare function safeResponseToString(response: GoogleLLMResponse, safetyHandler: GoogleAISafetyHandler): string;
32
+ export declare function responseToGenerationInfo(response: GoogleLLMResponse): {
33
+ usage_metadata?: undefined;
34
+ safety_ratings?: undefined;
35
+ finish_reason?: undefined;
36
+ } | {
37
+ usage_metadata: {
38
+ prompt_token_count: unknown;
39
+ candidates_token_count: unknown;
40
+ total_token_count: unknown;
41
+ };
42
+ safety_ratings: {
43
+ category: string;
44
+ probability: string;
45
+ probability_score: unknown;
46
+ severity: unknown;
47
+ severity_score: unknown;
48
+ }[];
49
+ finish_reason: string;
50
+ };
32
51
  export declare function responseToGeneration(response: GoogleLLMResponse): Generation;
33
52
  export declare function safeResponseToGeneration(response: GoogleLLMResponse, safetyHandler: GoogleAISafetyHandler): Generation;
34
53
  export declare function responseToChatGeneration(response: GoogleLLMResponse): ChatGenerationChunk;
@@ -154,11 +154,13 @@ function roleMessageToContent(role, message) {
154
154
  },
155
155
  ];
156
156
  }
157
- function systemMessageToContent(message) {
158
- return [
159
- ...roleMessageToContent("user", message),
160
- ...roleMessageToContent("model", new AIMessage("Ok")),
161
- ];
157
+ function systemMessageToContent(message, useSystemInstruction) {
158
+ return useSystemInstruction
159
+ ? roleMessageToContent("system", message)
160
+ : [
161
+ ...roleMessageToContent("user", message),
162
+ ...roleMessageToContent("model", new AIMessage("Ok")),
163
+ ];
162
164
  }
163
165
  function toolMessageToContent(message, prevMessage) {
164
166
  const contentStr = typeof message.content === "string"
@@ -207,11 +209,11 @@ function toolMessageToContent(message, prevMessage) {
207
209
  ];
208
210
  }
209
211
  }
210
- export function baseMessageToContent(message, prevMessage) {
212
+ export function baseMessageToContent(message, prevMessage, useSystemInstruction) {
211
213
  const type = message._getType();
212
214
  switch (type) {
213
215
  case "system":
214
- return systemMessageToContent(message);
216
+ return systemMessageToContent(message, useSystemInstruction);
215
217
  case "human":
216
218
  return roleMessageToContent("user", message);
217
219
  case "ai":
@@ -366,10 +368,31 @@ function safeResponseTo(response, safetyHandler, responseTo) {
366
368
  export function safeResponseToString(response, safetyHandler) {
367
369
  return safeResponseTo(response, safetyHandler, responseToString);
368
370
  }
371
+ export function responseToGenerationInfo(response) {
372
+ if (!Array.isArray(response.data)) {
373
+ return {};
374
+ }
375
+ const data = response.data[0];
376
+ return {
377
+ usage_metadata: {
378
+ prompt_token_count: data.usageMetadata?.promptTokenCount,
379
+ candidates_token_count: data.usageMetadata?.candidatesTokenCount,
380
+ total_token_count: data.usageMetadata?.totalTokenCount,
381
+ },
382
+ safety_ratings: data.candidates[0]?.safetyRatings?.map((rating) => ({
383
+ category: rating.category,
384
+ probability: rating.probability,
385
+ probability_score: rating.probabilityScore,
386
+ severity: rating.severity,
387
+ severity_score: rating.severityScore,
388
+ })),
389
+ finish_reason: data.candidates[0]?.finishReason,
390
+ };
391
+ }
369
392
  export function responseToGeneration(response) {
370
393
  return {
371
394
  text: responseToString(response),
372
- generationInfo: response,
395
+ generationInfo: responseToGenerationInfo(response),
373
396
  };
374
397
  }
375
398
  export function safeResponseToGeneration(response, safetyHandler) {
@@ -379,7 +402,7 @@ export function responseToChatGeneration(response) {
379
402
  return new ChatGenerationChunk({
380
403
  text: responseToString(response),
381
404
  message: partToMessageChunk(responseToParts(response)[0]),
382
- generationInfo: response,
405
+ generationInfo: responseToGenerationInfo(response),
383
406
  });
384
407
  }
385
408
  export function safeResponseToChatGeneration(response, safetyHandler) {
@@ -432,7 +455,7 @@ export function responseToChatGenerations(response) {
432
455
  if (ret.every((item) => typeof item.message.content === "string")) {
433
456
  const combinedContent = ret.map((item) => item.message.content).join("");
434
457
  const combinedText = ret.map((item) => item.text).join("");
435
- const toolCallChunks = ret[ret.length - 1].message.additional_kwargs?.tool_calls?.map((toolCall, i) => ({
458
+ const toolCallChunks = ret[ret.length - 1]?.message.additional_kwargs?.tool_calls?.map((toolCall, i) => ({
436
459
  name: toolCall.function.name,
437
460
  args: toolCall.function.arguments,
438
461
  id: toolCall.id,
@@ -442,7 +465,7 @@ export function responseToChatGenerations(response) {
442
465
  new ChatGenerationChunk({
443
466
  message: new AIMessageChunk({
444
467
  content: combinedContent,
445
- additional_kwargs: ret[ret.length - 1].message.additional_kwargs,
468
+ additional_kwargs: ret[ret.length - 1]?.message.additional_kwargs,
446
469
  tool_call_chunks: toolCallChunks,
447
470
  }),
448
471
  text: combinedText,
@@ -500,7 +523,7 @@ export function responseToChatResult(response) {
500
523
  const generations = responseToChatGenerations(response);
501
524
  return {
502
525
  generations,
503
- llmOutput: response,
526
+ llmOutput: responseToGenerationInfo(response),
504
527
  };
505
528
  }
506
529
  export function safeResponseToChatResult(response, safetyHandler) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/google-common",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "description": "Core types and classes for Google services.",
5
5
  "type": "module",
6
6
  "engines": {