@langchain/google-genai 0.1.4 → 0.1.5

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.
@@ -442,6 +442,12 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
442
442
  writable: true,
443
443
  value: true
444
444
  });
445
+ Object.defineProperty(this, "convertSystemMessageToHumanContent", {
446
+ enumerable: true,
447
+ configurable: true,
448
+ writable: true,
449
+ value: void 0
450
+ });
445
451
  Object.defineProperty(this, "client", {
446
452
  enumerable: true,
447
453
  configurable: true,
@@ -506,6 +512,35 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
506
512
  });
507
513
  this.streamUsage = fields?.streamUsage ?? this.streamUsage;
508
514
  }
515
+ useCachedContent(cachedContent, modelParams, requestOptions) {
516
+ if (!this.apiKey)
517
+ return;
518
+ this.client = new generative_ai_1.GoogleGenerativeAI(this.apiKey).getGenerativeModelFromCachedContent(cachedContent, modelParams, requestOptions);
519
+ }
520
+ get useSystemInstruction() {
521
+ return typeof this.convertSystemMessageToHumanContent === "boolean"
522
+ ? !this.convertSystemMessageToHumanContent
523
+ : this.computeUseSystemInstruction;
524
+ }
525
+ get computeUseSystemInstruction() {
526
+ // This works on models from April 2024 and later
527
+ // Vertex AI: gemini-1.5-pro and gemini-1.0-002 and later
528
+ // AI Studio: gemini-1.5-pro-latest
529
+ if (this.modelName === "gemini-1.0-pro-001") {
530
+ return false;
531
+ }
532
+ else if (this.modelName.startsWith("gemini-pro-vision")) {
533
+ return false;
534
+ }
535
+ else if (this.modelName.startsWith("gemini-1.0-pro-vision")) {
536
+ return false;
537
+ }
538
+ else if (this.modelName === "gemini-pro") {
539
+ // on AI Studio gemini-pro is still pointing at gemini-1.0-pro-001
540
+ return false;
541
+ }
542
+ return true;
543
+ }
509
544
  getLsParams(options) {
510
545
  return {
511
546
  ls_provider: "google_genai",
@@ -540,7 +575,13 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
540
575
  };
541
576
  }
