当前位置:Java -> 亚马逊Bedrock:利用Quarkus和AWS的基础模型

亚马逊Bedrock:利用Quarkus和AWS的基础模型

Bedrock 是亚马逊的新服务,它使用户能够更容易地访问由一些最高排名的人工智能专家提供的最新基础模型(Foundation Models,FM)。他们的列表相当令人印象深刻,包括但不限于:

  • Titan
  • Claude
  • Mistral AI
  • Llama2
  • ...

根据您的AWS区域,其中一些FM可能无法使用。例如,根据这篇文章,在我的区域 eu-west-3,唯一可用的FM是Titan和Mistral AI,但情况变化非常快。

那么,使用这项服务有什么意义呢?显然,这项服务除了让您访问其他FM外什么也没有做,对吗?亚马逊Bedrock的附加价值在于通过API公开所有这些FM,让您有机会通过无处不在的技术(如无服务器或REST)轻松地将生成式人工智能集成到您的应用程序中。这正是这篇文章想要演示的。那么,让我们开始吧!

生成式人工智能网关

为了说明这篇文章,选择了一个名为生成式人工智能网关的项目,其中用户可以访问一定数量的FM,每个FM都专门针对不同类型的用例,例如文本生成、对话界面、文本摘要、图像生成等。

下面的图表展示了示例应用程序的总体架构。

示例应用程序架构图

正如您所看到的,示例应用程序包括以下组件:

  • 一个Web前端,允许用户选择FM,配置其参数(如temperaturemax tokens等),并与其开始对话,例如提出问题。由于我们的应用程序是Quarkus应用程序,这里我们使用了quarkus-primefaces扩展。
  • 一个旨在公开专用端点的AWS REST网关,具体取决于所选择的FM。在此处,我们使用了quarkus-amazon-lambda-rest扩展,正如您很快将看到的,它能够自动生成部署REST网关到AWS所需的SAM(无服务器应用程序模型)模板。
  • 几个处理POST请求的REST端点,旨在通过Bedrock客户端调用所选择的FM。FM的响应通过REST网关返回到我们的Web应用程序。

现在让我们更详细地看看实现方式。

REST网关

我们的Maven多模块项目中的bedrock-gateway-api模块实现了这个组件。它包括一个Quarkus RESTeasy API,公开几个端点,用于处理POST请求,将用户交互作为输入参数,并返回FM的响应。输入参数是字符串,而在用户请求的结果是真正大量文本的情况下,它们是输入文件。

这些端点通过将关联输入转换为FM特定的语法来处理这些POST请求,其中包括以下参数:

  • temperature:介于0和1之间的实数,旨在影响FM的可预测性。较低的值意味着较可预测的输出,而较高的值将生成更随机的响应。
  • top P:介于0和1之间的实数,其值应该选择分布中最有可能的令牌。较低的值会导致响应的选择机会更少。
  • max-tokens:表示FM对于任何给定请求将处理的最大字数的整数值。

Bedrock文档可提供所有有关上述参数的必要遗漏细节。与FM服务交互的Bedrock客户端如下所示实例化:

private final BedrockRuntimeAsyncClient client = 
  BedrockRuntimeAsyncClient.builder().region(Region.EU_WEST_3).build();


这需要使用以下Maven构件:

<dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>bedrockruntime</artifactId>
</dependency>


Web前端

文章。
    @RegisterRestClient
    @Path("/bedrock")
    @Produces(MediaType.TEXT_PLAIN)
    @Consumes(MediaType.APPLICATION_JSON)
    public interface BedrockAiEndpoint
    {
      @POST
      @Path("mistral2")
      Response callMistralFm (BedrockAiInputParam bedrockAiInputParam);
      @POST
      @Path("titan2")
      Response callTitanFm (BedrockAiInputParam bedrockAiInputParam);
    }


运行示例应用程序

  • 在本地执行AWS REST网关和相关的AWS Lambda端点;
  • 在云中执行AWS REST网关和相关的AWS Lambda端点。

本地运行

run-local.sh的shell脚本在本地运行AWS REST网关和相关的AWS Lambda端点。以下是代码:
    #!/bin/bash
    mvn -Durl=http://localhost:3000 clean install
    sed -i 's/java11/java17/g' bedrock-gateway-api/target/sam.jvm.yaml
    sam local start-api -t ./bedrock-gateway-api/target/sam.jvm.yaml --log-file ./bedrock-gateway-api/sam.log &
    mvn -DskipTests=false failsafe:integration-test
    docker run --name bedrock -p 8082:8082 --rm --network host nicolasduminil/bedrock-gateway-web:1.0-SNAPSHOT
    ./cleanup-local.sh


