YouTubeでライブコーディングに挑戦したChatGPT×LINEボット。
この時はモデルはGPT3.5だったのですが、waitlistに登録していてついにGPT4が使えるようになりました!
ということで、GPT4に切り替えようと思ったのですが
すべてを切り替えると金額が大変なことになるので、ユーザー側でモデルを切り替えられるようにしました。
(API keyはGPT3.5でもGPT4でも同じで、modelを切り替えるだけでいけました。)
ライブコーディングではこちらのスプレッドシートを作りましたが
このスプレッドシートのGASのコードを一部書き換えました。
下記は書き換え後の全コードです。
2023/05/01 14:00修正
新規ユーザーがメッセージを送った場合モデルが選択されておらずエラーとなっておりました。
誤:var chatreplytext = Sent_ChatGPT(send_message)
正:var chatreplytext = Sent_ChatGPT(send_message,"gpt-3.5-turbo")
var SS = SpreadsheetApp.getActiveSpreadsheet();
var User_sheet = SS.getSheetByName("user_status");
var Log_sheet = SS.getSheetByName("log");
var Setting_sheet = SS.getSheetByName("setting")
var User_lastrow = User_sheet.getLastRow();
var User_data = User_sheet.getRange(1, 2, User_sheet.getLastRow() ).getValues();
var CHANNEL_ACCESS_TOKEN = Setting_sheet.getRange(1,2).getValue();
var ChatGPT_APIKEY = Setting_sheet.getRange(3,2).getValue();
function doPost(request) {
var receiveJSON = JSON.parse(request.postData.contents);
var event = receiveJSON.events[0];
var current = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/MM/dd HH:mm:ss');
//////////// ID チェック用 ////////////////
//ユーザーID
var userId = event.source.userId;
//2次元配列を1次元配列に変換
var arr_User = Array.prototype.concat.apply([], User_data);
//1次元配列に変換した User_data(A列)の中に、userIdが含まれているかチェック
var i = arr_User.indexOf(userId);
//////////// ID チェック用ここまで ////////////////
//type=messageだけを送る
if(event.type==="message"){
if(event.message.text==="GPT4"){
User_sheet.getRange(i+1,9).setValue("gpt-4");
replyToUser(event.replyToken, "モデルをGPT4に変更いたしました。GPT4はGPT3.5よりも回答が時間がかかる場合がございます。また一定時間がたちましたらGPT3.5に自動的に戻ります。","設定変更")
Log_sheet.appendRow([current,event.source.userId,event.message.text])
return;
}else if(event.message.text==="GPT3.5"){
User_sheet.getRange(i+1,9).setValue("gpt-3.5-turbo");
replyToUser(event.replyToken, "モデルをGPT3.5に変更いたしました。","設定変更")
Log_sheet.appendRow([current,event.source.userId,event.message.text])
return;
}
//User_sheetにuserIDがあった場合
if(i!==-1){
var arr_message = User_sheet.getRange(i+1,3,1,6).getValues();
var character = Setting_sheet.getRange(8,1).getValue();
//メッセージの送信の形は、ChatGPTのドキュメントに書いてある通りに記載
//https://platform.openai.com/docs/guides/chat/introduction
var send_message = [
{"role": "system", "content": character } ,
{"role": "user", "content": arr_message[0][4]},
{"role": "assistant", "content": arr_message[0][5]},
{"role": "user", "content": arr_message[0][2]},
{"role": "assistant", "content": arr_message[0][3]},
{"role": "user", "content": arr_message[0][0]},
{"role": "assistant", "content": arr_message[0][1]},
{"role": "user", "content": event.message.text},
]
//ChatGPTにメッセージを送信
var model = User_sheet.getRange(i+1,9).getValue();
var chatreplytext = Sent_ChatGPT(send_message,model)
//ChatGPTから返ってきたメッセージをLINE APIで返答
replyToUser(event.replyToken, chatreplytext,model)
//順番を入れ替えてスプレッドシートに貼り付け。これで会話を覚えている
var arr_new_message= arr_message.map(elm => [event.message.text,chatreplytext,elm[0],elm[1],elm[2],elm[3]]);
User_sheet.getRange(i+1,3,1,6).setValues(arr_new_message);
//User_sheetにuserIDがなかった場合
}else{
var character = Setting_sheet.getRange(8,1).getValue();
var send_message = [
{"role": "system", "content": character } ,
{"role": "user", "content": event.message.text},
]
//ChatGPTにメッセージを送信
var chatreplytext = Sent_ChatGPT(send_message,"gpt-3.5-turbo")
//ChatGPTから返ってきたメッセージをLINE APIで返答
replyToUser(event.replyToken, chatreplytext,"gpt-3.5-turbo")
User_sheet.appendRow([current,event.source.userId,event.message.text,chatreplytext,,,,,"gpt-3.5-turbo"]);
}
Log_sheet.appendRow([current,event.source.userId,event.message.text,chatreplytext,model])
}
}
/**
* ChatGPTへ送る
* @param {*} send_message
*/
function Sent_ChatGPT(send_message,model){
const options = {
method: 'POST',
headers: {
'content-type': 'application/json',
authorization: 'Bearer ' + ChatGPT_APIKEY
},
muteHttpExceptions: true,
payload: JSON.stringify({
"model": model,
"messages": send_message
})
}
const response = UrlFetchApp.fetch('https://api.openai.com/v1/chat/completions', options);
const chatreply = JSON.parse(response.getContentText());
//回答の抽出はドキュメントに方法が記載されてます
//https://platform.openai.com/docs/guides/chat/introduction
return chatreply['choices'][0]['message']['content'].trim();
}
/**
* 該当ユーザーへの
* @param {*} replyToken
* @param {*} text
*/
function replyToUser(replyToken, text,model) {
const replyText = {
"replyToken": replyToken,
"messages": [{
"type": "text",
"text": text,
"sender": {
"name": model
}
}]
}
const options = {
"method": "post",
"headers":
{
"Content-Type": "application/json",
"Authorization": "Bearer " + CHANNEL_ACCESS_TOKEN,
},
"payload": JSON.stringify(replyText)
};
// ユーザーに応答を返している
UrlFetchApp.fetch("https://api.line.me/v2/bot/message/reply", options);
}
その後、LINE オフィシャルアカウントマネージャーにリッチメニューを設置し
メニューをタップすることで「GPT3.5」「GPT4」のテキストを送信するようにしております。
今、どちらのモデルを使っているかわかりやすいように、LINE MessagingAPIのsenderでnameにモデル名を入れるようにしております。
下記に追記したところを抜粋しました。
ここでモデルタイプをメッセージで受信したときに、変更するようにします。
if(event.message.text==="GPT4"){
User_sheet.getRange(i+1,9).setValue("gpt-4");
replyToUser(event.replyToken, "モデルをGPT4に変更いたしました。GPT4はGPT3.5よりも回答が時間がかかる場合がございます。また一定時間がたちましたらGPT3.5に自動的に戻ります。","設定変更")
Log_sheet.appendRow([current,event.source.userId,event.message.text])
return;
}else if(event.message.text==="GPT3.5"){
User_sheet.getRange(i+1,9).setValue("gpt-3.5-turbo");
replyToUser(event.replyToken, "モデルをGPT3.5に変更いたしました。","設定変更")
Log_sheet.appendRow([current,event.source.userId,event.message.text])
return;
}
ここでLINEで受信したときに、どのモデルか表示するようにしております。
const replyText = {
"replyToken": replyToken,
"messages": [{
"type": "text",
"text": text,
"sender": {
"name": model
}
}]
}
LINEの画面はこのようになります。

GPT4は少し値段が上がりますので、基本はGPT3.5、何かの時はGPT4の様に切り替えると非常に便利です!!