Amazon Bedrock はリアルなカードゲームでも強い味方だった ?! (ポーカー編)

2024-05-01
日常で楽しむクラウドテクノロジー

Author : 井上 昌幸

今年の正月に久しぶりに親戚とトランプや麻雀で遊んで楽しかったのですが、たまーにしかやらないので、やっぱりルールとか役とか得点計算方法とかを忘れていて、どうしてもグダグダになりがちでした・・・。

ということで、今回はリアル世界のカードゲームを Amazon Bedrock にきっちりとアシストしてもらおうというネタです。

このデモでは、日本でポピュラーな「ファイブカード・ドロー・ポーカー」を例に、ゲーム中にこっそり Amazon Bedrock に手札を見てもらって、次の一手のアドバイスをもらう、というのにチャレンジしています。出来上がりは以下のような Web アプリになります。

これはプレイ中の映像なのですが、Amazon Bedrock が Web カメラの映像を認識して、トランプの手札の絵を表示し、その手札に対するアドバイスをくれているのがわかりますよね。

この例では、最初にワンペアであることを認識して、次のドロー方法のアドバイスをくれています。その後、3 枚ドローすると (途中で一瞬フラッシュと間違えていますが) 最終的にはロイヤルフラッシュだと認識して、ポーカーで最強のハンドなので、このまま勝負でいいよと教えてくれていますね、すごいっす !

ご注意

本記事で紹介する AWS サービスを起動する際には、料金がかかります。builders.flash メールメンバー特典の、クラウドレシピ向けクレジットコードプレゼントの入手をお勧めします。

*ハンズオン記事およびソースコードにおける免責事項 »

このクラウドレシピ (ハンズオン記事) を無料でお試しいただけます »

毎月提供されるクラウドレシピのアップデート情報とともに、クレジットコードを受け取ることができます。 


1. アーキテクチャ

全体のアーキテクチャは以下の図のようになります。

  • Web カメラからのポーカーの映像を Amazon Kinesis Video Streams (KVS) の S3 Delivery 機能を使って定期的に画像として取得し、Amazon S3 に置きます。
  • これをトリガーに AWS Lambda が起動し、Amazon Bedrock で手札の推論が動きます。
  • 推論結果は AWS IoT Core を経由してリアルタイムにブラウザに MQTT over WebSocket で Publish されブラウザで確認できます。

では、作っていきましょう !


2. サンプルコード

はじめに、サンプルコードをダウンロード してください。poker-builders-flash-v1.0.0.zip を展開すると以下のディレクトリ構成になっています。

.
├── README.md
├── cdk
│   ├── README.md
│   ├── bin
│   │   └── cdk.ts
│   ├── cdk.json
│   ├── jest.config.js
│   ├── lambda
│   │   └── lambda_function.py
│   ├── lib
│   │   └── cdk-stack.ts
│   ├── package-lock.json
│   ├── package.json
│   ├── test
│   │   └── cdk.test.ts
│   └── tsconfig.json
└── frontend
    ├── index.html
    ├── main.js
    ├── package-lock.json
    ├── package.json
    └── style.css

3. クラウドリソースの作成

今回は Bedrock で使用するモデルの関係で全てのリソースを us-east-1 リージョンに作成します。

3-1. Amazon Bedrock の設定

Bedrock の初期設定として、ユーザーガイド に沿ってモデルアクセスの設定をしてください。今回使用するモデルは Anthropic の Claude 3 Sonnet です。モデルの用途を入力する部分は “bulders.flash poker demo” としてください。

3-2. AWS Cloud Deployment Kit (CDK) の実行

AWS Cloud Deployment Kit (CDK) を使うのが初めての場合は、AWS CDK 概要 (Basic #1)【AWS Black Belt】CDK の開発者ガイド などを参考に CDK をインストールしてください。すでに CDK がインスールされていれば、以下のコマンドでセットアップできます。

node のバージョンは v20.11.1 を使用しています。

cd poker-builders-flash-v1.0.0/cdk
npm ci

cdk bootstrap # us-east-1でcdkの使用が初めての場合

export AWS_REGION=us-east-1
cdk deploy

これにより S3・Lambda・IoT Core・AWS IAM の設定が完了します。 cdk deploy 実行時に作成された S3 bucket 名が表示されます (例 : CdkStack.BucketNameOutput = cdkstack-pokerbucket3445747a-te5phsjp0uz7) ので控えておいてください。S3 bucket 名は AWS CloudFormation コンソール のスタックの Outputs でも確認することもできます。

3-3. Amazon Kinesis Video Streams (KVS) リソースの作成

以下のコマンドを実行し、ストリームの作成と S3 Delivery の設定を行います。

aws kinesisvideo create-stream --stream-name poker-stream
aws kinesisvideo update-image-generation-configuration --stream-name poker-stream --cli-input-json '{
    "ImageGenerationConfiguration": {
        "Status": "ENABLED",
        "ImageSelectorType": "SERVER_TIMESTAMP",
        "DestinationConfig": {
            "Uri": "s3://cdkstack-pokerbucket3445747a-te5phsjp0uz7",
            "DestinationRegion": "us-east-1"
        },
        "SamplingInterval": 10000,
        "Format": "JPEG",
        "FormatConfig": {
            "JPEGQuality": "100"
        },
        "WidthPixels": 640,
        "HeightPixels": 480
    }
}'