542
577
  async _generate(messages, options, runManager) {
543
- const prompt = (0, common_js_1.convertBaseMessagesToContent)(messages, this._isMultimodalModel);
578
+ const prompt = (0, common_js_1.convertBaseMessagesToContent)(messages, this._isMultimodalModel, this.useSystemInstruction);
579
+ let actualPrompt = prompt;
580
+ if (prompt[0].role === "system") {
581
+ const [systemInstruction] = prompt;
582
+ this.client.systemInstruction = systemInstruction;
583
+ actualPrompt = prompt.slice(1);
584
+ }
544
585
  const parameters = this.invocationParams(options);
545
586
  // Handle streaming
546
587
  if (this.streaming) {
@@ -563,7 +604,7 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
563
604
  }
564
605
  const res = await this.completionWithRetry({
565
606
  ...parameters,
566
- contents: prompt,
607
+ contents: actualPrompt,
567
608
  });
568
609
  let usageMetadata;
569
610
  if ("usageMetadata" in res.response) {
@@ -581,11 +622,17 @@ class ChatGoogleGenerativeAI extends chat_models_1.BaseChatModel {
581
622
  return generationResult;
582
623
  }
583
624
  async *_streamResponseChunks(messages, options, runManager) {
584
- const prompt = (0, common_js_1.convertBaseMessagesToContent)(messages, this._isMultimodalModel);
625
+ const prompt = (0, common_js_1.convertBaseMessagesToContent)(messages, this._isMultimodalModel, this.useSystemInstruction);
626
+ let actualPrompt = prompt;
627
+ if (prompt[0].role === "system") {
628
+ const [systemInstruction] = prompt;
629
+ this.client.systemInstruction = systemInstruction;
630
+ actualPrompt = prompt.slice(1);
631
+ }
585
632
  const parameters = this.invocationParams(options);
586
633
  const request = {
587
634
  ...parameters,
588
- contents: prompt,
635
+ contents: actualPrompt,
589
636
  };
590
637
  const stream = await this.caller.callWithOptions({ signal: options?.signal }, async () => {
591
638
  const { stream } = await this.client.generateContentStream(request);
@@ -1,4 +1,4 @@
1
- import { GenerateContentRequest, SafetySetting, Part as GenerativeAIPart } from "@google/generative-ai";
1
+ import { GenerateContentRequest, SafetySetting, Part as GenerativeAIPart, ModelParams, RequestOptions, type CachedContent } from "@google/generative-ai";
2
2
  import { CallbackManagerForLLMRun } from "@langchain/core/callbacks/manager";
3
3
  import { AIMessageChunk, BaseMessage } from "@langchain/core/messages";
4
4
  import { ChatGenerationChunk, ChatResult } from "@langchain/core/outputs";
@@ -120,6 +120,14 @@ export interface GoogleGenerativeAIChatInput extends BaseChatModelParams, Pick<G
120
120
  * @default false
121
121
  */
122
122
  json?: boolean;
123
+ /**
124
+ * Whether or not model supports system instructions.
125
+ * The following models support system instructions:
126
+ * - All Gemini 1.5 Pro model versions
127
+ * - All Gemini 1.5 Flash model versions
128
+ * - Gemini 1.0 Pro version gemini-1.0-pro-002
129
+ */
130
+ convertSystemMessageToHumanContent?: boolean | undefined;
123
131
  }
124
132
  /**
125
133
  * Google Generative AI chat model integration.
@@ -477,9 +485,13 @@ export declare class ChatGoogleGenerativeAI extends BaseChatModel<GoogleGenerati
477
485
  apiKey?: string;
478
486
  streaming: boolean;
479
487
  streamUsage: boolean;
488
+ convertSystemMessageToHumanContent: boolean | undefined;
480
489
  private client;
481
490
  get _isMultimodalModel(): boolean;
482
491
  constructor(fields?: GoogleGenerativeAIChatInput);
492
+ useCachedContent(cachedContent: CachedContent, modelParams?: ModelParams, requestOptions?: RequestOptions): void;
493
+ get useSystemInstruction(): boolean;
494
+ get computeUseSystemInstruction(): boolean;
483
495
  getLsParams(options: this["ParsedCallOptions"]): LangSmithParams;
484
496
  _combineLLMOutput(): never[];
485
497
  _llmType(): string;
@@ -439,6 +439,12 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
439
439
  writable: true,
440
440
  value: true
441
441
  });
442
+ Object.defineProperty(this, "convertSystemMessageToHumanContent", {
443
+ enumerable: true,
444
+ configurable: true,
445
+ writable: true,
446
+ value: void 0
447
+ });
442
448
  Object.defineProperty(this, "client", {
443
449
  enumerable: true,
444
450
  configurable: true,
@@ -503,6 +509,35 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
503
509
  });
504
510
  this.streamUsage = fields?.streamUsage ?? this.streamUsage;
505
511
  }
512
+ useCachedContent(cachedContent, modelParams, requestOptions) {
513
+ if (!this.apiKey)
514
+ return;
515
+ this.client = new GenerativeAI(this.apiKey).getGenerativeModelFromCachedContent(cachedContent, modelParams, requestOptions);
516
+ }
517
+ get useSystemInstruction() {
518
+ return typeof this.convertSystemMessageToHumanContent === "boolean"
519
+ ? !this.convertSystemMessageToHumanContent
520
+ : this.computeUseSystemInstruction;
521
+ }
522
+ get computeUseSystemInstruction() {
523
+ // This works on models from April 2024 and later
524
+ // Vertex AI: gemini-1.5-pro and gemini-1.0-002 and later
525
+ // AI Studio: gemini-1.5-pro-latest
526
+ if (this.modelName === "gemini-1.0-pro-001") {
527
+ return false;
528
+ }
529
+ else if (this.modelName.startsWith("gemini-pro-vision")) {
530
+ return false;
531
+ }
532
+ else if (this.modelName.startsWith("gemini-1.0-pro-vision")) {
533
+ return false;
534
+ }
535
+ else if (this.modelName === "gemini-pro") {
536
+ // on AI Studio gemini-pro is still pointing at gemini-1.0-pro-001
537
+ return false;
538
+ }
539
+ return true;
540
+ }
506
541
  getLsParams(options) {
507
542
  return {
508
543
  ls_provider: "google_genai",
@@ -537,7 +572,13 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
537
572
  };
538
573
  }
539
574
  async _generate(messages, options, runManager) {
540
- const prompt = convertBaseMessagesToContent(messages, this._isMultimodalModel);
575
+ const prompt = convertBaseMessagesToContent(messages, this._isMultimodalModel, this.useSystemInstruction);
576
+ let actualPrompt = prompt;
577
+ if (prompt[0].role === "system") {
578
+ const [systemInstruction] = prompt;
579
+ this.client.systemInstruction = systemInstruction;
580
+ actualPrompt = prompt.slice(1);
581
+ }
541
582
  const parameters = this.invocationParams(options);
542
583
  // Handle streaming
543
584
  if (this.streaming) {
@@ -560,7 +601,7 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
560
601
  }
561
602
  const res = await this.completionWithRetry({
562
603
  ...parameters,
563
- contents: prompt,
604
+ contents: actualPrompt,
564
605
  });
565
606
  let usageMetadata;
566
607
  if ("usageMetadata" in res.response) {
@@ -578,11 +619,17 @@ export class ChatGoogleGenerativeAI extends BaseChatModel {
578
619
  return generationResult;
579
620
  }
580
621
  async *_streamResponseChunks(messages, options, runManager) {
581
- const prompt = convertBaseMessagesToContent(messages, this._isMultimodalModel);
622
+ const prompt = convertBaseMessagesToContent(messages, this._isMultimodalModel, this.useSystemInstruction);
623
+ let actualPrompt = prompt;
624
+ if (prompt[0].role === "system") {
625
+ const [systemInstruction] = prompt;
626
+ this.client.systemInstruction = systemInstruction;
627
+ actualPrompt = prompt.slice(1);
628
+ }
582
629
  const parameters = this.invocationParams(options);
583
630
  const request = {
584
631
  ...parameters,
585
- contents: prompt,
632
+ contents: actualPrompt,
586
633
  };
587
634
  const stream = await this.caller.callWithOptions({ signal: options?.signal }, async () => {
588
635
  const { stream } = await this.client.generateContentStream(request);
@@ -33,6 +33,7 @@ function convertAuthorToRole(author) {
33
33
  case "model": // getMessageAuthor returns message.name. code ex.: return message.name ?? type;
34
34
  return "model";
35
35
  case "system":
36
+ return "system";
36
37
  case "human":
37
38
  return "user";
38
39
  case "tool":
@@ -144,7 +145,7 @@ function convertMessageContentToParts(message, isMultimodalModel) {
144
145
  return [...messageParts, ...functionCalls, ...functionResponses];
145
146
  }
146
147
  exports.convertMessageContentToParts = convertMessageContentToParts;
147
- function convertBaseMessagesToContent(messages, isMultimodalModel) {
148
+ function convertBaseMessagesToContent(messages, isMultimodalModel, convertSystemMessageToHumanContent = false) {
148
149
  return messages.reduce((acc, message, index) => {
149
150
  if (!(0, messages_1.isBaseMessage)(message)) {
150
151
  throw new Error("Unsupported message input");
@@ -173,7 +174,8 @@ function convertBaseMessagesToContent(messages, isMultimodalModel) {
173
174
  };
174
175
  }
175
176
  let actualRole = role;
176
- if (actualRole === "function") {
177
+ if (actualRole === "function" ||
178
+ (actualRole === "system" && !convertSystemMessageToHumanContent)) {
177
179
  // GenerativeAI API will throw an error if the role is not "user" or "model."
178
180
  actualRole = "user";
179
181
  }
@@ -182,7 +184,7 @@ function convertBaseMessagesToContent(messages, isMultimodalModel) {
182
184
  parts,
183
185
  };
184
186
  return {
185
- mergeWithPreviousContent: author === "system",
187
+ mergeWithPreviousContent: author === "system" && !convertSystemMessageToHumanContent,
186
188
  content: [...acc.content, content],
187
189
  };
188
190
  }, { content: [], mergeWithPreviousContent: false }).content;
@@ -11,7 +11,7 @@ export declare function getMessageAuthor(message: BaseMessage): string;
11
11
  */
12
12
  export declare function convertAuthorToRole(author: string): (typeof POSSIBLE_ROLES)[number];
13
13
  export declare function convertMessageContentToParts(message: BaseMessage, isMultimodalModel: boolean): Part[];
14
- export declare function convertBaseMessagesToContent(messages: BaseMessage[], isMultimodalModel: boolean): Content[];
14
+ export declare function convertBaseMessagesToContent(messages: BaseMessage[], isMultimodalModel: boolean, convertSystemMessageToHumanContent?: boolean): Content[];
15
15
  export declare function mapGenerateContentResultToChatResult(response: EnhancedGenerateContentResponse, extra?: {
16
16
  usageMetadata: UsageMetadata | undefined;
17
17
  }): ChatResult;
@@ -29,6 +29,7 @@ export function convertAuthorToRole(author) {
29
29
  case "model": // getMessageAuthor returns message.name. code ex.: return message.name ?? type;
30
30
  return "model";
31
31
  case "system":
32
+ return "system";
32
33
  case "human":
33
34
  return "user";
34
35
  case "tool":
@@ -138,7 +139,7 @@ export function convertMessageContentToParts(message, isMultimodalModel) {
138
139
  }
139
140
  return [...messageParts, ...functionCalls, ...functionResponses];
140
141
  }
141
- export function convertBaseMessagesToContent(messages, isMultimodalModel) {
142
+ export function convertBaseMessagesToContent(messages, isMultimodalModel, convertSystemMessageToHumanContent = false) {
142
143
  return messages.reduce((acc, message, index) => {
143
144
  if (!isBaseMessage(message)) {
144
145
  throw new Error("Unsupported message input");
@@ -167,7 +168,8 @@ export function convertBaseMessagesToContent(messages, isMultimodalModel) {
167
168
  };
168
169
  }
169
170
  let actualRole = role;
170
- if (actualRole === "function") {
171
+ if (actualRole === "function" ||
172
+ (actualRole === "system" && !convertSystemMessageToHumanContent)) {
171
173
  // GenerativeAI API will throw an error if the role is not "user" or "model."
172
174
  actualRole = "user";
173
175
  }
@@ -176,7 +178,7 @@ export function convertBaseMessagesToContent(messages, isMultimodalModel) {
176
178
  parts,
177
179
  };
178
180
  return {
179
- mergeWithPreviousContent: author === "system",
181
+ mergeWithPreviousContent: author === "system" && !convertSystemMessageToHumanContent,
180
182
  content: [...acc.content, content],
181
183
  };
182
184
  }, { content: [], mergeWithPreviousContent: false }).content;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/google-genai",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Google Generative AI integration for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {