Spring AIを利用してECS環境からBedrockに接続する

こんにちは、エキサイト株式会社の平石です。

エキサイトホールディングス Advent Calendar 2024のシリーズ2, 16日目を担当いたします。

今回は、Spring AIを利用してECS環境からAmazon Bedrockに接続する方法をご紹介します。

はじめに

Spring AIとは

Spring AIはSpringからAIモデルを利用するためのフレームワークです。
SpringがAIモデルを提供しているわけではなく、SpringアプリケーションからAIプロバイダーにリクエストを送り、レスポンスを受け取る部分をAPIとして提供してくれます。

今回紹介するAmazon Bedrock以外にも、OpenAIやStabilityAIなど多くのプロバイダーに対応しています。

spring.io

Amazon Bedrockとは

Amazon Bedrockは、AWS上で生成AIを利用できるようにするフルマネージドサービスです。
既存のモデルを容易に利用することもできますし、用途やデータに合わせてカスタマイズすることも可能です。

aws.amazon.com

環境

この記事のソースコードは以下の環境で動作確認をしています。

  • Java 21
  • SpringBoot 3.2.1
  • Gradle 8.5

依存関係

Spring AIを利用するためのGradleの依存関係は以下のとおりです。

allprojects {
    repositories {
        mavenCentral()
        maven { url 'https://repo.spring.io/milestone' }
        maven { url 'https://repo.spring.io/snapshot' }
    }
}

〜〜 略 〜〜

project(':project1:controller') {
    dependencies {
        〜〜 略 〜〜

        implementation platform("org.springframework.ai:spring-ai-bom:1.0.0-SNAPSHOT")
        implementation 'org.springframework.ai:spring-ai-bedrock-ai-spring-boot-starter'
    }
}

Spring AIのライブラリは2024年9月30日時点でMaven Centralにはないため、個別にrepositoryを指定する必要があります。

AWS認証情報の設定

まずは、Bedrockに接続するためのAWS認証情報の設定を行います。

@Configuration
public class BedrockApiConfig {
    @Bean
    @Profile("local")
    public AwsCredentialsProvider awsDefaultCredentialsProvider() {
        return DefaultCredentialsProvider.builder()
                .profileName("sample-profile-name")
                .build();
    }

    @Bean
    @Profile("!local")
    public AwsCredentialsProvider awsContainerCredentialsProvider() {
        return ContainerCredentialsProvider.builder().build();
    }
}

Spring AIに対してAWSの認証情報を渡すためにはAwsCredentialsProviderを実装したクラスのインスタンスを用意する必要があります。

ローカル環境で実行するときには、DefaultCredentialsProviderを用いてprofileNameで指定したプロファイル名で設定したアクセスキーやAWS SSOを用いてBedrockにアクセスできます。

当然、ECS環境内でもローカル環境と同じようにアクセスキーを発行してアクセスすることも可能ですが、より簡単な方法があります。

それは、AWS_CONTAINER_CREDENTIALS_RELATIVE_URIまたはAWS_CONTAINER_CREDENTIALS_FULL_URIという環境変数を用いる方法です。(基本的にはAWS_CONTAINER_CREDENTIALS_RELATIVE_URIがセットされているはず)

コンテナが起動するとAWS_CONTAINER_CREDENTIALS_RELATIVE_URIという環境変数に自動的に値がセットされます。この環境変数にセットされたURIにアクセスするとAWSの各サービスにアクセスするための認証情報を取得できます。

ContainerCredentialsProviderを使うと環境変数を参照し、認証情報を取得する一連の処理を自動でやってくれます。*1

今回は、ECS環境からBedrockにアクセスすることが目的ですが、ローカル環境での動作確認も開発上必要になることも考えられます。
そのため、@Profileを用いてローカル環境かどうかで使うAwsCredentialsProviderを切り替えています。*2

Bedrockに接続するための設定

実際にBedrockに接続するためには、利用するモデルに対応するクラスを利用します。

以下から、ご自身が利用したいモデルに対応するクラスをご確認ください。

Chat Model API :: Spring AI Reference

今回はAnthropic3のClaude 3.5というモデルを利用します。 Claude 3.5に対応するクラスはAnthropic3ChatBedrockApiBedrockAnthropic3ChatModelです。

@Configuration
public class BedrockApiConfig {
    // 略

    @Bean
    public Anthropic3ChatBedrockApi anthropic3ChatBedrockApi(final AwsCredentialsProvider awsCredentialsProvider) {
        return new Anthropic3ChatBedrockApi(
                Anthropic3ChatBedrockApi.AnthropicChatModel.CLAUDE_V3_5_SONNET.id(),
                awsCredentialsProvider,
                Region.AP_NORTHEAST_1.id(),
                new ObjectMapper()
        );
    }

    @Bean
    public BedrockAnthropic3ChatModel bedrockAnthropic3ChatModel(final Anthropic3ChatBedrockApi anthropic3ChatBedrockApi) {
        return new BedrockAnthropic3ChatModel(
                anthropic3ChatBedrockApi,
                Anthropic3ChatOptions.builder()
                        .withMaxTokens(4000)
                        .withAnthropicVersion(Anthropic3ChatBedrockApi.DEFAULT_ANTHROPIC_VERSION)
                        .build());
    }
}

Anthropic3ChatBedrockApiで東京リージョン(Region.AP_NORTHEAST_1.id())でClaude 3.5(Anthropic3ChatBedrockApi.AnthropicChatModel.CLAUDE_V3_5_SONNET.id())を指定した認証情報で利用するように設定しています。

また、BedrockAnthropic3ChatModelではAnthropic3ChatOptionsを用いて、Claudeモデルに関する設定を行っています。

上のソースコードで設定した以外にも設定項目はありますので、詳細は以下をご確認ください。

spring-ai/models/spring-ai-bedrock/src/main/java/org/springframework/ai/bedrock/anthropic3/Anthropic3ChatOptions.java at main · spring-projects/spring-ai · GitHub

実際に、Bedrockにリクエストを送信するには以下のように記述します。

@RestController
@RequiredArgsConstructor
@RequestMapping("bedrock/sample")
public class BedrockTestController {
    private final BedrockAnthropic3ChatModel bedrockAnthropic3ChatModel;

    @GetMapping
    public String callBedrockApi() {
        final String prompt = "Hello!"

        return bedrockAnthropic3ChatModel.call(prompt);
    }
}

SpringBoot アプリケーションを起動しhttp://localhost:{ポート番号}/bedrock/sampleにアクセスすると、以下のようなレスポンスが得られます。

Hello! How can I assist you today? Feel free to ask me any questions or let me know if you need help with anything.

おわりに

今回は、Spring AIを利用してECS環境からAmazon Bedrockに接続する方法をご紹介しました。

次回は、ECSコンテナとAmazon Bedrockの間でのPrivateLinkを確立する方法をご紹介します。

では、また次回。

参考文献

*1:公式ドキュメントにはDefaultCredentialsProviderでもAWS_CONTAINER_CREDENTIALS_RELATIVE_URIを参照すると書かれていますが、私が実行した限りではうまくいきませんでした

*2:環境変数SPRING_PROFILE_ACTIVEに環境名をセットする必要があります