とりあえずプログラムからAWS Bedrockに質問して回答もらうまで試してみたいって方へ　～AWS100本ノック～ 8/100

# はじめに

今年のAWSサミットでもAI系のセッションが非常に多かった印象がありますが、その中でもよく話題に上がるBedrockをとりあえず試してみたいって人に向けての記事になります。

※今回はBedrockの詳細なサービス説明や、生成AIの知識系は話しません(というか、私自身理解できていない)のでご了承ください:bow: 

# 今回出てくるもの

- AWS Bedrock：大手AI企業の高性能な基盤モデル(FM)を利用できるフルマネージドサービス
- Claude：Anthropic社が開発した生成AIモデル
- Laravel：PHPのFW

# やってみる

では、さっそくですが試してみます！

## Claudeを有効化

生成AIモデルは有効化しないと利用できないため、AWSコンソールから有効化していきます

左メニューの`ベースモデル`をクリックします
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/c8f6d930-4035-d315-5ed9-e10caff28acd.png)

ベースモデル一覧でClaudeを見ると、リクエストをする必要がある旨のメッセージが表示されるので、`モデルアクセス`をクリックします
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/59405ef1-20df-8754-874f-9f3ebcae1a64.png)

`モデルアクセスをリクエスト`をクリックします
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/d9ae8b16-83ad-3382-8f61-a7e43bd5d9d5.png)

Claudeにチェックを付けて、`Next`をクリックします
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/d3b52812-2a0a-d7d8-fa1f-2591aa8798e5.png)

リクエストに必要な情報を入力します。
会社名やウェブサイトのURL、利用用途などを入力して、`Next`をクリックします
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/60d1b376-265f-3047-4e91-d4cce75d74c7.png)

確認画面が出るので問題なければ、`Submit`をクリックするとリクエストが実行されます
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/7d0ae22f-4762-f105-4517-d23465b27239.png)

数分待つと、`アクセスが付与されました`と表示されるはずです。
これで、利用準備は完了です :smile: 
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/f34b0612-b0be-4d37-f4ff-b00a2c276235.png)

## ローカルからアクセスするためのIAMユーザを作成する

今回はローカル環境からアクセスするので、アクセスキーを発行して利用します

`ユーザの作成`をクリックします
![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/45a788ee-7441-e899-13c7-2eb8e43730fa.png)

任意の`ユーザ名`を入力し、`次へ`をクリックします
![15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/060d5a2b-03a0-546d-c5c6-a8c4ea68f5cc.png)

次に権限をアタッチするのですが、今回はインラインポリシーにするのでここでは何もせず、`次へ`をクリックします。
ユーザ作成時にインラインポリシー作れなくて不便... :cry: 
![16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/ac9729f5-f582-a1d2-bf91-476130f4a692.png)

確認画面が出るので、`ユーザの作成`をクリックすればIAMユーザの作成が完了です。
![17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/616d60c5-192a-8548-939c-c8e9951235ac.png)

次に、インラインポリシーを作成してBedrockへの権限を付与していきます。
`許可を追加`から`インラインポリシーを作成`をクリックします。
![18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/e77c295f-957a-1f31-f9a6-8eb0925ab5b3.png)

