昨今耳目を集めるAI業界ですが、今回は特に今アツいAIチャットボットであるChatGPTと電話で話したいと思います。
正確には音声をテキスト化したメッセージを、ChatGPTで利用されているモデルであるgpt-3.5-turboにAPIで送って回答を取得し、Pollyで発話させることで電話でやり取りできるようにします。
音声の入力をAmazon Connect、音声のテキスト化をLex、OpenAIのAPIを叩く部分をLambdaで構築していきます。
構成は下記のようなイメージとなります。
OpenAIのアカウント、APIキーの準備
まずはOpenAIのAPIを実行するために必要なAPIキーを準備します。
OpenAIにアカウントを登録してAPIキーの発行をします。参考→https://platform.openai.com/docs/api-reference/authentication
アカウントの作成は簡単で、私の場合はGoogleアカウントでサインアップ後、電話番号を登録するだけで完了しました。
アカウントの登録完了後、個人ページからAPIキーの取得が可能です。
Lambda
続いて、OpenAI APIにメッセージを送り返答を取得するLambdaを作成します。
ランタイムはPython3.9です。
コードの解説はインラインに記載しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
import openai import os # 環境変数からOpenAIのAPI_KEYを取得 openai.api_key = os.environ['API_KEY'] def lambda_handler(event, context): if not event['inputTranscript'] : # Lexからのinputが空文字、nullなら空のメッセージを返す # 結構雑な実装なので改善の余地あり return { "sessionState": { "dialogAction": { "type": "ElicitIntent" }, "intent": { "name": "ConnectToGPT", "state": "Fulfilled" } }, "messages": [ { "contentType": "PlainText", "content": "、" } ] } else: # OpenAIのAPIをたたく query = openai.ChatCompletion.create( # 使用するモデルはgpt-3.5-turbo model="gpt-3.5-turbo", messages=[ # GPT側のキャラ設定を指定する {"role": "system", "content": "あなたは親しい友人です。敬語は使わず、フランクな口調で回答してください。回答は3文までに収めてください"}, # ユーザーからのメッセージとしてLexからのinputを指定する {"role": "user", "content": event['inputTranscript']}, ], temperature=0.5, max_tokens=100, presence_penalty=0.6, ) content = query["choices"][0]["message"]["content"] # ログ print({ "input": { "transcript": event['inputTranscript'], }, "output": { "message": content, } }) # Lex用のフォーマットでOpenAI APIのレスポンスを返す return { "sessionState": { "dialogAction": { "type": "ElicitIntent" }, "intent": { "name": "ConnectToGPT", "state": "Fulfilled" } }, "messages": [ { "contentType": "PlainText", "content": content } ] } |
その他、Lambdaに以下の設定をしておきます。
- OpenAIからのレスポンスには数秒の時間がかかるため、タイムアウトは5秒以上を設定
- 環境変数としてOpenAIのAPIキーを設定
Lex
次はLambdaとAmazon Connectを橋渡しするLexボットを作成します。
Lexでは入力した音声がサンプル発話にヒットした場合にそのインテントが実行されますが、
今回はどんな入力でも受け付けてLambdaに連携したいと思います。
まずは先ほど作成したLambda関数をLexから呼び出せるように設定します。
続いて適当な発話サンプルを持った基本のインテントを作成します
今回は「おはよう」という言葉をサンプル発話に持ったConnectToGPTというインテントを作成します。
また、このインテントのコードフックオプションにチェックを入れて、インテントがLambdaを呼び出すようにします。
さて、これだけでは「おはよう」以外の発話があった場合、FallbackIntentに振り分けられてLambdaに連携されません。
というわけでFallbackIntentのコードフックオプションにもチェックを入れて、どんなときでもLambdaを呼び出すようにしました。
上記のような実装はあまりよくないかもしれませんが、今回はChatGPTで遊ぶことが目的なのでこれで進めていきます。
Amazon Connect
最後にLexを統合したコンタクトフローを作成します。
内容はシンプルで、ログや音声の設定後、Lexの呼び出しを行うのみとなっています。
いざ、実演
準備ができました。
実際に電話してみましょう。(寝起きで録画したのでテンションがとても低いです)
Amazon Connectなので電話はもちろん、フローをそのまま利用してGPTとのチャットも可能です
さて、それっぽく動作しているように見えますが、実は大きな穴があります
それはOpenAIのAPIを発話の都度呼び出しており、GPT側が発話の履歴を記憶していないため、コンテキストに沿った回答ができないという点です
このあたりについてはDynamoDBに履歴を保存しておき、APIを実行する際に直前の2, 3回分の履歴を合わせてリクエストを送る、などで対応可能そうです
とりあえずChatGPTと話すという目的は達成できたので今回はここまでとしたいと思います
- Remix SPAモードで静的WebサイトをGithub Pagesにデプロイする - 2024-11-05
- LangGraph入門!LLMアプリ開発ライブラリのQuick StartをAmazon Bedrockでやってみる - 2024-10-10
- AWS ChatbotでSlackからAmazon Bedrock Agentにアクセスしてみる - 2024-09-18
- Amazon Bedrockの新機能「Prompt flows」を試してみた - 2024-07-11
- Amazon ConnectのZero-ETLがGAされたので試してみた - 2024-06-03