通过AWS Lambda调用Amazon Bedrock时凭证加载失败的问题
问题分析与解决方案
错误原因是Lambda运行环境中不存在本地AWS配置文件(default凭证配置文件),而代码中指定了credentials_profile_name='default',导致Bedrock客户端无法加载有效凭证。Sagemaker笔记本能正常运行是因为它自动使用了实例关联的IAM角色凭证,而Lambda需要依赖自身的执行角色来获取权限。
修复步骤
1. 移除硬编码的凭证配置参数
删除Bedrock初始化时的credentials_profile_name='default'参数,让boto3自动使用Lambda执行角色的临时凭证。
2. 手动创建Bedrock客户端(更可靠的方式)
显式创建boto3 Bedrock Runtime客户端并传入LangChain的Bedrock类,避免自动初始化时的凭证问题。修改qa函数中的Bedrock初始化代码:
def qa(query): secrets = json.loads(get_secret()) kendra_index_id = secrets['kendra_index_id'] # 用Lambda的默认session创建Bedrock Runtime客户端 session = boto3.Session(region_name='us-east-1') bedrock_client = session.client(service_name='bedrock-runtime') # 将客户端传入LangChain的Bedrock类 llm = Bedrock( model_id="amazon.titan-tg1-large", client=bedrock_client, model_kwargs={"maxTokenCount": 4096} ) # 后续代码保持不变...
3. 配置Lambda执行角色的权限
确保Lambda的执行角色拥有以下权限,添加对应的IAM政策:
- Bedrock权限:允许调用Titan模型,添加
bedrock:InvokeModel动作,资源指定arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-tg1-large - Kendra权限:允许检索Kendra索引内容,添加
kendra:Retrieve动作,资源指定你的Kendra索引ARN - Secrets Manager权限:允许获取指定密钥,添加
secretsmanager:GetSecretValue动作,资源指定kendraRagApp密钥的ARN
示例IAM政策(按需调整资源ARN):
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "bedrock:InvokeModel", "Resource": "arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-tg1-large" }, { "Effect": "Allow", "Action": "kendra:Retrieve", "Resource": "arn:aws:kendra:us-east-1:你的账号ID:index/你的Kendra索引ID" }, { "Effect": "Allow", "Action": "secretsmanager:GetSecretValue", "Resource": "arn:aws:secretsmanager:us-east-1:你的账号ID:secret:kendraRagApp-随机后缀" } ] }
4. 验证修改后的完整代码
修改后的main.py关键部分如下:
from langchain.llms.bedrock import Bedrock import boto3 from langchain.retrievers import AmazonKendraRetriever from langchain.chains import RetrievalQA from langchain.prompts import PromptTemplate import json from botocore.exceptions import ClientError def get_secret(): secret_name = "kendraRagApp" session = boto3.session.Session() client = session.client(service_name='secretsmanager') try: get_secret_value_response = client.get_secret_value(SecretId=secret_name) except ClientError as e: raise e secret = get_secret_value_response['SecretString'] return secret def qa(query): secrets = json.loads(get_secret()) kendra_index_id = secrets['kendra_index_id'] # 显式创建Bedrock Runtime客户端 session = boto3.Session(region_name='us-east-1') bedrock_client = session.client('bedrock-runtime') llm = Bedrock( model_id="amazon.titan-tg1-large", client=bedrock_client, 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) def handler(event, context): query = event['query'] response = qa(query) if response.get("result"): return { 'statusCode': 200, 'body': response["result"] } else: return { 'statusCode': 400, 'body': "Could not answer the query based on the context available" }
关键注意点
- Lambda运行环境中没有本地AWS配置文件,永远不要在Lambda代码中指定
credentials_profile_name - 调用Bedrock模型必须使用
bedrock-runtime客户端,而非bedrock客户端(后者用于模型管理操作) - 所有AWS服务访问都依赖Lambda执行角色的权限,必须确保角色拥有足够的权限范围
内容的提问来源于stack exchange,提问作者Mustapha Unubi Momoh
相关产品推荐
相关产品推荐

