亚马逊AWS官方博客

手把手教你使用 API Key 调用 Amazon Bedrock

背景

Amazon Bedrock 是一项完全托管的服务,提供各种来自领先 AI 公司(包括 AI21 Labs、Anthropic、Cohere、Stability AI 和 Amazon)的高性能基础模型(FM),以及用于构建生成式人工智能应用程序的广泛功能,可简化开发,同时维护隐私和安全。借助 Bedrock 您无需管理任何基础设施,就可以使用您已经熟悉的 AWS 服务将生成式人工智能功能安全地集成和部署到您的应用程序中。

Amazon Bedrock 通过 IAM 进行权限验证。如果想在应用中调用 Amazon Bedrock,则需要创建对应的 IAM Role/User,使用其 Access Key 和 Secret Access Key 对于每次调用进行 SigV4 的签名。AWS SDK for Python(Boto3)以及其它其它语言的 AWS SDK 通过把签名逻辑封装在内部,简化了构建以 Amazon Bedrock 为“大脑”的智能应用难度。具体代码可以参见 Amazon Bedrock 与 Langchain 的集成

对于有大量用户,并且需要对每个用户的调用进行精细化管理的场景而言,通过 API Key 进行用户的认证是一种更常用的设计。本文针对这一场景,以 Bedrock Cluade2 模型为例,给出对应的解决方案。

架构

本方案整体架构如下:

其中:

API Gateway 是 AWS 提供的用于创建、发布、维护、监控和保护 REST、HTTP 和 WebSocket API 的一项服务。它作为基于 Web 的应用程序的入口点,可以将传入的 Web 请求转换为由 Lambda 函数、AWS 服务和 HTTP 端点处理的事件。在本方案中负责 API key 的管理和验证以及根据请求调用 Lambda 函数。

Lambda 是 AWS 提供的一项无需服务器即能运行函数代码的服务。在本方案中负责处理掉用 Amazon Bedrock 的验证以及请求、响应体的转换。

实现

首先请您确保您的账号已经开通了 Bedrock 相关的权限。

开发环境设置

由于需要构建运行在 X86_64 架构下的 Lambda 函数,我们使用 AWS Cloud9 这个 AWS 的云端 IDE,配合 X86_64 的机型,例如 m6i.2xlarge 来作为我们的开发环境。

打开 Cloud9 后我们首先关闭 AWS managed temporary credentials,防止在与 AWS 交互过程中使用 EC2 上挂钩的 IAM Role,然后在 terminal 中执行 AWS configure 配置开发环境用到的 IAM User。简单起见可以配置包含 AdministratorAccess 这一 Policy 的 IAM User,更精细化的权限配置可以参考 https://docs.aws.amazon.com/bedrock/latest/userguide/security_iam_id-based-policy-examples.html

然后,我们使用 Conda 创建一个 Python 的虚拟环境

wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
chmod +x Miniconda3-latest-Linux-x86_64.sh 
sudo ./Miniconda3-latest-Linux-x86_64.sh

重启 terminal 后执行

conda create -n py310 python=3.10
conda activate py310

boto3 版本在 1.28.59 以上已经支持 Bedrock 相关功能

pip install boto3>=1.28.59

使用 AWS Chalice 进行 API Gateway 和 Lambda 的开发

AWS Chalice 是一个用于编写 Python 无服务器应用程序的框架。它允许您快速创建和部署使用 AWS Lambda 的应用程序。它提供以下功能:

  • 一个命令行工具,用于创建、部署和管理您的应用程序
  • 基于装饰器的 API,用于与 Amazon API Gateway、Amazon S3、Amazon SNS、Amazon SQS 和其他 AWS 服务集成
  • 自动 IAM 策略生成

AWS Chalice 的安装与项目生成

python3 -m pip install chalice
chalice new-project bedrock-invoke

项目生成完成后,打开 app.py 并修改为以下内容,注意使用您开通的 Bedrock 所在的 region_name 和 endpoint_url。

import boto3
import botocore
import json
from chalice import Chalice

app = Chalice(app_name='bedrock-invoke')
print(boto3.__version__)
print(botocore.__version__)

