@langchain/google-genai 0.0.15 → 0.0.17

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.
@@ -4,7 +4,11 @@ exports.ChatGoogleGenerativeAI = void 0;
4
4
  const generative_ai_1 = require("@google/generative-ai");
5
5
  const env_1 = require("@langchain/core/utils/env");
6
6
  const chat_models_1 = require("@langchain/core/language_models/chat_models");
7
- const utils_js_1 = require("./utils.cjs");
7
+ const runnables_1 = require("@langchain/core/runnables");
8
+ const types_1 = require("@langchain/core/utils/types");
9
+ const zod_to_genai_parameters_js_1 = require("./utils/zod_to_genai_parameters.cjs");
10
+ const common_js_1 = require("./utils/common.cjs");
11
+ const output_parsers_js_1 = require("./output_parsers.cjs");
8
12
  /**
9
13
  * A class that wraps the Google Palm chat model.
10
14
  * @example
@@ -36,7 +40,7 @@ const utils_js_1 = require("./utils.cjs");
36
40
  */
37
41
  class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
38
42
  static lc_name() {
39
- return "googlegenerativeai";
43
+ return "ChatGoogleGenerativeAI";
40
44
  }
41
45
  get lc_secrets() {
42
46
  return {
@@ -177,13 +181,12 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
177
181
  });
178
182
  }
179
183
  getLsParams(options) {
180
- const params = this.invocationParams(options);
181
184
  return {
182
185
  ls_provider: "google_genai",
183
186
  ls_model_name: this.model,
184
187
  ls_model_type: "chat",
185
- ls_temperature: params.temperature ?? undefined,
186
- ls_max_tokens: params.maxOutputTokens ?? undefined,
188
+ ls_temperature: this.client.generationConfig.temperature,
189
+ ls_max_tokens: this.client.generationConfig.maxOutputTokens,
187
190
  ls_stop: options.stop,
188
191
  };
189
192
  }
@@ -193,8 +196,27 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
193
196
  _llmType() {
194
197
  return "googlegenerativeai";
195
198
  }
199
+ bindTools(tools, kwargs) {
200
+ return this.bind({ tools: (0, common_js_1.convertToGenerativeAITools)(tools), ...kwargs });
201
+ }
202
+ invocationParams(options) {
203
+ const tools = options?.tools;
204
+ if (Array.isArray(tools) &&
205
+ !tools.some(
206
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
207
+ (t) => !("lc_namespace" in t))) {
208
+ // Tools are in StructuredToolInterface format. Convert to GenAI format
209
+ return {
210
+ tools: (0, common_js_1.convertToGenerativeAITools)(options?.tools),
211
+ };
212
+ }
213
+ return {
214
+ tools: options?.tools,
215
+ };
216
+ }
196
217
  async _generate(messages, options, runManager) {
197
- const prompt = (0, utils_js_1.convertBaseMessagesToContent)(messages, this._isMultimodalModel);
218
+ const prompt = (0, common_js_1.convertBaseMessagesToContent)(messages, this._isMultimodalModel);
219
+ const parameters = this.invocationParams(options);
198
220
  // Handle streaming
199
221
  if (this.streaming) {
200
222
  const tokenUsage = {};
@@ -218,6 +240,7 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
218
240
  let output;
219
241
  try {
220
242
  output = await this.client.generateContent({
243
+ ...parameters,
221
244
  contents: prompt,
222
245
  });
223
246
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -231,20 +254,22 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
231
254
  }
232
255
  return output;
233
256
  });
234
- const generationResult = (0, utils_js_1.mapGenerateContentResultToChatResult)(res.response);
257
+ const generationResult = (0, common_js_1.mapGenerateContentResultToChatResult)(res.response);
235
258
  await runManager?.handleLLMNewToken(generationResult.generations[0].text ?? "");
236
259
  return generationResult;
237
260
  }
238
261
  async *_streamResponseChunks(messages, options, runManager) {
239
- const prompt = (0, utils_js_1.convertBaseMessagesToContent)(messages, this._isMultimodalModel);
262
+ const prompt = (0, common_js_1.convertBaseMessagesToContent)(messages, this._isMultimodalModel);
263
+ const parameters = this.invocationParams(options);
240
264
  const stream = await this.caller.callWithOptions({ signal: options?.signal }, async () => {
241
265
  const { stream } = await this.client.generateContentStream({
266
+ ...parameters,
242
267
  contents: prompt,
243
268
  });
244
269
  return stream;
245
270
  });
246
271
  for await (const response of stream) {
247
- const chunk = (0, utils_js_1.convertResponseContentToChatGenerationChunk)(response);
272
+ const chunk = (0, common_js_1.convertResponseContentToChatGenerationChunk)(response);
248
273
  if (!chunk) {
249
274
  continue;
250
275
  }
@@ -252,5 +277,88 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
252
277
  await runManager?.handleLLMNewToken(chunk.text ?? "");
253
278
  }
254
279
  }
