英会話レッスンを(ほぼ)無料でいつでもやりたい!
英会話レッスンを受けたいとき、お金がかかり時間も拘束される。
そこで、ほとんど無料でいつでもpcブラウザやスマホで英会話レッスンができるアプリが欲しいと思い開発することにした。
ほとんど無料である理由は、ChatGPTを呼び出すためにOpenAIのAPIにクエリを投げる際にごく少額の料金がかかるからである。(だいたい1会話0.1円未満)
アプリの構成
アプリはpcブラウザ、スマホからアクセスできアクセス元の環境に関係なく、前回までの会話を続けられるようにする。
会話の入力はpcブラウザ、スマホの音声入力APIを使って行い、入力に対するChatGPTの応答は音声読み上げAPIを使って読み上げることにより、会話ができる。
また、会話はルーム単位で管理する。
なお、今回は英会話レッスンをすることが目的であるため英会話のみに対応すれば十分であるが、音声入力APIと音声読み上げAPIは多くの言語に対応しているため、中国語、フランス語、スペイン語などAPIが対応している言語のレッスンも本アプリでは行うことができる。(ルーム単位で設定言語を変更できる)
TL;DR
- APIサーバーとクライアントを作成する(go,react)
- ios,androidアプリを作成する(react-native)
- Dockerコンテナ化する
リポジトリ
- server: OpenAIのAPIとやりとりするサーバー
- client: ブラウザ版のクライアント
- phoneapp: ios, android版のクライアント
- infra: docker-composeファイル
1.APIサーバーとクライアントを作成する
OpenAIのChatGPT APIにサーバーから会話データを投げ、応答を取得する。そのためにはOpenAIのアカウントを作り、APIキーをあらかじめ取得しておく必要がある。APIキーを取得したら、以下ファイルの==[Write your key]==
に自分のキーを指定する。
server/chatgpt/ChatGPTBot.go
サーバー内でルームとしてChatGPTとのトーク履歴を管理しており、ユーザはルームに入ってChatGPTと会話できる。
サーバーはserverディレクトリ以下でgo run main.go
により立ち上がりhttp://localhost:8080
にアクセスすると以下画面が表示される。
クライアントはReactで作成した。
右下の「S2T」ボタンを押すと、初回はブラウザからマイクの使用を許可するか聞かれるので許可する。すると、S2Tのボタンが赤色になり音声受付状態になる。そこで英語を話すと音声認識により話した英語がフォームに入力される。
意図した英語が入力されたら「Send」ボタンを押すことで、ChatGPTに会話が投げられる。そして、ChatGPTからの返答が返ってくると英語の音声で読み上げられることで、英会話を続けられる。
なお、「Interact」モードを選択することで、S2T→Sendというボタンを押すことなく会話を継続でき、より自然な英会話に近づけることができる。
(以下は中国語。言語を切り替えれば中国語やフランス語、スペイン語なども会話可能)
2. ios,androidアプリを作成する
今回、ブラウザのクライアントを作成することでios,androidのブラウザからアクセスすればスマホからも英会話レッスンを受けられる予定であったが、iosのgoogle chromeが音声認識に対応していないことが判明し、androidのみの対応となってしまった。
そこで、ReactNativeでios,androidアプリをネイティブアプリとして作成することにした。起動するにはxcode,android studioをインストールし、適宜エミュレータを導入する必要がある。
serverをローカルで起動して、phoneappディレクトリでnpm run ios
を入力することでiosアプリが起動する。
右下の「Voice」ボタンを押すことで音声入力が開始する。終了したら再度ボタンを押し音声入力を終了して、「Send」ボタンを押すことで会話をサーバーに送る。
- 起動直後の画面。会話を選択
- ルームを選択した時のルーム画面。ルーム名を選択するとルームの言語とプロンプト設定が行える。
3. Dockerコンテナ化する
最後にサーバーをコンテナ化してdockerなどのコンテナランタイム上で動作するようにする。
とは言っても、Dockerfileを作成しただけであるので開発としてはおまけである。
server/Dockerfileにマルチステージビルドでサーバーをコンテナとしてデプロイするファイルがあり、こちらをbuildすることでコンテナを作成することができる。