見出し画像

【コピペOK】文脈理解できるLINE Bot(AI社労士)をノープログラミングでChatGPT、Googleスプレッドシート、GASで作成する方法を現役社労士が解説(3.応用編)

現状の課題

この記事では、第1回(準備編)第2回(構築編)とAI社労士LINE botの構築方法を解説してきました。
実際に構築してみた方はお気づきかもしれないですが、このAI社労士LINE botには大きな課題があります。
現在のLINE botは、1日のトーク上限が設けられていません。
ユーザーが1日中、何度でもトークすることが可能だということです。
トークをするとその度にOpenAI APIでChatGPTにリクエストが送られトークンが消費されます。
トークンとはChatGPTの課金の単位と思って下さい。
英語の場合、1単語=1トークンと計算され記号も1トークンとして消費します。
それに対して、日本語の場合は1文字が1トークン以上とカウントされます。
ひらがなは1トークン、漢字は2から3トークンが消費されてしまうのです。
このようにLINE botとしてChatGPTを利用していると、思わぬ高額請求になる場合があります。
また文脈を理解させるために、Googleスプレットシートを使用していますが、過去の会話履歴をすべてOpenAI APIにリクエストを行っています。
これは前述のトークンの消費量が増えることだけではなく、トークのレスポンス速度が遅くなってしまう問題点があります。
この記事では以上の問題点を解決する機能追加を行います。

なお、機能追加版のLINE botは、服部社会保険労務士事務所で公開しています。


機能追加の方針

以下の通り、機能追加の方針を設定します。

  • 1日のトーク上限を設定する

  • OpenAIに送信する会話履歴の上限を設定する

ソースの変更

機能追加の方針を元にソースの追加修正を行います。

const LINE_ACCESS_TOKEN = 'LINEアクセストークン';
const OPENAI_APIKEY = 'OpenAI APIキー';
const SPREADSHEET_ID = 'スプレッドシートID';

const DAILY_LIMIT = 10; // 1日の会話数の上限を設定
const CONVERSATION_HISTORY_LIMIT = 5; // OpenAIに送信する会話履歴の上限

function doPost(e) {
  const event = JSON.parse(e.postData.contents).events[0];
  const replyToken = event.replyToken;
  const messageType = event.message.type;
  const userId = event.source.userId;
  const url = 'https://api.line.me/v2/bot/message/reply';

  if (messageType !== 'text') {
    const errorMessage = 'すみません。私はスタンプや画像などは理解できません。テキストメッセージをお願いします。';
    reply(userId, replyToken, errorMessage, url);
    return;
  }

  let userMessage = event.message.text;

  const sheet = getOrCreateSheet(userId);
  const numRows = sheet.getLastRow();

  if (numRows >= DAILY_LIMIT * 2) {
    const errorMessage = '本日の会話数が上限に達しました。明日以降にお試しください。';
    reply(userId, replyToken, errorMessage, url);
    return;
  }

  sheet.appendRow([new Date(), 'user', userMessage]);

  const conversationHistoryStartRow = Math.max(1, numRows - CONVERSATION_HISTORY_LIMIT * 2 + 1);
  const conversationHistory = sheet.getRange(conversationHistoryStartRow, 2, numRows - conversationHistoryStartRow + 1, 2).getValues().flat();
  const messages = conversationHistory.map((message, index) => {
    return {
      role: (conversationHistoryStartRow + index) % 2 === 0 ? 'user' : 'assistant',
      content: message
    };
  });

  const requestOptions = {
    method: 'post',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer ' + OPENAI_APIKEY
    },
    payload: JSON.stringify({
      model: 'gpt-3.5-turbo',
      messages: [
        {
          role: 'system',
          content: `
          あなたは社会保険労務士としてロールプレイを行います。以下の制約条件と行動指針を厳密に守ってください。

          制約条件:
          * 一人称は「社労士AIアシスタント」を使ってください。
          * あなたは親切で丁寧な新人の20代男性です。
          * 回答はAIであり正確でない場合があることを、最後に必ず付け加えてください。
          * 正確な回答が知りたい場合は、服部社会保険労務士事務所に問い合わせる案内を入れてください。
          * 問い合わせ先のURLは、https://hattori-sr.jp/contact/
          * 問い合わせ先のURLを案内する場合、正しくリンクされるように、別の会話としてURLだけ送信してください。

          社会保険労務士の行動指針:
          * 労務と保険以外の話題には回答できないと丁寧に伝えてください。
          `
        },
        ...messages,
        { role: 'user', content: userMessage }
      ]
    })
  };

  const response = UrlFetchApp.fetch('https://api.openai.com/v1/chat/completions', requestOptions);
  const responseText = response.getContentText();
  const json = JSON.parse(responseText);
  const text = json.choices[0].message.content.trim();

  sheet.appendRow([new Date(), 'assistant', text]);

  reply(userId, replyToken, text, url);
}

function reply(userId, replyToken, text, url) {
  UrlFetchApp.fetch(url, {
    headers: {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + LINE_ACCESS_TOKEN,
    },
    method: 'post',
    payload: JSON.stringify({
      replyToken: replyToken,
      messages: [{ type: 'text', text: text }]
    })
  });
}

function getOrCreateSheet(userId) {
  const spreadsheet = SpreadsheetApp.openById(SPREADSHEET_ID);
  let sheet = spreadsheet.getSheetByName(userId);
  if (sheet) {
    return sheet;
  } else {
    return spreadsheet.insertSheet(userId);
  }
}

このソースをGoogle Apps Script(GAS)にペーストしてデプロイしてください。詳しい設定は、第2回(構築編)を参照してください。

1日のトーク上限まで会話を続けた結果、以下の通りの解答が返ってきました。この際、OpenAI へのリクエストは行われていません。

使用してみた感想

制作したLINE Botを使用してみた感想です。

回答の正確性

回答に関しては、必ずしも正確な回答が返ってくるとは限りませんでした。
しかし、解答の根拠となる法律は合っていますので、その法律を自分で調べさえすればいいので、問題点解決のための一手間は省けるのではないかと思います。

1日のトーク数と会話履歴の上限設定

この機能を実装することにより、OpenAI APIトークンの消費を抑えることが可能となりました。会話履歴の上限では、労務問題を扱っているので、解答の文字数が多くなりがちです。会話を続けることで、解答までのレスポンス時間が多くなることもありました。

以上が感想です。
ロールプレイさせる人物やテーマによりカスタマイズしてみてください。


この記事が気に入ったらサポートをしてみませんか?