@langchain/google-genai 0.2.10 → 0.2.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.
@@ -670,7 +670,7 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
670
670
  const generationResult = (0, common_js_1.mapGenerateContentResultToChatResult)(res.response, {
671
671
  usageMetadata,
672
672
  });
673
- // may not have generations in output if there was a refusal for safety reasons
673
+ // may not have generations in output if there was a refusal for safety reasons, malformed function call, etc.
674
674
  if (generationResult.generations?.length > 0) {
675
675
  await runManager?.handleLLMNewToken(generationResult.generations[0]?.text ?? "");
676
676
  }
@@ -760,7 +760,7 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
760
760
  if (method === "functionCalling") {
761
761
  let functionName = name ?? "extract";
762
762
  let tools;
763
- if ((0, types_1.isZodSchema)(schema)) {
763
+ if ((0, types_1.isInteropZodSchema)(schema)) {
764
764
  const jsonSchema = (0, zod_to_genai_parameters_js_1.schemaToGenerativeAIParameters)(schema);
765
765
  tools = [
766
766
  {
@@ -5,7 +5,7 @@ import { ChatGenerationChunk, ChatResult } from "@langchain/core/outputs";
5
5
  import { BaseChatModel, type BaseChatModelCallOptions, type LangSmithParams, type BaseChatModelParams } from "@langchain/core/language_models/chat_models";
6
6
  import { BaseLanguageModelInput, StructuredOutputMethodOptions } from "@langchain/core/language_models/base";
7
7
  import { Runnable } from "@langchain/core/runnables";
8
- import type { z } from "zod";
8
+ import { InteropZodType } from "@langchain/core/utils/types";
9
9
  import { GoogleGenerativeAIToolType } from "./types.js";
10
10
  export type BaseMessageExamplePair = {
11
11
  input: BaseMessage;
@@ -534,8 +534,8 @@ export declare class ChatGoogleGenerativeAI extends BaseChatModel<GoogleGenerati
534
534
  _generate(messages: BaseMessage[], options: this["ParsedCallOptions"], runManager?: CallbackManagerForLLMRun): Promise<ChatResult>;
535
535
  _streamResponseChunks(messages: BaseMessage[], options: this["ParsedCallOptions"], runManager?: CallbackManagerForLLMRun): AsyncGenerator<ChatGenerationChunk>;
536
536
  completionWithRetry(request: string | GenerateContentRequest | (string | GenerativeAIPart)[], options?: this["ParsedCallOptions"]): Promise<import("@google/generative-ai").GenerateContentResult>;
537
- withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: z.ZodType<RunOutput> | Record<string, any>, config?: StructuredOutputMethodOptions<false>): Runnable<BaseLanguageModelInput, RunOutput>;
538
- withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: z.ZodType<RunOutput> | Record<string, any>, config?: StructuredOutputMethodOptions<true>): Runnable<BaseLanguageModelInput, {
537
+ withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: InteropZodType<RunOutput> | Record<string, any>, config?: StructuredOutputMethodOptions<false>): Runnable<BaseLanguageModelInput, RunOutput>;
538
+ withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: InteropZodType<RunOutput> | Record<string, any>, config?: StructuredOutputMethodOptions<true>): Runnable<BaseLanguageModelInput, {
539
539
  raw: BaseMessage;
540
540
  parsed: RunOutput;
541
541
  }>;
@@ -2,7 +2,7 @@ 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
4
  import { RunnablePassthrough, RunnableSequence, } from "@langchain/core/runnables";
5
- import { isZodSchema } from "@langchain/core/utils/types";
5
+ import { isInteropZodSchema, } from "@langchain/core/utils/types";
6
6
  import { JsonOutputParser, } from "@langchain/core/output_parsers";
7
7
  import { schemaToGenerativeAIParameters, removeAdditionalProperties, } from "./utils/zod_to_genai_parameters.js";
8
8
  import { convertBaseMessagesToContent, convertResponseContentToChatGenerationChunk, mapGenerateContentResultToChatResult, } from "./utils/common.js";
@@ -667,7 +667,7 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
667
667
  const generationResult = mapGenerateContentResultToChatResult(res.response, {
668
668
  usageMetadata,
669
669
  });
670
- // may not have generations in output if there was a refusal for safety reasons
670
+ // may not have generations in output if there was a refusal for safety reasons, malformed function call, etc.
671
671
  if (generationResult.generations?.length > 0) {
672
672
  await runManager?.handleLLMNewToken(generationResult.generations[0]?.text ?? "");
673
673
  }
@@ -757,7 +757,7 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
757
757
  if (method === "functionCalling") {
758
758
  let functionName = name ?? "extract";
759
759
  let tools;
760
- if (isZodSchema(schema)) {
760
+ if (isInteropZodSchema(schema)) {
761
761
  const jsonSchema = schemaToGenerativeAIParameters(schema);
762
762
  tools = [
763
763
  {
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GoogleGenerativeAIToolsOutputParser = void 0;
4
4
  const output_parsers_1 = require("@langchain/core/output_parsers");
5
+ const types_1 = require("@langchain/core/utils/types");
5
6
  class GoogleGenerativeAIToolsOutputParser extends output_parsers_1.BaseLLMOutputParser {
6
7
  static lc_name() {
7
8
  return "GoogleGenerativeAIToolsOutputParser";
@@ -48,12 +49,12 @@ class GoogleGenerativeAIToolsOutputParser extends output_parsers_1.BaseLLMOutput
48
49
  if (this.zodSchema === undefined) {
49
50
  return result;
50
51
  }
51
- const zodParsedResult = await this.zodSchema.safeParseAsync(result);
52
+ const zodParsedResult = await (0, types_1.interopSafeParseAsync)(this.zodSchema, result);
52
53
  if (zodParsedResult.success) {
53
54
  return zodParsedResult.data;
54
55
  }
55
56
  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
+ throw new output_parsers_1.OutputParserException(`Failed to parse. Text: "${JSON.stringify(result, null, 2)}". Error: ${JSON.stringify(zodParsedResult.error.issues)}`, JSON.stringify(result, null, 2));
57
58
  }
58
59
  }
59
60
  async parseResult(generations) {
@@ -1,8 +1,8 @@
1
- import type { z } from "zod";
2
1
  import { BaseLLMOutputParser } from "@langchain/core/output_parsers";
3
- import { JsonOutputKeyToolsParserParams } from "@langchain/core/output_parsers/openai_tools";
4
2
  import { ChatGeneration } from "@langchain/core/outputs";
5
- interface GoogleGenerativeAIToolsOutputParserParams<T extends Record<string, any>> extends JsonOutputKeyToolsParserParams<T> {
3
+ import { InteropZodType } from "@langchain/core/utils/types";
4
+ import { JsonOutputKeyToolsParserParamsInterop } from "@langchain/core/output_parsers/openai_tools";
5
+ interface GoogleGenerativeAIToolsOutputParserParams<T extends Record<string, any>> extends JsonOutputKeyToolsParserParamsInterop<T> {
6
6
  }
7
7
  export declare class GoogleGenerativeAIToolsOutputParser<T extends Record<string, any> = Record<string, any>> extends BaseLLMOutputParser<T> {
8
8
  static lc_name(): string;
@@ -12,7 +12,7 @@ export declare class GoogleGenerativeAIToolsOutputParser<T extends Record<string
12
12
  keyName: string;
13
13
  /** Whether to return only the first tool call. */
14
14
  returnSingle: boolean;
15
- zodSchema?: z.ZodType<T>;
15
+ zodSchema?: InteropZodType<T>;
16
16
  constructor(params: GoogleGenerativeAIToolsOutputParserParams<T>);
17
17
  protected _validateResult(result: unknown): Promise<T>;
18
18
  parseResult(generations: ChatGeneration[]): Promise<T>;
@@ -1,4 +1,5 @@
1
1
  import { BaseLLMOutputParser, OutputParserException, } from "@langchain/core/output_parsers";
2
+ import { interopSafeParseAsync, } from "@langchain/core/utils/types";
2
3
  export class GoogleGenerativeAIToolsOutputParser extends BaseLLMOutputParser {
3
4
  static lc_name() {
4
5
  return "GoogleGenerativeAIToolsOutputParser";
@@ -45,12 +46,12 @@ export class GoogleGenerativeAIToolsOutputParser extends BaseLLMOutputParser {
45
46
  if (this.zodSchema === undefined) {
46
47
  return result;
47
48
  }
48
- const zodParsedResult = await this.zodSchema.safeParseAsync(result);
49
+ const zodParsedResult = await interopSafeParseAsync(this.zodSchema, result);
49
50
  if (zodParsedResult.success) {
50
51
  return zodParsedResult.data;
51
52
  }
52
53
  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
+ throw new OutputParserException(`Failed to parse. Text: "${JSON.stringify(result, null, 2)}". Error: ${JSON.stringify(zodParsedResult.error.issues)}`, JSON.stringify(result, null, 2));
54
55
  }
55
56
  }
56
57
  async parseResult(generations) {
@@ -390,10 +390,13 @@ function mapGenerateContentResultToChatResult(response, extra) {
390
390
  const [candidate] = response.candidates;
391
391
  const { content: candidateContent, ...generationInfo } = candidate;
392
392
  let content;
393
- if (candidateContent?.parts.length === 1 && candidateContent.parts[0].text) {
393
+ if (Array.isArray(candidateContent?.parts) &&
394
+ candidateContent.parts.length === 1 &&
395
+ candidateContent.parts[0].text) {
394
396
  content = candidateContent.parts[0].text;
395
397
  }
396
- else {
398
+ else if (Array.isArray(candidateContent?.parts) &&
399
+ candidateContent.parts.length > 0) {
397
400
  content = candidateContent.parts.map((p) => {
398
401
  if ("text" in p) {
399
402
  return {
@@ -416,17 +419,22 @@ function mapGenerateContentResultToChatResult(response, extra) {
416
419
  return p;
417
420
  });
418
421
  }
422
+ else {
423
+ // no content returned - likely due to abnormal stop reason, e.g. malformed function call
424
+ content = [];
425
+ }
419
426
  let text = "";
420
427
  if (typeof content === "string") {
421
428
  text = content;
422
429
  }
423
- else if ("text" in content[0]) {
424
- text = content[0].text;
430
+ else if (Array.isArray(content) && content.length > 0) {
431
+ const block = content.find((b) => "text" in b);
432
+ text = block?.text ?? text;
425
433
  }
426
434
  const generation = {
427
435
  text,
428
436
  message: new messages_1.AIMessage({
429
- content,
437
+ content: content ?? "",
430
438
  tool_calls: functionCalls?.map((fc) => {
431
439
  return {
432
440
  ...fc,
@@ -462,11 +470,11 @@ function convertResponseContentToChatGenerationChunk(response, extra) {
462
470
  const { content: candidateContent, ...generationInfo } = candidate;
463
471
  let content;
464
472
  // Checks if some parts do not have text. If false, it means that the content is a string.
465
- if (candidateContent?.parts &&
473
+ if (Array.isArray(candidateContent?.parts) &&
466
474
  candidateContent.parts.every((p) => "text" in p)) {
467
475
  content = candidateContent.parts.map((p) => p.text).join("");
468
476
  }
469
- else if (candidateContent.parts) {
477
+ else if (Array.isArray(candidateContent?.parts)) {
470
478
  content = candidateContent.parts.map((p) => {
471
479
  if ("text" in p) {
472
480
  return {
@@ -489,12 +497,17 @@ function convertResponseContentToChatGenerationChunk(response, extra) {
489
497
  return p;
490
498
  });
491
499
  }
500
+ else {
501
+ // no content returned - likely due to abnormal stop reason, e.g. malformed function call
502
+ content = [];
503
+ }
492
504
  let text = "";
493
505
  if (content && typeof content === "string") {
494
506
  text = content;
495
507
  }
496
- else if (content && typeof content === "object" && "text" in content[0]) {
497
- text = content[0].text;
508
+ else if (Array.isArray(content)) {
509
+ const block = content.find((b) => "text" in b);
510
+ text = block?.text ?? "";
498
511
  }
499
512
  const toolCallChunks = [];
500
513
  if (functionCalls) {
@@ -383,10 +383,13 @@ export function mapGenerateContentResultToChatResult(response, extra) {
383
383
  const [candidate] = response.candidates;
384
384
  const { content: candidateContent, ...generationInfo } = candidate;
385
385
  let content;
386
- if (candidateContent?.parts.length === 1 && candidateContent.parts[0].text) {
386
+ if (Array.isArray(candidateContent?.parts) &&
387
+ candidateContent.parts.length === 1 &&
388
+ candidateContent.parts[0].text) {
387
389
  content = candidateContent.parts[0].text;
388
390
  }
389
- else {
391
+ else if (Array.isArray(candidateContent?.parts) &&
392
+ candidateContent.parts.length > 0) {
390
393
  content = candidateContent.parts.map((p) => {
391
394
  if ("text" in p) {
392
395
  return {
@@ -409,17 +412,22 @@ export function mapGenerateContentResultToChatResult(response, extra) {
409
412
  return p;
410
413
  });
411
414
  }
415
+ else {
416
+ // no content returned - likely due to abnormal stop reason, e.g. malformed function call
417
+ content = [];
418
+ }
412
419
  let text = "";
413
420
  if (typeof content === "string") {
414
421
  text = content;
415
422
  }
416
- else if ("text" in content[0]) {
417
- text = content[0].text;
423
+ else if (Array.isArray(content) && content.length > 0) {
424
+ const block = content.find((b) => "text" in b);
425
+ text = block?.text ?? text;
418
426
  }
419
427
  const generation = {
420
428
  text,
421
429
  message: new AIMessage({
422
- content,
430
+ content: content ?? "",
423
431
  tool_calls: functionCalls?.map((fc) => {
424
432
  return {
425
433
  ...fc,
@@ -454,11 +462,11 @@ export function convertResponseContentToChatGenerationChunk(response, extra) {
454
462
  const { content: candidateContent, ...generationInfo } = candidate;
455
463
  let content;
456
464
  // Checks if some parts do not have text. If false, it means that the content is a string.
457
- if (candidateContent?.parts &&
465
+ if (Array.isArray(candidateContent?.parts) &&
458
466
  candidateContent.parts.every((p) => "text" in p)) {
459
467
  content = candidateContent.parts.map((p) => p.text).join("");
460
468
  }
461
- else if (candidateContent.parts) {
469
+ else if (Array.isArray(candidateContent?.parts)) {
462
470
  content = candidateContent.parts.map((p) => {
463
471
  if ("text" in p) {
464
472
  return {
@@ -481,12 +489,17 @@ export function convertResponseContentToChatGenerationChunk(response, extra) {
481
489
  return p;
482
490
  });
483
491
  }
492
+ else {
493
+ // no content returned - likely due to abnormal stop reason, e.g. malformed function call
494
+ content = [];
495
+ }
484
496
  let text = "";
485
497
  if (content && typeof content === "string") {
486
498
  text = content;
487
499
  }
488
- else if (content && typeof content === "object" && "text" in content[0]) {
489
- text = content[0].text;
500
+ else if (Array.isArray(content)) {
501
+ const block = content.find((b) => "text" in b);
502
+ text = block?.text ?? "";
490
503
  }
491
504
  const toolCallChunks = [];
492
505
  if (functionCalls) {
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.jsonSchemaToGeminiParameters = exports.schemaToGenerativeAIParameters = exports.removeAdditionalProperties = void 0;
5
5
  const types_1 = require("@langchain/core/utils/types");
6
- const zod_to_json_schema_1 = require("zod-to-json-schema");
6
+ const json_schema_1 = require("@langchain/core/utils/json_schema");
7
7
  function removeAdditionalProperties(
8
8
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
9
  obj) {
@@ -36,7 +36,7 @@ exports.removeAdditionalProperties = removeAdditionalProperties;
36
36
  function schemaToGenerativeAIParameters(schema) {
37
37
  // GenerativeAI doesn't accept either the $schema or additionalProperties
38
38
  // attributes, so we need to explicitly remove them.
39
- const jsonSchema = removeAdditionalProperties((0, types_1.isZodSchema)(schema) ? (0, zod_to_json_schema_1.zodToJsonSchema)(schema) : schema);
39
+ const jsonSchema = removeAdditionalProperties((0, types_1.isInteropZodSchema)(schema) ? (0, json_schema_1.toJsonSchema)(schema) : schema);
40
40
  const { $schema, ...rest } = jsonSchema;
41
41
  return rest;
42
42
  }
@@ -1,6 +1,6 @@
1
- import type { z } from "zod";
2
1
  import { type FunctionDeclarationSchema as GenerativeAIFunctionDeclarationSchema, type SchemaType as FunctionDeclarationSchemaType } from "@google/generative-ai";
3
- import { type JsonSchema7Type } from "zod-to-json-schema";
2
+ import { InteropZodType } from "@langchain/core/utils/types";
3
+ import { type JsonSchema7Type } from "@langchain/core/utils/json_schema";
4
4
  export interface GenerativeAIJsonSchema extends Record<string, unknown> {
5
5
  properties?: Record<string, GenerativeAIJsonSchema>;
6
6
  type: FunctionDeclarationSchemaType;
@@ -10,5 +10,5 @@ export interface GenerativeAIJsonSchemaDirty extends GenerativeAIJsonSchema {
10
10
  additionalProperties?: boolean;
11
11
  }
12
12
  export declare function removeAdditionalProperties(obj: Record<string, any>): GenerativeAIJsonSchema;
13
- export declare function schemaToGenerativeAIParameters<RunOutput extends Record<string, any> = Record<string, any>>(schema: z.ZodType<RunOutput> | z.ZodEffects<z.ZodType<RunOutput>> | JsonSchema7Type): GenerativeAIFunctionDeclarationSchema;
13
+ export declare function schemaToGenerativeAIParameters<RunOutput extends Record<string, any> = Record<string, any>>(schema: InteropZodType<RunOutput> | JsonSchema7Type): GenerativeAIFunctionDeclarationSchema;
14
14
  export declare function jsonSchemaToGeminiParameters(schema: Record<string, any>): GenerativeAIFunctionDeclarationSchema;
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
- import { isZodSchema } from "@langchain/core/utils/types";
3
- import { zodToJsonSchema } from "zod-to-json-schema";
2
+ import { isInteropZodSchema, } from "@langchain/core/utils/types";
3
+ import { toJsonSchema, } from "@langchain/core/utils/json_schema";
4
4
  export function removeAdditionalProperties(
5
5
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
6
  obj) {
@@ -32,7 +32,7 @@ obj) {
32
32
  export function schemaToGenerativeAIParameters(schema) {
33
33
  // GenerativeAI doesn't accept either the $schema or additionalProperties
34
34
  // attributes, so we need to explicitly remove them.
35
- const jsonSchema = removeAdditionalProperties(isZodSchema(schema) ? zodToJsonSchema(schema) : schema);
35
+ const jsonSchema = removeAdditionalProperties(isInteropZodSchema(schema) ? toJsonSchema(schema) : schema);
36
36
  const { $schema, ...rest } = jsonSchema;
37
37
  return rest;
38
38
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/google-genai",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "description": "Google Generative AI integration for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {
@@ -36,15 +36,14 @@
36
36
  "license": "MIT",
37
37
  "dependencies": {
38
38
  "@google/generative-ai": "^0.24.0",
39
- "uuid": "^11.1.0",
40
- "zod-to-json-schema": "^3.22.4"
39
+ "uuid": "^11.1.0"
41
40
  },
42
41
  "peerDependencies": {
43
- "@langchain/core": ">=0.3.55 <0.4.0"
42
+ "@langchain/core": ">=0.3.58 <0.4.0"
44
43
  },
45
44
  "devDependencies": {
46
45
  "@jest/globals": "^29.5.0",
47
- "@langchain/core": "0.3.57",
46
+ "@langchain/core": "workspace:*",
48
47
  "@langchain/scripts": ">=0.1.0 <0.2.0",
49
48
  "@langchain/standard-tests": "0.0.0",
50
49
  "@swc/core": "^1.3.90",
@@ -68,7 +67,7 @@
68
67
  "rollup": "^4.5.2",
69
68
  "ts-jest": "^29.1.0",
70
69
  "typescript": "<5.2.0",
71
- "zod": "^3.22.4"
70
+ "zod": "^3.25.32"
72
71
  },
73
72
  "publishConfig": {
74
73
  "access": "public"
@@ -92,4 +91,4 @@
92
91
  "index.d.ts",
93
92
  "index.d.cts"
94
93
  ]
95
- }
94
+ }