LINEbot×GAS×ChatGPTでGPT3.5とGPT4をLINEの画面から切り替え

YouTubeでライブコーディングに挑戦したChatGPT×LINEボット。

https://www.youtube.com/live/opi-2A3KRls?feature=share

この時はモデルはGPT3.5だったのですが、waitlistに登録していてついにGPT4が使えるようになりました！

ということで、GPT4に切り替えようと思ったのですが
すべてを切り替えると金額が大変なことになるので、ユーザー側でモデルを切り替えられるようにしました。
(API keyはGPT3.5でもGPT4でも同じで、modelを切り替えるだけでいけました。)

ライブコーディングではこちらのスプレッドシートを作りましたが

https://docs.google.com/spreadsheets/d/103tgm0pHp6m7VlEtMdqHFatysNO6QIIV_Uebqw_kbRs/edit?usp=sharing

このスプレッドシートのGASのコードを一部書き換えました。
下記は書き換え後の全コードです。

:::note info
2023/05/01 14:00修正
新規ユーザーがメッセージを送った場合モデルが選択されておらずエラーとなっておりました。
誤：var chatreplytext = Sent_ChatGPT(send_message)
正：var chatreplytext = Sent_ChatGPT(send_message,"gpt-3.5-turbo")
:::

```javascript:コード.gs

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にモデル名を入れるようにしております。



下記に追記したところを抜粋しました。

ここでモデルタイプをメッセージで受信したときに、変更するようにします。
```javascript:モデル変更.gs
 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で受信したときに、どのモデルか表示するようにしております。
```javascript:senderの表示.gs
    const replyText = {
        "replyToken": replyToken,
        "messages": [{
            "type": "text",
            "text": text,
            "sender": {
              "name": model
              }
        }]
    }
```


LINEの画面はこのようになります。

<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624933/a5e10524-7ced-f0ee-8b1a-acf14438640d.jpeg">

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