こんにちは!最近人間ドックの結果を受けて禁ラーメン生活しましたが2週間で限界がきてる志水です。人類はラーメンから逃げることなんて出来ないんだなと痛感しております。つけ麺ならいいよね?
はじめに
さて、ついにAmazon BedrockがGAされましたね!
aws.amazon.com
re:Inventでくるのかなー?来年くるのかなー?ともうちょっと先のGAを思ってたので予想外でした。
じゃあBedrockで何か作らねば!と思ったので、以前作ったOtterで書き起こされた文章をChatGPTで要約するスクリプトをBedrockで作り直してみました。
ツールの背景
AWSの大きなイベントであるre:Inventは多くの情報が英語で提供されるため、英語が苦手な方にとってはハードルが高いものとなっています。
私自身も英語が得意ではないため、リアルタイムに英語の会話を文字起こししてくれるOtterを利用し、耳で聞くのではなく目で読むことで理解を深めていました。
ただ、読むだけでもなかなか大変で、難しい単語やフレーズに出くわすと理解が難しくなってしまいました。
そのような時に文字の要約や翻訳が得意なChatGPTやBedrockを利用すればまとめる部分も担ってくれるので理解促進されるのではないかなと思いました。
もともとは日本語が使えそうなClaude2モデルを使いたかったのですが、プレビューはまだ通らず、代わりにJurassic-2のモデルを利用し、翻訳ではなく要約のみを行うことにしました。
構成
今回実装したシステムの構成は以下になります。
この構成は非常にシンプルで、主な流れは以下のようになります:
- ユーザーが英語の音声をOtterによりテキスト化します。
- テキスト化された内容をダウンロードし、インプット用のS3バケットにアップロードします。
- このアップロードアクションにより、Lambda関数が自動的にトリガーされます。
- Lambda関数はBedrockのモデルに要約のプロンプトを送信し、要約結果を受け取ります。
- 受け取った要約結果を出力用のS3バケットにアップロードします。
この流れにより、ユーザーは英語の音声データを簡単に要約し、それを後で参照できるように保存できます。
作ってみた
CDK
最初に、AWSのリソースをCDK (Cloud Development Kit) で作成します。今回はプログラム言語としてPythonを選択しました。
input_bucket = s3.Bucket(self, "BedrockInput", versioned=True, removal_policy=RemovalPolicy.DESTROY, ) output_bucket = s3.Bucket(self, "BedrockOutput", versioned=True, removal_policy=RemovalPolicy.DESTROY, ) # Create a Lambda Layer for boto3 boto3_layer = _lambda.LayerVersion(self, "Boto3Layer", code=_lambda.Code.from_asset("lambda/layer/boto3_layer.zip"), # Assume the layer zip is in the "lambda-layer" directory compatible_runtimes=[_lambda.Runtime.PYTHON_3_11], license="Apache-2.0", description="A layer to include the latest version of boto3", ) # Create a Lambda function function = _lambda.Function(self, "MyFunction", runtime=_lambda.Runtime.PYTHON_3_11, handler="app.handler", code=_lambda.Code.from_asset("lambda/function"), layers=[boto3_layer], timeout=Duration.seconds(60 * 15), environment={ 'OUTPUT_BUCKET': output_bucket.bucket_name, # Set the output bucket name as an environment variable } )
この実装では、入力と出力用のS3バケットおよびLambda関数を作成しています。また、Lambda Layerも利用しています。Lambda Layerの利用理由は、2023年10月3日現在、Lambdaにデフォルトで含まれているboto3のバージョンではBedrockを操作することができないためです。そのため、最新版のboto3を含むLambda Layerを作成して利用しています。
あとはLambdaのイベントソースと権限の追加を行い、CDKは完了です。
# Add S3 event trigger function.add_event_source(S3EventSource(input_bucket, events=[s3.EventType.OBJECT_CREATED])) # Add the necessary policy to the Lambda function's execution role function.role.add_to_policy(iam.PolicyStatement( actions=["bedrock:InvokeModel"], resources=["*"] # Replace with the ARN of the specific resource if known )) # Grant the Lambda function permissions to read objects from the input bucket input_bucket.grant_read(function) # Grant the Lambda function permissions to put objects in the output bucket output_bucket.grant_put(function)
Lambda
次にLambdaです。まずはBedrockへプロンプトを送信する部分を下記で作成します。モデルはJurassic-2 Ultraを利用しています。プロンプトはSummarize the below text in 5 bullets.
と5個のまとめを作ってもらうようにしました。
import boto3 import json import os region = os.environ.get('AWS_REGION') bedrock_runtime_client = boto3.client('bedrock-runtime', region_name=region) def prompt_bedrock(contents): modelId = 'ai21.j2-ultra-v1' contentType = 'application/json' accept = 'application/json' prompt = f"Summarize the below text in 5 bullets.\n---\n{contents}" body = json.dumps({ "prompt": prompt, "maxTokens": 800, "temperature": 0.7, "topP": 0.95 }) response = bedrock_runtime_client.invoke_model( modelId=modelId, contentType=contentType, accept=accept, body=body ) response_body = json.loads(response.get('body').read()) return response_body['completions'][0]['data']['text']
次に、作成した関数を活用して、S3のファイルの内容をBedrockへのプロンプトとして送信します。具体的には、S3バケットからテキストファイルを取得し、その内容をBedrockのモデルに送信するプロンプトとして使用します。Bedrockはこのプロンプトを基に内容を要約し、その要約された結果を別のS3バケットにアップロードします。これにより、要約された情報が出力用のS3バケットに格納され、後で参照できるようになります。
def handler(event, context): # S3 event data s3_event = event['Records'][0]['s3'] bucket_name = s3_event['bucket']['name'] object_key = s3_event['object']['key'] s3_client = boto3.client('s3') response = s3_client.get_object(Bucket=bucket_name, Key=object_key) file_content = response['Body'].read().decode('utf-8') # prompting response = prompt_bedrock(file_content) # Get the output bucket name from environment variable output_bucket_name = os.environ.get('OUTPUT_BUCKET') output_file_name = f"summary_{object_key}" # Upload the response to the output bucket s3_client.put_object( Bucket=output_bucket_name, Key=output_file_name, Body=response ) return { 'statusCode': 200, 'body': json.dumps('Process completed successfully!') }
実行結果
作成したものを動かしてみましょう。まず、2022年re:InventのKeynote with Dr. Werner Vogelsのデータを利用します。
これをOtterで読み込ませて出力したテキストデータを入力用S3へ配置します。今回はデータを最初の30分までとしています。
オブジェクトをアップロードすると自動でLambdaが起動し、出力用のS3へオブジェクトが配置されていることが分かります。
中身は下記になります。
And so, again, this sort of the architecture is evolvable. You can add more components, you can modify the components, you can change things, you can delete them. And it also gives you suggestions of services to use. And so, for example, in one of our examples, we show you how you can use Step Functions, EventBridge, DynamoDB, S3, Route 53, and CloudWatch to build an end-to-end serverless application. Now, this shows you, again, how sort of the architecture works. So, again, this is all about simplifying the architecture, simplifying the coding, making it easier for you to build these event-driven architectures. So again, the world is asynchronous. The digital world is asynchronous. The real world is asynchronous. And for systems to work, you have to build asynchronous systems.
和訳したものが下記です。
そしてまた、この種のアーキテクチャは進化可能だ。コンポーネントを追加したり、変更したり、削除したりできる。また、利用すべきサービスを提案してくれる。例えば、Step Functions、EventBridge、DynamoDB、S3、Route 53、CloudWatchを使ってエンド・ツー・エンドのサーバーレス・アプリケーションを構築する方法を紹介します。 この例では、アーキテクチャがどのように機能するかを示している。繰り返しますが、これはすべてアーキテクチャの簡素化、コーディングの簡素化、イベント・ドリブン・アーキテクチャの構築を容易にするためのものです。繰り返しますが、世界は非同期です。デジタルの世界は非同期だ。現実の世界も非同期だ。システムを機能させるためには、非同期システムを構築しなければならない。
5個にまとめてくれていなかったり、少し日本語が不安定だったりしますが、非同期アーキテクチャの話を出していて重要な部分も抜き出せています。出来ていない部分はプロンプトをしっかり考えればフォロー出来る部分かと思っています。また、下記記事でClaude2が非常に高品質な結果で出来ているので、Claude2のモデルを利用するとより良い結果になっていたのではないでしょうか。
Bedrockはこのように複数のモデルを選択できるというのも強みとしてあるので、それを駆使して求めるアーキテクチャやモデルを選別していくのが良いと触っていて感じました。どのモデルを利用すれば良いかは下記の小西先生の記事を見て考えるのが良いかと思います。
おわりに
やっと出たBedrockを使って会話のデータを要約してみました。他にもたくさんモデルはあり、チューニングも試せるのでいくらでも遊べそうです。
皆さんも是非Bedrockちゃんをいじくり倒しましょう!