@langchain/google-common 0.1.4 → 0.1.6

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.
@@ -53,10 +53,33 @@ class ChatConnection extends connection_js_1.AbstractGoogleLLMConnection {
53
53
  }
54
54
  return true;
55
55
  }
56
+ computeGoogleSearchToolAdjustmentFromModel() {
57
+ if (this.modelName.startsWith("gemini-1.0")) {
58
+ return "googleSearchRetrieval";
59
+ }
60
+ else if (this.modelName.startsWith("gemini-1.5")) {
61
+ return "googleSearchRetrieval";
62
+ }
63
+ else {
64
+ return "googleSearch";
65
+ }
66
+ }
67
+ computeGoogleSearchToolAdjustment(apiConfig) {
68
+ const adj = apiConfig.googleSearchToolAdjustment;
69
+ if (adj === undefined || adj === true) {
70
+ return this.computeGoogleSearchToolAdjustmentFromModel();
71
+ }
72
+ else {
73
+ return adj;
74
+ }
75
+ }
56
76
  buildGeminiAPI() {
77
+ const apiConfig = this.apiConfig ?? {};
78
+ const googleSearchToolAdjustment = this.computeGoogleSearchToolAdjustment(apiConfig);
57
79
  const geminiConfig = {
58
80
  useSystemInstruction: this.useSystemInstruction,
59
- ...this.apiConfig,
81
+ googleSearchToolAdjustment,
82
+ ...apiConfig,
60
83
  };
61
84
  return (0, gemini_js_1.getGeminiAPI)(geminiConfig);
62
85
  }
@@ -199,7 +222,13 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
199
222
  return new auth_js_1.ApiKeyGoogleAuth(apiKey);
200
223
  }
201
224
  buildApiKey(fields) {
202
- return fields?.apiKey ?? (0, env_1.getEnvironmentVariable)("GOOGLE_API_KEY");
225
+ if (fields?.platformType !== "gcp") {
226
+ return fields?.apiKey ?? (0, env_1.getEnvironmentVariable)("GOOGLE_API_KEY");
227
+ }
228
+ else {
229
+ // GCP doesn't support API Keys
230
+ return undefined;
231
+ }
203
232
  }
204
233
  buildClient(fields) {
205
234
  const apiKey = this.buildApiKey(fields);
@@ -356,6 +385,7 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
356
385
  }
357
386
  const llm = this.bind({
358
387
  tools,
388
+ tool_choice: functionName,
359
389
  });
