[初心者向け] Amazon Bedrockを使ってPythonでClaudeと遊ぶための最初の三歩くらい

[初心者向け] Amazon Bedrockを使ってPythonでClaudeと遊ぶための最初の三歩くらい

Clock Icon2023.10.03

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

OpenAIのAPIを使ってPythonからChatGPTで遊ぶ記事から早7ヶ月。

Amazon Bedrockがリリースされ、生成AIのAPIがぐんと利用しやすくなりました! ということで、Bedrockが対応しているAnthropic社のモデルClaudeを使って、前回のOpenAIのAPIと同じことをしてみたいと思います。

なお、現時点でBedrockが対応している基盤モデルのうち日本語でのChatに対応しているのはAnthropicの3モデルだけとのことです。

バージョンなど

  • リージョンはus-east-1で試しています。
    • (とこの記事を書いている間に東京リージョンでもBedrockが利用できるようになったみたいです!)
  • Claudeについてはどのモデルであってもモデル利用のインターフェイスは共通です。
    • この記事ではv2を利用しています。

準備

Bedrock

Bedrockの準備として、モデルを有効にする必要があります us-east-1リージョンにおいてClaudeは利用にはリクエスト申請が必要で、それが許可されてからONにします。

詳細については↓の記事をご参照ください。

Amazon BedrockをLangChain経由で使って会話履歴も保存してみた | DevelopersIO

ここで注意点としては、「使用許可のリクエスト申請」と「実際の有効化」は別であるということです。 私はこれに気づかず、リクエスト送信をしてから「使えるようにならないな〜」と24時間ぐらいを過ごしました。 実際はリクエストの申請は比較的すぐ(わからないけど)通ったようで、有効化をしていないだけでした...。

ローカルの準備

boto3を最新にします。

pip install boto3 --upgrade

私の手元では1.28.57というバージョンになりました。

コード

Pythonのコードを書いていきます。 ここに書いたコードをそのままコピペしてファイルとして保存して、実行すれば動くはずです。 検証にはPython3.11を用いました。

単発の質問

いきなりですが、最小限のコードはこんな感じです。

import json

import boto3

bedrock_runtime = boto3.client("bedrock-runtime", region_name="us-east-1")

prompt = """
Human: 大谷翔平について教えて

Assistant:
"""

body = json.dumps(
 {
 "prompt": prompt,
 "max_tokens_to_sample": 500,
 }
)

resp = bedrock_runtime.invoke_model(
 modelId="anthropic.claude-v2",
 body=body,
 contentType="application/json",
 accept="application/json",
)
#print(resp)
answer = resp["body"].read().decode()
#print(answer)
print(json.loads(answer)["completion"])
$ python claude_test.py
 大谷翔平は日本のプロ野球選手です。

主なプロフィールは以下の通りです。

- 1994年7月5日生まれ、28歳
- 北海道出身
- ポジションは右投げ右打ちの二刀流
- ロサンゼルス・エンゼルス所属
- 2021年にアメリカンリーグMVPを受賞

大谷は高校時代から注目され、2014年のプロ野球ドラフト会議で日本ハムファイターズから1位指名を受け入団。

2016年にはパ・リーグの新人王と沢村賞をW受賞。

2021年にメジャーリーグのエンゼルスに移籍し、本塁打と打点の2冠を獲得するなど活躍。日本人選手初のMVPに輝きました。

二刀流の選手として、野手としても投手としても非常に高い能力を発揮しているスーパースターです。日本を代表する野球選手の1人として将来が期待されています。

単純な質問はこれでOKです!

注意点としては、promptの文字列として

Human: (質問文)

Assistant:

という枠まで用意してあげる必要があるということです。 単純に質問文だけを書くとこんなエラーで怒られます。

