この記事では、GoogleスプレッドシートでChatGPT風のやりとりができるツールの作り方を紹介します。
ツールのポイントは、一問一答ではなく「会話履歴を保持したチャットができる」ことです。また、ChatGPTと同じ言語モデルである「GPT3.5」を使用するので、応答の内容もChatGPTと同様です。
ツールのイメージは以下の画像のとおりです。
①GPTに与える役割を入力
②A列に質問を入力してGAS実行
③B列に応答が返ってくる
→②③の繰り返しで、スプレッドシート上で会話が続けられます。
それでは、ツールの作り方を紹介していきます。
Contents
【事前準備】OpenAIのAPIキーの取得
事前準備として、ChatGPTの開発元であるOpenAIのAPIキーを取得する必要があります。まだ取得していない場合は、手順がわかりやすく記載されている以下のサイトを参照してAPIキーを取得してください。
【2023年版】OpenAIのAPIキー発行手順!ChatGPTや文章生成AI、画像生成AIを利用可能
会話履歴を保持できる「Chat」モデルを使う
スプレッドシート上でChatGPTライクな会話をするためには、OpenAIのAPIの「Chat」モデルを使用します。
Chatモデルは、会話形式のメッセージに基づいて新たな応答を返します。一問一答形式ではなく、会話履歴を保持しながら応答してくれる、まさにChatGPT風なやりとりが可能なモデルです。
公式ドキュメント:
https://platform.openai.com/docs/api-reference/chat
https://platform.openai.com/docs/guides/chat
Chatモデルの会話の流れ
Chatモデルで会話をするためには、APIリクエストのプログラムの書き方に工夫が必要です。Chatモデルが自動的に会話履歴を保持してくれるわけではなく、ユーザー自身が「これまでの会話履歴を付けたうえで、新しい質問を送る」という仕組みです。
具体的には、以下のようなリクエスト&レスポンスの流れを実装します。
【1往復目】
「役割」+「質問1」を送信する
→「応答1」が返ってくる
【2往復目】
「役割」+「質問1」+「応答1」に加えて「質問2」を送信する
→送信された会話履歴をもとに「応答2」が返ってくる
【3往復目】
「役割」+「質問1」+「応答1」+「質問2」+「応答2」に加えて「質問3」を送信する
→送信された会話履歴をもとに「応答3」が返ってくる
Chatモデルは、メッセージにroleプロパティがあります。roleには以下の3つの値があります。
- system:GPTの役割を指定(例:あなたは一流のシェフです)
- user:ユーザーの質問
- assistant:GPTの応答
APIリクエスト時のデータのメッセージの作り方の説明です。まず1回目のリクエストでは、オブジェクトの中身に「役割」と「1回目の質問」を設定します。
1 2 3 4 |
[ { role: 'system', content: 'あなたは一流のシェフです。' }, //役割(固定) { role: 'user', content: '30分以内で作れる夕食のメニューを考えて。' } //1回目の質問 ] |
2回目以降のリクエストでは、「役割」は固定で、これまでの会話履歴をオブジェクトに追加していきます。
具体的には、「1回目の質問」で返ってきた応答文をオブジェクトに追加したうえで「2回目の質問」をmessagesの末尾に加えます。
1 2 3 4 5 6 7 8 |
[ { role: 'system', content: 'あなたは一流のシェフです。' }, //役割(固定) { role: 'user', content: '30分以内で作れる夕食のメニューを考えて。' }, //1回目の質問 { role: 'assistant', content: 'はい、30分以内で作れる夕食のメニューを以下に提案します。(省略)' }, //1回目の質問の応答 { role: 'user', content: '提案メニューの中の「鮭の白ワイン蒸し」の作り方を詳しく教えて。' } //2回目の質問 ] |
前述のとおり、自動で会話履歴を保持してくれるわけではないので、ユーザー自身でオブジェクト形式の会話履歴を作る必要があります。
それでは、実際にスプレッドシート上でツール化していきましょう。
スプレッドシート上でChatGPTライクな会話を実現する
スプレッドシートを用意します。新規作成のスプレッドシートでも、すでに業務等で使っている既存のスプレッドシートでも構いません。
スプレッドシートに入力欄を用意する
スプレッドシートに以下の3種類の入力欄を用意します。
- B1セル:この会話でのGPTの役割を設定する(任意)
- A列(A4セル以降):質問を入力する欄
- B列(B4セル以降):応答を出力する欄
GASでChatモデルAPIにリクエストする
OpenAIのChatモデルのAPIにリクエストを送るコードです。変数API_KEY
は各自のAPIキーを設定してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
function chat() { const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("チャット"); if (sheet.getRange("A4").getValue() == "") { Browser.msgBox("質問が入力されていません。A4セルに最初の質問を入力してください。"); return; } const headerRow = 3, answerCol = 2; //会話履歴の取得 const lastRow = sheet.getRange(headerRow, 1).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow(); const values = sheet.getRange(headerRow + 1, 1, lastRow - headerRow, answerCol).getValues(); //GPTに与える役割と送信用オブジェクトの作成 const system = sheet.getRange("B1").getValue(); //役割 const messages = []; //API送信用 if (system !== "") { messages.push({ role: "system", content: system }); } for (const value of values) { messages.push({ role: "user", content: value[0] }); if (value[1] !== "") { messages.push({ role: "assistant", content: value[1] }); } } const answer = requestToGPT_(messages); sheet.getRange(headerRow + values.length, answerCol).setValue(answer); } function requestToGPT_(messages) { //Chatモデルのエンドポイント const url = "https://api.openai.com/v1/chat/completions"; const payload = { model: "gpt-3.5-turbo", messages: messages }; const options = { contentType: "application/json", headers: { Authorization: "Bearer " + API_KEY }, payload: JSON.stringify(payload), muteHttpExceptions: true }; const response = JSON.parse(UrlFetchApp.fetch(url, options).getContentText()); const content = response.choices[0].message.content; return content; } |
スクリプト使用時の注意点
上記のスクリプトを使用する際は、以下の注意事項をご確認ください。
①エラー処理
この記事で紹介するスクリプトは簡易的なため、エラー処理は最低限しか含めていません。例えば、途中に空行がある(例:A4セルの次にA7セルに質問が入力されている)ような場合は想定していません。必要に応じてコードを書き換えて使用してください。
②会話の文字数制限
使用モデル「gpt-3.5-turbo」のMAX TOKENSは4,096トークンです。日本語はざっくり1文字1トークンなので、ひとつのChatでやりとり可能な文字数は約4,000文字です。
「ひとつのChat」というのは、1往復のやりとりではなく、すべての会話履歴の合計です。例えば、1回の質問が50文字+応答が350文字=計400文字とすると、約10往復のやりとりができる計算になります。
(GPTの応答文字数はランダムなので、あくまで目安にお考えください)
スプレッドシート上で質問を入力してGASを実行する
スプレッドシートのA列に質問を入力し、関数chatを実行すると、B列に応答が返ってきます。スプレッドシート上からスクリプトを実行しやすいよう「カスタムメニュー」を作ったり、図形描画でボタンを作って「スクリプトを割り当て」したりするとよいでしょう。
1 2 3 4 5 6 7 8 9 |
function onOpen() { const myMenu = [ { name: "実行", functionName: "chat" } ]; SpreadsheetApp.getActiveSpreadsheet().addMenu("ChatGPT", myMenu); //メニューを追加 } |
スプレッドシート上でChatGPTを再現することで、会話履歴を記録しておくことができ、周囲の人と共有することも可能です。ぜひ、GASとスプレッドシートを活用してChatGPTを再現してみてくださいね。