Introduction
先日、ChatGPTがAPIの提供を開始しました。
周りでもChatGPTのAPIをつかっていろいろつくっている人がいるので、
私もVoskとVOICESBOXを使用して、
音声でChatGPTに話しかけて返答を読み上げてくれる
スクリプトを(雑に)つくってみました。
Environment
今回試した環境は以下のとおりです。
- MacBook Pro (13-inch, M1, 2020)
- OS : MacOS 12.4
- VOICEBOX : 0.14.5
- Node : v18.2.0
Try
やってることはシンプルです。
Voskで音声入力して内容をChatGPTになげ、かえってきた答えをVOICEBOXにPOSTします。
次にVOICEBOXからのレスポンスをwavに保存して、afplayで再生するという雑仕様。
(VOICEBOXのところとか再生の部分はいい方法がいくらでもあるはず)
とりあえず動く状態なレベルですが、やってみます。
まずはVOICEBOXのインストールです。
ここからダウンロードしてインストール&起動します。
VOICEBOXはhttpサーバとして起動しているので、RESTでアクセスできます。
APIの使い方は、http://localhost:50021/docsにアクセスすれば
詳しい説明があります。
次はOpenAIのAPIを使うための準備です。
このへんとかこのへんをみて
API Keyの発行をしましょう。
後述するプログラムで使います。
nodeプログラムで使うモジュールをnpmでインストールします。
% mkdir example && cd example
% npm install vosk web-audio-api openai axios
次に、ここからVoskのモデル(vosk-model-small-ja-0.22)を
ダウンロードして解凍し、example直下に置いておきます。
そして下記のjavascriptプログラム(main.js)を作成します。
//main.js
const vosk = require("vosk");
const { Configuration, OpenAIApi } = require("openai");
const { default: axios } = require("axios");
const fs = require("fs");
const { execSync } = require("child_process");
var mic = require("mic");
const conf = new Configuration({
apiKey: "<api key>",
});
const openai = new OpenAIApi(conf);
const SAMPLE_RATE = 16000
const MODEL_PATH = "./vosk-model-small-ja-0.22";
vosk.setLogLevel(0);
const model = new vosk.Model(MODEL_PATH);
const rec = new vosk.Recognizer({model: model, sampleRate: SAMPLE_RATE});
var micInstance = mic({
rate: String(SAMPLE_RATE),
channels: '1',
debug: false,
device: 'default',
});
var micInputStream = micInstance.getAudioStream();
async function ask(prompt) {
const completion = await openai.createChatCompletion({
model: "gpt-3.5-turbo",
messages: [{role: "user", content: prompt}],
});
return completion;
}
var play_flag = false;
micInputStream.on('data', data => {
if (rec.acceptWaveform(data)) {
let question = rec.result().text;
console.log("question=" + question);
if(question !== null && question.length > 3 && play_flag == false) {
play_flag = true;
//chatGPTに質問を投げる
ask(question).then((result) => {
let prompt = result.data.choices[0].message.content;
// VOICEVOXでchatGPTからの返答を音声合成
axios.post(`http://127.0.0.1:50021/audio_query?speaker=1&text="${prompt}"`)
.then((queryRes) => {
axios.post(`http://127.0.0.1:50021/synthesis?speaker=1`, queryRes.data, {
responseType: "arraybuffer",
})
.then((res) => {
//VOICEBOXで生成した音声データをwavで出力してafplayで再生
fs.writeFileSync("tmp_voice.wav", res.data);
execSync("afplay tmp_voice.wav");
play_flag = false;
});
});
})
.catch((e) => {
console.error(e.message);
throw e;
});
} else {
console.log("do not exec ask & play);
}
}
});
micInputStream.on('audioProcessExitComplete', function() {
console.log(rec.finalResult());
rec.free();
model.free();
});
process.on('SIGINT', function() {
console.log("SIGINT");
micInstance.stop();
});
micInstance.start();
スクリプトの記述ができたら起動してみます。
% node main.js
マイクにむかってしゃべってみれば、その内容がchatGPTにPOSTされ、
返答がVOICEBOXで音声になって再生されます。
Summary
今回はchatGPTと音声入力を組み合わせてみました。
動作が遅いとか、アルファベットがそのまま読まれたりとか
いろいろ問題はありますが、とりあえず音声で会話っぽくなってる感じです。