langchain-ai / langchainjs

πŸ¦œπŸ”— Build context-aware reasoning applications πŸ¦œπŸ”—
https://js.langchain.com/docs/
MIT License
12.65k stars 2.17k forks source link

Inconsistent Response MIME Type Configuration for ChatGoogleGenerativeAI and ChatVertexAI in LangChain #5944

Closed rossanodr closed 4 months ago

rossanodr commented 4 months ago

Checked other resources

Example Code

import { ChatVertexAI, ChatGoogleGenerativeAI } from "@langchain/google-genai";

const vertexAIChat = new ChatVertexAI({ responseMimeType: "application/json" // or "text/plain" });

const googleGenerativeAIChat = new ChatGoogleGenerativeAI({ responseMimeType: "application/json" }); // This results in the error: // Object literal may only specify known properties, and 'responseMimeType' does not exist in type 'GoogleGenerativeAIChatInput'.ts(2353)

Error Message and Stack Trace (if applicable)

No response

Description

I'm trying to use the responseMimeType configuration option with the new ChatVertexAI class, and it works as expected. However, when I try to use the same option with the new ChatGoogleGenerativeAI class, it results in the error: Object literal may only specify known properties, and 'responseMimeType' does not exist in type 'GoogleGenerativeAIChatInput'.ts(2353)

System Info

yarn info langchain └─ langchain@npm:0.2.5 β”œβ”€ Instances: 1 β”œβ”€ Version: 0.2.5 β”‚ └─ Dependencies β”œβ”€ @langchain/core@npm:^0.2.5 β†’ npm:0.2.7 β”œβ”€ @langchain/openai@npm:~0.1.0 β†’ npm:0.1.3 β”œβ”€ @langchain/textsplitters@npm:~0.0.0 β†’ npm:0.0.3 β”œβ”€ binary-extensions@npm:^2.2.0 β†’ npm:2.3.0 β”œβ”€ js-tiktoken@npm:^1.0.12 β†’ npm:1.0.12 β”œβ”€ js-yaml@npm:^4.1.0 β†’ npm:4.1.0 β”œβ”€ jsonpointer@npm:^5.0.1 β†’ npm:5.0.1 β”œβ”€ langchainhub@npm:~0.0.8 β†’ npm:0.0.11 β”œβ”€ langsmith@npm:~0.1.30 β†’ npm:0.1.32 β”œβ”€ ml-distance@npm:^4.0.0 β†’ npm:4.0.1 β”œβ”€ openapi-types@npm:^12.1.3 β†’ npm:12.1.3 β”œβ”€ p-retry@npm:4 β†’ npm:4.6.2 β”œβ”€ uuid@npm:^9.0.0 β†’ npm:9.0.1 β”œβ”€ yaml@npm:^2.2.1 β†’ npm:2.4.5 β”œβ”€ zod-to-json-schema@npm:^3.22.3 β†’ npm:3.23.1 └─ zod@npm:^3.22.4 β†’ npm:3.23.8

  "@langchain/community": "^0.2.5",

"@langchain/core": "^0.2.5", "@langchain/google-genai": "^0.0.21", "@langchain/google-vertexai": "^0.0.17", "@langchain/google-vertexai-web": "^0.0.17",

dosubot[bot] commented 4 months ago

The responseMimeType configuration option works with ChatVertexAI but not with ChatGoogleGenerativeAI because the ChatGoogleGenerativeAI implementation does not include handling for the responseMimeType option.

To resolve this inconsistency, you need to add support for the responseMimeType option in the ChatGoogleGenerativeAI implementation. This involves modifying the convertMessageContentToParts function to handle the responseMimeType configuration.

Here is an example of how you can modify the convertMessageContentToParts function to include the responseMimeType option:

function messageContentMedia(content: MessageContentComplex): Part {
  if ("mimeType" in content && "data" in content) {
    return {
      inlineData: {
        mimeType: content.mimeType,
        data: content.data,
      },
    };
  }

  throw new Error("Invalid media content");
}

export function convertMessageContentToParts(
  message: BaseMessage,
  isMultimodalModel: boolean
): Part[] {
  if (typeof message.content === "string" && message.content !== "") {
    return [{ text: message.content }];
  }

  let functionCalls: FunctionCallPart[] = [];
  let functionResponses: FunctionResponsePart[] = [];
  let messageParts: Part[] = [];

  if (
    "tool_calls" in message &&
    Array.isArray(message.tool_calls) &&
    message.tool_calls.length > 0
  ) {
    functionCalls = message.tool_calls.map((tc) => ({
      functionCall: {
        name: tc.name,
        args: tc.args,
      },
    }));
  } else if (message._getType() === "tool" && message.name && message.content) {
    functionResponses = [
      {
        functionResponse: {
          name: message.name,
          response: message.content,
        },
      },
    ];
  } else if (Array.isArray(message.content)) {
    messageParts = message.content.map((c) => {
      if (c.type === "text") {
        return {
          text: c.text,
        };
      }

      if (c.type === "image_url") {
        if (!isMultimodalModel) {
          throw new Error(`This model does not support images`);
        }
        let source;
        if (typeof c.image_url === "string") {
          source = c.image_url;
        } else if (typeof c.image_url === "object" && "url" in c.image_url) {
          source = c.image_url.url;
        } else {
          throw new Error("Please provide image as base64 encoded data URL");
        }
        const [dm, data] = source.split(",");
        if (!dm.startsWith("data:")) {
          throw new Error("Please provide image as base64 encoded data URL");
        }
        const [mimeType, encoding] = dm.replace(/^data:/, "").split(";");
        if (encoding !== "base64") {
          throw new Error("Please provide image as base64 encoded data URL");
        }

        return {
          inlineData: {
            data,
            mimeType,
          },
        };
      } else if (c.type === "media") {
        return messageContentMedia(c);
      } else if (c.type === "tool_use") {
        return {
          functionCall: {
            name: c.name,
            args: c.input,
          },
        };
      }
      throw new Error(`Unknown content type ${(c as { type: string }).type}`);
    });
  }

  return [...messageParts, ...functionCalls, ...functionResponses];
}

By adding the responseMimeType property handling in the convertMessageContentToParts function, you ensure that the responseMimeType option is properly handled in the ChatGoogleGenerativeAI implementation [1][2].

To continue talking to Dosu, mention @dosu.

afirstenberg commented 4 months ago

Is there a reason you're trying to use both the google-genai package and the google-vertexai packages? You should be able to use the google-gauth or google-webauth packages to access both using a single library. (The google-vertexai package is mostly a wrapper that locks it into Vertex.)

rossanodr commented 4 months ago

Is there a reason you're trying to use both the google-genai package and the google-vertexai packages? You should be able to use the google-gauth or google-webauth packages to access both using a single library. (The google-vertexai package is mostly a wrapper that locks it into Vertex.)

Vertex AI does not allow setting the threshold to 'BLOCK_NONE'. I want to use Google GenAI, but it's not possible to set the responseMimeType on it.

afirstenberg commented 4 months ago

The google-genai and google-webauth packages can be used to access the "GenAI" platform. You just need to have the API Key set. It doesn't use Vertex AI in that case.

rossanodr commented 4 months ago

The google-genai and google-webauth packages can be used to access the "GenAI" platform. You just need to have the API Key set. It doesn't use Vertex AI in that case.

If I try to use the genai api key with the "new ChatVertexAI" I get the error [Error: APIs that require a project ID cannot use an API key]

afirstenberg commented 4 months ago

@rossanodr

The google-genai and google-webauth packages can be used to access the "GenAI" platform. You just need to have the API Key set. It doesn't use Vertex AI in that case.

If I try to use the genai api key with the "new ChatVertexAI" I get the error [Error: APIs that require a project ID cannot use an API key]

Use the "google-webauth" package and new ChatGoogle. These classes work for both GenAI and Vertex.

See either of the following (same article on different platforms):

rossanodr commented 4 months ago

@rossanodr

The google-genai and google-webauth packages can be used to access the "GenAI" platform. You just need to have the API Key set. It doesn't use Vertex AI in that case.

If I try to use the genai api key with the "new ChatVertexAI" I get the error [Error: APIs that require a project ID cannot use an API key]

Use the "google-webauth" package and new ChatGoogle. These classes work for both GenAI and Vertex.

See either of the following (same article on different platforms):

Thank you!!! save my life