280
+ withStructuredOutput(outputSchema, config) {
281
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
282
+ const schema = outputSchema;
283
+ const name = config?.name;
284
+ const method = config?.method;
285
+ const includeRaw = config?.includeRaw;
286
+ if (method === "jsonMode") {
287
+ throw new Error(`ChatGoogleGenerativeAI only supports "functionCalling" as a method.`);
288
+ }
289
+ let functionName = name ?? "extract";
290
+ let outputParser;
291
+ let tools;
292
+ if ((0, types_1.isZodSchema)(schema)) {
293
+ const jsonSchema = (0, zod_to_genai_parameters_js_1.zodToGenerativeAIParameters)(schema);
294
+ tools = [
295
+ {
296
+ functionDeclarations: [
297
+ {
298
+ name: functionName,
299
+ description: jsonSchema.description ?? "A function available to call.",
300
+ parameters: jsonSchema,
301
+ },
302
+ ],
303
+ },
304
+ ];
305
+ outputParser = new output_parsers_js_1.GoogleGenerativeAIToolsOutputParser({
306
+ returnSingle: true,
307
+ keyName: functionName,
308
+ zodSchema: schema,
309
+ });
310
+ }
311
+ else {
312
+ let geminiFunctionDefinition;
313
+ if (typeof schema.name === "string" &&
314
+ typeof schema.parameters === "object" &&
315
+ schema.parameters != null) {
316
+ geminiFunctionDefinition = schema;
317
+ functionName = schema.name;
318
+ }
319
+ else {
320
+ geminiFunctionDefinition = {
321
+ name: functionName,
322
+ description: schema.description ?? "",
323
+ parameters: schema,
324
+ };
325
+ }
326
+ tools = [
327
+ {
328
+ functionDeclarations: [geminiFunctionDefinition],
329
+ },
330
+ ];
331
+ outputParser = new output_parsers_js_1.GoogleGenerativeAIToolsOutputParser({
332
+ returnSingle: true,
333
+ keyName: functionName,
334
+ });
335
+ }
336
+ const llm = this.bind({
337
+ tools,
338
+ });
339
+ if (!includeRaw) {
340
+ return llm.pipe(outputParser).withConfig({
341
+ runName: "ChatGoogleGenerativeAIStructuredOutput",
342
+ });
343
+ }
344
+ const parserAssign = runnables_1.RunnablePassthrough.assign({
345
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
346
+ parsed: (input, config) => outputParser.invoke(input.raw, config),
347
+ });
348
+ const parserNone = runnables_1.RunnablePassthrough.assign({
349
+ parsed: () => null,
350
+ });
351
+ const parsedWithFallback = parserAssign.withFallbacks({
352
+ fallbacks: [parserNone],
353
+ });
354
+ return runnables_1.RunnableSequence.from([
355
+ {
356
+ raw: llm,
357
+ },
358
+ parsedWithFallback,
359
+ ]).withConfig({
360
+ runName: "StructuredOutputRunnable",
361
+ });
362
+ }
255
363
  }
256
364
  exports.ChatGoogleGenerativeAI = ChatGoogleGenerativeAI;
@@ -1,12 +1,19 @@
1
- import type { SafetySetting } from "@google/generative-ai";
1
+ import { FunctionDeclarationsTool as GoogleGenerativeAIFunctionDeclarationsTool, GenerateContentRequest, SafetySetting } from "@google/generative-ai";
2
2
  import { CallbackManagerForLLMRun } from "@langchain/core/callbacks/manager";
3
- import { BaseMessage } from "@langchain/core/messages";
3
+ import { AIMessageChunk, BaseMessage } from "@langchain/core/messages";
4
4
  import { ChatGenerationChunk, ChatResult } from "@langchain/core/outputs";
5
5
  import { BaseChatModel, LangSmithParams, type BaseChatModelParams } from "@langchain/core/language_models/chat_models";
6
+ import { BaseLanguageModelCallOptions, BaseLanguageModelInput, StructuredOutputMethodOptions } from "@langchain/core/language_models/base";
7
+ import { StructuredToolInterface } from "@langchain/core/tools";
8
+ import { Runnable } from "@langchain/core/runnables";
9
+ import type { z } from "zod";
6
10
  export type BaseMessageExamplePair = {
7
11
  input: BaseMessage;
8
12
  output: BaseMessage;
9
13
  };
14
+ export interface GoogleGenerativeAIChatCallOptions extends BaseLanguageModelCallOptions {
15
+ tools?: StructuredToolInterface[] | GoogleGenerativeAIFunctionDeclarationsTool[];
16
+ }
10
17
  /**
11
18
  * An interface defining the input to the ChatGoogleGenerativeAI class.
12
19
  */
@@ -124,7 +131,7 @@ export interface GoogleGenerativeAIChatInput extends BaseChatModelParams {
124
131
  * console.log({ res });
125
132
  * ```
126
133
  */
127
- export declare class ChatGoogleGenerativeAI extends BaseChatModel implements GoogleGenerativeAIChatInput {
134
+ export declare class ChatGoogleGenerativeAI extends BaseChatModel<GoogleGenerativeAIChatCallOptions, AIMessageChunk> implements GoogleGenerativeAIChatInput {
128
135
  static lc_name(): string;
129
136
  lc_serializable: boolean;
130
137
  get lc_secrets(): {
@@ -143,9 +150,16 @@ export declare class ChatGoogleGenerativeAI extends BaseChatModel implements Goo
143
150
  private client;
144
151
  get _isMultimodalModel(): boolean;
145
152
  constructor(fields?: GoogleGenerativeAIChatInput);
146
- protected getLsParams(options: this["ParsedCallOptions"]): LangSmithParams;
153
+ getLsParams(options: this["ParsedCallOptions"]): LangSmithParams;
147
154
  _combineLLMOutput(): never[];
148
155
  _llmType(): string;
156
+ bindTools(tools: (StructuredToolInterface | Record<string, unknown>)[], kwargs?: Partial<GoogleGenerativeAIChatCallOptions>): Runnable<BaseLanguageModelInput, AIMessageChunk, GoogleGenerativeAIChatCallOptions>;
157
+ invocationParams(options?: this["ParsedCallOptions"]): Omit<GenerateContentRequest, "contents">;
149
158
  _generate(messages: BaseMessage[], options: this["ParsedCallOptions"], runManager?: CallbackManagerForLLMRun): Promise<ChatResult>;
150
159
  _streamResponseChunks(messages: BaseMessage[], options: this["ParsedCallOptions"], runManager?: CallbackManagerForLLMRun): AsyncGenerator<ChatGenerationChunk>;
160
+ withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: z.ZodType<RunOutput> | Record<string, any>, config?: StructuredOutputMethodOptions<false>): Runnable<BaseLanguageModelInput, RunOutput>;
161
+ withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: z.ZodType<RunOutput> | Record<string, any>, config?: StructuredOutputMethodOptions<true>): Runnable<BaseLanguageModelInput, {
162
+ raw: BaseMessage;
163
+ parsed: RunOutput;
164
+ }>;
151
165
  }
@@ -1,7 +1,11 @@
1
1
  import { GoogleGenerativeAI as GenerativeAI, } from "@google/generative-ai";
2
2
  import { getEnvironmentVariable } from "@langchain/core/utils/env";
3
3
  import { BaseChatModel, } from "@langchain/core/language_models/chat_models";
4
- import { convertBaseMessagesToContent, convertResponseContentToChatGenerationChunk, mapGenerateContentResultToChatResult, } from "./utils.js";
4
+ import { RunnablePassthrough, RunnableSequence, } from "@langchain/core/runnables";
5
+ import { isZodSchema } from "@langchain/core/utils/types";
6
+ import { zodToGenerativeAIParameters } from "./utils/zod_to_genai_parameters.js";
7
+ import { convertBaseMessagesToContent, convertResponseContentToChatGenerationChunk, convertToGenerativeAITools, mapGenerateContentResultToChatResult, } from "./utils/common.js";
8
+ import { GoogleGenerativeAIToolsOutputParser } from "./output_parsers.js";
5
9
  /**
6
10
  * A class that wraps the Google Palm chat model.
7
11
  * @example
@@ -33,7 +37,7 @@ import { convertBaseMessagesToContent, convertResponseContentToChatGenerationChu
33
37
  */
34
38
  export class ChatGoogleGenerativeAI extends BaseChatModel {
35
39
  static lc_name() {
36
- return "googlegenerativeai";
40
+ return "ChatGoogleGenerativeAI";
37
41
  }
38
42
  get lc_secrets() {
39
43
  return {
@@ -174,13 +178,12 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
174
178
  });
175
179
  }
176
180
  getLsParams(options) {
177
- const params = this.invocationParams(options);
178
181
  return {
179
182
  ls_provider: "google_genai",
180
183
  ls_model_name: this.model,
181
184
  ls_model_type: "chat",
182
- ls_temperature: params.temperature ?? undefined,
183
- ls_max_tokens: params.maxOutputTokens ?? undefined,
185
+ ls_temperature: this.client.generationConfig.temperature,
186
+ ls_max_tokens: this.client.generationConfig.maxOutputTokens,
184
187
  ls_stop: options.stop,
185
188
  };
186
189
  }
@@ -190,8 +193,27 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
190
193
  _llmType() {
191
194
  return "googlegenerativeai";
192
195
  }
196
+ bindTools(tools, kwargs) {
197
+ return this.bind({ tools: convertToGenerativeAITools(tools), ...kwargs });
198
+ }
199
+ invocationParams(options) {
200
+ const tools = options?.tools;
201
+ if (Array.isArray(tools) &&
202
+ !tools.some(
203
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
204
+ (t) => !("lc_namespace" in t))) {
205
+ // Tools are in StructuredToolInterface format. Convert to GenAI format
206
+ return {
207
+ tools: convertToGenerativeAITools(options?.tools),
208
+ };
209
+ }
210
+ return {
211
+ tools: options?.tools,
212
+ };
213
+ }
193
214
  async _generate(messages, options, runManager) {
194
215
  const prompt = convertBaseMessagesToContent(messages, this._isMultimodalModel);
216
+ const parameters = this.invocationParams(options);
195
217
  // Handle streaming
196
218
  if (this.streaming) {
197
219
  const tokenUsage = {};
@@ -215,6 +237,7 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
215
237
  let output;
216
238
  try {
217
239
  output = await this.client.generateContent({
240
+ ...parameters,
218
241
  contents: prompt,
219
242
  });
220
243
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -234,8 +257,10 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
234
257
  }
235
258
  async *_streamResponseChunks(messages, options, runManager) {
236
259
  const prompt = convertBaseMessagesToContent(messages, this._isMultimodalModel);
260
+ const parameters = this.invocationParams(options);
237
261
  const stream = await this.caller.callWithOptions({ signal: options?.signal }, async () => {
238
262
  const { stream } = await this.client.generateContentStream({
263
+ ...parameters,
239
264
  contents: prompt,
240
265
  });
241
266
  return stream;
@@ -249,4 +274,87 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
249
274
  await runManager?.handleLLMNewToken(chunk.text ?? "");
250
275
  }
251
276
  }
277
+ withStructuredOutput(outputSchema, config) {
278
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
279
+ const schema = outputSchema;
280
+ const name = config?.name;
281
+ const method = config?.method;
282
+ const includeRaw = config?.includeRaw;
283
+ if (method === "jsonMode") {
284
+ throw new Error(`ChatGoogleGenerativeAI only supports "functionCalling" as a method.`);
285
+ }
286
+ let functionName = name ?? "extract";
287
+ let outputParser;
288
+ let tools;
289
+ if (isZodSchema(schema)) {
290
+ const jsonSchema = zodToGenerativeAIParameters(schema);
291
+ tools = [
292
+ {
293
+ functionDeclarations: [
294
+ {
295
+ name: functionName,
296
+ description: jsonSchema.description ?? "A function available to call.",
297
+ parameters: jsonSchema,
298
+ },
299
+ ],
300
+ },
301
+ ];
302
+ outputParser = new GoogleGenerativeAIToolsOutputParser({
303
+ returnSingle: true,
304
+ keyName: functionName,
305
+ zodSchema: schema,
306
+ });
307
+ }
308
+ else {
309
+ let geminiFunctionDefinition;
310
+ if (typeof schema.name === "string" &&
311
+ typeof schema.parameters === "object" &&
312
+ schema.parameters != null) {
313
+ geminiFunctionDefinition = schema;
314
+ functionName = schema.name;
315
+ }
316
+ else {
317
+ geminiFunctionDefinition = {
318
+ name: functionName,
319
+ description: schema.description ?? "",
320
+ parameters: schema,
321
+ };
322
+ }
323
+ tools = [
324
+ {
325
+ functionDeclarations: [geminiFunctionDefinition],
326
+ },
327
+ ];
328
+ outputParser = new GoogleGenerativeAIToolsOutputParser({
329
+ returnSingle: true,
330
+ keyName: functionName,
331
+ });
332
+ }
333
+ const llm = this.bind({
334
+ tools,
335
+ });
336
+ if (!includeRaw) {
337
+ return llm.pipe(outputParser).withConfig({
338
+ runName: "ChatGoogleGenerativeAIStructuredOutput",
339
+ });
340
+ }
341
+ const parserAssign = RunnablePassthrough.assign({
342
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
343
+ parsed: (input, config) => outputParser.invoke(input.raw, config),
344
+ });
345
+ const parserNone = RunnablePassthrough.assign({
346
+ parsed: () => null,
347
+ });
348
+ const parsedWithFallback = parserAssign.withFallbacks({
349
+ fallbacks: [parserNone],
350
+ });
351
+ return RunnableSequence.from([
352
+ {
353
+ raw: llm,
354
+ },
355
+ parsedWithFallback,
356
+ ]).withConfig({
357
+ runName: "StructuredOutputRunnable",
358
+ });
359
+ }
252
360
  }
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GoogleGenerativeAIToolsOutputParser = void 0;
4
+ const output_parsers_1 = require("@langchain/core/output_parsers");
5
+ class GoogleGenerativeAIToolsOutputParser extends output_parsers_1.BaseLLMOutputParser {
6
+ static lc_name() {
7
+ return "GoogleGenerativeAIToolsOutputParser";
8
+ }
9
+ constructor(params) {
10
+ super(params);
11
+ Object.defineProperty(this, "lc_namespace", {
12
+ enumerable: true,
13
+ configurable: true,
14
+ writable: true,
15
+ value: ["langchain", "google_genai", "output_parsers"]
16
+ });
17
+ Object.defineProperty(this, "returnId", {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value: false
22
+ });
23
+ /** The type of tool calls to return. */
24
+ Object.defineProperty(this, "keyName", {
25
+ enumerable: true,
26
+ configurable: true,
27
+ writable: true,
28
+ value: void 0
29
+ });
30
+ /** Whether to return only the first tool call. */
31
+ Object.defineProperty(this, "returnSingle", {
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true,
35
+ value: false
36
+ });
37
+ Object.defineProperty(this, "zodSchema", {
38
+ enumerable: true,
39
+ configurable: true,
40
+ writable: true,
41
+ value: void 0
42
+ });
43
+ this.keyName = params.keyName;
44
+ this.returnSingle = params.returnSingle ?? this.returnSingle;
45
+ this.zodSchema = params.zodSchema;
46
+ }
47
+ async _validateResult(result) {
48
+ if (this.zodSchema === undefined) {
49
+ return result;
50
+ }
51
+ const zodParsedResult = await this.zodSchema.safeParseAsync(result);
52
+ if (zodParsedResult.success) {
53
+ return zodParsedResult.data;
54
+ }
55
+ else {
56
+ throw new output_parsers_1.OutputParserException(`Failed to parse. Text: "${JSON.stringify(result, null, 2)}". Error: ${JSON.stringify(zodParsedResult.error.errors)}`, JSON.stringify(result, null, 2));
57
+ }
58
+ }
59
+ async parseResult(generations) {
60
+ const tools = generations.flatMap((generation) => {
61
+ const { message } = generation;
62
+ if (!("tool_calls" in message) || !Array.isArray(message.tool_calls)) {
63
+ return [];
64
+ }
65
+ return message.tool_calls;
66
+ });
67
+ if (tools[0] === undefined) {
68
+ throw new Error("No parseable tool calls provided to GoogleGenerativeAIToolsOutputParser.");
69
+ }
70
+ const [tool] = tools;
71
+ const validatedResult = await this._validateResult(tool.args);
72
+ return validatedResult;
73
+ }
74
+ }
75
+ exports.GoogleGenerativeAIToolsOutputParser = GoogleGenerativeAIToolsOutputParser;
@@ -0,0 +1,20 @@
1
+ import type { z } from "zod";
2
+ import { BaseLLMOutputParser } from "@langchain/core/output_parsers";
3
+ import { JsonOutputKeyToolsParserParams } from "@langchain/core/output_parsers/openai_tools";
4
+ import { ChatGeneration } from "@langchain/core/outputs";
5
+ interface GoogleGenerativeAIToolsOutputParserParams<T extends Record<string, any>> extends JsonOutputKeyToolsParserParams<T> {
6
+ }
7
+ export declare class GoogleGenerativeAIToolsOutputParser<T extends Record<string, any> = Record<string, any>> extends BaseLLMOutputParser<T> {
8
+ static lc_name(): string;
9
+ lc_namespace: string[];
10
+ returnId: boolean;
11
+ /** The type of tool calls to return. */
12
+ keyName: string;
13
+ /** Whether to return only the first tool call. */
14
+ returnSingle: boolean;
15
+ zodSchema?: z.ZodType<T>;
16
+ constructor(params: GoogleGenerativeAIToolsOutputParserParams<T>);
17
+ protected _validateResult(result: unknown): Promise<T>;
18
+ parseResult(generations: ChatGeneration[]): Promise<T>;
19
+ }
20
+ export {};
@@ -0,0 +1,71 @@
1
+ import { BaseLLMOutputParser, OutputParserException, } from "@langchain/core/output_parsers";
2
+ export class GoogleGenerativeAIToolsOutputParser extends BaseLLMOutputParser {
3
+ static lc_name() {
4
+ return "GoogleGenerativeAIToolsOutputParser";
5
+ }
6
+ constructor(params) {
7
+ super(params);
8
+ Object.defineProperty(this, "lc_namespace", {
9
+ enumerable: true,
10
+ configurable: true,
11
+ writable: true,
12
+ value: ["langchain", "google_genai", "output_parsers"]
13
+ });
14
+ Object.defineProperty(this, "returnId", {
15
+ enumerable: true,
16
+ configurable: true,
17
+ writable: true,
18
+ value: false
19
+ });
20
+ /** The type of tool calls to return. */
21
+ Object.defineProperty(this, "keyName", {
22
+ enumerable: true,
23
+ configurable: true,
24
+ writable: true,
25
+ value: void 0
26
+ });
27
+ /** Whether to return only the first tool call. */
28
+ Object.defineProperty(this, "returnSingle", {
29
+ enumerable: true,
30
+ configurable: true,
31
+ writable: true,
32
+ value: false
33
+ });
34
+ Object.defineProperty(this, "zodSchema", {
35
+ enumerable: true,
36
+ configurable: true,
37
+ writable: true,
38
+ value: void 0
39
+ });
40
+ this.keyName = params.keyName;
41
+ this.returnSingle = params.returnSingle ?? this.returnSingle;
42
+ this.zodSchema = params.zodSchema;
43
+ }
44
+ async _validateResult(result) {
45
+ if (this.zodSchema === undefined) {
46
+ return result;
47
+ }
48
+ const zodParsedResult = await this.zodSchema.safeParseAsync(result);
49
+ if (zodParsedResult.success) {
50
+ return zodParsedResult.data;
51
+ }
52
+ else {
53
+ throw new OutputParserException(`Failed to parse. Text: "${JSON.stringify(result, null, 2)}". Error: ${JSON.stringify(zodParsedResult.error.errors)}`, JSON.stringify(result, null, 2));
54
+ }
55
+ }
56
+ async parseResult(generations) {
57
+ const tools = generations.flatMap((generation) => {
58
+ const { message } = generation;
59
+ if (!("tool_calls" in message) || !Array.isArray(message.tool_calls)) {
60
+ return [];
61
+ }
62
+ return message.tool_calls;
63
+ });
64
+ if (tools[0] === undefined) {
65
+ throw new Error("No parseable tool calls provided to GoogleGenerativeAIToolsOutputParser.");
66
+ }
67
+ const [tool] = tools;
68
+ const validatedResult = await this._validateResult(tool.args);
69
+ return validatedResult;
70
+ }
71
+ }
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.convertResponseContentToChatGenerationChunk = exports.mapGenerateContentResultToChatResult = exports.convertBaseMessagesToContent = exports.convertMessageContentToParts = exports.convertAuthorToRole = exports.getMessageAuthor = void 0;
3
+ exports.convertToGenerativeAITools = exports.convertResponseContentToChatGenerationChunk = exports.mapGenerateContentResultToChatResult = exports.convertBaseMessagesToContent = exports.convertMessageContentToParts = exports.convertAuthorToRole = exports.getMessageAuthor = void 0;
4
4
  const messages_1 = require("@langchain/core/messages");
5
5
  const outputs_1 = require("@langchain/core/outputs");
6
+ const function_calling_1 = require("@langchain/core/utils/function_calling");
7
+ const zod_to_genai_parameters_js_1 = require("./zod_to_genai_parameters.cjs");
6
8
  function getMessageAuthor(message) {
7
9
  const type = message._getType();
8
10
  if (messages_1.ChatMessage.isInstance(message)) {
@@ -142,6 +144,7 @@ function mapGenerateContentResultToChatResult(response) {
142
144
  },
143
145
  };
144
146
  }
147
+ const functionCalls = response.functionCalls();
145
148
  const [candidate] = response.candidates;
146
149
  const { content, ...generationInfo } = candidate;
147
150
  const text = content?.parts[0]?.text ?? "";
@@ -149,8 +152,10 @@ function mapGenerateContentResultToChatResult(response) {
149
152
  text,
150
153
  message: new messages_1.AIMessage({
151
154
  content: text,
152
- name: !content ? undefined : content.role,
153
- additional_kwargs: generationInfo,
155
+ tool_calls: functionCalls,
156
+ additional_kwargs: {
157
+ ...generationInfo,
158
+ },
154
159
  }),
155
160
  generationInfo,
156
161
  };
@@ -179,3 +184,25 @@ function convertResponseContentToChatGenerationChunk(response) {
179
184
  });
180
185
  }
181
186
  exports.convertResponseContentToChatGenerationChunk = convertResponseContentToChatGenerationChunk;
187
+ function convertToGenerativeAITools(structuredTools) {
188
+ if (structuredTools.every((tool) => "functionDeclarations" in tool &&
189
+ Array.isArray(tool.functionDeclarations))) {
190
+ return structuredTools;
191
+ }
192
+ return [
193
+ {
194
+ functionDeclarations: structuredTools.map((structuredTool) => {
195
+ if ((0, function_calling_1.isStructuredTool)(structuredTool)) {
196
+ const jsonSchema = (0, zod_to_genai_parameters_js_1.zodToGenerativeAIParameters)(structuredTool.schema);
197
+ return {
198
+ name: structuredTool.name,
199
+ description: structuredTool.description,
200
+ parameters: jsonSchema,
201
+ };
202
+ }
203
+ return structuredTool;
204
+ }),
205
+ },
206
+ ];
207
+ }
208
+ exports.convertToGenerativeAITools = convertToGenerativeAITools;
@@ -1,6 +1,7 @@
1
- import { EnhancedGenerateContentResponse, Content, Part } from "@google/generative-ai";
1
+ import { EnhancedGenerateContentResponse, Content, Part, type FunctionDeclarationsTool as GoogleGenerativeAIFunctionDeclarationsTool } from "@google/generative-ai";
2
2
  import { BaseMessage, MessageContent } from "@langchain/core/messages";
3
3
  import { ChatGenerationChunk, ChatResult } from "@langchain/core/outputs";
4
+ import { StructuredToolInterface } from "@langchain/core/tools";
4
5
  export declare function getMessageAuthor(message: BaseMessage): string;
5
6
  /**
6
7
  * Maps a message type to a Google Generative AI chat author.
@@ -13,3 +14,4 @@ export declare function convertMessageContentToParts(content: MessageContent, is
13
14
  export declare function convertBaseMessagesToContent(messages: BaseMessage[], isMultimodalModel: boolean): Content[];
14
15
  export declare function mapGenerateContentResultToChatResult(response: EnhancedGenerateContentResponse): ChatResult;
15
16
  export declare function convertResponseContentToChatGenerationChunk(response: EnhancedGenerateContentResponse): ChatGenerationChunk | null;
17
+ export declare function convertToGenerativeAITools(structuredTools: (StructuredToolInterface | Record<string, unknown>)[]): GoogleGenerativeAIFunctionDeclarationsTool[];
@@ -1,5 +1,7 @@
1
1
  import { AIMessage, AIMessageChunk, ChatMessage, isBaseMessage, } from "@langchain/core/messages";
2
2
  import { ChatGenerationChunk, } from "@langchain/core/outputs";
3
+ import { isStructuredTool } from "@langchain/core/utils/function_calling";
4
+ import { zodToGenerativeAIParameters } from "./zod_to_genai_parameters.js";
3
5
  export function getMessageAuthor(message) {
4
6
  const type = message._getType();
5
7
  if (ChatMessage.isInstance(message)) {
@@ -135,6 +137,7 @@ export function mapGenerateContentResultToChatResult(response) {
135
137
  },
136
138
  };
137
139
  }
140
+ const functionCalls = response.functionCalls();
138
141
  const [candidate] = response.candidates;
139
142
  const { content, ...generationInfo } = candidate;
140
143
  const text = content?.parts[0]?.text ?? "";
@@ -142,8 +145,10 @@ export function mapGenerateContentResultToChatResult(response) {
142
145
  text,
143
146
  message: new AIMessage({
144
147
  content: text,
145
- name: !content ? undefined : content.role,
146
- additional_kwargs: generationInfo,
148
+ tool_calls: functionCalls,
149
+ additional_kwargs: {
150
+ ...generationInfo,
151
+ },
147
152
  }),
148
153
  generationInfo,
149
154
  };
@@ -170,3 +175,24 @@ export function convertResponseContentToChatGenerationChunk(response) {
170
175
  generationInfo,
171
176
  });
172
177
  }
178
+ export function convertToGenerativeAITools(structuredTools) {
179
+ if (structuredTools.every((tool) => "functionDeclarations" in tool &&
180
+ Array.isArray(tool.functionDeclarations))) {
181
+ return structuredTools;
182
+ }
183
+ return [
184
+ {
185
+ functionDeclarations: structuredTools.map((structuredTool) => {
186
+ if (isStructuredTool(structuredTool)) {
187
+ const jsonSchema = zodToGenerativeAIParameters(structuredTool.schema);
188
+ return {
189
+ name: structuredTool.name,
190
+ description: structuredTool.description,
191
+ parameters: jsonSchema,
192
+ };
193
+ }
194
+ return structuredTool;
195
+ }),
196
+ },
197
+ ];
198
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ /* eslint-disable @typescript-eslint/no-unused-vars */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.zodToGenerativeAIParameters = void 0;
5
+ const zod_to_json_schema_1 = require("zod-to-json-schema");
6
+ function removeAdditionalProperties(schema) {
7
+ const updatedSchema = { ...schema };
8
+ if (Object.hasOwn(updatedSchema, "additionalProperties")) {
9
+ delete updatedSchema.additionalProperties;
10
+ }
11
+ if (updatedSchema.properties) {
12
+ const keys = Object.keys(updatedSchema.properties);
13
+ removeProperties(updatedSchema.properties, keys, 0);
14
+ }
15
+ return updatedSchema;
16
+ }
17
+ function removeProperties(properties, keys, index) {
18
+ if (index >= keys.length || !properties) {
19
+ return;
20
+ }
21
+ const key = keys[index];
22
+ // eslint-disable-next-line no-param-reassign
23
+ properties[key] = removeAdditionalProperties(properties[key]);
24
+ removeProperties(properties, keys, index + 1);
25
+ }
26
+ function zodToGenerativeAIParameters(
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
+ zodObj) {
29
+ // GenerativeAI doesn't accept either the $schema or additionalProperties
30
+ // attributes, so we need to explicitly remove them.
31
+ const jsonSchema = removeAdditionalProperties((0, zod_to_json_schema_1.zodToJsonSchema)(zodObj));
32
+ const { $schema, ...rest } = jsonSchema;
33
+ return rest;
34
+ }
35
+ exports.zodToGenerativeAIParameters = zodToGenerativeAIParameters;
@@ -0,0 +1,11 @@
1
+ import type { z } from "zod";
2
+ import { type FunctionDeclarationSchema as GenerativeAIFunctionDeclarationSchema, FunctionDeclarationSchemaType } from "@google/generative-ai";
3
+ export interface GenerativeAIJsonSchema extends Record<string, unknown> {
4
+ properties?: Record<string, GenerativeAIJsonSchema>;
5
+ type: FunctionDeclarationSchemaType;
6
+ }
7
+ export interface GenerativeAIJsonSchemaDirty extends GenerativeAIJsonSchema {
8
+ properties?: Record<string, GenerativeAIJsonSchemaDirty>;
9
+ additionalProperties?: boolean;
10
+ }
11
+ export declare function zodToGenerativeAIParameters(zodObj: z.ZodType<any>): GenerativeAIFunctionDeclarationSchema;
@@ -0,0 +1,31 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import { zodToJsonSchema } from "zod-to-json-schema";
3
+ function removeAdditionalProperties(schema) {
4
+ const updatedSchema = { ...schema };
5
+ if (Object.hasOwn(updatedSchema, "additionalProperties")) {
6
+ delete updatedSchema.additionalProperties;
7
+ }
8
+ if (updatedSchema.properties) {
9
+ const keys = Object.keys(updatedSchema.properties);
10
+ removeProperties(updatedSchema.properties, keys, 0);
11
+ }
12
+ return updatedSchema;
13
+ }
14
+ function removeProperties(properties, keys, index) {
15
+ if (index >= keys.length || !properties) {
16
+ return;
17
+ }
18
+ const key = keys[index];
19
+ // eslint-disable-next-line no-param-reassign
20
+ properties[key] = removeAdditionalProperties(properties[key]);
21
+ removeProperties(properties, keys, index + 1);
22
+ }
23
+ export function zodToGenerativeAIParameters(
24
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
+ zodObj) {
26
+ // GenerativeAI doesn't accept either the $schema or additionalProperties
27
+ // attributes, so we need to explicitly remove them.
28
+ const jsonSchema = removeAdditionalProperties(zodToJsonSchema(zodObj));
29
+ const { $schema, ...rest } = jsonSchema;
30
+ return rest;
31
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/google-genai",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "description": "Sample integration for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {
@@ -14,37 +14,35 @@
14
14
  },
15
15
  "homepage": "https://github.com/langchain-ai/langchainjs/tree/main/libs/langchain-google-genai/",
16
16
  "scripts": {
17
- "build": "yarn run build:deps && yarn clean && yarn build:esm && yarn build:cjs && yarn build:scripts",
18
- "build:deps": "yarn run turbo:command build --filter=@langchain/core",
19
- "build:esm": "NODE_OPTIONS=--max-old-space-size=4096 tsc --outDir dist/ && rm -rf dist/tests dist/**/tests",
20
- "build:cjs": "NODE_OPTIONS=--max-old-space-size=4096 tsc --outDir dist-cjs/ -p tsconfig.cjs.json && yarn move-cjs-to-dist && rm -rf dist-cjs",
21
- "build:watch": "yarn create-entrypoints && tsc --outDir dist/ --watch",
22
- "build:scripts": "yarn create-entrypoints && yarn check-tree-shaking",
17
+ "build": "yarn turbo:command build:internal --filter=@langchain/google-genai",
18
+ "build:internal": "yarn lc-build:v2 --create-entrypoints --pre --tree-shaking",
23
19
  "lint:eslint": "NODE_OPTIONS=--max-old-space-size=4096 eslint --cache --ext .ts,.js src/",
24
20
  "lint:dpdm": "dpdm --exit-code circular:1 --no-warning --no-tree src/*.ts src/**/*.ts",
25
21
  "lint": "yarn lint:eslint && yarn lint:dpdm",
26
22
  "lint:fix": "yarn lint:eslint --fix && yarn lint:dpdm",
27
- "clean": "rm -rf dist/ && NODE_OPTIONS=--max-old-space-size=4096 yarn lc-build --config ./langchain.config.js --create-entrypoints --pre",
23
+ "clean": "rm -rf .turbo dist/",
28
24
  "prepack": "yarn build",
29
- "test": "yarn build:deps && NODE_OPTIONS=--experimental-vm-modules jest --testPathIgnorePatterns=\\.int\\.test.ts --testTimeout 30000 --maxWorkers=50%",
30
- "test:watch": "yarn build:deps && NODE_OPTIONS=--experimental-vm-modules jest --watch --testPathIgnorePatterns=\\.int\\.test.ts",
31
- "test:single": "yarn build:deps && NODE_OPTIONS=--experimental-vm-modules yarn run jest --config jest.config.cjs --testTimeout 100000",
32
- "test:int": "yarn build:deps && NODE_OPTIONS=--experimental-vm-modules jest --testPathPattern=\\.int\\.test.ts --testTimeout 100000 --maxWorkers=50%",
25
+ "test": "NODE_OPTIONS=--experimental-vm-modules jest --testPathIgnorePatterns=\\.int\\.test.ts --testTimeout 30000 --maxWorkers=50%",
26
+ "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch --testPathIgnorePatterns=\\.int\\.test.ts",
27
+ "test:single": "NODE_OPTIONS=--experimental-vm-modules yarn run jest --config jest.config.cjs --testTimeout 100000",
28
+ "test:int": "NODE_OPTIONS=--experimental-vm-modules jest --testPathPattern=\\.int\\.test.ts --testTimeout 100000 --maxWorkers=50%",
29
+ "test:standard:unit": "NODE_OPTIONS=--experimental-vm-modules jest --testPathPattern=\\.standard\\.test.ts --testTimeout 100000 --maxWorkers=50%",
30
+ "test:standard:int": "NODE_OPTIONS=--experimental-vm-modules jest --testPathPattern=\\.standard\\.int\\.test.ts --testTimeout 100000 --maxWorkers=50%",
31
+ "test:standard": "yarn test:standard:unit && yarn test:standard:int",
33
32
  "format": "prettier --config .prettierrc --write \"src\"",
34
- "format:check": "prettier --config .prettierrc --check \"src\"",
35
- "move-cjs-to-dist": "yarn lc-build --config ./langchain.config.js --move-cjs-dist",
36
- "create-entrypoints": "yarn lc-build --config ./langchain.config.js --create-entrypoints",
37
- "check-tree-shaking": "yarn lc-build --config ./langchain.config.js --tree-shaking"
33
+ "format:check": "prettier --config .prettierrc --check \"src\""
38
34
  },
39
35
  "author": "LangChain",
40
36
  "license": "MIT",
41
37
  "dependencies": {
42
38
  "@google/generative-ai": "^0.7.0",
43
- "@langchain/core": ">0.1.5 <0.3.0"
39
+ "@langchain/core": ">0.1.5 <0.3.0",
40
+ "zod-to-json-schema": "^3.22.4"
44
41
  },
45
42
  "devDependencies": {
46
43
  "@jest/globals": "^29.5.0",
47
- "@langchain/scripts": "~0.0",
44
+ "@langchain/scripts": "~0.0.14",
45
+ "@langchain/standard-tests": "workspace:*",
48
46
  "@swc/core": "^1.3.90",
49
47
  "@swc/jest": "^0.2.29",
50
48
  "@tsconfig/recommended": "^1.0.3",
@@ -65,7 +63,8 @@
65
63
  "release-it": "^15.10.1",
66
64
  "rollup": "^4.5.2",
67
65
  "ts-jest": "^29.1.0",
68
- "typescript": "<5.2.0"
66
+ "typescript": "<5.2.0",
67
+ "zod": "^3.22.4"
69
68
  },
70
69
  "publishConfig": {
71
70
  "access": "public"