はじめに
本記事では、生成AIを活用したプレゼン支援ツール「AIでプレゼン内容をフィードバックするアプリ」の実装についてご紹介します。このアプリは、作成された報告資料のデータを読み込み、プレゼンの音声と表示しているスライドを紐づけて記録・評価することで、資料との齟齬や分かりにくさ、フィラーの有無などをフィードバックすることを目的として開発したものを紹介しています。
2.背景
仕事上、お客様に資料を使って説明する機会があるのですが、その際に自分の作った資料と話し方で果たしてうまく伝わるのか、不安に思うことがありました。特に緊張すると「ええと」「あのー」といった口癖(フィラーというらしいです)が多くなるのも気になっており。かといって誰かに聞いてもらうのも時間が取れず、、
そこで、「自分のプレゼン内容に対してアドバイスをくれるAIが欲しい」ということで、生成AIを活用したプレゼン支援アプリを作ってみることにしました!
アプリケーションの機能
上記だけだと分かりにくいので、簡単なイメージを作ってみました。(これでもまだ分かりにくいですが)
3. 開発環境
本アプリの実装はPythonで開発を進めました。最終的にはpyinstaller
を使用してexeファイルとしてパッケージ化しています。
フォルダ構成
exe実行時のフォルダ構成は以下の通りです。exe
フォルダに実行ファイルとシステムプロンプトファイル、confidential
フォルダに各クラウド(Azure OpenAIとGoogle Cloud)の認証情報が格納されたkey.json
ファイルをそれぞれ配置します。
├ exe
│ ├ 実行ファイル.exe ・・・実行ファイル。条件をそろえた状態で本ファイル実行
│ └ systemprompt.txt ・・・システムプロンプト。AIの役割、評価時の条件を追記
└ confidential ・・・各クラウドサービス利用時に必要な認証情報を格納
├ Azure
│ └ key.json
└ Google Cloud
└ key.json
4. 実装手順
主要な処理を担うコードの一部を抜粋して説明します。
※本コードはCopilotなどAIアシスタントも使いながら実装しておりますが、「動くこと」を第一優先として実装しているため、一部可読性が悪かったり、コーディング規約に則っていない記載方法があることをご了承ください。
ステップ1: 設定値と定数定義
この部分は、アプリケーション全体で利用する各種設定値と、クラウドサービスへの認証情報をロードする処理を定義しています。GCP_KEY_FILE_PATH
やAZURE_KEY_FILE_PATH
で指定されたJSONファイルからAPIキーなどの認証情報を読み込み、Google Speech-to-TextとAzure OpenAIサービスを利用するための準備を行います。
# --- 設定値と定数定義 ---
# クラウドサービスの認証情報JSONファイルのパス
GCP_KEY_FILE_PATH = '../confidentials/googleSpeechToTextAPI/key.json'
AZURE_KEY_FILE_PATH = '../confidentials/Azure/key.json'
# システムプロンプトファイル(AIへの指示内容)のパス
SYSTEM_PROMPT_FILE_PATH = 'systemprompt.txt'
# 音声認識とストリーミングに関する設定
STREAMING_LIMIT_MS = 600000 # 音声ストリーミングの最大制限時間(ミリ秒) - 10分
AUDIO_RATE_HZ = 16000 # 音声のサンプリングレート(Hz)
AUDIO_CHUNK_SIZE = int(AUDIO_RATE_HZ / 10) # 1回のオーディオバッファで処理するフレーム数(100ミリ秒分)
# 音声認識結果のリアルタイム表示に関する設定
TRANSCRIPT_DISPLAY_WIDTH = 50 # リアルタイム表示時に改行する文字数
# Azure OpenAIに関する設定
AZURE_OPENAI_DEPLOYMENT_NAME = "gpt-4o" # 使用するAzure OpenAIモデルのデプロイメント名
AZURE_OPENAI_MAX_TOKENS = 1600 # AI応答の最大トークン数
AZURE_OPENAI_TEMPERATURE = 0.7 # AI応答のランダム性 (0.0-1.0, 高いほど多様)
AZURE_OPENAI_TOP_P = 0.95 # AI応答の多様性 (0.0-1.0, 高いほど多様)
# --- 認証情報とシステムプロンプトのロード ---
def load_credentials_and_config():
"""
JSONファイルからAzure OpenAIとGoogle Cloudの認証情報を読み込み、グローバル変数に設定します。
"""
# ... (認証情報ロードの具体的な処理) ...
def load_system_prompt():
"""
システムプロンプトファイルを読み込み、その内容を返します。
"""
# ... (システムプロンプトロードの具体的な処理) ...
ステップ2: PowerPointイベントハンドラの処理
PowerPointEventHandler
クラスはスライドの変更をリアルタイムで検知します。process_slide_change_in_edit_mode
メソッドでは、スライドが切り替わるたびにそのスライド番号と、スライド表示時間を記録します。これにより、「どのスライドをどのくらいの時間表示し、その間何を話したか」というのが判断できるようになります。
class PowerPointEventHandler:
"""
PowerPointアプリケーションからのイベント(スライドショー開始、終了、スライド変更)を捕捉し、
プレゼンテーションの進行状況と発表内容(スライドと発言)を記録・管理します。
"""
def __init__(self):
self.current_slide_index = None
self.slide_start_time = None
self.recorded_presentation_content = ''
self.powerpoint_file_path = ''
# ... (その他の初期化) ...
def process_slide_change_in_edit_mode(self, ppt_window):
"""
PowerPoint編集モードでスライドが変更された際に情報を処理し、
発表内容にスライド切り替え情報と前スライドの発言内容を追記します。
"""
current_slide_index = ppt_window.View.Slide.SlideIndex
if current_slide_index > 0 and current_slide_index != self.current_slide_index:
# ... (スライド切り替え時の時間計算と記録処理) ...
self.recorded_presentation_content += slide_change_info_message + '\n'
# ... (文字起こし内容の記録処理) ...
self.current_slide_index = current_slide_index
self.slide_start_time = datetime.now()
ステップ3: 音声認識とAIフィードバック生成ループ
listen_and_print_loop
関数は、マイクからの音声をGoogle Cloud Speech-to-Textにストリーミングし、リアルタイムで文字起こしを行います。発表練習を終わらせたい場合は「終わります」というキーワードを話すと終了と判断し、これまでの発表内容とPowerPoint資料のテキスト情報を基に、Azure OpenAIに対してフィードバック生成のリクエストを送信します。この時、PowerPointから抽出したテキストコンテンツと、これまでの発言内容がプロンプトとして渡されます。
def listen_and_print_loop(audio_stream, event_handler, quit_flag):
"""
Google Cloud Speech-to-Textからのストリーミングレスポンスを処理し、
リアルタイムで文字起こしを表示し、特定のキーワードで発表を終了させます。
"""
# ... (音声認識結果のリアルタイム表示処理) ...
if result.is_final: # 最終的な認識結果(発話の区切り)が確定した場合
# ... (確定した文字起こし内容の処理) ...
if re.search(r'(終わります)', event_handler.current_transcript, re.I):
# ... (発表終了時の処理とAIフィードバックの生成) ...
ai_client = AzureOpenAI(
azure_endpoint=AZURE_OPENAI_ENDPOINT,
api_key=AZURE_OPENAI_API_KEY,
api_version="2024-05-01-preview",
)
slide_texts_list = extract_text_from_pptx(event_handler.powerpoint_file_path)
# ... (AIへのプロンプト構築とフィードバック生成リクエスト) ...
completion = ai_client.chat.completions.create(
model=AZURE_OPENAI_DEPLOYMENT_NAME,
messages=initial_chat_messages,
# ... (その他のパラメータ) ...
)
initial_feedback_content = completion.choices[0].message.content
# ... (フィードバックの再確認とファイル出力) ...
5. 挙動確認
早速このアプリを使っていきます!systemprompt.txt
とパワーポイント資料は以下の通りです。パワーポイント資料はCopilotにそれらしいサンプルを作ってもらいました。
systemprompt.txt
#役割
あなたは優秀なプレゼンターです。
#タスク
添付した資料(プロジェクト計画書)を説明する練習を行います。[発表内容:]を聞き、以下「#条件」を実施して説明に対する指摘をしてください。
#条件
1.今回の発表に対する前提は以下の通りです。この発表では特に、聞き手の立場を想定して指摘をしてください。
・発表者:プロジェクトマネージャー
・聞き手:得意先
A:社内の情報セキュリティ部門になります。明確な期日はありませんが、
セキュリティにおいては明確な指標を満たさないと承認してくれません。
B:社外の会社様になります。期日は確実に守る必要があります。
担当者が多忙なため、定例の会議も多くは参加できません。
・この会議の目的:プロジェクト計画書の記載内容でプロジェクトを進めることを合意頂く
2.以下記載の通り、資料の内容を加味したレビューをしてください
・資料記載と齟齬のある発言はないか
・資料記載の説明漏れはないか(スライドページ単位で説明漏れがないかも含む)
・資料記載の重要度に合わせた説明粒度になっているか
・資料記載内自体に齟齬はないか
3.以下記載の通り、一般的な発表の内容に対するレビューをしてください
・用語の名称にばらつきがなく、統一した表現になっているか
・フィラー「ええと」「まぁ」の多用はないか
・時間内に説明できているか。説明の少ない(もしくは多い)スライドはないか。(全体の発表時間は1分です)
挙動確認
実際にこのアプリケーションを実行すると、コンソール画面が立ち上がり、PowerPointの監視が開始されたことを表示します。(左がパワーポイント画面、右が今回のアプリのコンソール画面)
Agent: パワーポイント資料のモニタリングを開始しました。
対象資料: C:\架空のプロジェクト計画書.pptx
---
練習を開始する場合:Enterキーを入力してください。
終了する場合:'q'を入力してEnterを入力してください
:
ここでEnterキーを入力すると、プレゼン練習が開始され、音声認識がアクティブになります。
Agent: プレゼンテーション練習を開始します。
Agent: 発表を始めてください。「終わります」の発言で評価を始めます。
- START!!
実際にパソコンのマイクに向かって話をしてみます。話した内容がリアルタイムでコンソール上に文字起こしされました。スライドを切り替えると、そのスライド番号と、前のスライドで話していた時間が表示されています。
スライド:1, 時間:0:00:13.083112 プロジェクト概要ですがこのプロジェクトは楽空のプロジェクトとして計画されています目的は
的はこのプロジェクト計画書の作成とその説明資料を作成することです
・・・
発表の最後に「終わります」と発言すると、アプリケーションは発表終了を検知し、AIによる評価が開始されます。
以上で発表を終わります
スライド: 7, 時間:0:00:28.605165
- FINISH!! - Agent: 発表終了と判断しました。評価いたしますので少々お待ちください...
評価完了すると、発表評価.txt
というファイルが出力されました。
実際に出力されたテキストの中身はこのような感じでした。(一部抜粋)
【評価】
スライド 1:
- 指摘内容: 特に問題はありませんが、スライドの内容が簡潔すぎるため、もう少し詳しく説明しても良いかもしれません。(追記)特にプロジェクトの概要や背景についての説明を追加すると、聞き手の理解が深まるでしょう。
-(中略)-
スライド 5:
- 指摘内容: メンバー紹介の際に「スタバ 高橋」との発言がありますが、「テスター 高橋健一」と修正する必要があります。また、各メンバーの役割をもう少し具体的に説明すると聞き手にとって理解しやすくなります。(追記)メンバーの専門性や経験、役割がプロジェクトにどう寄与するのかを詳しく説明すると良いでしょう。
-(中略)-
全体のフィードバック:
- 発表全体の時間が1分以内で終わっており、各スライドの説明が不十分な印象があります。特に重要なスライド(目的、タイムライン、リスクと軽減策)はもう少し時間をかけて説明することをお勧めします。(追記)聞き手の理解を深めるために、各スライドに対する質問を想定し、それに対する準備を行うと良いでしょう。
- フィラー「ええと」「あの」の多用が見られ、聞き手に不安を与える可能性があります。フィラーを減らす努力が必要です。(追記)練習を重ねることでフィラーを減らし、より流暢に話すことができるようにすることをお勧めします。
全体的にフィラーの指摘や時間配分の指摘、資料との整合性を加味した指摘はある程度できている印象でした!
音声認識の誤り(テスター→スタバ)は、文字起こしサービスの精度向上や設定見直し、話す環境(マイクとの距離や環境音の抑制)を整えたり、
指摘内容が抽象的なものはシステムプロンプトで指示内容をもう少し具体的にすることで改善の余地はありそうです!
6. まとめ
今回の開発を通して、課題は残っているものの、生成AIを活用したプレゼン支援ツールの可能性を確かに感じることができました。
しかし、それ以上に驚きだったのは、クラウドサービス(Google Cloud Speech-to-TextやAzure OpenAIなど)やPythonのライブラリ、さらにはCopilotといったAIアシスタントを組み合わせることで、これほどのシステムがある程度一人でも実装可能であるという点です。ほんの数年前までは特別な環境や開発スキルがないとできなかったことが、今では実現できるようになり、技術の進化に喜びと驚きを感じています。
今後も様々なサービスが登場すると思われるので、引き続きアンテナを張り巡らせつつ、新しい技術を活用した様々なアプリを試作していきたいと思います!
7. 参考リンク
Google Cloud Speech-to-Text公式ドキュント(ストリーミング入力の音声を文字に変換する)
Slide.Application プロパティ (PowerPoint)
Views: 0