ここで、DestinationConfig は CDK で作成した S3 bucket を指定します。また、WidthPixelsHeightPixels は「デバイス側の設定」で設定するカメラの設定値と合わせるのが望ましいです。

この設定により、Web カメラからの画像を KVS が 10 秒毎に切り出して、S3 bucket に置きます。


4. デバイス側の設定

トランプを読み取るためのハードウェアは Raspberry Pi に一般的な Web カメラを繋いだものです。

KVS に動画を送るために、以下の手順で Raspberry Pi に KVS の SDK とサンプルコード をインストールします。

これが終わったら、ビルドされたサンプルコードを使って、Web カメラの映像を KVS に取り込んでみましょう。

cd ~/amazon-kinesis-video-streams-producer-sdk-cpp/build
./kvs_gstreamer_sample poker-stream -w 640 -h 480 -f 30

コマンドの引数は、使っている Webカメラが対応している値を指定します。ここでは 640x480 の解像度でフレームレートは 30 fps です。Web カメラが対応する値がわからない場合は、 gst-device-monitor-1.0 コマンドで確認できます。

ここまでできたら、KVS コンソールで poker-stream を確認してみることで動画が再生されること、また S3 bucket にイメージが置かれていくのがわかると思います。


5. Web フロントエンドの設定

フロントエンドは Vite と AWS Amplify を使って作っていきます。IoT デバイスからのメッセージをブラウザがリアルタイムに受け取る方法は、AWS AppSync など含めいくつか方法がありますが、ここでは私が簡単なデモを作る際によく使う Amplify PubSub を使う方法を紹介します。

Amplify PubSubは、MQTT over WebSocket でメッセージを受け取る方法です。事前のスキーマ定義も必要なく、設定もシンプルで扱いやすいと思っています。例えば、以下のコードだけで IoT Core からリアルタイムなメッセージを受け取ることができます。

const pubsub = new PubSub({
  region: '<YOUR-IOT-REGION>',
  endpoint: 'wss://<CODE>.iot.<YOUR-IOT-REGION>.amazonaws.com/mqtt'
});

pubsub.subscribe({ topics: '<MQTT_TOPIC_NAME>' }).subscribe({
  next: (data) => console.log('Message received', data),
  error: (error) => console.error(error),
  complete: () => console.log('Done')
});

簡単ですね。

5-1. Vite と AWS Amplify のインストール

package-lock.json を使って Vite と Amplify のパッケージをインストールします。

cd poker-builders-flash-v1.0.0/frontend
npm ci

5-2. AWS Amplify の設定

プロジェクト名を webui として設定していきます。

amplify init

? Enter a name for the project webui
? Initialize the project with the above configuration? Yes
? Select the authentication method you want to use: AWS profile
? Please choose the profile you want to use default
✔ Help improve Amplify CLI by sharing non-sensitive project configurations on failures (y/N) · yes

Amplify Auth を設定します。

amplify add auth

Do you want to use the default authentication and security configuration? Manual configuration
Select the authentication/authorization services that you want to use: User Sign-Up, Sign-In, connected with AWS IAM controls (Enables per-user Storag
e features for images or other content, Analytics, and more)
Provide a friendly name for your resource that will be used to label this category in the project: webui6fe3f9ad6fe3f9ad
Enter a name for your identity pool. webui6fe3f9ad_identitypool_6fe3f9ad
Allow unauthenticated logins? (Provides scoped down permissions that you can control via AWS IAM) Yes
Do you want to enable 3rd party authentication providers in your identity pool? No
Provide a name for your user pool: webui6fe3f9ad_userpool_6fe3f9ad

