祝GA🎉Amazon Bedrockの魅力を体感するためのサンプルChatbotアプリ

## はじめに
2023/9/28、ついに Amazon Bedrock が一般提供開始 (GA) されました🎉🎉🎉

https://aws.amazon.com/jp/blogs/aws/amazon-bedrock-is-now-generally-available-build-and-scale-generative-ai-applications-with-foundation-models/

Bedrock は Amazon や主要な AI スタートアップ企業が提供する基盤モデル (FM) を API を通じて利用できるようにするサービスです。2023/10/3 時点で以下のリージョンで利用できます。

* us-east-1
* us-east-2
* us-west-2
* ap-southeast-1
* ap-northeast-1  (2023/10/3)

Bedrock の魅力を体感するために Chanilit および LangChain を使用したサンプル Chatbot アプリケーションを作成しました。

https://github.com/Chainlit/chainlit

https://github.com/langchain-ai/langchain

画面イメージ:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/85773ba9-3aa5-7396-eadb-5c2f6cf2dddb.png)

特に Bedrock + Claude v2 組合せは日本の AWS ユーザーにとって強力な選択肢となるのではないでしょうか！複雑なことはできませんが、Playgrouds や CLI 以外からも触ってみたいみたいという方の参考になれば幸いです。


## ソースコード
以下の GitHub リポジトリで公開しています。

https://github.com/hayao-k/Bedrock-AIChatbot-Sample

## 動作環境
以下の環境で動作確認をしています。

* AWS リージョン: us-east-1
* AWS Copilot CLI: v1.30.1
* Python: v3.11.5
* boto3: v1.28.57
* LangChain: v0.0.309
* Chainlit: v0.7.1

:::note warn
GA Version の Bedrock API をサポートするため、LangChain および boto3 については必ず上記より新しいバージョンを使用してください。古いバージョンでは正常に動作しません。
:::

## Bedrock の利用開始
Amazon Bedrock の利用を開始するには事前に各基盤モデルへのアクセスリクエストを行う必要があります。モデルへのアクセスを追加するには Bedrock コンソールの Model access から Edit をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/248227f8-5663-830d-e984-47eb70850d8a.png)

利用したいモデルにチェックを入れて設定を保存します。

:::note info
Jurassic-2 や Claude などのサードパーティのモデルは　AWS Marketplace を通じてアクセスをリクエストします。つまりモデルの利用料金も Marketpalce の料金として発生することになります。
:::

:::note info
リージョンによって提供されるモデルに違いがあるようです。例えば東京リージョンでは 2023/10/3 時点では Titan Embeddings G1 - Text および Claude Instant のみが使用可能です。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/ba88f523-b777-4fd5-ad57-212050a3d785.png)

各モデルが利用できるようになるまでに少し時間がかかります。Access status が `Access granted` になったモデルは利用開始できます。Titan Text G1 - Express など GA 時点で Preview であり、すぐに利用開始できないモデルも含まれていますのでご注意ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/67895d7d-e858-b058-4e98-0ca55826a525.png)

AWS Marketplace から各モデルの Subscription についてメールが通知されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/b84d4441-6b27-9bd2-85d7-c96c7bbd238e.png)

Bedrock コンソールの Chat playgloud でモデルを選択し、文章を送信してみます。正常に応答があれば準備 OK です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/cbd9ca65-2b3f-d8c3-f754-52920afdce21.png)

参考: 請求明細のイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/b8346e7d-e0d8-7c23-02f8-bf432cff87ee.png)

## デプロイ
冒頭の GitHub リポジトリには AWS Copilot CLI でAWS App Runner にデプロイするためのマニフェストファイルが含まれています。以下の手順でデプロイできます。Copilot CLI を使用せずに Dockerfile で手動でイメージをビルドし、任意のインフラにデプロイすることも可能です。

必要に応じて AWS Copilot CLI をインストールします。

https://aws.github.io/copilot-cli/docs/getting-started/install/

```shell-session
sudo curl -Lo /usr/local/bin/copilot https://github.com/aws/copilot-cli/releases/latest/download/copilot-linux && sudo chmod +x /usr/local/bin/copilot
```


次の手順で App Runner にデプロイします。

```shell-session
export AWS_REGION=us-east-1
copilot app init bedrockchat-app
copilot deploy --name bedrockchat --env dev
```

デプロイが成功したらメッセージに出力された URL にアクセスします。以下のような画面が表示されたらデプロイ成功です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/7ff45b14-48e5-bb0e-600c-8aaa53229da2.png)


環境を削除する際は以下のコマンドを実行します。CloudWatch Logs group は残存してしまうので手動で削除してください。

```
copilot app delete
```

## 使い方
Settings panel から基盤モデル、Temperature、最大トークンサイズが変更できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/99dc2c95-4a6b-9d1e-daf9-71f9991620f7.png)

サンプルコードでは [ListFoundationModels API](https://docs.aws.amazon.com/bedrock/latest/userguide/api-methods-list.html) からモデル ID のリストを取得しています。Claude, Jurassic-2, Cohere Command, Amazon Titan Text といったモデルを切り替えながら性能を検証することができます。

:::note info
Amazon Titan Text G1 - Express (旧称: Amazon Titan Large) は 2023/9/29 時点では Preview ステータスです。アクセス許可は順次ロールアウトされるため、利用できないアカウントもあります。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/2a15b20b-6fad-ed1d-2ed0-83fae0bad40c.png)

あとは AI アシスタントと自由な会話をお楽しみください！セッション中の会話履歴を保持しているため、文脈を考慮して返答してくれます。

(Claude さんの超絶最高テンション笑ってしまう)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/57cdbaec-a70a-7bd5-5681-a25e4b8f3470.png)

## ソースコードの補足
### 基盤モデルの選択
前述のとおり、ListFoundationModels API からモデル ID の一覧を取得し、Chainlit の ChatSettings で選択可能にしています。

```app.py
@cl.on_chat_start
async def main():
    bedrock = boto3.client("bedrock", region_name=AWS_REGION)
    
    response = bedrock.list_foundation_models(
        byOutputModality="TEXT"
    )
    
    model_ids = []
    for item in response["modelSummaries"]:
        model_ids.append(item['modelId'])
    
    settings = await cl.ChatSettings(
        [
            Select(
                id="Model",
                label="Amazon Bedrock - Model",
                values=model_ids,
                initial_index=10,
            ),
以下省略   
```

モデル ID は Bedrock コンソール上の各モデル情報に記載されているサンプル API request から確認することもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/0b159d5d-0151-cabe-1754-59fe776943b6.png)

モデルの設定値を読み取り、LangChain で Bedrock の LLM をインスタンス化します。

```app.py
from langchain.llms.bedrock import Bedrock

@cl.on_settings_update
async def setup_agent(settings):
    global bedrock_model_id
    bedrock_model_id = settings["Model"]
    
    llm = Bedrock(
        region_name=aws_region,
        model_id=bedrock_model_id,
        model_kwargs={"temperature": settings["Temperature"]}
    )
```

:::note info
2023/9/29 時点で Bedrock の [Chat model](https://python.langchain.com/docs/integrations/chat/bedrock) は Anthropic のみをサポートしているため、意図的に LLM の方を使用しています。参考: [LLMs vs chat models](https://python.langchain.com/docs/modules/model_io/models/#llms-vs-chat-models)
:::

### AWS Copilot CLI
アプリケーションが使用する IAM ポリシーで Bedrock のモデル実行アクションおよびListFoundationModels アクションが許可されている必要があります

App Runner のインスタンスロールにポリシーを追加するため、Copilot の Addon 機能でテンプレートを追加しています。

```bedrock-access-policy.yaml
Parameters:
  App:
    Type: String
    Description: Your application's name.
  Env:
    Type: String
    Description: The environment name for the service.
  Name:
    Type: String
    Description: The name of the service.

Resources:
  BedrockAccessPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      PolicyDocument:
        Version: 2012-10-17
        Statement:
        - Sid: AllowInvokeModel
          Effect: Allow
          Action:
            - "bedrock:InvokeModel"
            - "bedrock:InvokeModelWithResponseStream"
            - "bedrock:ListFoundationModels"
          Resource: "*"

Outputs:
  ListBucketPolicyArn:
    Description: "The ARN of the ManagedPolicy to attatch to the instance role."
    Value: !Ref BedrockAccessPolicy
```

## ドキュメント
https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-service.html

https://python.langchain.com/docs/integrations/llms/bedrock

https://docs.chainlit.io/overview

以上です。
参考になれば幸いです。