今回作成する成果物
- AmazonBedrock (Claude 3 Sonnet)にLINEBOTから質問をできるようにする
参考サイト
構成図
前提
- AmazonBedrockでClaude 3 Sonnetが利用できるアカウントをすでに所有している
- AWSのリージョンは、バージニア北部(us-east-1)を利用する
- LINEアカウントを持っている状態
必要な工程
- LINEBOTの作成
- AWS側の準備(APIGateway、lambda作成)
- APIGatewayとLINEBOTの繋ぎこみ
- 動作確認
LINEBOTの作成
LINE Developerに接続し、LINEBOTを作成していきます。
右上の「Log in to Console」から進んでいきます。
ログイン後、ProvidersでCreateボタンを押します
必要事項を入力します
Company or owner's country or region: Japan
Channel name:LINEBOTの名前 (※7日間変更できません)
Channel description:チャンネルの説明
Category: 適切なもの
Subcategory: 適切なもの
Email address: 自分のメールアドレス
確認画面が出るので、OKで進める
登録が終わったら、
MessageAPIのタブの一番下にある、
Channel access token (long-lived)を発行し、メモしておく
Auto-reply messagesも有効となっているため、無効化する
LINEBOTを友達追加した際に、送信するメッセージや、受信したメッセージへ自動応答する設定
初期値だと、
「メッセージありがとうございます!申し訳ありませんが、このアカウントでは個別のお問い合わせを受け付けておりません。次の配信までお待ちください」
と応答してしまうため、OFFとする
lambdaの準備
ランタイム: Python 3.12
アーキテクチャ: arm64
IAMロールの権限: AmazonBedrockへの権限、CloudWatchLogsへの権限
import os
import json
from linebot import LineBotApi
from linebot.models import TextSendMessage
import boto3
import datetime
# 環境変数からLINE Botのチャネルアクセストークンを取得
LINE_CHANNEL_ACCESS_TOKEN = os.environ['LINE_CHANNEL_ACCESS_TOKEN']
# チャネルアクセストークンを使用して、LineBotApiのインスタンスを作成
LINE_BOT_API = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
# Amazon BedRock Claude 3 Sonnetクライアントを作成
bedrock_runtime = boto3.client(service_name='bedrock-runtime', region_name='us-east-1')
def lambda_handler(event, context):
try:
# LINEからメッセージを受信
if event['events'][0]['type'] == 'message':
# メッセージタイプがテキストの場合
if event['events'][0]['message']['type'] == 'text':
# リプライ用トークン
replyToken = event['events'][0]['replyToken']
# 受信メッセージ
messageText = event['events'][0]['message']['text']
model_id='anthropic.claude-3-sonnet-20240229-v1:0'
max_tokens=1000
body = json.dumps(
{
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": max_tokens,
"messages": [{"role": "user", "content": messageText}]
}
)
# Amazon BedRock Claude 3 Sonnetに質問を送信
response = bedrock_runtime.invoke_model(body=body, modelId=model_id)
response_body = response['body'].read().decode('utf-8')
# Amazon BedRockからの応答の中身のみを取り出す
response_text = json.loads(response_body)['content'][0]['text']
print("受信したメッセージ:", messageText)
print("Amazon BedRockからの応答:", response_text)
# メッセージを返信(Amazon BedRock Claude 3 Sonnetからの応答の中身を返す)
LINE_BOT_API.reply_message(replyToken, TextSendMessage(text=response_text))
# エラーが起きた場合
except Exception as e:
print(f"エラー: {e}")
return {'statusCode': 500, 'body': json.dumps(f'Exception occurred: {str(e)}')}
return {'statusCode': 200, 'body': json.dumps('Reply ended normally.')}
LINEBOTSDKのLayerも必要なので、
ローカル環境 または、Cloud9等で、layer用のZIPを作成する
pip install line-bot-sdk -t python
Layer設定が完了したら、lambdaの設定タブで以下を変更する
一般設定 タイムアウト:10分
環境変数 LINE_CHANNEL_ACCESS_TOKENにChannel access token(メモしたやつ)を入力
一旦、ここでlambdaの動作チェックを行います。
テストイベントに以下のjsonを入れ、実行します。
500エラーは発生しますが、ひとまずBedrockから回答が来れば、Lambdaの設定は問題ありません。
{
"events": [
{
"type": "message",
"message": {
"type": "text",
"text": "テストが見えていますか?"
},
"replyToken": "123456789",
"mode": "active"
}
]
}
APIGateway作成
APIGatewayを以下の要領で作成します。
プロトコル: REST
エンドポイント: Regional
メソッドの作成でPOSTを設定します。
その際、外部からたくさんのリクエストが来ると困るため、LINEからの通信のみ許可します。
HTTPリクエストヘッダーの設定で、x-line-signatureを追加し必須とします。
x-line-signatureが付与されていない通信が大量に来たとしても、APIGatewayで拒否できます。
初回デプロイなので、ステージがありません。
今回はprodとします。
※実際はなんでもOKです。のちほど出てくるWEBhookのURLになります。
ここまで来たら、AWS側の設定は完了です。
LINE developerに戻り、APIGatewayとLINEBOTの連携設定を行います。
LINEBOTとAPIGateway連携
Webhook settingsにメモしたAPIGatewayのURLを入力する。
入力後、Use webhookをONにする。
これで設定完了
あとは、QRコードを読み取って、Claudeとやり取りができるか確認します
動作確認
IaC
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
NameTag:
Type: String
Description: 'Common resource name'
Default: 'LineBOT'
LINEBOTChannelAccessToken:
Type: String
Description: 'ChannelAccessToken for LINEBOT'
NoEcho: true
Resources:
linebotFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub '${NameTag}-lambda'
Runtime: python3.12
Handler: index.lambda_handler
Role: !GetAtt LambdaExecutionRole.Arn
Code:
ZipFile: !Sub |
import os
import json
from linebot import LineBotApi
from linebot.models import TextSendMessage
import boto3
import datetime
# 環境変数からLINE Botのチャネルアクセストークンを取得
LINE_CHANNEL_ACCESS_TOKEN = os.environ['LINE_CHANNEL_ACCESS_TOKEN']
# チャネルアクセストークンを使用して、LineBotApiのインスタンスを作成
LINE_BOT_API = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
# Amazon BedRock Claude 3 Sonnetクライアントを作成
bedrock_runtime = boto3.client(service_name='bedrock-runtime', region_name='us-east-1')
def lambda_handler(event, context):
try:
# LINEからメッセージを受信
if event['events'][0]['type'] == 'message':
# メッセージタイプがテキストの場合
if event['events'][0]['message']['type'] == 'text':
# リプライ用トークン
replyToken = event['events'][0]['replyToken']
# 受信メッセージ
messageText = event['events'][0]['message']['text']
model_id='anthropic.claude-3-sonnet-20240229-v1:0'
max_tokens=1000
body = json.dumps(
{
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": max_tokens,
"messages": [{"role": "user", "content": messageText}]
}
)
# Amazon BedRock Claude 3 Sonnetに質問を送信
response = bedrock_runtime.invoke_model(body=body, modelId=model_id)
response_body = response['body'].read().decode('utf-8')
# Amazon BedRockからの応答の中身のみを取り出す
response_text = json.loads(response_body)['content'][0]['text']
print("受信したメッセージ:", messageText)
print("Amazon BedRockからの応答:", response_text)
# メッセージを返信(Amazon BedRock Claude 3 Sonnetからの応答の中身を返す)
LINE_BOT_API.reply_message(replyToken, TextSendMessage(text=response_text))
# エラーが起きた場合
except Exception as e:
print(f"エラー: {e}")
return {'statusCode': 500, 'body': json.dumps(f'Exception occurred: {str(e)}')}
return {'statusCode': 200, 'body': json.dumps('Reply ended normally.')}
MemorySize: 512
Timeout: 600
Architectures:
- arm64
Environment:
Variables:
LINE_CHANNEL_ACCESS_TOKEN: !Ref LINEBOTChannelAccessToken
Tags:
- Key: Name
Value: !Ref NameTag
LambdaPermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !GetAtt linebotFunction.Arn
Action: lambda:InvokeFunction
Principal: apigateway.amazonaws.com
SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGateway}/*/POST/
DependsOn:
- ApiGateway
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: AmazonBedrock
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action: bedrock:InvokeModel
Resource: !Sub 'arn:aws:bedrock:${AWS::Region}::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0'
Tags:
- Key: Name
Value: !Ref NameTag
ApiGateway:
Type: AWS::ApiGateway::RestApi
Properties:
Name: !Sub '${NameTag}-APIGateway'
EndpointConfiguration:
Types:
- REGIONAL
Tags:
- Key: Name
Value: !Ref NameTag
DependsOn:
- linebotFunction
ApiGatewayRootMethod:
Type: AWS::ApiGateway::Method
DependsOn:
- LambdaPermission
Properties:
RestApiId: !Ref ApiGateway
ResourceId: !GetAtt ApiGateway.RootResourceId
HttpMethod: POST
AuthorizationType: NONE
RequestParameters:
method.request.header.x-line-signature: true
MethodResponses:
- StatusCode: '200'
ResponseModels:
application/json: Empty
Integration:
Type: AWS
IntegrationHttpMethod: POST
Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${linebotFunction.Arn}/invocations'
PassthroughBehavior: WHEN_NO_MATCH
ContentHandling: CONVERT_TO_TEXT
TimeoutInMillis: 29000
CacheNamespace: !GetAtt ApiGateway.RootResourceId
IntegrationResponses:
- StatusCode: '200'
ApiGatewayDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn:
- ApiGatewayRootMethod
Properties:
RestApiId: !Ref ApiGateway
ApiGatewayStage:
Type: AWS::ApiGateway::Stage
DependsOn:
- ApiGatewayDeployment
Properties:
RestApiId: !Ref ApiGateway
DeploymentId: !Ref ApiGatewayDeployment
StageName: prod
Tags:
- Key: Name
Value: !Ref NameTag
なお、上記のymlに、 途中で作成した、LINEBOTSDKのlayer設定 が必要です。
パラメータ LINEBOTChannelAccessTokenには、LINEDeveloper内で取得した、
Channel access token (long-lived)の内容を入力してください。
最後に
LINEBOT×AWS×Claude 3 Sonnetで、LINEBOTを作ってみました。
LINE経由で、問い合わせできるのは、楽だなと思って作ってみましたが、誰かの役に立てばうれしいです。
なお、Amazon Bedrock (Claude 3 Sonnet Edition)だと、モデル提供ベンダーやAWSに問い合わせの履歴を見られることもないですが、
LINEは、トークのやり取りについて、情報収集を行っているため、機微な情報をやり取りする場合は、注意が必要かもしれません。
実際に、BOTを作るタイミングで、以下の同意画面が出ています
利用用途に応じて、適切にご利用ください!
ではまた!