Warning: you will not be able to edit these selections. 
How do you want users to be able to sign in? Username
Do you want to add User Pool Groups? No
Do you want to add an admin queries API? No
Multifactor authentication (MFA) user login options: OFF
Email based user registration/forgot password: Disabled (Uses SMS/TOTP as an alternative)
Please specify an SMS verification message: Your verification code is {####}
Do you want to override the default password policy for this User Pool? No

Warning: you will not be able to edit these selections. 
What attributes are required for signing up? Email
Specify the app's refresh token expiration period (in days): 30
Do you want to specify the user attributes this app can read and write? No
Do you want to enable any of the following capabilities? 
Do you want to use an OAuth flow? No
Do you want to configure Lambda Triggers for Cognito? No

ここでは未認証のアクセスを許可するために、最初の質問を Manual Configuration でスタートしています。ここを Default configuration にすると後半の質問をスキップできますが、その場合は、Amazon Cognito のコンソールの Identity Pool で Guest access を Activate してください。Allow unauthenticated logins?Yes を選択してください。

バックエンドをデプロイします。

amplify push

5-3. AWS IoT Core のポリシー付与

ブラウザから IoT Core にアクセスするためのポリシーを unauthRole に付与します。AWS IAM のコンソールで webui で検索して unauthRole (例えば amplify-webui-dev-205849-unauthRole) をみつけ、以下のポリシーを付与します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iot:Connect"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:<ACCOUNT_ID>:client/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "iot:Receive"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:<ACCOUNT_ID>:topic/poker-advice"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "iot:Subscribe"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:<ACCOUNT_ID>:topicfilter/poker-advice"
            ]
        }
    ]
}

これで、ブラウザは MQTT トピック poker-advice からのメッセージを受け取ることが許可されました。

5-4. サンプルコードのパラメータ更新

以下の二つのファイル内のパラメータを更新します。

index.html 内の <VIDEO_SOURCE_URL> は KVS が動的に生成するため、Web アプリを起動する前に生成して、設定します。この URL は以下のコマンドで取得できます。取得できない場合は、Web カメラからの映像がアップロードされている状態であることを確認して、再度実行してみてください。

STREAM=poker-stream

KVS_DATA_ENDPOINT=$(\
 aws kinesisvideo get-data-endpoint \
 --stream-name $STREAM \
 --api-name GET_HLS_STREAMING_SESSION_URL \
 --query 'DataEndpoint' --output text \
)

HLSStreamingSessionURL=$(\
aws kinesis-video-archived-media \
get-hls-streaming-session-url --endpoint-url $KVS_DATA_ENDPOINT \
--stream-name $STREAM \
--playback-mode LIVE \
--expires 43200 \
--query 'HLSStreamingSessionURL' --output text \
)

echo $HLSStreamingSessionURL

main.js<IOT_CORE_ENDPOINT> を変更します。エンドポイントは以下のコマンドで取得できます。

aws iot describe-endpoint --endpoint-type iot:Data-ATS --output text

5-5. Web アプリの実行

いよいよ、Web アプリを起動しましょう。

npm run dev

localhost にアクセスして、このような画面が出てきたら成功です。

おめでとうございます。あとは、ポーカーをプレイしながら、ちらちらと手札をカメラに見せて、相手にバレないように ? アドバイスをもらってください。


6. まとめ

今回は AWS の IoT と AI のマネージドサービスを活用して、リアル世界のポーカーとクラウド上の生成 AI をリアルタイムに繋いでみました。

便利に使おうとするとメガネにつけるくらいの小型カメラが必要かもしれませんが、手札の推論と次の一手のアドバイスについては、今回の単純な Prompt でも、Amazon Bedrock / Claude 3 がそこそこいい仕事をしてくれていると思います。

実は Amazon Bedrock を使う前に Amazon Rekognition でカスタムモデルの作成と推論をあれこれ試したのですが、それと比べてかなり短時間で高精度なものができました。またトランプ以外にも UNO や麻雀も試してみたところ、UNO のカードはそこそこ認識できる、麻雀牌はちょっと厳しいかな、という感じでした。RAG やファインチューニングなどを組み合わせれば、今回のアーキテクチャで他のゲームも楽しめるのではないかと思います。興味のある方はチャレンジしてみてください !


builders.flash メールメンバーへ登録することで
AWS のベストプラクティスを毎月無料でお試しいただけます

筆者紹介

井上 昌幸
アマゾン ウェブ サービス ジャパン合同会社
IoT Specialist Solutions Architect

Internet of Things と Robotics 界隈で面白い事を探しながら、今日もこつこつリアルな世界とクラウドを繋いでいます。あなたのとっておきのアイデアを AWS と一緒にカタチにしましょう。

AWS を無料でお試しいただけます

AWS 無料利用枠の詳細はこちら ≫
5 ステップでアカウント作成できます
無料サインアップ ≫
ご不明な点がおありですか?
日本担当チームへ相談する