以下のjsonを記載します。
※claudeのver2.1モデルを実行する権限を付与しています
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "bedrock:InvokeModel",
            "Resource": "arn:aws:bedrock:ap-northeast-1::foundation-model/anthropic.claude-v2:1"
        }
    ]
}
```
![19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/cb7e1bbf-909b-bbc4-e137-abe733d3c6e0.png)

:::note
アクセスキーに関しては永続的な認証情報なので、特に権限の追加に注意が必要です。
特別な事情がない限り、AWSの`最小権限の原則`に則って必要な権限だけ付与しましょう！
:::

任意の`ポリシー名`を入力して、`ポリシーの作成`をクリックしてインラインポリシーの作成は完了です :smile: 
![20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/a5d0bb4c-69ea-5b00-ec71-fda161a5ff4c.png)

## アクセスキーを発行します

IAMユーザを作成したので、アクセスキーを発行します。
`アクセスキーを作成`をクリックします

![21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/eda8e022-65c4-4416-2e70-55ba783980f3.png)

ユースケースとして`ローカルコード`を選択して、`次へ`をクリックします

:::note warn
表示にもあるようにローカルからのアクセスには、Identity Centerによる認証が推奨されています。
Identity Centerによる認証をする場合は、[こちら](https://docs.aws.amazon.com/ja_jp/toolkit-for-visual-studio/latest/user-guide/sso-credentials.html)のやり方で出来るようです
:::

![22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/aa18135f-f6d8-9ac7-b493-ca1b963c4b1e.png)

`アクセスキーを作成`をクリックすると、アクセスキーが払い出されます
![23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/cd2c6793-2e79-09df-0bce-7087a660dcdc.png)

払い出されたアクセスキーをメモ or CSVファイルをダウンロードして、`完了`をクリックします。
![24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87924/5c19c773-b06e-439c-2e81-831764d7b94a.png)

:::note
この画面でしかシークレットアクセスキーを確認できないので、取得を忘れないようにしましょう
:::


## LaravelでBedrockにリクエストしてみる

さぁ、最後にローカルから実行してみましょう。
`aws/aws-sdk-php`をcomposer installした状態で以下のコードを実行します。
※Laravelの環境構築については割愛します

```php
use Aws\BedrockRuntime\BedrockRuntimeClient;

// NOTE:https://docs.aws.amazon.com/ja_jp/code-library/latest/ug/php_3_bedrock-runtime_code_examples.html
// NOTE:https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/model-parameters-anthropic-claude-text-completion.html
try {
    $bedrockRuntimeClient = new BedrockRuntimeClient([
        'version' => '2023-09-30',
        'region' => 'ap-northeast-1',
        'credentials' => [
            'key' => 'xxx', // 取得したアクセスキー
            'secret' => 'xxx', // 取得したシークレットアクセスキー
        ],
    ]);

    $input = 'AWS Bedrockさん こんにちは。お元気ですか？あなたはどんなサービスなのか詳しく教えてください。'; // ここを任意の内容にしてください
    $prompt = "\n\nHuman: {$input}\n\nAssistant:";
    $result = $bedrockRuntimeClient->invokeModel([
        'contentType' => 'application/json',
        'body' => json_encode([
            'prompt' => $prompt,
            'max_tokens_to_sample' => 1000,
            'stop_sequences' => ["\n\nHuman:"],
            //'temperature' => 0.1,
            //'top_p': float,
            //'top_k': float,
        ]),
        'modelId' => 'anthropic.claude-v2:1',
    ]);
    $response_body = json_decode($result['body']);
    $completion = $response_body->completion;

    return Response::json(['result' => $completion], 200);
} catch (Exception $e) {
    var_dump("Error: ({$e->getCode()}) - {$e->getMessage()}\n");;
}
```

すると、こんな感じで返ってきました。うまく行ったようです :smile: 
```
{
    "result": " はい、こんにちは。AWS Bedrockと申します。\n\n私はAmazon Web Servicesが提供するサービスの1つで、ベースとなるインフラストラクチャの管理と運用を支援するサービスです。\n\n具体的には以下のような機能を提供しています。\n\n- AWSアカウントの作成と管理\n- アイデンティティやアクセス管理の設定\n- セキュリティ対策の基盤構築\n- コスト管理と利用状況の分析\n- リソースのプロビジョニングと設定の自動化\n\nつまりAWSの基盤となる部分をしっかり整備することで、上位のアプリケーションやワークロードをスムーズに構築・運用できる環境を提供するサービスです。\n\n複雑なインフラの管理から開発者を解放し、アプリそのものの開発に注力できるよう支援します。規模の拡大に合わせてインフラも柔軟に拡張できるのが特徴です。\n\n以上、簡単ではありますがAWS Bedrockの説明でした。ご不明な点があれば遠慮なく質問してください。"
}
```

# おわりに
今回はBedrockを使ってLaravelからClaudeに対して質問を投げてみました。
LaravelからBedrockにリクエストしたい人たちに少しだけ役立てば幸いです:smile: