langchain: Issue: Amazon Bedrock can't load my credentials when called from a Lambda function

Issue you’d like to raise.

Bedrock can’t seem to load my credentials when used within a Lambda function. My AWS credentials were set up in my local environment using environment variables. When I use the bedrock class directly, it is able to load my credentials and my code runs smoothly. Here is the RetrievalQA function that utilizes the bedrock class:

def qa(query):
    secrets = json.loads(get_secret())
    kendra_index_id = secrets['kendra_index_id']


    llm = Bedrock(model_id="amazon.titan-tg1-large", region_name='us-east-1')
    llm.model_kwargs = {"maxTokenCount": 4096}
    

    retriever = AmazonKendraRetriever(index_id=kendra_index_id)
    
    prompt_template = """
    {context}
    {question} If you are unable to find the relevant article, respond 'I can't generate the needed content based on the context provided.'
    """
    
    PROMPT = PromptTemplate(
    template=prompt_template, input_variables=["context", "question"])
    
    chain = RetrievalQA.from_chain_type(
    llm=llm,
    retriever=retriever,
    verbose=True,
    chain_type_kwargs={
    "prompt": PROMPT
    }
    )
    
    return chain(query)

The above code runs without issues when used directly. However, when used within a lambda function, it fails. The scripts file used to build my lambda function uses the bedrock class as written above, however, I run into the validation errors when I invoke the Lambda function. { "errorMessage": "1 validation error for Bedrock\n__root__\n Could not load credentials to authenticate with AWS client. Please check that credentials in the specified profile name are valid. (type=value_error)", "errorType": "ValidationError", "requestId": "b772f236-f582-4308-8af5-b5a418d4327f", "stackTrace": [ " File \"/var/task/main.py\", line 62, in handler\n response = qa(query)\n", " File \"/var/task/main.py\", line 32, in qa\n llm = Bedrock(model_id=\"amazon.titan-tg1-large\", region_name='us-east-1',) #client=BEDROCK_CLIENT)\n", " File \"/var/task/langchain/load/serializable.py\", line 74, in __init__\n super().__init__(**kwargs)\n", " File \"pydantic/main.py\", line 341, in pydantic.main.BaseModel.__init__\n raise validation_error\n" ]

As clearly indicated by the error message, bedrock couldn’t load credentials.

Suggestion:

I have looked at the official documentation of the bedrock class but still do not understand why my code fails. Any help will be appreciated. @3coins @jasondotparse @hwchase17

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 1
  • Comments: 22

Most upvoted comments

Answer generated by a 🤖

Answer

Hello,

The issue you’re experiencing is due to how the Bedrock class is handling AWS credentials. When running in your local environment, the Bedrock class is able to access your AWS credentials from the ~/.aws/credentials file or ~/.aws/config files. However, in the AWS Lambda environment, these files are not available and the credentials are provided through environment variables.

The Bedrock class should be modified to use the default credentials when the credentials_profile_name is not provided. This will allow it to use the IAM role associated with the Lambda function. Here is the modified code:

    @root_validator()
    def validate_environment(cls, values: Dict) -> Dict:
        """Validate that AWS credentials to and python package exists in environment."""

        if values["client"] is not None:
            return values

        try:
            import boto3

            if values["credentials_profile_name"] is not None:
                session = boto3.Session(profile_name=values["credentials_profile_name"])
            else:
                # use default credentials
                session = boto3.Session()

            client_params = {}
            if values["region_name"]:
                client_params["region_name"] = values["region_name"]

            if values["endpoint_url"]:
                client_params["endpoint_url"] = values["endpoint_url"]

            values["client"] = session.client("bedrock", **client_params)

        except ImportError:
            raise ModuleNotFoundError(
                "Could not import boto3 python package. "
                "Please install it with `pip install boto3`."
            )
        except Exception as e:
            raise ValueError(
                "Could not load credentials to authenticate with AWS client. "
                "Please check that credentials in the specified "
                "profile name are valid."
            ) from e

        return values

In this code, if credentials_profile_name is not provided, it will use the default session which will automatically use the credentials provided by the IAM role associated with the Lambda function.

Please try this modification and let me know if it resolves your issue. If you have any further questions, feel free to ask.

Best, Dosu

Sources


This response is meant to be useful, save you time, and share context. It is not meant to be a precise solution, but rather a starting point for your own research.

Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant.

Answer generated by a 🤖

Answer

Hello @3coins, @jasondotparse, @hwchase17,

I understand that you’re having trouble with the Bedrock class not being able to load your AWS credentials when called from a Lambda function. This issue is likely due to the difference in how AWS credentials are loaded in a local environment versus a Lambda function.

In your local environment, the Bedrock class is able to load your AWS credentials from the ~/.aws/credentials file or the ~/.aws/config file. However, when running in a Lambda function, these files are not available. Instead, AWS Lambda functions use IAM roles for permissions. The IAM role associated with your Lambda function needs to have the necessary permissions to access the Bedrock service.

To resolve this issue, you should ensure that the IAM role associated with your Lambda function has the necessary permissions to access the Bedrock service. If you’re using the default AWS SDK for Python (boto3) client, it will automatically use the credentials associated with the IAM role of the Lambda function.

Here’s the relevant part of the code that loads the credentials:

try:
    import boto3

    if values["credentials_profile_name"] is not None:
        session = boto3.Session(profile_name=values["credentials_profile_name"])
    else:
        # use default credentials
        session = boto3.Session()

    client_params = {}
    if values["region_name"]:
        client_params["region_name"] = values["region_name"]

    if values["endpoint_url"]:
        client_params["endpoint_url"] = values["endpoint_url"]

    values["client"] = session.client("bedrock", **client_params)

except ImportError:
    raise ModuleNotFoundError(
        "Could not import boto3 python package. "
        "Please install it with `pip install boto3`."
    )
except Exception as e:
    raise ValueError(
        "Could not load credentials to authenticate with AWS client. "
        "Please check that credentials in the specified "
        "profile name are valid."
    ) from e

In this code, if credentials_profile_name is not provided, it defaults to using the default credentials which, in the case of a Lambda function, would be the IAM role associated with the function.

There was a similar issue raised in the LangChain repository: AmazonKendraRetriever “Could not load credentials” error in latest release which was resolved by ensuring the IAM role associated with the Lambda function had the necessary permissions.

I hope this helps! Let me know if you have any other questions.

Sources


This response is meant to be useful, save you time, and share context. It is not meant to be a precise solution, but rather a starting point for your own research.

Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant.

Fine if you already have done with package installation then you could write something like that :

from boto3
from langchain.llms import Bedrock

session = boto3.Session(region_name = 'us-west-2')
boto3_bedrock = session.client(service_name="bedrock")

# Langchain LLM
llm = Bedrock(client=boto3_bedrock, model_id="anthropic.claude-v2", region_name='us-west-2')

in this case you bypass your first issue and your needs credential are provided by lambda role and not from profile. I made it works on Lambda and it works for me

I’m facing the same problem, locally with my credentials in the ~/.aws/credentials it works just fine, but in the Lambda it fails with:

  "errorMessage": "1 validation error for Bedrock\n__root__\n  Could not load credentials to authenticate with AWS client. Please check that credentials in the specified profile name are valid. (type=value_error)",

I don’t think the upgrades above about boto3 make sense anymore since it is already in version 1.28.63 and clearly already supports bedrock.

UPDATE

Nevermind this, ended up finding out that the docker environment wasn’t getting the latest version for the image that I was publishing. Once it got the latest, it works.