OpenAIChatCompletionAPIとSpeechRecognitionAPIと組み合わせてChatGPTと音声で会話する
概要
WebSpeechAPIを試しましたが思いのほかSpeechRecognitionAPIの精度が良く何かできないかなと思い、ChatGPTと組み合わせて音声で会話をするアプリをサクッと作ってみました。
作ったもの
テキストを入力しなくても、音声入力をオンにして話すだけでChatGPTからの返信が表示され音声で読み上げられます。
使った技術
- OpenAIChatCompletionAPI
- React
- SpeechRecognitionAPI
- VOICEVOX
手順
1. Reactの環境をセットアップ
create-react-appを利用しました。Reactを実行できる環境であれば何でもOKです。
npx create-react-app chat-with-chatgpt --template typescript
2. SpeechRecognitionAPIを用いて音声入力を実装
SpeechRecognition.startListening()
で音声入力開始、音声入力中はlistening
がtrueとなりSpeechRecognition.stopListening()
で音声入力終了するとlistening
がfalseとなります。
本来はuseSpeechRecognition
から識別した音声の値を取得して使うのですが、今回は音声認識が完了したタイミングでリクエストを行いたかったためcallbackを定義できるcommandsで実装しています。
import SpeechRecognition, {
useSpeechRecognition,
} from 'react-speech-recognition'
const { listening } = useSpeechRecognition({
commands: [
{
command: '*',
callback: async (command) => {
if (command) {
setMessages((prevState) => [
...prevState,
{ isMe: true, message: command },
])
await sendChatGPT(command)
}
},
},
],
})
const onStart = async () => {
setIsChecked(true)
await SpeechRecognition.startListening()
}
const onEnd = async () => {
setIsChecked(false)
await SpeechRecognition.stopListening()
}
3. OpenAIのChatCompletionAPIを用いてレスポンスを取得
APIはgpt-3.5-turboモデルを利用します。
Most capable GPT-3.5 model and optimized for chat at 1/10th the cost of text-davinci-003. Will be updated with our latest model iteration.
OpenAIよりAPIKeyを発行しOrganizationIDと一緒に環境変数へ指定します。
REACT_APP_OPENAI_ORGANIZATION_ID=xxxxxxxxxx
REACT_APP_OPENAI_API_KEY=xxxxxxxxxx
OpenAIAPIへのアクセスするためのライブラリを導入
yarn add openai
Authenticationに従ってAPIKeyとOrganizationIDを設定します。
Configの指定が完了したら次はChatCompletionAPIのリクエストを行います。createChatCompletion
メソッドで、モデル名、最大トークン数と一緒に2で音声入力したテキストデータをリクエスト含めます。
import { Configuration, OpenAIApi } from 'openai'
const sendChatGPT = async (question: string) => {
setIsLoading(true)
const configuration = new Configuration({
organization: process.env.REACT_APP_OPENAI_ORGANIZATION_ID,
apiKey: process.env.REACT_APP_OPENAI_API_KEY,
})
const openai = new OpenAIApi(configuration)
const completion = await openai.createChatCompletion({
model: 'gpt-3.5-turbo',
max_tokens: 400,
messages: [
{ role: 'user', content: question ?? '' },
],
})
setIsLoading(false)
const text = completion.data.choices[0].message?.content
(一部略)
}
4. VOICEVOXを用いてテキストを音声に変換
WebSpeechAPI試しておきながらSpeechSynthesisAPIではないんかいとつっこまれてしまいそうですがVOICEVOXでは簡単に美ボイスを利用できたのでついつい。
http://localhost:50021/docs へアクセスしてAPIドキュメントを確認します。今回は/audio_query
と/synthesis
を利用してwavファイルを取得します。
ChatCompletionAPIから返却されたテキストで音声合成用クエリを作成し、クエリを用いて音声合成を行います。
const sendChatGPT = async (question: string) => {
(一部省略)
const query = await createQuery(text) <-- ChatCompletionAPIから返却されたテキスト
const voice = await createVoice(query)
const audio = new Audio(voice ? window.URL.createObjectURL(voice) : '')
await audio.play()
audio.onended = () => onStart()
}
const createQuery = async (text = '') => {
const res = await axios.post(
`http://localhost:50021/audio_query?speaker=8&text=${text}`,
)
return res.data
}
const createVoice = async (query: string) => {
const res = await axios.post(
'http://localhost:50021/synthesis?speaker=8',
query,
{ responseType: 'blob' },
)
return res.data
}
5. 実際に動かしてみる
音声入力を開始すると初回のみ、マイクの使用許可を求められます。「許可する」をクリックすると音声入力可能となります。
ブラウザのマイクに向かって話すとテキストに変換され表示されます。
話した内容がリクエストされOpenAIのChatCompletionAPIがレスポンスを返します。返却されたテキストはVOICEVOXで音声に変換され読み上げられます。読み上げが完了後再度音声入力が可能となります。
APIリクエストで数秒時間がかかってしまうもののたった4ステップでChatGPTと会話することができました🎉
余談
ChatCompletionAPIの設定せずそのまま利用していたので、会話の文脈はガン無視です。。
assistant前の会話を含めたりプロンプトを工夫することで会話の質は高められそうですね
Discussion