360
390
  if (!includeRaw) {
361
391
  return llm.pipe(outputParser).withConfig({
@@ -7,15 +7,17 @@ import { BaseLanguageModelInput, StructuredOutputMethodOptions } from "@langchai
7
7
  import type { z } from "zod";
8
8
  import { Runnable } from "@langchain/core/runnables";
9
9
  import { AsyncCaller } from "@langchain/core/utils/async_caller";
10
- import { GoogleAIBaseLLMInput, GoogleAIModelParams, GoogleAISafetySetting, GoogleConnectionParams, GooglePlatformType, GoogleAIBaseLanguageModelCallOptions, GoogleAIAPI, GoogleAIAPIParams } from "./types.js";
10
+ import { GoogleAIBaseLLMInput, GoogleAIModelParams, GoogleAISafetySetting, GoogleConnectionParams, GooglePlatformType, GoogleAIBaseLanguageModelCallOptions, GoogleAIAPI, GoogleAIAPIParams, GoogleSearchToolSetting } from "./types.js";
11
11
  import { AbstractGoogleLLMConnection } from "./connection.js";
12
12
  import { GoogleAbstractedClient } from "./auth.js";
13
- import type { GoogleBaseLLMInput, GoogleAISafetyHandler, GoogleAISafetyParams, GoogleAIToolType } from "./types.js";
13
+ import type { GoogleBaseLLMInput, GoogleAISafetyHandler, GoogleAISafetyParams, GoogleAIToolType, GeminiAPIConfig } from "./types.js";
14
14
  export declare class ChatConnection<AuthOptions> extends AbstractGoogleLLMConnection<BaseMessage[], AuthOptions> {
15
15
  convertSystemMessageToHumanContent: boolean | undefined;
16
16
  constructor(fields: GoogleAIBaseLLMInput<AuthOptions> | undefined, caller: AsyncCaller, client: GoogleAbstractedClient, streaming: boolean);
17
17
  get useSystemInstruction(): boolean;
18
18
  get computeUseSystemInstruction(): boolean;
19
+ computeGoogleSearchToolAdjustmentFromModel(): Exclude<GoogleSearchToolSetting, boolean>;
20
+ computeGoogleSearchToolAdjustment(apiConfig: GeminiAPIConfig): Exclude<GoogleSearchToolSetting, true>;
19
21
  buildGeminiAPI(): GoogleAIAPI;
20
22
  get api(): GoogleAIAPI;
21
23
  }
@@ -50,10 +50,33 @@ export class ChatConnection extends AbstractGoogleLLMConnection {
50
50
  }
51
51
  return true;
52
52
  }
53
+ computeGoogleSearchToolAdjustmentFromModel() {
54
+ if (this.modelName.startsWith("gemini-1.0")) {
55
+ return "googleSearchRetrieval";
56
+ }
57
+ else if (this.modelName.startsWith("gemini-1.5")) {
58
+ return "googleSearchRetrieval";
59
+ }
60
+ else {
61
+ return "googleSearch";
62
+ }
63
+ }
64
+ computeGoogleSearchToolAdjustment(apiConfig) {
65
+ const adj = apiConfig.googleSearchToolAdjustment;
66
+ if (adj === undefined || adj === true) {
67
+ return this.computeGoogleSearchToolAdjustmentFromModel();
68
+ }
69
+ else {
70
+ return adj;
71
+ }
72
+ }
53
73
  buildGeminiAPI() {
74
+ const apiConfig = this.apiConfig ?? {};
75
+ const googleSearchToolAdjustment = this.computeGoogleSearchToolAdjustment(apiConfig);
54
76
  const geminiConfig = {
55
77
  useSystemInstruction: this.useSystemInstruction,
56
- ...this.apiConfig,
78
+ googleSearchToolAdjustment,
79
+ ...apiConfig,
57
80
  };
58
81
  return getGeminiAPI(geminiConfig);
59
82
  }
@@ -195,7 +218,13 @@ export class ChatGoogleBase extends BaseChatModel {
195
218
  return new ApiKeyGoogleAuth(apiKey);
196
219
  }
197
220
  buildApiKey(fields) {
198
- return fields?.apiKey ?? getEnvironmentVariable("GOOGLE_API_KEY");
221
+ if (fields?.platformType !== "gcp") {
222
+ return fields?.apiKey ?? getEnvironmentVariable("GOOGLE_API_KEY");
223
+ }
224
+ else {
225
+ // GCP doesn't support API Keys
226
+ return undefined;
227
+ }
199
228
  }
200
229
  buildClient(fields) {
201
230
  const apiKey = this.buildApiKey(fields);
@@ -352,6 +381,7 @@ export class ChatGoogleBase extends BaseChatModel {
352
381
  }
353
382
  const llm = this.bind({
354
383
  tools,
384
+ tool_choice: functionName,
355
385
  });
356
386
  if (!includeRaw) {
357
387
  return llm.pipe(outputParser).withConfig({
@@ -19,6 +19,10 @@ class EmbeddingsConnection extends connection_js_1.GoogleAIConnection {
19
19
  async buildUrlMethod() {
20
20
  return "predict";
21
21
  }
22
+ get modelPublisher() {
23
+ // All the embedding models are currently published by "google"
24
+ return "google";
25
+ }
22
26
  async formatData(input, parameters) {
23
27
  return {
24
28
  instances: input,
@@ -16,6 +16,10 @@ class EmbeddingsConnection extends GoogleAIConnection {
16
16
  async buildUrlMethod() {
17
17
  return "predict";
18
18
  }
19
+ get modelPublisher() {
20
+ // All the embedding models are currently published by "google"
21
+ return "google";
22
+ }
19
23
  async formatData(input, parameters) {
20
24
  return {
21
25
  instances: input,
package/dist/index.cjs CHANGED
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./chat_models.cjs"), exports);
18
18
  __exportStar(require("./llms.cjs"), exports);
19
19
  __exportStar(require("./embeddings.cjs"), exports);
20
+ __exportStar(require("./output_parsers.cjs"), exports);
20
21
  __exportStar(require("./auth.cjs"), exports);
21
22
  __exportStar(require("./connection.cjs"), exports);
22
23
  __exportStar(require("./types.cjs"), exports);
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./chat_models.js";
2
2
  export * from "./llms.js";
3
3
  export * from "./embeddings.js";
4
+ export * from "./output_parsers.js";
4
5
  export * from "./auth.js";
5
6
  export * from "./connection.js";
6
7
  export * from "./types.js";
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./chat_models.js";
2
2
  export * from "./llms.js";
3
3
  export * from "./embeddings.js";
4
+ export * from "./output_parsers.js";
4
5
  export * from "./auth.js";
5
6
  export * from "./connection.js";
6
7
  export * from "./types.js";
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MarkdownGoogleSearchOutputParser = exports.SimpleGoogleSearchOutputParser = exports.BaseGoogleSearchOutputParser = void 0;
4
+ const output_parsers_1 = require("@langchain/core/output_parsers");
5
+ class BaseGoogleSearchOutputParser extends output_parsers_1.BaseLLMOutputParser {
6
+ constructor() {
7
+ super(...arguments);
8
+ Object.defineProperty(this, "lc_namespace", {
9
+ enumerable: true,
10
+ configurable: true,
11
+ writable: true,
12
+ value: ["google_common", "output_parsers"]
13
+ });
14
+ }
15
+ generationToGroundingInfo(generation) {
16
+ if ("message" in generation) {
17
+ const responseMetadata = generation?.message?.response_metadata;
18
+ const metadata = responseMetadata.groundingMetadata;
19
+ const supports = responseMetadata.groundingSupport ?? metadata.groundingSupports ?? [];
20
+ if (metadata) {
21
+ return {
22
+ metadata,
23
+ supports,
24
+ };
25
+ }
26
+ }
27
+ return undefined;
28
+ }
29
+ generationsToGroundingInfo(generations) {
30
+ for (const generation of generations) {
31
+ const info = this.generationToGroundingInfo(generation);
32
+ if (info !== undefined) {
33
+ return info;
34
+ }
35
+ }
36
+ return undefined;
37
+ }
38
+ generationToString(generation) {
39
+ if ("message" in generation) {
40
+ const content = generation?.message?.content;
41
+ if (typeof content === "string") {
42
+ return content;
43
+ }
44
+ else {
45
+ return content
46
+ .map((c) => {
47
+ if (c?.type === "text") {
48
+ return c?.text ?? "";
49
+ }
50
+ else {
51
+ return "";
52
+ }
53
+ })
54
+ .reduce((previousValue, currentValue) => `${previousValue}${currentValue}`);
55
+ }
56
+ }
57
+ return generation.text;
58
+ }
59
+ generationsToString(generations) {
60
+ return generations
61
+ .map((generation) => this.generationToString(generation))
62
+ .reduce((previousValue, currentValue) => `${previousValue}${currentValue}`);
63
+ }
64
+ annotateSegment(text, grounding, support, index) {
65
+ const start = support.segment.startIndex ?? 0;
66
+ const end = support.segment.endIndex;
67
+ const textBefore = text.substring(0, start);
68
+ const textSegment = text.substring(start, end);
69
+ const textAfter = text.substring(end);
70
+ const textPrefix = this.segmentPrefix(grounding, support, index) ?? "";
71
+ const textSuffix = this.segmentSuffix(grounding, support, index) ?? "";
72
+ return `${textBefore}${textPrefix}${textSegment}${textSuffix}${textAfter}`;
73
+ }
74
+ annotateTextSegments(text, grounding) {
75
+ // Go through each support info in reverse, since the segment info
76
+ // is sorted, and we won't need to adjust string indexes this way.
77
+ let ret = text;
78
+ for (let co = grounding.supports.length - 1; co >= 0; co -= 1) {
79
+ const support = grounding.supports[co];
80
+ ret = this.annotateSegment(ret, grounding, support, co);
81
+ }
82
+ return ret;
83
+ }
84
+ /**
85
+ * Google requires us to
86
+ * "Display the Search Suggestion exactly as provided without any modifications"
87
+ * So this will typically be called from the textSuffix() method to get
88
+ * a string that renders HTML.
89
+ * See https://ai.google.dev/gemini-api/docs/grounding/search-suggestions
90
+ * @param grounding
91
+ */
92
+ searchSuggestion(grounding) {
93
+ return grounding.metadata.searchEntryPoint?.renderedContent ?? "";
94
+ }
95
+ annotateText(text, grounding) {
96
+ const prefix = this.textPrefix(text, grounding) ?? "";
97
+ const suffix = this.textSuffix(text, grounding) ?? "";
98
+ const body = this.annotateTextSegments(text, grounding);
99
+ return `${prefix}${body}${suffix}`;
100
+ }
101
+ async parseResult(generations, _callbacks) {
102
+ const text = this.generationsToString(generations);
103
+ const grounding = this.generationsToGroundingInfo(generations);
104
+ if (!grounding) {
105
+ return text;
106
+ }
107
+ return this.annotateText(text, grounding);
108
+ }
109
+ }
110
+ exports.BaseGoogleSearchOutputParser = BaseGoogleSearchOutputParser;
111
+ class SimpleGoogleSearchOutputParser extends BaseGoogleSearchOutputParser {
112
+ segmentPrefix(_grounding, _support, _index) {
113
+ return undefined;
114
+ }
115
+ segmentSuffix(_grounding, support, _index) {
116
+ const indices = support.groundingChunkIndices.map((i) => i + 1);
117
+ return ` [${indices.join(", ")}]`;
118
+ }
119
+ textPrefix(_text, _grounding) {
120
+ return "Google Says:\n";
121
+ }
122
+ chunkToString(chunk, index) {
123
+ const info = chunk.retrievedContext ?? chunk.web;
124
+ return `${index + 1}. ${info.title} - ${info.uri}`;
125
+ }
126
+ textSuffix(_text, grounding) {
127
+ let ret = "\n";
128
+ const chunks = grounding.metadata.groundingChunks;
129
+ chunks.forEach((chunk, index) => {
130
+ ret = `${ret}${this.chunkToString(chunk, index)}\n`;
131
+ });
132
+ return ret;
133
+ }
134
+ }
135
+ exports.SimpleGoogleSearchOutputParser = SimpleGoogleSearchOutputParser;
136
+ class MarkdownGoogleSearchOutputParser extends BaseGoogleSearchOutputParser {
137
+ segmentPrefix(_grounding, _support, _index) {
138
+ return undefined;
139
+ }
140
+ chunkLink(grounding, index) {
141
+ const chunk = grounding.metadata.groundingChunks[index];
142
+ const url = chunk.retrievedContext?.uri ?? chunk.web?.uri;
143
+ const num = index + 1;
144
+ return `[[${num}](${url})]`;
145
+ }
146
+ segmentSuffix(grounding, support, _index) {
147
+ let ret = "";
148
+ support.groundingChunkIndices.forEach((chunkIndex) => {
149
+ const link = this.chunkLink(grounding, chunkIndex);
150
+ ret = `${ret}${link}`;
151
+ });
152
+ return ret;
153
+ }
154
+ textPrefix(_text, _grounding) {
155
+ return undefined;
156
+ }
157
+ chunkSuffixLink(chunk, index) {
158
+ const num = index + 1;
159
+ const info = chunk.retrievedContext ?? chunk.web;
160
+ const url = info.uri;
161
+ const site = info.title;
162
+ return `${num}. [${site}](${url})`;
163
+ }
164
+ textSuffix(_text, grounding) {
165
+ let ret = "\n**Search Sources**\n";
166
+ const chunks = grounding.metadata.groundingChunks;
167
+ chunks.forEach((chunk, index) => {
168
+ ret = `${ret}${this.chunkSuffixLink(chunk, index)}\n`;
169
+ });
170
+ const search = this.searchSuggestion(grounding);
171
+ ret = `${ret}\n${search}`;
172
+ return ret;
173
+ }
174
+ }
175
+ exports.MarkdownGoogleSearchOutputParser = MarkdownGoogleSearchOutputParser;
@@ -0,0 +1,49 @@
1
+ import { BaseLLMOutputParser } from "@langchain/core/output_parsers";
2
+ import { Callbacks } from "@langchain/core/callbacks/manager";
3
+ import { ChatGeneration, Generation } from "@langchain/core/outputs";
4
+ import { GeminiGroundingChunk, GeminiGroundingMetadata, GeminiGroundingSupport } from "./types.js";
5
+ type Generations = Generation[] | ChatGeneration[];
6
+ type GroundingInfo = {
7
+ metadata: GeminiGroundingMetadata;
8
+ supports: GeminiGroundingSupport[];
9
+ };
10
+ export declare abstract class BaseGoogleSearchOutputParser extends BaseLLMOutputParser<string> {
11
+ lc_namespace: string[];
12
+ protected generationToGroundingInfo(generation: Generation | ChatGeneration): GroundingInfo | undefined;
13
+ protected generationsToGroundingInfo(generations: Generations): GroundingInfo | undefined;
14
+ protected generationToString(generation: Generation | ChatGeneration): string;
15
+ protected generationsToString(generations: Generations): string;
16
+ protected abstract segmentPrefix(grounding: GroundingInfo, support: GeminiGroundingSupport, index: number): string | undefined;
17
+ protected abstract segmentSuffix(grounding: GroundingInfo, support: GeminiGroundingSupport, index: number): string | undefined;
18
+ protected annotateSegment(text: string, grounding: GroundingInfo, support: GeminiGroundingSupport, index: number): string;
19
+ protected annotateTextSegments(text: string, grounding: GroundingInfo): string;
20
+ protected abstract textPrefix(text: string, grounding: GroundingInfo): string | undefined;
21
+ protected abstract textSuffix(text: string, grounding: GroundingInfo): string | undefined;
22
+ /**
23
+ * Google requires us to
24
+ * "Display the Search Suggestion exactly as provided without any modifications"
25
+ * So this will typically be called from the textSuffix() method to get
26
+ * a string that renders HTML.
27
+ * See https://ai.google.dev/gemini-api/docs/grounding/search-suggestions
28
+ * @param grounding
29
+ */
30
+ protected searchSuggestion(grounding: GroundingInfo): string;
31
+ protected annotateText(text: string, grounding: GroundingInfo): string;
32
+ parseResult(generations: Generations, _callbacks?: Callbacks): Promise<string>;
33
+ }
34
+ export declare class SimpleGoogleSearchOutputParser extends BaseGoogleSearchOutputParser {
35
+ protected segmentPrefix(_grounding: GroundingInfo, _support: GeminiGroundingSupport, _index: number): string | undefined;
36
+ protected segmentSuffix(_grounding: GroundingInfo, support: GeminiGroundingSupport, _index: number): string | undefined;
37
+ protected textPrefix(_text: string, _grounding: GroundingInfo): string;
38
+ protected chunkToString(chunk: GeminiGroundingChunk, index: number): string;
39
+ protected textSuffix(_text: string, grounding: GroundingInfo): string;
40
+ }
41
+ export declare class MarkdownGoogleSearchOutputParser extends BaseGoogleSearchOutputParser {
42
+ protected segmentPrefix(_grounding: GroundingInfo, _support: GeminiGroundingSupport, _index: number): string | undefined;
43
+ protected chunkLink(grounding: GroundingInfo, index: number): string;
44
+ protected segmentSuffix(grounding: GroundingInfo, support: GeminiGroundingSupport, _index: number): string | undefined;
45
+ protected textPrefix(_text: string, _grounding: GroundingInfo): string | undefined;
46
+ protected chunkSuffixLink(chunk: GeminiGroundingChunk, index: number): string;
47
+ protected textSuffix(_text: string, grounding: GroundingInfo): string | undefined;
48
+ }
49
+ export {};
@@ -0,0 +1,169 @@
1
+ import { BaseLLMOutputParser } from "@langchain/core/output_parsers";
2
+ export class BaseGoogleSearchOutputParser extends BaseLLMOutputParser {
3
+ constructor() {
4
+ super(...arguments);
5
+ Object.defineProperty(this, "lc_namespace", {
6
+ enumerable: true,
7
+ configurable: true,
8
+ writable: true,
9
+ value: ["google_common", "output_parsers"]
10
+ });
11
+ }
12
+ generationToGroundingInfo(generation) {
13
+ if ("message" in generation) {
14
+ const responseMetadata = generation?.message?.response_metadata;
15
+ const metadata = responseMetadata.groundingMetadata;
16
+ const supports = responseMetadata.groundingSupport ?? metadata.groundingSupports ?? [];
17
+ if (metadata) {
18
+ return {
19
+ metadata,
20
+ supports,
21
+ };
22
+ }
23
+ }
24
+ return undefined;
25
+ }
26
+ generationsToGroundingInfo(generations) {
27
+ for (const generation of generations) {
28
+ const info = this.generationToGroundingInfo(generation);
29
+ if (info !== undefined) {
30
+ return info;
31
+ }
32
+ }
33
+ return undefined;
34
+ }
35
+ generationToString(generation) {
36
+ if ("message" in generation) {
37
+ const content = generation?.message?.content;
38
+ if (typeof content === "string") {
39
+ return content;
40
+ }
41
+ else {
42
+ return content
43
+ .map((c) => {
44
+ if (c?.type === "text") {
45
+ return c?.text ?? "";
46
+ }
47
+ else {
48
+ return "";
49
+ }
50
+ })
51
+ .reduce((previousValue, currentValue) => `${previousValue}${currentValue}`);
52
+ }
53
+ }
54
+ return generation.text;
55
+ }
56
+ generationsToString(generations) {
57
+ return generations
58
+ .map((generation) => this.generationToString(generation))
59
+ .reduce((previousValue, currentValue) => `${previousValue}${currentValue}`);
60
+ }
61
+ annotateSegment(text, grounding, support, index) {
62
+ const start = support.segment.startIndex ?? 0;
63
+ const end = support.segment.endIndex;
64
+ const textBefore = text.substring(0, start);
65
+ const textSegment = text.substring(start, end);
66
+ const textAfter = text.substring(end);
67
+ const textPrefix = this.segmentPrefix(grounding, support, index) ?? "";
68
+ const textSuffix = this.segmentSuffix(grounding, support, index) ?? "";
69
+ return `${textBefore}${textPrefix}${textSegment}${textSuffix}${textAfter}`;
70
+ }
71
+ annotateTextSegments(text, grounding) {
72
+ // Go through each support info in reverse, since the segment info
73
+ // is sorted, and we won't need to adjust string indexes this way.
74
+ let ret = text;
75
+ for (let co = grounding.supports.length - 1; co >= 0; co -= 1) {
76
+ const support = grounding.supports[co];
77
+ ret = this.annotateSegment(ret, grounding, support, co);
78
+ }
79
+ return ret;
80
+ }
81
+ /**
82
+ * Google requires us to
83
+ * "Display the Search Suggestion exactly as provided without any modifications"
84
+ * So this will typically be called from the textSuffix() method to get
85
+ * a string that renders HTML.
86
+ * See https://ai.google.dev/gemini-api/docs/grounding/search-suggestions
87
+ * @param grounding
88
+ */
89
+ searchSuggestion(grounding) {
90
+ return grounding.metadata.searchEntryPoint?.renderedContent ?? "";
91
+ }
92
+ annotateText(text, grounding) {
93
+ const prefix = this.textPrefix(text, grounding) ?? "";
94
+ const suffix = this.textSuffix(text, grounding) ?? "";
95
+ const body = this.annotateTextSegments(text, grounding);
96
+ return `${prefix}${body}${suffix}`;
97
+ }
98
+ async parseResult(generations, _callbacks) {
99
+ const text = this.generationsToString(generations);
100
+ const grounding = this.generationsToGroundingInfo(generations);
101
+ if (!grounding) {
102
+ return text;
103
+ }
104
+ return this.annotateText(text, grounding);
105
+ }
106
+ }
107
+ export class SimpleGoogleSearchOutputParser extends BaseGoogleSearchOutputParser {
108
+ segmentPrefix(_grounding, _support, _index) {
109
+ return undefined;
110
+ }
111
+ segmentSuffix(_grounding, support, _index) {
112
+ const indices = support.groundingChunkIndices.map((i) => i + 1);
113
+ return ` [${indices.join(", ")}]`;
114
+ }
115
+ textPrefix(_text, _grounding) {
116
+ return "Google Says:\n";
117
+ }
118
+ chunkToString(chunk, index) {
119
+ const info = chunk.retrievedContext ?? chunk.web;
120
+ return `${index + 1}. ${info.title} - ${info.uri}`;
121
+ }
122
+ textSuffix(_text, grounding) {
123
+ let ret = "\n";
124
+ const chunks = grounding.metadata.groundingChunks;
125
+ chunks.forEach((chunk, index) => {
126
+ ret = `${ret}${this.chunkToString(chunk, index)}\n`;
127
+ });
128
+ return ret;
129
+ }
130
+ }
131
+ export class MarkdownGoogleSearchOutputParser extends BaseGoogleSearchOutputParser {
132
+ segmentPrefix(_grounding, _support, _index) {
133
+ return undefined;
134
+ }
135
+ chunkLink(grounding, index) {
136
+ const chunk = grounding.metadata.groundingChunks[index];
137
+ const url = chunk.retrievedContext?.uri ?? chunk.web?.uri;
138
+ const num = index + 1;
139
+ return `[[${num}](${url})]`;
140
+ }
141
+ segmentSuffix(grounding, support, _index) {
142
+ let ret = "";
143
+ support.groundingChunkIndices.forEach((chunkIndex) => {
144
+ const link = this.chunkLink(grounding, chunkIndex);
145
+ ret = `${ret}${link}`;
146
+ });
147
+ return ret;
148
+ }
149
+ textPrefix(_text, _grounding) {
150
+ return undefined;
151
+ }
152
+ chunkSuffixLink(chunk, index) {
153
+ const num = index + 1;
154
+ const info = chunk.retrievedContext ?? chunk.web;
155
+ const url = info.uri;
156
+ const site = info.title;
157
+ return `${num}. [${site}](${url})`;
158
+ }
159
+ textSuffix(_text, grounding) {
160
+ let ret = "\n**Search Sources**\n";
161
+ const chunks = grounding.metadata.groundingChunks;
162
+ chunks.forEach((chunk, index) => {
163
+ ret = `${ret}${this.chunkSuffixLink(chunk, index)}\n`;
164
+ });
165
+ const search = this.searchSuggestion(grounding);
166
+ ret = `${ret}\n${search}`;
167
+ return ret;
168
+ }
169
+ }
package/dist/types.cjs CHANGED
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.GoogleAISafetyMethod = exports.GoogleAISafetyThreshold = exports.GoogleAISafetyCategory = void 0;
17
+ exports.GeminiToolAttributes = exports.GeminiSearchToolAttributes = exports.GoogleAISafetyMethod = exports.GoogleAISafetyThreshold = exports.GoogleAISafetyCategory = void 0;
18
18
  __exportStar(require("./types-anthropic.cjs"), exports);
19
19
  exports.GoogleAISafetyCategory = {
20
20
  Harassment: "HARM_CATEGORY_HARASSMENT",
@@ -54,3 +54,12 @@ exports.GoogleAISafetyMethod = {
54
54
  Severity: "SEVERITY",
55
55
  Probability: "PROBABILITY",
56
56
  };
57
+ exports.GeminiSearchToolAttributes = [
58
+ "googleSearchRetrieval",
59
+ "googleSearch",
60
+ ];
61
+ exports.GeminiToolAttributes = [
62
+ "functionDeclaration",
63
+ "retrieval",
64
+ ...exports.GeminiSearchToolAttributes,
65
+ ];
package/dist/types.d.ts CHANGED
@@ -219,6 +219,60 @@ export type GeminiSafetyRating = {
219
219
  category: string;
220
220
  probability: string;
221
221
  } & Record<string, unknown>;
222
+ export interface GeminiCitationMetadata {
223
+ citations: GeminiCitation[];
224
+ }
225
+ export interface GeminiCitation {
226
+ startIndex: number;
227
+ endIndex: number;
228
+ uri: string;
229
+ title: string;
230
+ license: string;
231
+ publicationDate: GoogleTypeDate;
232
+ }
233
+ export interface GoogleTypeDate {
234
+ year: number;
235
+ month: number;
236
+ day: number;
237
+ }
238
+ export interface GeminiGroundingMetadata {
239
+ webSearchQueries?: string[];
240
+ searchEntryPoint?: GeminiSearchEntryPoint;
241
+ groundingChunks: GeminiGroundingChunk[];
242
+ groundingSupports?: GeminiGroundingSupport[];
243
+ retrievalMetadata?: GeminiRetrievalMetadata;
244
+ }
245
+ export interface GeminiSearchEntryPoint {
246
+ renderedContent?: string;
247
+ sdkBlob?: string;
248
+ }
249
+ export interface GeminiGroundingChunk {
250
+ web: GeminiGroundingChunkWeb;
251
+ retrievedContext: GeminiGroundingChunkRetrievedContext;
252
+ }
253
+ export interface GeminiGroundingChunkWeb {
254
+ uri: string;
255
+ title: string;
256
+ }
257
+ export interface GeminiGroundingChunkRetrievedContext {
258
+ uri: string;
259
+ title: string;
260
+ text: string;
261
+ }
262
+ export interface GeminiGroundingSupport {
263
+ segment: GeminiSegment;
264
+ groundingChunkIndices: number[];
265
+ confidenceScores: number[];
266
+ }
267
+ export interface GeminiSegment {
268
+ partIndex: number;
269
+ startIndex: number;
270
+ endIndex: number;
271
+ text: string;
272
+ }
273
+ export interface GeminiRetrievalMetadata {
274
+ googleSearchDynamicRetrievalScore: number;
275
+ }
222
276
  export type GeminiRole = "system" | "user" | "model" | "function";
223
277
  export interface GeminiContent {
224
278
  parts: GeminiPart[];
@@ -227,14 +281,20 @@ export interface GeminiContent {
227
281
  export interface GeminiTool {
228
282
  functionDeclarations?: GeminiFunctionDeclaration[];
229
283
  googleSearchRetrieval?: GoogleSearchRetrieval;
284
+ googleSearch?: GoogleSearch;
230
285
  retrieval?: VertexAIRetrieval;
231
286
  }
287
+ export type GoogleSearchToolSetting = boolean | "googleSearchRetrieval" | "googleSearch" | string;
288
+ export declare const GeminiSearchToolAttributes: string[];
289
+ export declare const GeminiToolAttributes: string[];
232
290
  export interface GoogleSearchRetrieval {
233
291
  dynamicRetrievalConfig?: {
234
292
  mode?: string;
235
293
  dynamicThreshold?: number;
236
294
  };
237
295
  }
296
+ export interface GoogleSearch {
297
+ }
238
298
  export interface VertexAIRetrieval {
239
299
  vertexAiSearch: {
240
300
  datastore: string;
@@ -288,6 +348,8 @@ interface GeminiResponseCandidate {
288
348
  index: number;
289
349
  tokenCount?: number;
290
350
  safetyRatings: GeminiSafetyRating[];
351
+ citationMetadata?: GeminiCitationMetadata;
352
+ groundingMetadata?: GeminiGroundingMetadata;
291
353
  }
292
354
  interface GeminiResponsePromptFeedback {
293
355
  blockReason?: string;
@@ -339,6 +401,17 @@ export interface GeminiAPIConfig {
339
401
  safetyHandler?: GoogleAISafetyHandler;
340
402
  mediaManager?: MediaManager;
341
403
  useSystemInstruction?: boolean;
404
+ /**
405
+ * How to handle the Google Search tool, since the name (and format)
406
+ * of the tool changes between Gemini 1.5 and Gemini 2.0.
407
+ * true - Change based on the model version. (Default)
408
+ * false - Do not change the tool name provided
409
+ * string value - Use this as the attribute name for the search
410
+ * tool, adapting any tool attributes if possible.
411
+ * When the model is created, a "true" or default setting
412
+ * will be changed to a string based on the model.
413
+ */
414
+ googleSearchToolAdjustment?: GoogleSearchToolSetting;
342
415
  }
343
416
  export type GoogleAIAPIConfig = GeminiAPIConfig | AnthropicAPIConfig;
344
417
  export interface GoogleAIAPIParams {
package/dist/types.js CHANGED
@@ -37,3 +37,12 @@ export const GoogleAISafetyMethod = {
37
37
  Severity: "SEVERITY",
38
38
  Probability: "PROBABILITY",
39
39
  };
40
+ export const GeminiSearchToolAttributes = [
41
+ "googleSearchRetrieval",
42
+ "googleSearch",
43
+ ];
44
+ export const GeminiToolAttributes = [
45
+ "functionDeclaration",
46
+ "retrieval",
47
+ ...GeminiSearchToolAttributes,
48
+ ];
@@ -4,6 +4,7 @@ exports.copyAndValidateModelParamsInto = exports.validateModelParams = exports.m
4
4
  const base_1 = require("@langchain/core/language_models/base");
5
5
  const function_calling_1 = require("@langchain/core/utils/function_calling");
6
6
  const gemini_js_1 = require("./gemini.cjs");
7
+ const types_js_1 = require("../types.cjs");
7
8
  const zod_to_gemini_parameters_js_1 = require("./zod_to_gemini_parameters.cjs");
8
9
  const anthropic_js_1 = require("./anthropic.cjs");
9
10
  function copyAIModelParams(params, options) {
@@ -37,11 +38,22 @@ function processToolChoice(toolChoice, allowedFunctionNames) {
37
38
  }
38
39
  throw new Error("Object inputs for tool_choice not supported.");
39
40
  }
41
+ function isGeminiTool(tool) {
42
+ for (const toolAttribute of types_js_1.GeminiToolAttributes) {
43
+ if (toolAttribute in tool) {
44
+ return true;
45
+ }
46
+ }
47
+ return false;
48
+ }
49
+ function isGeminiNonFunctionTool(tool) {
50
+ return isGeminiTool(tool) && !("functionDeclaration" in tool);
51
+ }
40
52
  function convertToGeminiTools(tools) {
41
53
  const geminiTools = [];
42
54
  let functionDeclarationsIndex = -1;
43
55
  tools.forEach((tool) => {
44
- if ("googleSearchRetrieval" in tool || "retrieval" in tool) {
56
+ if (isGeminiNonFunctionTool(tool)) {
45
57
  geminiTools.push(tool);
46
58
  }
47
59
  else {
@@ -1,4 +1,4 @@
1
- import type { GeminiTool, GoogleAIBaseLanguageModelCallOptions, GoogleAIModelParams, GoogleAIModelRequestParams, GoogleAIToolType, VertexModelFamily } from "../types.js";
1
+ import { GeminiTool, GoogleAIBaseLanguageModelCallOptions, GoogleAIModelParams, GoogleAIModelRequestParams, GoogleAIToolType, VertexModelFamily } from "../types.js";
2
2
  export declare function copyAIModelParams(params: GoogleAIModelParams | undefined, options: GoogleAIBaseLanguageModelCallOptions | undefined): GoogleAIModelRequestParams;
3
3
  export declare function convertToGeminiTools(tools: GoogleAIToolType[]): GeminiTool[];
4
4
  export declare function copyAIModelParamsInto(params: GoogleAIModelParams | undefined, options: GoogleAIBaseLanguageModelCallOptions | undefined, target: GoogleAIModelParams): GoogleAIModelRequestParams;
@@ -1,6 +1,7 @@
1
1
  import { isOpenAITool } from "@langchain/core/language_models/base";
2
2
  import { isLangChainTool } from "@langchain/core/utils/function_calling";
3
3
  import { isModelGemini, validateGeminiParams } from "./gemini.js";
4
+ import { GeminiToolAttributes, } from "../types.js";
4
5
  import { jsonSchemaToGeminiParameters, zodToGeminiParameters, } from "./zod_to_gemini_parameters.js";
5
6
  import { isModelClaude, validateClaudeParams } from "./anthropic.js";
6
7
  export function copyAIModelParams(params, options) {
@@ -33,11 +34,22 @@ function processToolChoice(toolChoice, allowedFunctionNames) {
33
34
  }
34
35
  throw new Error("Object inputs for tool_choice not supported.");
35
36
  }
37
+ function isGeminiTool(tool) {
38
+ for (const toolAttribute of GeminiToolAttributes) {
39
+ if (toolAttribute in tool) {
40
+ return true;
41
+ }
42
+ }
43
+ return false;
44
+ }
45
+ function isGeminiNonFunctionTool(tool) {
46
+ return isGeminiTool(tool) && !("functionDeclaration" in tool);
47
+ }
36
48
  export function convertToGeminiTools(tools) {
37
49
  const geminiTools = [];
38
50
  let functionDeclarationsIndex = -1;
39
51
  tools.forEach((tool) => {
40
- if ("googleSearchRetrieval" in tool || "retrieval" in tool) {
52
+ if (isGeminiNonFunctionTool(tool)) {
41
53
  geminiTools.push(tool);
42
54
  }
43
55
  else {
@@ -6,6 +6,7 @@ const messages_1 = require("@langchain/core/messages");
6
6
  const outputs_1 = require("@langchain/core/outputs");
7
7
  const function_calling_1 = require("@langchain/core/utils/function_calling");
8
8
  const safety_js_1 = require("./safety.cjs");
9
+ const types_js_1 = require("../types.cjs");
9
10
  const zod_to_gemini_parameters_js_1 = require("./zod_to_gemini_parameters.cjs");
10
11
  class DefaultGeminiSafetyHandler {
11
12
  constructor(settings) {
@@ -523,6 +524,8 @@ function getGeminiAPI(config) {
523
524
  severity: rating.severity,
524
525
  severity_score: rating.severityScore,
525
526
  })),
527
+ citation_metadata: data.candidates[0]?.citationMetadata,
528
+ grounding_metadata: data.candidates[0]?.groundingMetadata,
526
529
  finish_reason: data.candidates[0]?.finishReason,
527
530
  };
528
531
  }
@@ -577,12 +580,59 @@ function getGeminiAPI(config) {
577
580
  message,
578
581
  });
579
582
  }
580
- function responseToChatGenerations(response) {
583
+ function groundingSupportByPart(groundingSupports) {
584
+ const ret = [];
585
+ if (!groundingSupports || groundingSupports.length === 0) {
586
+ return [];
587
+ }
588
+ groundingSupports?.forEach((groundingSupport) => {
589
+ const segment = groundingSupport?.segment;
590
+ const partIndex = segment?.partIndex ?? 0;
591
+ if (ret[partIndex]) {
592
+ ret[partIndex].push(groundingSupport);
593
+ }
594
+ else {
595
+ ret[partIndex] = [groundingSupport];
596
+ }
597
+ });
598
+ return ret;
599
+ }
600
+ function responseToGroundedChatGenerations(response) {
581
601
  const parts = responseToParts(response);
582
602
  if (parts.length === 0) {
583
603
  return [];
584
604
  }
585
- let ret = parts.map((part) => partToChatGeneration(part));
605
+ // Citation and grounding information connected to each part / ChatGeneration
606
+ // to make sure they are available in downstream filters.
607
+ const candidate = response?.data
608
+ ?.candidates?.[0];
609
+ const groundingMetadata = candidate?.groundingMetadata;
610
+ const citationMetadata = candidate?.citationMetadata;
611
+ const groundingParts = groundingSupportByPart(groundingMetadata?.groundingSupports);
612
+ const ret = parts.map((part, index) => {
613
+ const gen = partToChatGeneration(part);
614
+ if (!gen.generationInfo) {
615
+ gen.generationInfo = {};
616
+ }
617
+ if (groundingMetadata) {
618
+ gen.generationInfo.groundingMetadata = groundingMetadata;
619
+ const groundingPart = groundingParts[index];
620
+ if (groundingPart) {
621
+ gen.generationInfo.groundingSupport = groundingPart;
622
+ }
623
+ }
624
+ if (citationMetadata) {
625
+ gen.generationInfo.citationMetadata = citationMetadata;
626
+ }
627
+ return gen;
628
+ });
629
+ return ret;
630
+ }
631
+ function responseToChatGenerations(response) {
632
+ let ret = responseToGroundedChatGenerations(response);
633
+ if (ret.length === 0) {
634
+ return [];
635
+ }
586
636
  if (ret.every((item) => typeof item.message.content === "string")) {
587
637
  const combinedContent = ret.map((item) => item.message.content).join("");
588
638
  const combinedText = ret.map((item) => item.text).join("");
@@ -788,14 +838,43 @@ function getGeminiAPI(config) {
788
838
  parameters: jsonSchema,
789
839
  };
790
840
  }
841
+ function searchToolName(tool) {
842
+ for (const name of types_js_1.GeminiSearchToolAttributes) {
843
+ if (name in tool) {
844
+ return name;
845
+ }
846
+ }
847
+ return undefined;
848
+ }
849
+ function cleanGeminiTool(tool) {
850
+ const orig = searchToolName(tool);
851
+ const adj = config?.googleSearchToolAdjustment;
852
+ if (orig && adj && adj !== orig) {
853
+ return {
854
+ [adj]: {},
855
+ };
856
+ }
857
+ else {
858
+ return tool;
859
+ }
860
+ }
791
861
  function formatTools(parameters) {
792
862
  const tools = parameters?.tools;
793
863
  if (!tools || tools.length === 0) {
794
864
  return [];
795
865
  }
796
- // Group all LangChain tools into a single functionDeclarations array
797
- const langChainTools = tools.filter(function_calling_1.isLangChainTool);
798
- const otherTools = tools.filter((tool) => !(0, function_calling_1.isLangChainTool)(tool));
866
+ // Group all LangChain tools into a single functionDeclarations array.
867
+ // Gemini Tools may be normalized to different tool names
868
+ const langChainTools = [];
869
+ const otherTools = [];
870
+ tools.forEach((tool) => {
871
+ if ((0, function_calling_1.isLangChainTool)(tool)) {
872
+ langChainTools.push(tool);
873
+ }
874
+ else {
875
+ otherTools.push(cleanGeminiTool(tool));
876
+ }
877
+ });
799
878
  const result = [...otherTools];
800
879
  if (langChainTools.length > 0) {
801
880
  result.push({
@@ -808,10 +887,19 @@ function getGeminiAPI(config) {
808
887
  if (!parameters.tool_choice || typeof parameters.tool_choice !== "string") {
809
888
  return undefined;
810
889
  }
890
+ if (["auto", "any", "none"].includes(parameters.tool_choice)) {
891
+ return {
892
+ functionCallingConfig: {
893
+ mode: parameters.tool_choice,
894
+ allowedFunctionNames: parameters.allowed_function_names,
895
+ },
896
+ };
897
+ }
898
+ // force tool choice to be a single function name in case of structured output
811
899
  return {
812
900
  functionCallingConfig: {
813
- mode: parameters.tool_choice,
814
- allowedFunctionNames: parameters.allowed_function_names,
901
+ mode: "any",
902
+ allowedFunctionNames: [parameters.tool_choice],
815
903
  },
816
904
  };
817
905
  }
@@ -3,6 +3,7 @@ import { AIMessage, AIMessageChunk, isAIMessage, } from "@langchain/core/message
3
3
  import { ChatGenerationChunk, } from "@langchain/core/outputs";
4
4
  import { isLangChainTool } from "@langchain/core/utils/function_calling";
5
5
  import { GoogleAISafetyError } from "./safety.js";
6
+ import { GeminiSearchToolAttributes, } from "../types.js";
6
7
  import { zodToGeminiParameters } from "./zod_to_gemini_parameters.js";
7
8
  export class DefaultGeminiSafetyHandler {
8
9
  constructor(settings) {
@@ -518,6 +519,8 @@ export function getGeminiAPI(config) {
518
519
  severity: rating.severity,
519
520
  severity_score: rating.severityScore,
520
521
  })),
522
+ citation_metadata: data.candidates[0]?.citationMetadata,
523
+ grounding_metadata: data.candidates[0]?.groundingMetadata,
521
524
  finish_reason: data.candidates[0]?.finishReason,
522
525
  };
523
526
  }
@@ -572,12 +575,59 @@ export function getGeminiAPI(config) {
572
575
  message,
573
576
  });
574
577
  }
575
- function responseToChatGenerations(response) {
578
+ function groundingSupportByPart(groundingSupports) {
579
+ const ret = [];
580
+ if (!groundingSupports || groundingSupports.length === 0) {
581
+ return [];
582
+ }
583
+ groundingSupports?.forEach((groundingSupport) => {
584
+ const segment = groundingSupport?.segment;
585
+ const partIndex = segment?.partIndex ?? 0;
586
+ if (ret[partIndex]) {
587
+ ret[partIndex].push(groundingSupport);
588
+ }
589
+ else {
590
+ ret[partIndex] = [groundingSupport];
591
+ }
592
+ });
593
+ return ret;
594
+ }
595
+ function responseToGroundedChatGenerations(response) {
576
596
  const parts = responseToParts(response);
577
597
  if (parts.length === 0) {
578
598
  return [];
579
599
  }
580
- let ret = parts.map((part) => partToChatGeneration(part));
600
+ // Citation and grounding information connected to each part / ChatGeneration
601
+ // to make sure they are available in downstream filters.
602
+ const candidate = response?.data
603
+ ?.candidates?.[0];
604
+ const groundingMetadata = candidate?.groundingMetadata;
605
+ const citationMetadata = candidate?.citationMetadata;
606
+ const groundingParts = groundingSupportByPart(groundingMetadata?.groundingSupports);
607
+ const ret = parts.map((part, index) => {
608
+ const gen = partToChatGeneration(part);
609
+ if (!gen.generationInfo) {
610
+ gen.generationInfo = {};
611
+ }
612
+ if (groundingMetadata) {
613
+ gen.generationInfo.groundingMetadata = groundingMetadata;
614
+ const groundingPart = groundingParts[index];
615
+ if (groundingPart) {
616
+ gen.generationInfo.groundingSupport = groundingPart;
617
+ }
618
+ }
619
+ if (citationMetadata) {
620
+ gen.generationInfo.citationMetadata = citationMetadata;
621
+ }
622
+ return gen;
623
+ });
624
+ return ret;
625
+ }
626
+ function responseToChatGenerations(response) {
627
+ let ret = responseToGroundedChatGenerations(response);
628
+ if (ret.length === 0) {
629
+ return [];
630
+ }
581
631
  if (ret.every((item) => typeof item.message.content === "string")) {
582
632
  const combinedContent = ret.map((item) => item.message.content).join("");
583
633
  const combinedText = ret.map((item) => item.text).join("");
@@ -783,14 +833,43 @@ export function getGeminiAPI(config) {
783
833
  parameters: jsonSchema,
784
834
  };
785
835
  }
836
+ function searchToolName(tool) {
837
+ for (const name of GeminiSearchToolAttributes) {
838
+ if (name in tool) {
839
+ return name;
840
+ }
841
+ }
842
+ return undefined;
843
+ }
844
+ function cleanGeminiTool(tool) {
845
+ const orig = searchToolName(tool);
846
+ const adj = config?.googleSearchToolAdjustment;
847
+ if (orig && adj && adj !== orig) {
848
+ return {
849
+ [adj]: {},
850
+ };
851
+ }
852
+ else {
853
+ return tool;
854
+ }
855
+ }
786
856
  function formatTools(parameters) {
787
857
  const tools = parameters?.tools;
788
858
  if (!tools || tools.length === 0) {
789
859
  return [];
790
860
  }
791
- // Group all LangChain tools into a single functionDeclarations array
792
- const langChainTools = tools.filter(isLangChainTool);
793
- const otherTools = tools.filter((tool) => !isLangChainTool(tool));
861
+ // Group all LangChain tools into a single functionDeclarations array.
862
+ // Gemini Tools may be normalized to different tool names
863
+ const langChainTools = [];
864
+ const otherTools = [];
865
+ tools.forEach((tool) => {
866
+ if (isLangChainTool(tool)) {
867
+ langChainTools.push(tool);
868
+ }
869
+ else {
870
+ otherTools.push(cleanGeminiTool(tool));
871
+ }
872
+ });
794
873
  const result = [...otherTools];
795
874
  if (langChainTools.length > 0) {
796
875
  result.push({
@@ -803,10 +882,19 @@ export function getGeminiAPI(config) {
803
882
  if (!parameters.tool_choice || typeof parameters.tool_choice !== "string") {
804
883
  return undefined;
805
884
  }
885
+ if (["auto", "any", "none"].includes(parameters.tool_choice)) {
886
+ return {
887
+ functionCallingConfig: {
888
+ mode: parameters.tool_choice,
889
+ allowedFunctionNames: parameters.allowed_function_names,
890
+ },
891
+ };
892
+ }
893
+ // force tool choice to be a single function name in case of structured output
806
894
  return {
807
895
  functionCallingConfig: {
808
- mode: parameters.tool_choice,
809
- allowedFunctionNames: parameters.allowed_function_names,
896
+ mode: "any",
897
+ allowedFunctionNames: [parameters.tool_choice],
810
898
  },
811
899
  };
812
900
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/google-common",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Core types and classes for Google services.",
5
5
  "type": "module",
6
6
  "engines": {