【社内ハンズオン手順】Amazon Bedrock 生成AIアプリ開発入門を題材にしたハンズオン

[Amazon Bedrock 生成AIアプリ開発入門 [AWS深掘りガイド]](https://www.sbcr.jp/product/4815626440/)を使った社内ハンズオン手順です。

書籍の補助的な位置づけなので、書籍は買ってね！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/4ee7905a-0808-d36f-2098-8bedff4e5d16.png)

## 書籍との違い

書籍使用する開発環境が異なります。以下の手順に従って開発環境を構築してください。

## 開発環境の準備

[参考](https://qiita.com/moritalous/items/4ac5f68cc7ccabfe3788)

開発環境として、[Visual Studio Code Server](https://code.visualstudio.com/docs/remote/vscode-server)（VS Code Server）をインストールしたEC2を構築します。

:::note
Bedrockの使用リージョンの都合でバージニア北部とします。
:::

:::note warn
複数人でハンズオンを実施する場合、クオーター制限に気をつけてください。

引っかかりそうなクオーター

* **VPCs per Region** （VPCのクオーター。デフォルトが5）
* **EC2-VPC Elastic IPs** （EC2のクオーター。デフォルトが5）

:::


構築はAWS CloudFormationを使用します。

1. 以下のリンク先の、CloudFormationテンプレートをローカルにダウンロードします

    [CloudFormationテンプレート](https://workshop.bedrock.day/cfn/vscode-server.yaml)

    :::note
    AWS提供のテンプレートから以下の点を修正しています
    
    * WebSocket対応
    * 同一リージョンで複数環境を構築できるように調整
   :::
   

1. CloudFormationの管理画面を開きます
    リージョンが「バージニア北部」であることを確認してください
    「スタックの作成」メニューの「新しいリソースを使用（標準）」をクリックします

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/472f2393-6e78-1fd3-ac5e-20f83af3cb14.png)

1. 以下の手順を実施します

    * テンプレートの準備は「既存のテンプレートを選択」を選択します
    * テンプレートソースは「テンプレートファイルのアップロード」を選択します
    * 先ほどダウンロードしたファイルを選択します
    * 「次へ」をクリックします

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/87545f83-a3c9-a285-720a-db4a0754b224.png)

1. スタック名に「vscode-server-{ユーザー名}」を入力し、「次へ」をクリックします

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/c7ad7db0-b044-8fe8-5749-20f5eeed90df.png)

1. 画面最下部の「AWS CloudFormation によって IAM リソースが作成される場合があることを承認します。」にチェックを入れ、「次へ」をクリックします

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/701212aa-34f3-3193-acaf-1282b027cdd6.png)

1. 画面最下部の「送信」をクリックします

    ![us-east-1.console.aws.amazon.com_cloudformation_home_region=us-east-1 (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/55107b02-2720-e4d9-e291-dbca49c43baf.png)

1. リソースの作成が始まります

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/ec313bfa-c449-c739-37c5-e2dd1a499bb8.png)

    作成が完了すると、ステータスが「CREATE_COMPLETE」になると作成完了です。

1. 「出力」タブに切り替えます
    「PasswordURL」欄のリンクを新しいタブで開きます
    
    ![us-east-1.console.aws.amazon.com_cloudformation_home_region=us-east-1 (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/4772cdad-a3c1-d169-a93b-5dc1eb99d621.png)

1. AWS Secrets Managerの管理画面が開きます
    シークレットの値セクションにある「シークレットの値を取得する」をクリックします
    表示される値をメモします

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/65810a9a-a1e8-1bbe-ba75-7d69ad048a8e.png)

1. CloudFormationの画面に戻り、「URL」欄のリンクを新しいタブで開きます

    ![us-east-1.console.aws.amazon.com_cloudformation_home_region=us-east-1 (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/4772cdad-a3c1-d169-a93b-5dc1eb99d621.png)

1. VS Code Serverの画面が表示されます
    先程のパスワードを入力し、「SUBMIT」をクリックします

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/18df65b8-e0cc-12ac-b8d1-0f9b52464d7a.png)

    :::note warn
    CloudFormationスタックのステータスが「CREATE_COMPLETE」に変わったあと、非同期でEC2内の環境セットアップが行われます。502エラーが表示される場合はしばらく待って再度アクセスを試みてください
   :::

    ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/1467abeb-188c-6f51-066c-030de2b60207.png)


## ソースコードの取得

ハンズオンのソースコードはGitHubで公開しているので、取得します

```shell
git clone https://github.com/minorun365/bedrock-book.git
```

これで開発環境の準備は完了です。

## ハンズオン１：2.11 Bedrockを実際に試してみよう

P.80以降を実施します。

### 2.11.1 プレイグラウンドを利用してGUI上で生成する方法

書籍を参考にマネジメントコンソールで実施します

### 2.11.2 AWS SDKを用いて各モデルのAPIへリクエストを行う方法

書籍を参考にVS Code Serverで実施します

:::note
貼り付けは　`Ctrl` + `Shift` + `V`
:::

```shell
cd ~/environment/bedrock-book/chapter2/
```

* ライブラリーのインストール

    ```shell
    pip install boto3==1.34.87
    ```

* モデル一覧の出力

    ```shell
    python3 1_list-models.py
    ```

* モデル呼び出し

    ```shell
    python3 2_invoke-model.py
    ```

:::note
Converse API版
```shell
python3 2-1_invoke-converse.py
```
:::

* モデル呼び出し（ストリーミング）

    ```shell
    python3 3_streaming.py 
    ```

:::note
Converse API版
```shell
python3 3-1_streaming-converse.py
```
:::

* モデル呼び出し（マルチモーダル）

    ```shell
    python3 4_multimodal.py 
    ```

## ハンズオン２：3.5 LangChainとStreamlitを使った生成AIアプリ開発

P.143以降を実施します。

```shell
cd ~/environment/bedrock-book/chapter3/3_with_langchain_streamlit/
```

### 3.5.1 開発環境の準備

```shell
pip install -r requirements.txt 
```

<details><summary>書籍に記載の方法</summary>

```shell
pip install boto3==1.34.87 langchain==0.2.0 langchain-aws==0.1.4 langchain-community==0.2.0 streamlit==1.33.0 python-dateutil==2.8.2
```

</details>


### 3.5.2 【ステップ１】 LangChainの実装

```python
python3 1_langchain.py
```

### 3.5.3 【ステップ２】ストリーム出力

```python
python3 3_langchain-streaming.py
```

### 3.5.4 【ステップ３】Streamlitとの統合

```shell
streamlit hello --server.port 8081 --server.baseUrlPath app
```

:::note warn
Cloud9とVS Code Serverの違いがあるため、書籍とコマンドが異なります。

`--server.port 8080`の部分を`--server.port 8081 --server.baseUrlPath app`に変更してください。
:::

ブラウザで「`https://{VS Code Serverのドメイン}/app`」にアクセスします。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/46de0b6e-0899-4e70-0e40-2668d448bc70.png)

:::note
EC2の内部ではVS Code Serverの前段にNginxがリバースプロキシとして配置されています。
「/」へのリクエストがVS Code Serverへ転送され、「/app」へのリクエストが8081番ポートに転送されるように設定されています。
:::

Streamlitで構築したアプリを起動

```python
streamlit run 4_streamlit.py --server.port 8081 --server.baseUrlPath app
```

### 3.5.5 【ステップ４】チャット形式の継続したやり取り

```shell
streamlit run 5_streamlit-session.py --server.port 8081 --server.baseUrlPath app
```

### 3.5.6 【ステップ５】チャット履歴の永続化

DynamoDBのテーブル名は「BedrockChatSessionTable-{ユーザー名}」としてください。
そのうえで、Pythonのコードも以下のように修正してください。

```diff_python:6_streamlit-dynamodb.py（15行目～19行目）
# セッションに履歴を定義
  if "history" not in st.session_state:
      st.session_state.history = DynamoDBChatMessageHistory(
-         table_name="BedrockChatSessionTable", session_id=st.session_state.session_id
+         table_name="BedrockChatSessionTable-{ユーザー名}", session_id=st.session_state.session_id
      )
```

```shell
streamlit run 6_streamlit-dynamodb.py --server.port 8081 --server.baseUrlPath app
```

## ハンズオン１：4.2 Knowledge basesでRAGを実装してみよう

P.192以降を実施します。

### 4.2.1 Knowledge basesの仕組み　～　4.2.6 ナレッジベース単体での動作を確認する

書籍を参考にマネジメントコンソールで実施します

:::note warn
複数人で同時に実行する場合APIの同時実行制限に掛かる可能性があるので、少しずつ時間をずらして実行してください。

* ナレッジベース作成APIは2リクエスト/秒が上限
* 同期は同時に5リクエストが上限

など
:::


### 4.2.7 フロントエンドを実装する　～　4.2.8 RAGアプリケーションを実行する

書籍を参考にVS Code Serverで実施します

```shell
cd ~/environment/bedrock-book/chapter4/
```

knowledge_base_idを指定します

```diff_python:1_rag.py（9行目～13行目）
# 検索手段を指定
  retriever = AmazonKnowledgeBasesRetriever(
-     knowledge_base_id="XXXXXXXXXX",  # ここにナレッジベースIDを記載する
+     knowledge_base_id="{ナレッジベースID}",  # ここにナレッジベースIDを記載する
      retrieval_config={"vectorSearchConfiguration": {"numberOfResults": 10}},
  )
```

```python
streamlit run 1_rag.py --server.port 8081 --server.baseUrlPath app
```

:::note
コラムの内容

```diff_python:2_rag-boto3.py（16行目～26行目）
    # ナレッジベースを定義
    response = kb.retrieve_and_generate(
        input={"text": question},
        retrieveAndGenerateConfiguration={
            "type": "KNOWLEDGE_BASE",
            "knowledgeBaseConfiguration": {
-               "knowledgeBaseId": "XXXXXXXXXX",  # ナレッジベースID
+               "knowledgeBaseId": "{ナレッジベースID}",  # ナレッジベースID
                "modelArn": "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0",
            },
        },
    )
```

```python
streamlit run 2_rag-boto3.py --server.port 8081 --server.baseUrlPath app
```

:::


お疲れ様でした！

## まとめ

今回は短縮版としてお届けしました。書籍では他にも色々取り扱っていますのでぜひ実施してください。
今回のハンズオンをやりきっていれば他の部分も実施できると思います。

目次
1. 生成AIの基本と動向
1. Amazon Bedrock入門
1. 生成AIアプリの開発手法
1. 社内文書検索RAGアプリを作ってみよう
1. 便利な自律型AIエージェントを作ってみよう
1. Bedrockの機能を使いこなそう
1. さまざまなAWSサービスとBedrockを連携しよう
1. 生成AIアプリをローコードで開発しよう
1. Bedrock以外の生成AI関連サービスの紹介
1. Bedrockの活用事例
1. お勧めの最新情報のキャッチアップ方法

不明点があれば気軽に質問してください。