🗿

Bedrock Workshopをできるだけお金をかけずに試してみたい…

2023/10/29に公開

はじめに

BedRockがGAされて1カ月以上たちますが、そろそろ触っておきたいということで以下のワークショップを実践してみます。
ゆくゆくAlexaからBedrockを触りたいなーと思っているのでチャットボットセクションを試してみます。
https://catalog.us-east-1.prod.workshops.aws/workshops/a4bdb007-5600-4368-81c5-ff5b4154f518/en-US
どうせならClaudeを…とも思ったんですが、申請が億劫だったので今回はAI21Labを使ってみます。
(後述していますが、利用申請すごく簡単だったので結局Claudeも触ってます!)

ただし、個人の検証環境で試すためできるだけお金をかけないように実施していきます。

いざハンズオン開始

1. 環境設定

Prerequisites

初めに環境設定。Github上では以下の通り、SageMakerStudioやSageMakerNotebookの使用を推奨していますが、節約のためvscodeで実施していきます。

This workshop is presented as a series of Python notebooks, which you can run from the environment of your choice:
For a fully-managed environment with rich AI/ML features, we'd recommend using SageMaker Studio. To get started quickly, you can refer to the instructions for domain quick setup.
For a fully-managed but more basic experience, you could instead create a SageMaker Notebook Instance.
If you prefer to use your existing (local or other) notebook environment, make sure it has credentials for calling AWS.

ローカルPC上にboto3やawscli、botcoreを実行できる環境を構築します。
(クレデンシャルの設定等面倒な方はCloud9で始めてしまうのが手っ取り早いかもしれません。)

今回はvenvでPythonの仮想環境を構築し、その中に必要なライブラリをインストールします。

python -m venv bedrock
.\bedrock\Scripts\activate
pip install --no-build-isolation --force-reinstall "boto3>=1.28.57" "awscli>=1.29.57"   "botocore>=1.31.57"

続いてLangChainをインストール。

pip install --quiet langchain==0.0.304

Create the boto3 client

続いて実際にbedrockのAPIをたたくための、boto3クライアントを作成します。
boto3にはクレデンシャルを渡してあげることで、AWSのAPIをたたきにいってもらいます。
今回のWorkshopではutilsフォルダにある「bedrock.py」を利用するように書いてありました。
ここではプログラム側でAssumeRoleさせたいときにロール名やリージョン等を指定することができますが、今回はローカル環境の~.aws/credentialsに一時クレデンシャルを格納してboto3を利用します。
ここで利用する一時クレデンシャルはAssumeRoleで取得しています。RoleにはAdministratorAccessを割り当てています。

クレデンシャルも設定できたので、実際にboto3のクライアントを作成し、APIをたたいてみます。

00_Intro/bedrock_boto3_setup.ipynb
import json
import os
import sys

import boto3
import botocore

module_path = ".."
sys.path.append(os.path.abspath(module_path))
from utils import bedrock, print_ww


# ---- ⚠️ Un-comment and edit the below lines as needed for your AWS setup ⚠️ ----

# os.environ["AWS_DEFAULT_REGION"] = "<REGION_NAME>"  # E.g. "us-east-1"
# os.environ["AWS_PROFILE"] = "<YOUR_PROFILE>"
# os.environ["BEDROCK_ASSUME_ROLE"] = "<YOUR_ROLE_ARN>"  # E.g. "arn:aws:..."


boto3_bedrock = bedrock.get_bedrock_client(
    assumed_role=os.environ.get("BEDROCK_ASSUME_ROLE", None),
    region=os.environ.get("AWS_DEFAULT_REGION", None),
    runtime=False
)
Create new client
  Using region: None