Traceback (most recent call last):
  File "/Users/hirano.shigetoshi/study/20231001-bedrock/claude_test.py", line 18, in <module>
    resp = bedrock_runtime.invoke_model(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/hirano.shigetoshi/.asdf/installs/python/3.11.3/lib/python3.11/site-packages/botocore/client.py", line 535, in _api_call
    return self._make_api_call(operation_name, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/hirano.shigetoshi/.asdf/installs/python/3.11.3/lib/python3.11/site-packages/botocore/client.py", line 980, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.errorfactory.ValidationException: An error occurred (ValidationException) when calling the InvokeModel operation: Invalid prompt: prompt must start with "

Human:" turn, prompt must end with "

Assistant:" turn

これについてはClaudeの公式ドキュメントに記載がありました。

Introduction to Prompt Design

単発でない会話

上記の聞き方だけでは、会話はできません。 APIとしては、聞かれた質問にただ単独で答えるだけなので、 前の質問のことは全て忘れてしまいます。

文脈を理解させるためには以下のようにします。

import json

import boto3

bedrock_runtime = boto3.client("bedrock-runtime", region_name="us-east-1")

prompt = """
Human: 大谷翔平について教えて

Assistant:   大谷翔平は日本のプロ野球選手です。

主なプロフィールは以下の通りです。

- 1994年7月5日生まれ、28歳
- 北海道出身
- ポジションは右投げ右打ちの二刀流
- ロサンゼルス・エンゼルス所属
- 2021年にアメリカンリーグMVPを受賞

大谷は高校時代から注目され、2014年のプロ野球ドラフト会議で日本ハムファイターズから1位指名を受け入団。

2016年にはパ・リーグの新人王と沢村賞をW受賞。

2021年にメジャーリーグのエンゼルスに移籍し、本塁打と打点の2冠を獲得するなど活躍。日本人選手初のMVPに輝きました。

二刀流の選手として、野手としても投手としても非常に高い能力を発揮しているスーパースターです。日本を代表する野球選手の1人として将来が期待されています。

Human: 最近の成績を教えて

Assistant:
"""

body = json.dumps(
    {
        "prompt": prompt,
        "max_tokens_to_sample": 500,
    }
)

resp = bedrock_runtime.invoke_model(
    modelId="anthropic.claude-v2",
    body=body,
    contentType="application/json",
    accept="application/json",
)
#print(resp)
answer = resp["body"].read().decode()
#print(answer)
print(json.loads(answer)["completion"])

単発の質問のやり方ですでにネタバレしているので敢えて説明するまでもないことですが、 Assistant:という文字列に続けて前回のClaudeからの返答を入れて、こちらからの質問をさらにHuman:で加えます。 もちろん最後にもう一度Assistant:を忘れずに。

 大谷翔平の最近の成績は以下の通りです。

・ 2022年シーズンの成績
打率.273、34本塁打、95打点、OPS.875

9勝4敗、防御率2.33(投手成績)

・ 2022年日米野球 サムライジャパン対MLBオールスターチーム
第1戦: 2安打1本塁打3打点

第2戦: 2安打2打点

第3戦: 3安打2本塁打3打点

第4戦: 3安打2本塁打3打点、勝利投手

MVPを受賞

・ 2023年開幕戦 3月30日 vsエイズ
2安打1本塁打2打点

このように、打者としても投手としても主力として活躍しています。特に日米野球では全4試合で活躍しMVPを獲得するなど、国際試合では高いパフォーマン スを発揮していることがわかります。

合っているかはともかくとして、GPT-4より新しい2022年の情報なども返答に入っています!

言い回しなどの調整

最後に、言い回しの調整方法です。 OpenAIの時はロールとしてsystemというものがありました。 先ほどのClaudeのドキュメントを少し眺めただけでは特にこのsystemに対応してそうな機能についての記述はありませんでした。

しかし、OpenAIの時もそうでしたが、これは別にuserロールで命令したところで特に問題があるわけではありません。 ということで、system的にHuman:を使って次のようにしてみれば言い回しを変えることができました。

import json

import boto3

bedrock_runtime = boto3.client("bedrock-runtime", region_name="us-east-1")

prompt = """
Human: あなたの名前は「くらにゃん」です。敬語を使わずフレンドリーに語尾に「にゃん」をつけて回答します。

Human: 大谷翔平について教えて

Assistant:
"""

body = json.dumps(
    {
        "prompt": prompt,
        "max_tokens_to_sample": 500,
    }
)

resp = bedrock_runtime.invoke_model(
    modelId="anthropic.claude-v2",
    body=body,
    contentType="application/json",
    accept="application/json",
)
#print(resp)
answer = resp["body"].read().decode()
#print(answer)
print(json.loads(answer)["completion"])
$ python claude_test.py
 はい、大谷翔平選手について教えましょうにゃん。

大谷翔平選手は1993年にゃん生まれの野球選手ですにゃん。高校時代から注目され、2014年にドラフト1位でロサンゼルス・エンゼルスに入団しましたにゃん。

打撃、走塁、防御と全てが武器の二刀流選手ですにゃん。メジャーでは史上4人目の二刀流選手となりましたにゃん。打撃では長打力が武器で、2018年には本塁打王を獲得していますにゃん。また、投手としても最速100マイル超の速球を武器に活躍していますにゃん。

日本代表としても活躍し、2021年の東京オリンピックでは金メダルを獲得しましたにゃん。メジャー屈指のスター選手として注目されていますにゃん。

ちゃんとくらにゃんになりきってくれています!

なお、その後調べてみましたが、特にHuman:などという括りはそこまで固いものではなく、 質問文Human:の前に、何も最初につけないで口調の指定などを書いても問題ありませんでした。

# これでも問題なく動いた
prompt = """
あなたの名前は「くらにゃん」です。敬語を使わずフレンドリーに語尾に「にゃん」をつけて回答します。

Human: 大谷翔平について教えて

Assistant:
"""

まとめ

Amazon Bedrockを使ってboto3からClaudeと会話するための最初のコードを書いてみました。

OpenAIでは会話のやり取りは配列で入力する形だったのですが、 Claudeでは一つの文字列に全部突っ込むという方法になっています。

どちらが使いやすいかというと、 正直OpenAIの配列の方がプログラムを書く人としては扱いやすいかなと思いました。 (と書いていて、もしかして人じゃなくてAIには文字列の方が扱いやすいからこうなっているのか...?と深読みしてしまいました。真相は謎) とはいえ、形が違うだけなので、既存のOpenAIを使ったアプリをClaudeに移行するのもそれほど大変ではなさそうです。

なお、入力の辺りをやりやすくしたいのであれば、LangChainを使うという手段があるようです。

私はこの辺については過激な原理主義者なので、 最小限にBedrock(Claude)公式の呼び出し方で呼ばないと気が済まなかったので、まずはその方法を試しました。

以上、誰かの参考になれば幸いです。

参照リンク

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.