aws / aws-sdk-js-v3

Modularized AWS SDK for JavaScript.
Apache License 2.0
2.95k stars 554 forks source link

Bedrock Converse API missing exports for commonjs #6188

Open mtliendo opened 2 weeks ago

mtliendo commented 2 weeks ago

Checkboxes for prior research

Describe the bug

When using ES Modules, the docs state that I should be able to import the methods like so:

import { BedrockRuntimeClient, ConverseCommand } from "@aws-sdk/client-bedrock-runtime"; // ES Modules import

However that results in the following runtime error:

"SyntaxError: Named export 'ConverseCommand' not found. The requested module '@aws-sdk/client-bedrock-runtime' is a CommonJS module, which may not support all module.exports as named exports.\nCommonJS modules can always be imported via the default export, for example using:\n\nimport pkg from '@aws-sdk/client-bedrock-runtime';\nconst { ConverseCommand } = pkg;\n"

The solution is to do something like import * from '@aws-sdk/client-bedrock-runtime'. Though this is not mentioned in the docs.


The other issue is that it doesn't seem possible to call the ConverseCommand(input). If I prefix it with new, then I get a runtime error saying that it is not a constructor. If I omit the new keyword, I get an error saying it is not a function. Logging out bedrock.ConverseCommand returns undefined.

For reference, this is my sample code:

import bedrock from '@aws-sdk/client-bedrock-runtime'

const client = new bedrock.BedrockRuntimeClient({
    region: 'us-east-1',
})

export const handler = async () => {
    const input = {
        modelId: 'anthropic.claude-3-haiku-20240307-v1:0',
        messages: [
            {
                role: 'assistant' as bedrock.ConversationRole,
                content: [
                    {
                        text: 'You are a sassy intern. You reply with the letter "B" as the first item in your sentence.',
                    },
                ],
            },
            {
                role: 'user' as bedrock.ConversationRole,
                content: [
                    {
                        text: 'What is a good type of taco?',
                    },
                ],
            },
        ],
    }

    const command = new bedrock.ConverseCommand(input)
    const response = await client.send(command)

    console.log('the response', response)
    return 'Hello, World!'
}

SDK version number

@aws-sdk/client-bedrock-runtime@^3.592.0

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

node 20

Reproduction Steps

Create a lambda function with version 20 and paste in the provided code. make sure the lambdas package.json type is set to module.

Observed Behavior

pasted in details section.

Expected Behavior

bedrock output.

Possible Solution

No response

Additional Information/Context

No response

mtliendo commented 2 weeks ago

I think I see the issue. The commonjs libs (dist-cjs) seem to be missing the commands folder. So when esbuild transpiles to commonjs in my Lambda, it's not being found.

image
mtliendo commented 2 weeks ago

To help in troubleshooting, I created the following repo: https://github.com/mtliendo/sample-converse

The converse.cjs file works and can be ran with node converse.mjs so long as the shell environment has the proper AWS credentials configured.

I also created a Lambda function with AWS Amplify located in amplify/functions/testConverse/resource.ts. This file uses the adjacent main.ts as the handler code. This code is written in TypeScript and transpiled with esbuild. When deployed, I get the following error:

Named export 'ConverseCommand' not found. The requested module '@aws-sdk/client-bedrock-runtime' is a CommonJS module, which may not support all module.exports as named exports.\nCommonJS modules can always be imported via the default export, for example using:\n\nimport pkg from '@aws-sdk/client-bedrock-runtime';\n",

To further debug, I created a standard NodeJSFunction Lambda using the L2 construct in the CDK. This is located in the amplify/backend.ts file (unaffiliated with Amplify). When deployed and tested, I get a related but slightly different error message:

  "errorMessage": "import_client_bedrock_runtime.ConverseCommand is not a constructor",

As shown in the above screenshot, it appears the commands folder that is visible in dist-es, is not available in dist-cjs.

DennisTraub commented 2 weeks ago

I'm not sure why the issue occurs. It looks like your deployment is missing the dependencies.

Have a look at this repo that successfully deploys and tests your TS example: https://github.com/DennisTraub/bedrock-converse-lambda-ts

jennapederson commented 2 weeks ago

I'm running into the same issue with a Lambda function created via Amplify as well. I was able to verify that the version used by the Lambda function is different than what’s in package.json. Reading this and then trying out this example to get the version verifies it’s 3.552.0 (from a couple months ago).

aBurmeseDev commented 2 weeks ago

Hi everyone - thanks for checking in.

Based off your comments, it sounds like this reported behavior only occurs in Lambda provided SDK via Amplify since I'm not able to reproduce it with JavaScript SDK itself.

