🐙
ローカルからbedrockのAPIでcohereやclaudeを使ってみる
ローカルからBedrockのAPIを叩きたい。
boto3でできるようなのでやってみる。
準備@コンソール
IAMユーザに権限付与
-
”BedrockUsers”と名付けたユーザグループに
AmazonBedrockFullAccess のポリシーをアタッチ
-
IAMユーザを”BedrockUsers”と名付けたユーザグループに追加する
-
IAMユーザのアクセスキーも事前に発行しておく。
- セキュリティ認証 > アクセスキー > アクセスキーの作成
モデルのアクセス付与
東京リージョンでbedrockを触りたいので、リージョンを東京に変更。
サイドバーから「モデルアクセス」を選択。
利用したいモデルのモデルアクセスをリクエストする。
今回は
- 接続チェックのためにチャット用でAnthropicのClaudeのモデルを扱いたいため、Anthropic (2) > Claudeを選択
- cohere の embeddingモデルで日本語を扱いたいため Cohere (2) > Embed Multilingualを選択
Cohere(コーヒア)とは、生成AI関連のスタートアップ企業であり、オラクル、エヌビディア(NVIDIA)、セールスフォース・ベンチャーズ(Salesforce Ventures)、センチネルワン(SentinelOne)などが支援しているみたいです。
今回はcohere の embeddingモデルで日本語を扱いたいため
Cohere (2) > Embed Multilingualを選択します。
リクエスト可能になると「アクセスが付与されました」と表示される。リクエストをした際は数分でアクセス付与された。
準備@ローカル
アクセスキー設定
プロファイル名は「besdrock_profile」とする
> aws configure --profile bedrock_profile
AWS Access Key ID [None]: (先ほど発行したアクセスキー)
AWS Secret Access Key [None]: (先ほど発行したシークレットアクセスキー)
Default region name [None]: ap-northeast-1 (← 東京リージョンに指定)
Default output format [None]: json
プロファイルが有効になったことを確認
> aws --profile bedrock_profile sts get-caller-identity
{
"UserId": "(アクセスキー)",
"Account": "(アカウントID)",
"Arn": "arn:aws:iam::(アカウントID):user/(作成したユーザ)"
}
modelの確認
公式サイトにも載ってはいるが、動かないものもあったりなかったりなので、コマンドラインで確認してみる。
% aws --profile bedrock_profile bedrock list-foundation-models
{
"modelSummaries": [
{
"modelArn": "arn:aws:bedrock:ap-northeast-1::foundation-model/amazon.titan-text-express-v1:0:8k",
"modelId": "amazon.titan-text-express-v1:0:8k",
"modelName": "Titan Text G1 - Express",
"providerName": "Amazon",
"inputModalities": [
"TEXT"
],
"outputModalities": [
"TEXT"
],
"responseStreamingSupported": true,
"customizationsSupported": [],
"inferenceTypesSupported": [],
"modelLifecycle": {
"status": "ACTIVE"
}
},
{
"modelArn": "arn:aws:bedrock:ap-northeast-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": [],
"inferenceTypesSupported": [
"ON_DEMAND"
],
"modelLifecycle": {
"status": "ACTIVE"
}
},
{
"modelArn": "arn:aws:bedrock:ap-northeast-1::foundation-model/amazon.titan-embed-text-v1:2:8k",
"modelId": "amazon.titan-embed-text-v1:2:8k",
"modelName": "Titan Embeddings G1 - Text",
"providerName": "Amazon",
"inputModalities": [
"TEXT"
],
"outputModalities": [
"EMBEDDING"
],
"responseStreamingSupported": false,
"customizationsSupported": [],
"inferenceTypesSupported": [],
"modelLifecycle": {
"status": "ACTIVE"
}
},
{
"modelArn": "arn:aws:bedrock:ap-northeast-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": false,
"customizationsSupported": [],
"inferenceTypesSupported": [
"ON_DEMAND"
],
"modelLifecycle": {
"status": "ACTIVE"
}
},
{
"modelArn": "arn:aws:bedrock:ap-northeast-1::foundation-model/anthropic.claude-instant-v1:2:18k",
"modelId": "anthropic.claude-instant-v1:2:18k",
"modelName": "Claude Instant",
"providerName": "Anthropic",
"inputModalities": [
"TEXT"
],
"outputModalities": [
"TEXT"
],
"responseStreamingSupported": true,
"customizationsSupported": [],
"inferenceTypesSupported": [],
"modelLifecycle": {
"status": "ACTIVE"
}
},
{
"modelArn": "arn:aws:bedrock:ap-northeast-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"
],
"modelLifecycle": {
"status": "ACTIVE"
}
},
{
"modelArn": "arn:aws:bedrock:ap-northeast-1::foundation-model/anthropic.claude-v2:1:18k",
"modelId": "anthropic.claude-v2:1:18k",
"modelName": "Claude",
"providerName": "Anthropic",
"inputModalities": [
"TEXT"
],
"outputModalities": [
"TEXT"
],
"responseStreamingSupported": true,
"customizationsSupported": [],
"inferenceTypesSupported": [
"PROVISIONED"
],
"modelLifecycle": {
"status": "ACTIVE"
}
},
{
"modelArn": "arn:aws:bedrock:ap-northeast-1::foundation-model/anthropic.claude-v2:1:200k",
"modelId": "anthropic.claude-v2:1:200k",
"modelName": "Claude",
"providerName": "Anthropic",
"inputModalities": [
"TEXT"
],
"outputModalities": [
"TEXT"
],
"responseStreamingSupported": true,
"customizationsSupported": [],
"inferenceTypesSupported": [
"PROVISIONED"
],
"modelLifecycle": {
"status": "ACTIVE"
}
},
{
"modelArn": "arn:aws:bedrock:ap-northeast-1::foundation-model/anthropic.claude-v2:1",
"modelId": "anthropic.claude-v2:1",
"modelName": "Claude",
"providerName": "Anthropic",
"inputModalities": [
"TEXT"
],
"outputModalities": [
"TEXT"
],
"responseStreamingSupported": true,
"customizationsSupported": [],
"inferenceTypesSupported": [
"ON_DEMAND"
],
"modelLifecycle": {
"status": "ACTIVE"
}
},
{
"modelArn": "arn:aws:bedrock:ap-northeast-1::foundation-model/cohere.embed-english-v3",
"modelId": "cohere.embed-english-v3",
"modelName": "Embed English",
"providerName": "Cohere",
"inputModalities": [
"TEXT"
],
"outputModalities": [
"EMBEDDING"
],
"responseStreamingSupported": false,
"customizationsSupported": [],
"inferenceTypesSupported": [
"ON_DEMAND"
],
"modelLifecycle": {
"status": "ACTIVE"
}
},
{
"modelArn": "arn:aws:bedrock:ap-northeast-1::foundation-model/cohere.embed-multilingual-v3",
"modelId": "cohere.embed-multilingual-v3",
"modelName": "Embed Multilingual",
"providerName": "Cohere",
"inputModalities": [
"TEXT"
],
"outputModalities": [
"EMBEDDING"
],
"responseStreamingSupported": false,
"customizationsSupported": [],
"inferenceTypesSupported": [
"ON_DEMAND"
],
"modelLifecycle": {
"status": "ACTIVE"
}
}
]
}
anthropic.claude-v2:1 があるかを確認してみる
% aws --profile bedrock_profile bedrock get-foundation-model --model-identifier anthropic.claude-v2:1
{
"modelDetails": {
"modelArn": "arn:aws:bedrock:ap-northeast-1::foundation-model/anthropic.claude-v2:1",
"modelId": "anthropic.claude-v2:1",
"modelName": "Claude",
"providerName": "Anthropic",
"inputModalities": [
"TEXT"
],
"outputModalities": [
"TEXT"
],
"responseStreamingSupported": true,
"customizationsSupported": [],
"inferenceTypesSupported": [
"ON_DEMAND"
],
"modelLifecycle": {
"status": "ACTIVE"
}
}
}
できそうなので
pythonからのAPIアクセス
チャットでお試し
- 省略するがpoetryなどでboto3をインストールする
- コードを作成
% vi runtime-chat-test.py
import boto3
import json
boto3_session = boto3.Session(profile_name="bedrock_profile", region_name="ap-northeast-1")
bedrock = boto3_session.client(service_name='bedrock-runtime')
body = json.dumps({
"prompt": "\n\nHuman:ジュビロ磐田について小学生でもわかるように説明してくださ:い。\n\nAssistant:",
"max_tokens_to_sample": 1024,
"temperature": 0.1,
"top_p": 0.9,
})
modelId = 'anthropic.claude-v2:1'
accept = 'application/json'
contentType = 'application/json'
response = bedrock.invoke_model(body=body, modelId=modelId, accept=accept, contentType=contentType)
response_body = json.loads(response.get('body').read())
print(response_body.get('completion'))
実行
% poetry run python runtime-chat-test.py
ジュビロ磐田は日本のプロサッカーチームです。
- 1917年に創設され、100年以上の歴史があります。
- 本拠地は静岡県磐田市のヤマハスタジアムです。
- チームカラーはオレンジと黒です。
- 過去にJリーグで2回優勝した強豪チームです。
- 主力選手にFW山口蛍、MF長友佑都、GK西川周作などがいます。
ジュビロとはポルトガル語で「喜び」という意味です。つまり、ジュビロ磐田は「磐田の喜び」といったチーム名です。
サポーターの人たちは熱心で、ホームスタジアムはいつも大勢の声援で盛り上がっています。
小学生にもわかりやすい説明になっているでしょうか。ご不明な点があれば遠慮なく質問してください。
ちょっと山口蛍とかいないのでハルシネーションですが、まあいいでしょう。
embeddingお試し
import boto3
import json
import numpy as np
boto3_session = boto3.Session(profile_name="bedrock_profile", region_name="ap-northeast-1")
bedrock_client = boto3_session.client(service_name='bedrock-runtime')
def bedrock_embedding(input_str: str):
# print(input_str)
bedrock_body = {
"texts": [input_str], # listで与える。
"input_type": "search_document",
"truncate": "NONE",
"embedding_types": ["float"]
}
body_bytes = json.dumps(bedrock_body)
# print(body_bytes)
response = bedrock_client.invoke_model(
body=body_bytes,
contentType="application/json",
accept="*/*",
modelId="cohere.embed-multilingual-v3",
)
response_body = json.loads(response.get("body").read())
# print(response_body)
# print(response_body.get("inputTextTokenCount"))
embedding = response_body.get("embeddings")
return embedding
def cosine_similarity(v1, v2):
v1 = np.array(v1)
v2 = np.array(v2)
return np.dot(v1, v2.T) / (np.linalg.norm(v1) * np.linalg.norm(v2))
a = bedrock_embedding("埋め込みの実験のためのサンプルテキストです").get('float')
b = bedrock_embedding("私はジュビロ磐田サポーター").get('float')
c = bedrock_embedding("This is Sample Text. for Experimental of embeddings.").get('float')
print(cosine_similarity(a, b))
print(cosine_similarity(b, c))
print(cosine_similarity(a, c))
参考
Discussion