bedrock_client= boto3.client(service_name='bedrock', region_name=''YOUR_BEDROCK_REGION' )

@app.route('/', methods=['POST'])
def index():
    prompt_data = app.current_request.json_body.get('prompt_data')
    bedrock = boto3.client(service_name="bedrock-runtime")
    body = json.dumps(
        {
            "prompt": prompt_data,
            "max_tokens_to_sample": 200,
        }
    )
    response = bedrock.invoke_model(body=body, modelId="anthropic.claude-v2")
    response_body = json.loads(response.get("body").read())
    output_text = print(response_body.get("completion"))
return {'response': output_text}

接着我们本地测试一下这个函数

cd bedrock-invoke
mkdir tests
touch tests/{__init__.py,test_app.py}

修改 tests/test_app.py 为以下内容

from chalice.test import Client
from app import app
import json

def test_foo_function():
    prompt_data = """"\n\nHuman: who are you \n\nAssistant:"""
    with Client(app) as client:
        response = client.http.post('/', 
            headers={'Content-Type':'application/json'},
            body=json.dumps({'prompt_data': prompt_data})
            )
        print(response)

安装 pytest 工具

pip install pytest
$ py.test -s tests/test_app.py

测试成功的话会看到类似这样的输出

部署

由于目前 Lambda 默认的 Boto3 还不支持 Bedrock 相关的功能,我们需要把环境中的 Boto3 作为依赖打包进 Lambda Layer 中。Chalice 包含了自动打包 Layer 的功能,我们只需要将这些依赖放到 bedrock-invoke/vendor 目录下。

pip install boto3 -t ./vendor

另外,由于 Chalice 目前还不支持 Bedrock 相关功能的自动权限识别,因此我们需要在.chalice 文件夹下增加 bedrock-policy.json 来指定 Lambda 需要的权限。

// bedrock-policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:*:logs:*:*:*"
        },
        {
            "Effect": "Allow",
            "Action": "bedrock:*",
            "Resource": "*"
        }
    ]
}

最后,我们修改.chalice/config.json,增加 automatic_layer 的设置以及去除 autogen_policy 的设置。

{
  "version": "2.0",
  "app_name": "bedrock-invoke",
  "automatic_layer": true,
  "stages": {
    "dev": {
      "api_gateway_stage": "api",
      "autogen_policy": false,
      "iam_policy_file": "bedrock-policy.json",
      "automatic_layer": true
    }
  }
}

最后我们执行 chalice deploy,它会同时部署 Lambda Layer,Lambda 以及 API Gateway 以及对应的权限(初次部署输出略有不同)。

在 AWS Console 上可以看到部署的 Lambda 和 API Gateway

不过由于 Chalice 还不支持设置 API Key 的认证方式,现在部署的 API Gateway 没有任何认证,我们通过 Console 给它增加 API Key 的认证。

1. 把 API Key Required 修改为 true

点击 Actions → Deploy API

2. 创建 Usage Plan

点击 Create API Key and add to Usage Plan

测试

这里使用 Postman 来进行测试。

1. 首先我们可以在 API Keys 中找到刚创建的 API Key 并进行复制

2. 设置 API Key

3. 发送请求进行测试

至此我们就完成了所有的开发测试工作。

总结

通过 API Gateway+Lambda,我们实现了 Amazon Bedrock 认证方式的转换,可以更方便地集成到其他应用中或者给到终端用户进行直接使用。在开发过程中,我们使用了 Cloud9 作为 IDE 并在 EC2 上直接进行开发,减少了不同环境造成的影响。通过使用 Chalice 框架,我们也降低了手工部署 API Gateway,Lambda,Lambda Layer 以及相应权限的复杂程度。当然,我们还可以对 Usage Plan 进行更加精细的设置来控制用户的调用频率等等。

本篇作者

施俊

AWS 解决方案架构师,主要负责数字金融客户和企业级客户在 AWS 上的架构设计与实施。10+年金融软件研发和机器学习经验。

曹镏

亚马逊云科技解决方案架构师,负责企业信息化方案的咨询和架构设计。超过 10 年的研发经验,曾在大型国企和互联网独角兽任职,并主导百亿级平台的技术架构和数据架构的设计与落地。专注数智融合以及生成式 AI 方向,赋能企业创新成长。

张尹

AWS 技术客户经理,负责企业级客户的架构和成本优化、技术支持等工作。有多年的大数据架构设计,数仓建模等实战经验。在加入 AWS 之前,长期负责头部电商大数据平台架构设计、数仓建模、运维等相关工作。