@langchain/google-common 0.1.7 → 0.2.0

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.
@@ -131,25 +131,25 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
131
131
  enumerable: true,
132
132
  configurable: true,
133
133
  writable: true,
134
- value: 0.7
134
+ value: void 0
135
135
  });
136
136
  Object.defineProperty(this, "maxOutputTokens", {
137
137
  enumerable: true,
138
138
  configurable: true,
139
139
  writable: true,
140
- value: 1024
140
+ value: void 0
141
141
  });
142
142
  Object.defineProperty(this, "topP", {
143
143
  enumerable: true,
144
144
  configurable: true,
145
145
  writable: true,
146
- value: 0.8
146
+ value: void 0
147
147
  });
148
148
  Object.defineProperty(this, "topK", {
149
149
  enumerable: true,
150
150
  configurable: true,
151
151
  writable: true,
152
- value: 40
152
+ value: void 0
153
153
  });
154
154
  Object.defineProperty(this, "presencePenalty", {
155
155
  enumerable: true,
@@ -173,7 +173,7 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
173
173
  enumerable: true,
174
174
  configurable: true,
175
175
  writable: true,
176
- value: false
176
+ value: void 0
177
177
  });
178
178
  Object.defineProperty(this, "topLogprobs", {
179
179
  enumerable: true,
@@ -246,13 +246,7 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
246
246
  return new auth_js_1.ApiKeyGoogleAuth(apiKey);
247
247
  }
248
248
  buildApiKey(fields) {
249
- if (fields?.platformType !== "gcp") {
250
- return fields?.apiKey ?? (0, env_1.getEnvironmentVariable)("GOOGLE_API_KEY");
251
- }
252
- else {
253
- // GCP doesn't support API Keys
254
- return undefined;
255
- }
249
+ return fields?.apiKey ?? (0, env_1.getEnvironmentVariable)("GOOGLE_API_KEY");
256
250
  }
257
251
  buildClient(fields) {
258
252
  const apiKey = this.buildApiKey(fields);
@@ -127,25 +127,25 @@ export class ChatGoogleBase extends BaseChatModel {
127
127
  enumerable: true,
128
128
  configurable: true,
129
129
  writable: true,
130
- value: 0.7
130
+ value: void 0
131
131
  });
132
132
  Object.defineProperty(this, "maxOutputTokens", {
133
133
  enumerable: true,
134
134
  configurable: true,
135
135
  writable: true,
136
- value: 1024
136
+ value: void 0
137
137
  });
138
138
  Object.defineProperty(this, "topP", {
139
139
  enumerable: true,
140
140
  configurable: true,
141
141
  writable: true,
142
- value: 0.8
142
+ value: void 0
143
143
  });
144
144
  Object.defineProperty(this, "topK", {
145
145
  enumerable: true,
146
146
  configurable: true,
147
147
  writable: true,
148
- value: 40
148
+ value: void 0
149
149
  });
150
150
  Object.defineProperty(this, "presencePenalty", {
151
151
  enumerable: true,
@@ -169,7 +169,7 @@ export class ChatGoogleBase extends BaseChatModel {
169
169
  enumerable: true,
170
170
  configurable: true,
171
171
  writable: true,
172
- value: false
172
+ value: void 0
173
173
  });
174
174
  Object.defineProperty(this, "topLogprobs", {
175
175
  enumerable: true,
@@ -242,13 +242,7 @@ export class ChatGoogleBase extends BaseChatModel {
242
242
  return new ApiKeyGoogleAuth(apiKey);
243
243
  }
244
244
  buildApiKey(fields) {
245
- if (fields?.platformType !== "gcp") {
246
- return fields?.apiKey ?? getEnvironmentVariable("GOOGLE_API_KEY");
247
- }
248
- else {
249
- // GCP doesn't support API Keys
250
- return undefined;
251
- }
245
+ return fields?.apiKey ?? getEnvironmentVariable("GOOGLE_API_KEY");
252
246
  }
253
247
  buildClient(fields) {
254
248
  const apiKey = this.buildApiKey(fields);
@@ -223,8 +223,14 @@ class GoogleAIConnection extends GoogleHostConnection {
223
223
  throw new Error(`Unknown API: ${this.apiName}`);
224
224
  }
225
225
  }
226
+ get isApiKey() {
227
+ return this.client.clientType === "apiKey";
228
+ }
226
229
  get computedPlatformType() {
227
- if (this.client.clientType === "apiKey") {
230
+ // This is not a completely correct assumption, since GCP can
231
+ // have an API Key. But if so, then people need to set the platform
232
+ // type explicitly.
233
+ if (this.isApiKey) {
228
234
  return "gai";
229
235
  }
230
236
  else {
@@ -246,13 +252,27 @@ class GoogleAIConnection extends GoogleHostConnection {
246
252
  const url = `https://generativelanguage.googleapis.com/${this.apiVersion}/models/${this.model}:${method}`;
247
253
  return url;
248
254
  }
249
- async buildUrlVertex() {
255
+ async buildUrlVertexExpress() {
256
+ const method = await this.buildUrlMethod();
257
+ const publisher = this.modelPublisher;
258
+ const url = `https://aiplatform.googleapis.com/${this.apiVersion}/publishers/${publisher}/models/${this.model}:${method}`;
259
+ return url;
260
+ }
261
+ async buildUrlVertexLocation() {
250
262
  const projectId = await this.client.getProjectId();
251
263
  const method = await this.buildUrlMethod();
252
264
  const publisher = this.modelPublisher;
253
265
  const url = `https://${this.endpoint}/${this.apiVersion}/projects/${projectId}/locations/${this.location}/publishers/${publisher}/models/${this.model}:${method}`;
254
266
  return url;
255
267
  }
268
+ async buildUrlVertex() {
269
+ if (this.isApiKey) {
270
+ return this.buildUrlVertexExpress();
271
+ }
272
+ else {
273
+ return this.buildUrlVertexLocation();
274
+ }
275
+ }
256
276
  async buildUrl() {
257
277
  switch (this.platform) {
258
278
  case "gai":
@@ -50,10 +50,13 @@ export declare abstract class GoogleAIConnection<CallOptions extends AsyncCaller
50
50
  get computedAPIName(): string;
51
51
  get apiName(): string;
52
52
  get api(): GoogleAIAPI;
53
+ get isApiKey(): boolean;
53
54
  get computedPlatformType(): GooglePlatformType;
54
55
  get computedLocation(): string;
55
56
  abstract buildUrlMethod(): Promise<string>;
56
57
  buildUrlGenerativeLanguage(): Promise<string>;
58
+ buildUrlVertexExpress(): Promise<string>;
59
+ buildUrlVertexLocation(): Promise<string>;
57
60
  buildUrlVertex(): Promise<string>;
58
61
  buildUrl(): Promise<string>;
59
62
  abstract formatData(input: InputType, parameters: GoogleAIModelRequestParams): Promise<unknown>;
@@ -217,8 +217,14 @@ export class GoogleAIConnection extends GoogleHostConnection {
217
217
  throw new Error(`Unknown API: ${this.apiName}`);
218
218
  }
219
219
  }
220
+ get isApiKey() {
221
+ return this.client.clientType === "apiKey";
222
+ }
220
223
  get computedPlatformType() {
221
- if (this.client.clientType === "apiKey") {
224
+ // This is not a completely correct assumption, since GCP can
225
+ // have an API Key. But if so, then people need to set the platform
226
+ // type explicitly.
227
+ if (this.isApiKey) {
222
228
  return "gai";
223
229
  }
224
230
  else {
@@ -240,13 +246,27 @@ export class GoogleAIConnection extends GoogleHostConnection {
240
246
  const url = `https://generativelanguage.googleapis.com/${this.apiVersion}/models/${this.model}:${method}`;
241
247
  return url;
242
248
  }
243
- async buildUrlVertex() {
249
+ async buildUrlVertexExpress() {
250
+ const method = await this.buildUrlMethod();
251
+ const publisher = this.modelPublisher;
252
+ const url = `https://aiplatform.googleapis.com/${this.apiVersion}/publishers/${publisher}/models/${this.model}:${method}`;
253
+ return url;
254
+ }
255
+ async buildUrlVertexLocation() {
244
256
  const projectId = await this.client.getProjectId();
245
257
  const method = await this.buildUrlMethod();
246
258
  const publisher = this.modelPublisher;
247
259
  const url = `https://${this.endpoint}/${this.apiVersion}/projects/${projectId}/locations/${this.location}/publishers/${publisher}/models/${this.model}:${method}`;
248
260
  return url;
249
261
  }
262
+ async buildUrlVertex() {
263
+ if (this.isApiKey) {
264
+ return this.buildUrlVertexExpress();
265
+ }
266
+ else {
267
+ return this.buildUrlVertexLocation();
268
+ }
269
+ }
250
270
  async buildUrl() {
251
271
  switch (this.platform) {
252
272
  case "gai":
@@ -19,12 +19,12 @@ function failedAttemptHandler(error) {
19
19
  if (status === 0) {
20
20
  // What is this?
21
21
  console.error("failedAttemptHandler", error);
22
+ throw error;
22
23
  }
23
24
  // What errors shouldn't be retried?
24
25
  if (STATUS_NO_RETRY.includes(+status)) {
25
26
  throw error;
26
27
  }
27
- throw error;
28
28
  }
29
29
  exports.failedAttemptHandler = failedAttemptHandler;
30
30
  function ensureParams(params) {
@@ -16,12 +16,12 @@ export function failedAttemptHandler(error) {
16
16
  if (status === 0) {
17
17
  // What is this?
18
18
  console.error("failedAttemptHandler", error);
19
+ throw error;
19
20
  }
20
21
  // What errors shouldn't be retried?
21
22
  if (STATUS_NO_RETRY.includes(+status)) {
22
23
  throw error;
23
24
  }
24
- throw error;
25
25
  }
26
26
  export function ensureParams(params) {
27
27
  const base = params ?? {};
@@ -5,6 +5,7 @@ const uuid_1 = require("uuid");
5
5
  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
+ const stream_1 = require("@langchain/core/utils/stream");
8
9
  const safety_js_1 = require("./safety.cjs");
9
10
  const types_js_1 = require("../types.cjs");
10
11
  const zod_to_gemini_parameters_js_1 = require("./zod_to_gemini_parameters.cjs");
@@ -604,9 +605,12 @@ function getGeminiAPI(config) {
604
605
  function partToChatGeneration(part) {
605
606
  const message = partToMessageChunk(part);
606
607
  const text = partToText(part);
608
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
609
+ const generationInfo = {};
607
610
  return new outputs_1.ChatGenerationChunk({
608
611
  text,
609
612
  message,
613
+ generationInfo,
610
614
  });
611
615
  }
612
616
  function groundingSupportByPart(groundingSupports) {
@@ -657,43 +661,134 @@ function getGeminiAPI(config) {
657
661
  });
658
662
  return ret;
659
663
  }
664
+ function combineContent(gen, forceComplex = false) {
665
+ const allString = gen.every((item) => typeof item.message.content === "string");
666
+ if (allString && !forceComplex) {
667
+ // Everything is a string, and we don't want to force it to return
668
+ // MessageContentComplex[], so concatenate the content into one string
669
+ return gen.map((item) => item.message.content).join("");
670
+ }
671
+ else {
672
+ // We either have complex types, or we want to force them, so turn
673
+ // it into an array of complex types.
674
+ const ret = [];
675
+ gen.forEach((item) => {
676
+ if (typeof item.message.content === "string") {
677
+ // If this is a string, turn it into a text type
678
+ ret.push({
679
+ text: item.message.content,
680
+ });
681
+ }
682
+ else {
683
+ // Otherwise, add all the complex types to what we're returning
684
+ item.message.content.forEach((c) => {
685
+ ret.push(c);
686
+ });
687
+ }
688
+ });
689
+ return ret;
690
+ }
691
+ }
692
+ function combineText(gen) {
693
+ return gen.map((item) => item.text ?? "").join("");
694
+ }
695
+ /*
696
+ * We don't really need the entire AIMessageChunk here, but it is
697
+ * a conventient way to combine all the Tool Calling information.
698
+ */
699
+ function combineToolCalls(gen) {
700
+ let ret = new messages_1.AIMessageChunk("");
701
+ gen.forEach((item) => {
702
+ const message = item?.message;
703
+ ret = (0, stream_1.concat)(ret, message);
704
+ });
705
+ return ret;
706
+ }
707
+ function combineAdditionalKwargs(gen) {
708
+ const ret = {};
709
+ gen.forEach((item) => {
710
+ const message = item?.message;
711
+ const kwargs = message?.additional_kwargs ?? {};
712
+ const keys = Object.keys(kwargs);
713
+ keys.forEach((key) => {
714
+ const value = kwargs[key];
715
+ if (Object.hasOwn(ret, key) &&
716
+ Array.isArray(ret[key]) &&
717
+ Array.isArray(value)) {
718
+ ret[key].push(...value);
719
+ }
720
+ else {
721
+ ret[key] = value;
722
+ }
723
+ });
724
+ });
725
+ return ret;
726
+ }
727
+ function combineGenerations(generations, response) {
728
+ const gen = splitGenerationTypes(generations, response);
729
+ const combinedContent = combineContent(gen.content);
730
+ const combinedText = combineText(gen.content);
731
+ const combinedToolCalls = combineToolCalls(gen.content);
732
+ const kwargs = combineAdditionalKwargs(gen.content);
733
+ const lastContent = gen.content[gen.content.length - 1];
734
+ // Add usage metadata
735
+ let usageMetadata;
736
+ if ("usageMetadata" in response.data) {
737
+ usageMetadata = {
738
+ input_tokens: response.data.usageMetadata.promptTokenCount,
739
+ output_tokens: response.data.usageMetadata
740
+ .candidatesTokenCount,
741
+ total_tokens: response.data.usageMetadata.totalTokenCount,
742
+ };
743
+ }
744
+ // Add thinking / reasoning
745
+ // if (gen.reasoning && gen.reasoning.length > 0) {
746
+ // kwargs.reasoning_content = combineContent(gen.reasoning, true);
747
+ // }
748
+ // Build the message and the generation chunk to return
749
+ const message = new messages_1.AIMessageChunk({
750
+ content: combinedContent,
751
+ additional_kwargs: kwargs,
752
+ usage_metadata: usageMetadata,
753
+ tool_calls: combinedToolCalls.tool_calls,
754
+ invalid_tool_calls: combinedToolCalls.invalid_tool_calls,
755
+ });
756
+ return [
757
+ new outputs_1.ChatGenerationChunk({
758
+ message,
759
+ text: combinedText,
760
+ generationInfo: lastContent.generationInfo,
761
+ }),
762
+ ];
763
+ }
764
+ function splitGenerationTypes(generations, _response) {
765
+ const content = [];
766
+ const reasoning = [];
767
+ generations.forEach((gen) => {
768
+ if (gen?.generationInfo?.thought) {
769
+ reasoning.push(gen);
770
+ }
771
+ else {
772
+ content.push(gen);
773
+ }
774
+ });
775
+ return {
776
+ content,
777
+ reasoning,
778
+ };
779
+ }
780
+ /**
781
+ * Although this returns an array, only the first (or maybe last)
782
+ * element in the array is used. So we need to combine them into
783
+ * just one element that contains everything we need.
784
+ * @param response
785
+ */
660
786
  function responseToChatGenerations(response) {
661
- let ret = responseToGroundedChatGenerations(response);
662
- if (ret.length === 0) {
787
+ const generations = responseToGroundedChatGenerations(response);
788
+ if (generations.length === 0) {
663
789
  return [];
664
790
  }
665
- if (ret.every((item) => typeof item.message.content === "string")) {
666
- const combinedContent = ret.map((item) => item.message.content).join("");
667
- const combinedText = ret.map((item) => item.text).join("");
668
- const toolCallChunks = ret[ret.length - 1]?.message.additional_kwargs?.tool_calls?.map((toolCall, i) => ({
669
- name: toolCall.function.name,
670
- args: toolCall.function.arguments,
671
- id: toolCall.id,
672
- index: i,
673
- type: "tool_call_chunk",
674
- }));
675
- let usageMetadata;
676
- if ("usageMetadata" in response.data) {
677
- usageMetadata = {
678
- input_tokens: response.data.usageMetadata.promptTokenCount,
679
- output_tokens: response.data.usageMetadata
680
- .candidatesTokenCount,
681
- total_tokens: response.data.usageMetadata.totalTokenCount,
682
- };
683
- }
684
- ret = [
685
- new outputs_1.ChatGenerationChunk({
686
- message: new messages_1.AIMessageChunk({
687
- content: combinedContent,
688
- additional_kwargs: ret[ret.length - 1]?.message.additional_kwargs,
689
- tool_call_chunks: toolCallChunks,
690
- usage_metadata: usageMetadata,
691
- }),
692
- text: combinedText,
693
- generationInfo: ret[ret.length - 1].generationInfo,
694
- }),
695
- ];
696
- }
791
+ const ret = combineGenerations(generations, response);
697
792
  // Add logprobs information to the message
698
793
  const candidate = response?.data
699
794
  ?.candidates?.[0];
@@ -829,7 +924,7 @@ function getGeminiAPI(config) {
829
924
  }
830
925
  }
831
926
  function formatGenerationConfig(parameters) {
832
- return {
927
+ const ret = {
833
928
  temperature: parameters.temperature,
834
929
  topK: parameters.topK,
835
930
  topP: parameters.topP,
@@ -838,9 +933,23 @@ function getGeminiAPI(config) {
838
933
  maxOutputTokens: parameters.maxOutputTokens,
839
934
  stopSequences: parameters.stopSequences,
840
935
  responseMimeType: parameters.responseMimeType,
841
- responseLogprobs: parameters.logprobs,
842
- logprobs: parameters.topLogprobs,
843
936
  };
937
+ // Add the logprobs if explicitly set
938
+ if (typeof parameters.logprobs !== "undefined") {
939
+ ret.responseLogprobs = parameters.logprobs;
940
+ if (parameters.logprobs &&
941
+ typeof parameters.topLogprobs !== "undefined") {
942
+ ret.logprobs = parameters.topLogprobs;
943
+ }
944
+ }
945
+ // Remove any undefined properties, so we don't send them
946
+ let attribute;
947
+ for (attribute in ret) {
948
+ if (ret[attribute] === undefined) {
949
+ delete ret[attribute];
950
+ }
951
+ }
952
+ return ret;
844
953
  }
845
954
  function formatSafetySettings(parameters) {
846
955
  return parameters.safetySettings ?? [];
@@ -2,6 +2,7 @@ import { v4 as uuidv4 } from "uuid";
2
2
  import { AIMessage, AIMessageChunk, isAIMessage, } from "@langchain/core/messages";
3
3
  import { ChatGenerationChunk, } from "@langchain/core/outputs";
4
4
  import { isLangChainTool } from "@langchain/core/utils/function_calling";
5
+ import { concat } from "@langchain/core/utils/stream";
5
6
  import { GoogleAISafetyError } from "./safety.js";
6
7
  import { GeminiSearchToolAttributes, } from "../types.js";
7
8
  import { zodToGeminiParameters } from "./zod_to_gemini_parameters.js";
@@ -599,9 +600,12 @@ export function getGeminiAPI(config) {
599
600
  function partToChatGeneration(part) {
600
601
  const message = partToMessageChunk(part);
601
602
  const text = partToText(part);
603
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
604
+ const generationInfo = {};
602
605
  return new ChatGenerationChunk({
603
606
  text,
604
607
  message,
608
+ generationInfo,
605
609
  });
606
610
  }
607
611
  function groundingSupportByPart(groundingSupports) {
@@ -652,43 +656,134 @@ export function getGeminiAPI(config) {
652
656
  });
653
657
  return ret;
654
658
  }
659
+ function combineContent(gen, forceComplex = false) {
660
+ const allString = gen.every((item) => typeof item.message.content === "string");
661
+ if (allString && !forceComplex) {
662
+ // Everything is a string, and we don't want to force it to return
663
+ // MessageContentComplex[], so concatenate the content into one string
664
+ return gen.map((item) => item.message.content).join("");
665
+ }
666
+ else {
667
+ // We either have complex types, or we want to force them, so turn
668
+ // it into an array of complex types.
669
+ const ret = [];
670
+ gen.forEach((item) => {
671
+ if (typeof item.message.content === "string") {
672
+ // If this is a string, turn it into a text type
673
+ ret.push({
674
+ text: item.message.content,
675
+ });
676
+ }
677
+ else {
678
+ // Otherwise, add all the complex types to what we're returning
679
+ item.message.content.forEach((c) => {
680
+ ret.push(c);
681
+ });
682
+ }
683
+ });
684
+ return ret;
685
+ }
686
+ }
687
+ function combineText(gen) {
688
+ return gen.map((item) => item.text ?? "").join("");
689
+ }
690
+ /*
691
+ * We don't really need the entire AIMessageChunk here, but it is
692
+ * a conventient way to combine all the Tool Calling information.
693
+ */
694
+ function combineToolCalls(gen) {
695
+ let ret = new AIMessageChunk("");
696
+ gen.forEach((item) => {
697
+ const message = item?.message;
698
+ ret = concat(ret, message);
699
+ });
700
+ return ret;
701
+ }
702
+ function combineAdditionalKwargs(gen) {
703
+ const ret = {};
704
+ gen.forEach((item) => {
705
+ const message = item?.message;
706
+ const kwargs = message?.additional_kwargs ?? {};
707
+ const keys = Object.keys(kwargs);
708
+ keys.forEach((key) => {
709
+ const value = kwargs[key];
710
+ if (Object.hasOwn(ret, key) &&
711
+ Array.isArray(ret[key]) &&
712
+ Array.isArray(value)) {
713
+ ret[key].push(...value);
714
+ }
715
+ else {
716
+ ret[key] = value;
717
+ }
718
+ });
719
+ });
720
+ return ret;
721
+ }
722
+ function combineGenerations(generations, response) {
723
+ const gen = splitGenerationTypes(generations, response);
724
+ const combinedContent = combineContent(gen.content);
725
+ const combinedText = combineText(gen.content);
726
+ const combinedToolCalls = combineToolCalls(gen.content);
727
+ const kwargs = combineAdditionalKwargs(gen.content);
728
+ const lastContent = gen.content[gen.content.length - 1];
729
+ // Add usage metadata
730
+ let usageMetadata;
731
+ if ("usageMetadata" in response.data) {
732
+ usageMetadata = {
733
+ input_tokens: response.data.usageMetadata.promptTokenCount,
734
+ output_tokens: response.data.usageMetadata
735
+ .candidatesTokenCount,
736
+ total_tokens: response.data.usageMetadata.totalTokenCount,
737
+ };
738
+ }
739
+ // Add thinking / reasoning
740
+ // if (gen.reasoning && gen.reasoning.length > 0) {
741
+ // kwargs.reasoning_content = combineContent(gen.reasoning, true);
742
+ // }
743
+ // Build the message and the generation chunk to return
744
+ const message = new AIMessageChunk({
745
+ content: combinedContent,
746
+ additional_kwargs: kwargs,
747
+ usage_metadata: usageMetadata,
748
+ tool_calls: combinedToolCalls.tool_calls,
749
+ invalid_tool_calls: combinedToolCalls.invalid_tool_calls,
750
+ });
751
+ return [
752
+ new ChatGenerationChunk({
753
+ message,
754
+ text: combinedText,
755
+ generationInfo: lastContent.generationInfo,
756
+ }),
757
+ ];
758
+ }
759
+ function splitGenerationTypes(generations, _response) {
760
+ const content = [];
761
+ const reasoning = [];
762
+ generations.forEach((gen) => {
763
+ if (gen?.generationInfo?.thought) {
764
+ reasoning.push(gen);
765
+ }
766
+ else {
767
+ content.push(gen);
768
+ }
769
+ });
770
+ return {
771
+ content,
772
+ reasoning,
773
+ };
774
+ }
775
+ /**
776
+ * Although this returns an array, only the first (or maybe last)
777
+ * element in the array is used. So we need to combine them into
778
+ * just one element that contains everything we need.
779
+ * @param response
780
+ */
655
781
  function responseToChatGenerations(response) {
656
- let ret = responseToGroundedChatGenerations(response);
657
- if (ret.length === 0) {
782
+ const generations = responseToGroundedChatGenerations(response);
783
+ if (generations.length === 0) {
658
784
  return [];
659
785
  }
660
- if (ret.every((item) => typeof item.message.content === "string")) {
661
- const combinedContent = ret.map((item) => item.message.content).join("");
662
- const combinedText = ret.map((item) => item.text).join("");
663
- const toolCallChunks = ret[ret.length - 1]?.message.additional_kwargs?.tool_calls?.map((toolCall, i) => ({
664
- name: toolCall.function.name,
665
- args: toolCall.function.arguments,
666
- id: toolCall.id,
667
- index: i,
668
- type: "tool_call_chunk",
669
- }));
670
- let usageMetadata;
671
- if ("usageMetadata" in response.data) {
672
- usageMetadata = {
673
- input_tokens: response.data.usageMetadata.promptTokenCount,
674
- output_tokens: response.data.usageMetadata
675
- .candidatesTokenCount,
676
- total_tokens: response.data.usageMetadata.totalTokenCount,
677
- };
678
- }
679
- ret = [
680
- new ChatGenerationChunk({
681
- message: new AIMessageChunk({
682
- content: combinedContent,
683
- additional_kwargs: ret[ret.length - 1]?.message.additional_kwargs,
684
- tool_call_chunks: toolCallChunks,
685
- usage_metadata: usageMetadata,
686
- }),
687
- text: combinedText,
688
- generationInfo: ret[ret.length - 1].generationInfo,
689
- }),
690
- ];
691
- }
786
+ const ret = combineGenerations(generations, response);
692
787
  // Add logprobs information to the message
693
788
  const candidate = response?.data
694
789
  ?.candidates?.[0];
@@ -824,7 +919,7 @@ export function getGeminiAPI(config) {
824
919
  }
825
920
  }
826
921
  function formatGenerationConfig(parameters) {
827
- return {
922
+ const ret = {
828
923
  temperature: parameters.temperature,
829
924
  topK: parameters.topK,
830
925
  topP: parameters.topP,
@@ -833,9 +928,23 @@ export function getGeminiAPI(config) {
833
928
  maxOutputTokens: parameters.maxOutputTokens,
834
929
  stopSequences: parameters.stopSequences,
835
930
  responseMimeType: parameters.responseMimeType,
836
- responseLogprobs: parameters.logprobs,
837
- logprobs: parameters.topLogprobs,
838
931
  };
932
+ // Add the logprobs if explicitly set
933
+ if (typeof parameters.logprobs !== "undefined") {
934
+ ret.responseLogprobs = parameters.logprobs;
935
+ if (parameters.logprobs &&
936
+ typeof parameters.topLogprobs !== "undefined") {
937
+ ret.logprobs = parameters.topLogprobs;
938
+ }
939
+ }
940
+ // Remove any undefined properties, so we don't send them
941
+ let attribute;
942
+ for (attribute in ret) {
943
+ if (ret[attribute] === undefined) {
944
+ delete ret[attribute];
945
+ }
946
+ }
947
+ return ret;
839
948
  }
840
949
  function formatSafetySettings(parameters) {
841
950
  return parameters.safetySettings ?? [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/google-common",
3
- "version": "0.1.7",
3
+ "version": "0.2.0",
4
4
  "description": "Core types and classes for Google services.",
5
5
  "type": "module",
6
6
  "engines": {