boto3 Bedrock client successfully created!
bedrock(https://bedrock.us-east-1.amazonaws.com)

正常にクライアントを立ち上げることができました。

続いて利用可能なモデルの一覧を照会するAPIを叩きます。
事前に以下の記事を参照しながら、AI21とを有効化しておきました。
https://qiita.com/nidcode/items/2b607ac52bb5f34f0b01

00_Intro/bedrock_boto3_setup.ipynb
boto3_bedrock.list_foundation_models()

きちんとAPIをたたくことができました。
どんなモデルなのかや、モデルのArnなどのメタ的な情報が取れるようです。

出力結果
{'ResponseMetadata': {'RequestId': 'c3d2bff1-159f-402d-aadc-c48d4504c5d4',
  'HTTPStatusCode': 200,
  'HTTPHeaders': {'date': 'Sun, 29 Oct 2023 08:35:22 GMT',
   'content-type': 'application/json',
   'content-length': '6095',
   'connection': 'keep-alive',
   'x-amzn-requestid': 'c3d2bff1-159f-402d-aadc-c48d4504c5d4'},
  'RetryAttempts': 0},
 'modelSummaries': [{'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-tg1-large',
   'modelId': 'amazon.titan-tg1-large',
   'modelName': 'Titan Text Large',
   'providerName': 'Amazon',
   'inputModalities': ['TEXT'],
   'outputModalities': ['TEXT'],
   'responseStreamingSupported': True,
   'customizationsSupported': ['FINE_TUNING'],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-e1t-medium',
   'modelId': 'amazon.titan-e1t-medium',
   'modelName': 'Titan Text Embeddings',
   'providerName': 'Amazon',
   'inputModalities': ['TEXT'],
   'outputModalities': ['EMBEDDING'],
   'customizationsSupported': [],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-embed-g1-text-02',
   'modelId': 'amazon.titan-embed-g1-text-02',
   'modelName': 'Titan Text Embeddings v2',
   'providerName': 'Amazon',
   'inputModalities': ['TEXT'],
   'outputModalities': ['EMBEDDING'],
   'customizationsSupported': [],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-text-lite-v1',
   'modelId': 'amazon.titan-text-lite-v1',
   'modelName': 'Titan Text G1 - Lite',
   'providerName': 'Amazon',
   'inputModalities': ['TEXT'],
   'outputModalities': ['TEXT'],
   'responseStreamingSupported': True,
   'customizationsSupported': ['FINE_TUNING'],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-text-express-v1',
   'modelId': 'amazon.titan-text-express-v1',
   'modelName': 'Titan Text G1 - Express',
   'providerName': 'Amazon',
   'inputModalities': ['TEXT'],
   'outputModalities': ['TEXT'],
   'responseStreamingSupported': True,
   'customizationsSupported': ['FINE_TUNING'],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-embed-text-v1',
   'modelId': 'amazon.titan-embed-text-v1',
   'modelName': 'Titan Embeddings G1 - Text',
   'providerName': 'Amazon',
   'inputModalities': ['TEXT'],
   'outputModalities': ['EMBEDDING'],
   'responseStreamingSupported': True,
   'customizationsSupported': [],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/stability.stable-diffusion-xl',
   'modelId': 'stability.stable-diffusion-xl',
   'modelName': 'Stable Diffusion XL',
   'providerName': 'Stability AI',
   'inputModalities': ['TEXT', 'IMAGE'],
   'outputModalities': ['IMAGE'],
   'customizationsSupported': [],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/stability.stable-diffusion-xl-v0',
   'modelId': 'stability.stable-diffusion-xl-v0',
   'modelName': 'Stable Diffusion XL',
   'providerName': 'Stability AI',
   'inputModalities': ['TEXT', 'IMAGE'],
   'outputModalities': ['IMAGE'],
   'customizationsSupported': [],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/ai21.j2-grande-instruct',
   'modelId': 'ai21.j2-grande-instruct',
   'modelName': 'J2 Grande Instruct',
   'providerName': 'AI21 Labs',
   'inputModalities': ['TEXT'],
   'outputModalities': ['TEXT'],
   'responseStreamingSupported': False,
   'customizationsSupported': [],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/ai21.j2-jumbo-instruct',
   'modelId': 'ai21.j2-jumbo-instruct',
   'modelName': 'J2 Jumbo Instruct',
   'providerName': 'AI21 Labs',
   'inputModalities': ['TEXT'],
   'outputModalities': ['TEXT'],
   'responseStreamingSupported': False,
   'customizationsSupported': [],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/ai21.j2-mid',
   'modelId': 'ai21.j2-mid',
   'modelName': 'Jurassic-2 Mid',
   'providerName': 'AI21 Labs',
   'inputModalities': ['TEXT'],
   'outputModalities': ['TEXT'],
   'responseStreamingSupported': False,
   'customizationsSupported': [],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/ai21.j2-mid-v1',
   'modelId': 'ai21.j2-mid-v1',
   'modelName': 'Jurassic-2 Mid',
   'providerName': 'AI21 Labs',
   'inputModalities': ['TEXT'],
   'outputModalities': ['TEXT'],
   'responseStreamingSupported': False,
   'customizationsSupported': [],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/ai21.j2-ultra',
   'modelId': 'ai21.j2-ultra',
   'modelName': 'Jurassic-2 Ultra',
   'providerName': 'AI21 Labs',
   'inputModalities': ['TEXT'],
   'outputModalities': ['TEXT'],
   'responseStreamingSupported': False,
   'customizationsSupported': [],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/ai21.j2-ultra-v1',
   'modelId': 'ai21.j2-ultra-v1',
   'modelName': 'Jurassic-2 Ultra',
   'providerName': 'AI21 Labs',
   'inputModalities': ['TEXT'],
   'outputModalities': ['TEXT'],
   'responseStreamingSupported': False,
   'customizationsSupported': [],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-instant-v1',
   'modelId': 'anthropic.claude-instant-v1',
   'modelName': 'Claude Instant',
   'providerName': 'Anthropic',
   'inputModalities': ['TEXT'],
   'outputModalities': ['TEXT'],
   'responseStreamingSupported': True,
   'customizationsSupported': [],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-v1',
   'modelId': 'anthropic.claude-v1',
   'modelName': 'Claude',
   'providerName': 'Anthropic',
   'inputModalities': ['TEXT'],
   'outputModalities': ['TEXT'],
   'responseStreamingSupported': True,
   'customizationsSupported': [],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-v2',
   'modelId': 'anthropic.claude-v2',
   'modelName': 'Claude',
   'providerName': 'Anthropic',
   'inputModalities': ['TEXT'],
   'outputModalities': ['TEXT'],
   'responseStreamingSupported': True,
   'customizationsSupported': [],
   'inferenceTypesSupported': ['ON_DEMAND']},
  {'modelArn': 'arn:aws:bedrock:us-east-1::foundation-model/cohere.command-text-v14',
   'modelId': 'cohere.command-text-v14',
   'modelName': 'Command',
   'providerName': 'Cohere',
   'inputModalities': ['TEXT'],
   'outputModalities': ['TEXT'],
   'responseStreamingSupported': True,
   'customizationsSupported': [],
   'inferenceTypesSupported': ['ON_DEMAND']}]}

2. AI21Labを動かしてみる

1.でも利用してきた「00_Intro/bedrock_boto3_setup.ipynb」ですが、巻末に各基盤モデルのサンプルコードがあります。
チャットボット編に移る前に簡単に動作確認をしてみます。

# If you'd like to try your own prompt, edit this parameter!
prompt_data = """Command: AWSにおける大規模言語モデルについて、手を動かしつつ、できるだけ安価に勉強したいです。

Answer:
"""python:00_Intro/bedrock_boto3_setup.ipynb
body = json.dumps({"prompt": prompt_data, "maxTokens": 200})
modelId = "ai21.j2-mid-v1"  # change this to use a different version from the model provider
accept = "application/json"
contentType = "application/json"

try:

    response = bedrock_runtime.invoke_model(
        body=body, modelId=modelId, accept=accept, contentType=contentType
    )
    response_body = json.loads(response.get("body").read())

    print(response_body.get("completions")[0].get("data").get("text"))

except botocore.exceptions.ClientError as error:

    if error.response['Error']['Code'] == 'AccessDeniedException':
           print(f"\x1b[41m{error.response['Error']['Message']}\
                \nTo troubeshoot this issue please refer to the following resources.\
                 \nhttps://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_access-denied.html\
                 \nhttps://docs.aws.amazon.com/bedrock/latest/userguide/security-iam.html\x1b[0m\n")

    else:
        raise error
まずAWSの各大規模言語モデルにおけるインスタンスとプロビジョンを理解します。また、各言語モデルに沿ったモジュールやサービス関数を勉強してからなります。毎日または毎週練習を行うと、徐々に理解の強化を測ることができるようになります。われわれの経験から言えるように、当然言語モデルを全然終わらないですが、余すことはないですから充分利用して勉強してくださいね!
また、割愛や共有するようにしたいなら、AWSコンサルティングから分享する際に使用することが良くあります
Learning

正常にレスポンスを受け取れました!
ただし、日本語が弱いのか基盤モデルの問題なのか、はたまたこちらのプロンプトが悪いのかわかりませんが、ChatGPTと比べるとちょっと見劣るような結果になりました。
Claudeも使ってみたい…
急遽予定を変更してClaudeも利用できるようにしてみて試してみようと思います。

3. Claudeでも動かしてみた

まずは利用申請から。
以下の通り適当にリクエストを投げてみました。


1分も経たないうちに「Offers: New offer accepted」という件名のメールを受信し、マネコンからもClaude2が使えるようになっていることを確認できました。

さて早速実践!

00_Intro/bedrock_boto3_setup.ipynb
# If you'd like to try your own prompt, edit this parameter!
prompt_data = """Human: AWSにおける大規模言語モデルについて、手を動かしつつ、できるだけ安価に勉強したいです。

Assistant:
"""
body = json.dumps({"prompt": prompt_data, "max_tokens_to_sample": 500})
modelId = "anthropic.claude-instant-v1"  # change this to use a different version from the model provider
accept = "application/json"
contentType = "application/json"

try:

    response = bedrock_runtime.invoke_model(
        body=body, modelId=modelId, accept=accept, contentType=contentType
    )
    response_body = json.loads(response.get("body").read())

    print(response_body.get("completion"))

except botocore.exceptions.ClientError as error:

    if error.response['Error']['Code'] == 'AccessDeniedException':
           print(f"\x1b[41m{error.response['Error']['Message']}\
                \nTo troubeshoot this issue please refer to the following resources.\
                 \nhttps://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_access-denied.html\
                 \nhttps://docs.aws.amazon.com/bedrock/latest/userguide/security-iam.html\x1b[0m\n")

    else:
        raise error

少しプロンプトのフォーマットが違いますね。
勉強会で以下資料の発表を聞いていたので、噂のClaude村の一端に触れることができたと少し嬉しい気持ち。
https://www.docswell.com/s/s3kzk/58G697-20231027-bedrock-lt

AWSには大規模言語モデルを無料で使えるオプションがいくつかあります。
- Amazon Lex - 会話型AIサービスでChatbotなどを無料ティアで作成できます。
- Amazon Polly - テキストから音声合成を行うサービスで、月50分までは無料で利用可能です。
- Amazon Translate - 自然言語翻訳サービスで、月定額制のプランがあり初期1年間は無料です。 
- Amazon Comprehend - NLPサービスでテキストから構成要素の抽出や分類を行います。月1,000件までは無料です。
- Amazon Textract - 画像からテキスト認識を行うサービスで、月50ページまでは無料です。
これらのサービスを利用して、Chatbotの実装、テキストから音声合成、翻訳アプリの開発などを手軽に体験できるでしょう。
また、AWS Free Tierプログラムに登録することで、EC2インスタンスやS3などの基盤サービスも初期であるために一定量は無料で利用可能です。大規模言語モデルの学習自体は人件費が高価なため、上記ようなアプリ開発を中心に勉強する方法をおすすめします。

差は歴然と言ったところでしょうか…!
日本語も違和感ないですし、費用面についてもしっかり言及してくれています。

4. さいごに

本当であればchatbot編まで試してみたかったですが、思ったよりボリューミーになったのでここでいったん終了します。
あまり費用について言及できていないですが、ノートブックを実行する環境の性能はそこまで必要なさそうに感じたので、Sagemakerのインスタンスを建てなくても、ローカルPCのvscodeで十分だなと感じました。

Discussion