在这里我们需要做的第一件事是通过运行Maven命令来构建应用程序。这将导致包括一个名为nicolasduminil/bedrock-gateway-web的Docker镜像的生成,该镜像专用于运行Web前端。同时,Quarkus将生成SAM模板(target\sam.jvm.yam),用来创建包含AWS REST Gateway和端点AWS Lambda函数的AWS CloudFormation堆栈。

由于某种原因,用于此目的的Quarkusquarkus-amazon-lambda-rest扩展将运行时配置为Java 11,即使在联系支持后,我也没有找到任何修改方式。因此,脚本中使用了sed命令来将运行时修改为Java 17。

然后,使用sam cli来运行start-api命令,这将在本地执行所需端点的网关。接下来,我们可以代表Mavenfailsafe插件来运行集成测试。初始运行构建时,我们无法执行集成测试,因为本地堆栈还没有部署。

最后,该脚本启动一个运行nicolasduminil/bedrock-gateway-web镜像的Docker容器,该镜像之前由quarkus-container-image-jib扩展创建。这是我们的前端。现在,为了测试它,你可以转到下一节进行测试。

在云中运行

以下所示的名为`deploy.sh`的脚本在云中部署我们的应用程序:

    #!/bin/bash
    mvn -pl bedrock-gateway-api -am clean install
    sed -i 's/java11/java17/g' bedrock-gateway-api/target/sam.jvm.yaml
    RANDOM=$$
    BUCKET_NAME=bedrock-gateway-bucket-$RANDOM
    STACK_NAME=bedrock-gateway-stack
    echo $BUCKET_NAME > bucket-name.txt
    aws s3 mb s3://$BUCKET_NAME
    sam deploy -t bedrock-gateway-api/src/main/resources/template.yaml --s3-bucket $BUCKET_NAME --stack-name  $STACK_NAME --capabilities CAPABILITY_IAM
    API_ENDPOINT=$(aws cloudformation describe-stacks --stack-name $STACK_NAME --query 'Stacks[0].Outputs[0].OutputValue' --output text)
    mvn -pl bedrock-gateway-web -Durl=$API_ENDPOINT clean install
    docker run --name bedrock -p 8082:8082 --rm --network host nicolasduminil/bedrock-gateway-web:1.0-SNAPSHOT


这次事情变得有点复杂。脚本的第一行的Maven构建使用-pl开关来仅选择bedrock-gateway-api模块。这是因为在这种情况下,我们无法预先知道AWS RESY Gateway URL,而其他模块bedrock-gateway-web需要这个URL以便执行Microprofile JAX-RS客户端。

接下来,sed命令用于同样的目的,但为了在云中部署我们的堆栈,我们需要一个S3存储桶。由于S3存储桶名称必须在全球范围内是唯一的,我们需要随机生成它们并将它们存储在文本文件中,以便在之后找到它们,例如在销毁时。

现在,是时候部署我们的CloudFormation堆栈了。请注意我们如何使用--query--output选项来捕获关联的URL。此刻,我们需要构建bedrock-gateway-web模块,因为我们已经有了AWS REST Gateway URL,我们通过Maven的-D选项作为环境变量传递它。在这一点上,我们只需启动我们的Docker容器并开始测试。

测试应用程序

为了测试该应用程序,无论是在本地还是在云中,操作如下:

  1. 克隆存储库:
    $ git clone https://github.com/nicolasduminil/bedrock-gateway.git
  2. cd进入根目录:
    $ cd bedrock-gateway
  3. 运行启动脚本(run-local.shdeploy.sh)。执行可能需要一段时间,尤其是首次运行时。
  4. 打开你喜爱的浏览器,进入http://localhost:8082。你将看到以下屏幕:

amazon bedrock sandbox

使用菜单栏,选择Titan sandbox。将会呈现给你一个新的屏幕,如下所示。使用滑块,配置你希望的参数TemperatureTop PMax tokens。在标有Prompt的文本区域中输入你选择的FM的问题,它的响应将显示在最右侧的文本区域标为Response

simplex software

请尝试使用不同的参数组合来注意两个FM响应之间的区别。如果在云中进行测试,完成后不要忘记运行脚本cleanup.sh,以避免被计费。

玩得开心!

推荐阅读: 28.HashMap多线程导致死循环问题

本文链接: 亚马逊Bedrock:利用Quarkus和AWS的基础模型