こんにちは、佐野です。
今回は、Bedrockを使うことで何ができるのかを学ぶために「自動議事録」をClaude 3 sonnetモデルを使って実装してみました。
たぶん皆さんも業務の中で「録音ファイル→文字起こし→要約→他者とクラウドストレージでの共有」といった議事録作成フローを自動化したいケースは少なくないと思います。
そこで、以下の要件を満たす自動化パイプラインをAWS上で構築してみたので、構成や設計判断を技術的な観点から共有していきたいと思います!
【目次】
・実現した要件
・なぜClaude 3 Sonnetを採用したのか?
・実装にあたり苦戦した点,工夫した点
・今後改善するべき点
・まとめ
1.音声ファイル(mp3)をS3にアップロードすると処理が自動開始
2.Amazon Transcribeを用いて日本語の文字起こしを実行
3.Claude(Bedrock)を使って抽象度の高い要約を生成
4.生成された要約をPDF化して再度S3に保存
5.LINE Bot経由で署名付きURLを通知
図1:今回作成した「自動議事録」システムのアーキテクチャ図
Amazon Bedrockでは複数のモデルが選べますが、今回選んだのは Anthropic社の Claude 3 Sonnet です。
比較軸
|
Claude 3 Sonnet
|
Command R+(Cohere)
|
Titan Text G1(Amazon)
|
要約精度
|
◎
|
〇
(構造化出力) |
△
|
日本語対応
|
◎
(自然な生成) |
△
|
△
|
レイテンシ
|
〇
|
◎
|
◎
|
トークン長
|
約200K context
|
約4K〜
|
約4K〜
|
表1:Claude 3 Sonnet の特徴(要約タスクにおける優位性)
※本表は、各モデルの公式ドキュメントをもとにまとめたものです。
Claude 3は、非英語言語の理解力が大きく向上しており、日本語の自然な要約生成も非常に安定しています。
"The Claude 3 family improves significantly on fluency in non-English languages like Spanish and Japanese."
出典:https://www-cdn.anthropic.com/de8ba9b01c9ab7cbabf5c33b80b7bbc618857627/Model_Card_Claude_3.pdf
また、Claude 3 SonnetはClaude 3 Opusほどコストが高くなく、低レイテンシで高速応答を実現できるため、リアルタイム性を求めるシステムには適しています。
実際に使用したmp3ファイル(例:好きなAWSを紹介している人の音声データ)
※今回は、音読さんという音声読み上げソフトでsample.mp3を作成しました。(https://ondoku3.com/ja/)
実際に生成された要約ファイル
# Claudeへプロンプト送信
prompt = f"""
以下はある会議の全文です。この内容を要約し、やるべきこと(ToDo)を箇条書きで抽出してください。
【会議内容】
{all_text}
【出力形式】
- 要約:
- (要約文)
- ToDo:
- (やること1)
- (やること2)
"""
body = {
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 1024,
"temperature": 0.5,
"messages": [{"role": "user", "content": prompt}]
}
今回Claudeに送信したプロンプトは上記のものとなります。このように指示を簡単に書いてもまともに要約してくれるClaude。すごいですね…!
音声ファイルの文字起こしには、Amazon Transcribeを使用しました。Lambda関数から非同期ジョブを開始し、その完了をポーリングで確認しています。
# Transcribe完了を最大90秒待つ
for i in range(90):
response = transcribe.get_transcription_job(TranscriptionJobName=job_name)
status = response['TranscriptionJob']['TranscriptionJobStatus']
print(f"[{i+1}s] Transcribeステータス: {status}")
if status == 'COMPLETED':
uri = response['TranscriptionJob']['Transcript']['TranscriptFileUri']
break
elif status == 'FAILED':
return {'statusCode': 500, 'body': 'Transcription failed'}
time.sleep(1)
else:
return {'statusCode': 500, 'body': 'Transcription timeout'}
print()を1秒おきに設定することでログを追えるようにしました。
図2 CloudWatchのログストリームでTranscribeジョブを確認したもの
body = {
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 1024,
"temperature": 0.5,
"messages": [{"role": "user", "content": prompt}]
}
max_tokensとは、Claudeから生成される出力の最大長(トークン数)を制限するパラメータのことです。
そもそもトークンとは、AIモデルが内部的に文章を分割して処理する単位。つまり、AIがテキストの理解や生成を行う際に扱う単位となります。
今回の場合だと、1024トークンで設定しているため日本語での生成で約900~1000文字程度の出力量とされています。出力量を設定しない場合は、入力+出力の合計がモデルの最大トークン長(Claude 3 Sonnetでは200k)を超えない範囲で、最大限出力を生成します。そのため、max_tokensを設定しないと、出力が長すぎて不自然になったり、意図しない話題に逸れたりすることがあるため設定しました。
temperatureは、AIが次の単語(トークン)を選ぶ際の「ランダム性」をコントロールするためのパラメータのことです。0から1の範囲で設定され、値が低いほど保守的・決定論的になり、値が高いほど多様で創造的な文章を生成します。
今回の場合、生成AI(Claude 3 Sonnet)の出力の「安定性」と「創造性」の両方をバランスよく取りたかったこともあり、「temperature = 0.5」にしました。
また、比較用に「temperature = 0」、「temperature = 1」に変更して生成されたファイルも掲載しておきます。ご確認してみて下さい!
「temperature = 0」にした場合
「temperature = 1」にした場合
temperature
|
temperature = 0
|
temperature = 0.5
|
temperature = 1
|
網羅性・明確性
|
やや形式的で機械的。情報の欠落は少ないが、抽象度が高い。
|
適度な抽象化と具体例のバランスが取れている。自然な文体で読みやすい。
|
言い換えや説明が豊かだが、冗長気味。やや説明調で、簡潔さに欠ける。
|
議事録としての
実用性 |
内容は正確だが、説明が淡泊で、読み手が背景知識を持っていない場合に理解しにくい。
|
現場経験に基づく具体的なコメントがあり、説得力と実務への橋渡しができている。
|
読み物としては良いが、議事録にしてはやや自由すぎる。要点が散る恐れあり。
|
ToDoの具体性
|
シンプルでまとまっているが、やや一般論に留まり、実務での活用には具体例が欲しいところ。
|
要点が整理されていて、実行可能性が高い。現場で「次に何をすべきか」が明確である。
|
豊富ではあるが、優先順位や行動計画がぼやけやすい傾向がある。
|
総評
|
「正確さ・堅実さ」は高評価。社内報告書の骨格としては安定。
|
最もバランスが良く、会議後の共有・実務への展開に適している。
|
説明文・教育資料向き。議事録としては冗長かつ方向性がぼやけやすい。
|
表2:temperatureを0, 0.5, 1にした場合に出力される生成ファイルの特徴
議事録としての「正確性」を重視したい場合には、「temperature = 0」もアリなのかもしれません…!
参考:https://moji.or.jp/ipafont/ipafontdownload/
このフォルダ内にあるttfファイルが日本語でPDFを出力するのに必要であったため使用しました。ttfファイルを使うために他のpythonライブラリ同様、Lambda関数内で使用できるようにzipファイルにしてアップロードを行いました。
①ローカル環境で新規フォルダを作成し、そのフォルダ内に必要なライブラリを保存する。(日本語でPDFを生成するのに取得したttfファイルも使うため置いておきます。)
②以下のコマンドでzipファイルを作成します。必要なライブラリをインストールしたフォルダのディレクトリで実行してください。(windows powershellで行いました。)
PS C:\Users\sanom\lambda-pdf> Compress-Archive -Path * -DestinationPath lambda_function.zip
③作成したzipファイルを任意のLambda関数の「コード」タブのコードソースにある、「アップロード元」をクリックし、zipファイルを選択
これでLambda関数内で使用したいライブラリやファイルを扱うことができます!
生成したPDFは、同じS3バケット内のsummary-pdf/ プレフィックスに保存し、ダウンロード用の署名付きURLを作成しています。
# S3アップロード
s3.put_object(Bucket=bucket, Key=pdf_key, Body=pdf_buffer, ContentType='application/pdf')
# 署名付きURLを生成(1時間有効)
pdf_url = s3.generate_presigned_url(
'get_object',
Params={'Bucket': bucket, 'Key': pdf_key},
ExpiresIn=3600
)
図3 summary-pdfフォルダ内に保存されたPDF
署名付きURLの有効期限は1時間(3600秒)に設定。利用者が認証なしにS3内のPDFファイル内容を確認できるようにしており、LINEやSlackでも共有することができます。
※今回は手元ですぐに確認できるようにするため署名付きURL発行し、一時的に公開可能な形式にしています。業務上機密性が高いデータを扱う場合は、S3アクセス権限やIAMを利用した制限を検討することが推奨されます。
図4 Linebot経由でPDF作成完了を通知
今回作成したものでは1秒おきにポーリングしているため、以下のようなデメリットがあります。
そのため、Transcribeジョブが完了することを確認した今現在では、Amazon SNS連携によるイベント駆動の方が上記のデメリットを解消でき、無駄のない設計になると言えます。
具体的には、
Lambda①:
S3アップロードトリガーで起動し、Transcribeジョブを開始 → 完了通知はSNSで送信。
Lambda②:
SNS通知で起動し、Transcribe結果を取得 → Claudeで要約 → PDF生成 → S3保存&LINE通知。
のような設計が良いと思います。
これによりLambda関数のタイムアウトの心配や課金リスクを大幅に減らすことができます。また、処理を分けることでマイクロサービスアーキテクチャーとなり、エラー箇所の特定や生成AIのモデル変更・通知するアプリケーションを変更しやすくなるなど、保守性や拡張性も向上します。
処理が複雑になる際には、Step Functionsを使うのも良いのではないかと思っています。
図5 Lambda関数を2つに分け、「自動議事録」システムを再構成したアーキテクチャ図
本記事では、AWS × Claude を使って、自動的に議事録を生成・共有する仕組みを構築しました。実装を通して、Amazon Bedrockの特徴やClaude 3 Sonnetの活用方法について深く理解することができたと思います。
特に以下の点が印象的でした。
今回の学びを通じて、「AIを業務にどう使うか」という視点が一気に現実味を帯びたように思います。今後は要約だけでなく、分類・FAQ生成・意見の対立点抽出など、より踏み込んだ活用にも挑戦していきたいと思いました。
皆さんもAmazon Bedrockを活用したシステム構築,お試しください!