@mtliendo - do you mind checking if you can run it with SDK but not in Lambda?

@DennisTraub - I believe the repo you shared isn't reachable, may be private. I'd appreciate if you can share it with us.

RanVaknin commented 2 weeks ago

Hi,

I see that the Converse API operation was only introduced 2 weeks ago. The Lambda provided SDK is not the latest released SDK (Lambda only updates it roughly twice a year) therefore it would not contain the latest features released via the SDK.

In order to use the latest features, you'll need to provide the desired SDK version yourself (either with a Lambda Layer or with bundling and minifying and uploading to Lambda)

The SDK team does not control which SDK version is vended through lambda, and therefore this is not actionable by our team so I'm inclined to close this issue.

Can you please give this a try and see if it solves your issue? Thanks, Ran

DennisTraub commented 2 weeks ago

@aBurmeseDev Oh, my bad. I made it public now. It basically confirms what @RanVaknin already said: It works if you bundle the dependencies into the package.

SumiyaE commented 5 days ago

I am encountering the same issue and seeking assistance. I created a Lambda function using the aws-lambda-nodejs module in CDK. In this case, the modules are bundled by default with esbuild, so I understand that the version of the SDK specified in my package.json is used on Lambda. However, like @mtliendo previously posted, I am encountering the error import_client_bedrock_runtime.ConverseCommand is not a constructor.

lambda handler code is here

import { Handler } from 'aws-lambda';
import {
    BedrockRuntimeClient,
    ConverseCommand, Message,
} from "@aws-sdk/client-bedrock-runtime";

export const handler: Handler = async (event, context) => {
    console.log('EVENT: \n' + JSON.stringify(event, null, 2));
    console.log('hello this is lambda message')
    const client = new BedrockRuntimeClient();
    const modelId = "anthropic.claude-v2:1";
    const userMessage = "please tell me how to use bedrock";

    const conversation:Message[] = [
        {
            role: "user",
            content: [{ text: userMessage }],
        },
    ];

    // ------------- here is the problem area. ------------- 
    const command : ConverseCommand = new ConverseCommand({
        modelId,
        messages: conversation,
        inferenceConfig: { maxTokens: 512, temperature: 0.5, topP: 0.9 },
    });

    try {
        // Send the command to the model and wait for the response
        const response = await client.send(command);

        // Extract and print the streamed response text in real-time.
        const responseText = response.output?.message?.content?.[0].text ?? 'No response text available';
    } catch (err) {
        console.log(`ERROR: Can't invoke '${modelId}'. Reason: ${err}`);
    }

};

cdk stack code is here

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import {NodejsFunction} from "aws-cdk-lib/aws-lambda-nodejs";
import {Architecture, Runtime} from "aws-cdk-lib/aws-lambda";
// import * as sqs from 'aws-cdk-lib/aws-sqs';

export class BedrockTrainStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const lambda =  new NodejsFunction(this, 'BedrockTrainLambda', {
        entry: 'lambda/index.ts',
        handler: 'handler',
        runtime: Runtime.NODEJS_18_X,
        architecture:Architecture.ARM_64,
    })
  }
}

How can I resolve this issue?

SumiyaE commented 5 days ago

Hi! I wanted to share how I resolved import_client_bedrock_runtime.ConverseCommand is not a constructor error I posted about earlier.

When creating a Lambda function using the aws-lambda-nodejs module with CDK, it indeed seems that esbuild automatically bundles the node_modules. However, if you specify a runtime other than NODEJS_LATEST, esbuild appears to exclude the aws-sdk from the bundle.

You can refer to the official documentation for more details (the relevant section in the README is here, and the related tests are mentioned here).

To address this issue, if you're specifying a runtime other than NODEJS_LATEST, you need to explicitly indicate that there are no modules to exclude from the bundle, like this:

const lambda = new NodejsFunction(this, 'BedrockTrainLambda', {
    entry: 'lambda/index.ts',
    handler: 'handler',
    runtime: Runtime.NODEJS_20_X,
    architecture: Architecture.ARM_64,
    bundling: {
        externalModules: [], // here
    }
});

Alternatively, as I mentioned earlier, specifying NODEJS_LATEST for the runtime also resolves this issue:

const lambda = new NodejsFunction(this, 'BedrockTrainLambda', {
    entry: 'lambda/index.ts',
    handler: 'handler',
    runtime: Runtime.NODEJS_LATEST,
    architecture: Architecture.ARM_64,
});

believe this solution will also work for @mtliendo's issue.