見出し画像

ChatGPTのプロンプト同士がスプレッドシート上で会話するスクリプト

はじめに


近年、AI技術の進化により、自然言語処理がますます人間のような対話を実現できるようになっています。その中で、OpenAIのChatGPTは、様々な会話を行うことができるAIとして注目を集めています。今回は、異なった設定のChatGPT同士が会話するChatGPT-3.5を用いたスクリプトをご紹介します。

注意事項

  • このスクリプトは、OpenAI APIを利用しているため、事前にAPIキーが必要です。APIキーは、OpenAIのウェブサイトから取得できます。

  • このスクリプトはインターフェースとしてGoogle SpreadsheetとGoogle Apps Scriptを利用しているため事前にGoogleアカウントが必要です。

  • 過去ログが文字数を超えてしまう現象を確認したため5月1日に対策を入れました。

  • このスクリプトは自由に使っていただいて構いません。使ってみて役にたったと思った時点でサポートいただけると有り難いです。

利用シーン

このスクリプトを使うことで、例えば以下のような場面で活用が可能です。

お気に入りのキャラクター同士の会話
 貴方が今までに作ったキャラクター設定をプロンプトを割り当てることで、キャラクター同士の会話を楽しめます。

筆者のお気に入りのボット達

ディベートや意見交換
異なる立場や視点を持つプロンプトを設定することで、ディベートや意見交換のシミュレーションが行えます。

ボット達による議論例

問答応答の改善
それぞれのプロンプトがお互いの発言を参照しながら会話を進めることで、より自然でスムーズな問答応答を生成することができます。

会話が壊れました

スクリプトの要概

スクリプトは以下のような構成になっています。

startConversation関数
スプレッドシートから設定値を読み込み、会話を開始する。

haveConversation関数
会話を続けるための再帰関数。設定された回数だけ会話を続ける。

countTokens関数
メッセージ履歴のトークン数を計算する。

getChatGPTResponse関数
OpenAI APIを呼び出して、次の会話を取得する。

スクリプトは以下です。次の章からスクリプトの設置手順について説明します。

//5月1日版
const props = PropertiesService.getScriptProperties();
const OPENAI_APIKEY = props.getProperty("OPENAI_APIKEY");
const MAX_TOKENS = 2048; // トークン数の上限を設定
const COUNT = 15; //最大ターン回数

//会話をスタートさせる関数
function startConversation() {
  const configSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Config");
  const outputSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Output");

  const botConfig = configSheet.getRange("A1:B").getValues().filter((row) => row[0] && row[1]);

  // ConfigシートからinitialMessageを読み込む
  const initialMessageRange = outputSheet.getRange("B1");
  const initialMessage = initialMessageRange.getValue();

  haveConversation(outputSheet, botConfig, [{ role: "user", content: initialMessage }], COUNT);
}

//会話を継続させる再帰関数
function haveConversation(sheet, botConfig, messageHistory, turns) {
  if (turns <= 0) {
    return;
  }

  let currentMessageHistory = messageHistory;
  for (let botIndex = 0; botIndex < botConfig.length; botIndex++) {
    const botName = botConfig[botIndex][0];
    const botSystemPrompt = botConfig[botIndex][1];

    // トークン数が上限を超える場合、古いメッセージを削除
    while (countTokens([...currentMessageHistory, { role: "system", content: botSystemPrompt }]) > MAX_TOKENS) {
      currentMessageHistory.shift();
    }

    // systemPromptを適切な場所に挿入
    const newMessageHistory = currentMessageHistory;
    const botResponse = getChatGPTResponse(botSystemPrompt, newMessageHistory, botIndex);

    // トークン数が上限を超える場合、古いメッセージを削除
    while (countTokens([...newMessageHistory, { role: "assistant", content: botResponse }]) > MAX_TOKENS) {
      newMessageHistory.shift();
    }

    sheet.appendRow([botName, botResponse]);

    // Update messageHistory with the bot's response
    currentMessageHistory.push({ role: "user", content: botResponse });

    if (currentMessageHistory.length > 1) {
      // Swap the roles of all previous messages
      currentMessageHistory = currentMessageHistory.slice(0, -1).map((msg) => {
        return {
          role: msg.role === "user" ? "assistant" : "user",
          content: msg.content,
        };
      }).concat(currentMessageHistory.slice(-1));
    }

    Logger.log("Bot Index: %s, Message History: %s, Bot Response: %s", botIndex, JSON.stringify(currentMessageHistory), botResponse);
  }

  // Call haveConversation with the updated messageHistory
  haveConversation(sheet, botConfig, currentMessageHistory, turns - 1);
}



// トークン数の計算関数
function countTokens(messageHistory) {
  return messageHistory
    .map((msg) => msg.content)
    .join("")
    .length;
}

//ChatGPT呼出関数
function getChatGPTResponse(systemPrompt, messageHistory, botIndex) {
  const apiKey = OPENAI_APIKEY;
  const url = "https://api.openai.com/v1/chat/completions";

  const requestOptions = {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: "Bearer " + apiKey,
    },
    payload: JSON.stringify({
      model: "gpt-3.5-turbo", // Use the GPT-3.5 model
      presence_penalty : 0,
      messages: [
        { role: "system", content: systemPrompt },
        ...messageHistory,
      ],
    }),
  };

  const response = UrlFetchApp.fetch(url, requestOptions);
  const jsonResponse = JSON.parse(response.getContentText());
  const chatResponse = jsonResponse.choices[0].message.content;

  return chatResponse.trim();
}

スプレッドシートの作成

Google スプレッドシートを開き、新規スプレッドシートを作成します。

作成したスプレッドシートに、2つのシートを追加します。それぞれのシートの名前は、「Config」と「Output」としてください。

半角で大文字小文字を守って設定してください。

Configシートの設定

Configシートに移動し、A列にそれぞれのプロンプトに関連する名前(例:Bot1, Bot2)を記入します。これらの名前は、後でOutputシートに表示される際に使われます。
同じ行のB列に、それぞれのプロンプトが持つシステムプロンプトを記入します。システムプロンプトは、それぞれのプロンプトが会話に参加する際の基本情報や役割を表します。

Configシートの記入例

Outputシートの設定

Outputシートに移動し、B1セルに議題となるテーマを記入してください。これが会話のトリガーとなります。
これで、スプレッドシートの準備が完了です。


OutPutシートの記入例

スクリプトの設置

Google スプレッドシートを開き、上部メニューの「拡張機能」から「Apps Script」を選択し、新しいプロジェクトを作成します。

スクリプトエディタが開いたら、コード.gsファイルに先程提示したスクリプトをコピー&ペーストして保存ボタンを押します。

スクリプトエディタの左のメニューから「プロジェクトの設定」を選択します。

一番下までスクロールし「スクリプトプロパティを追加」を選択します。

「プロパティ」に "OPENAI_APIKEY" と入力し、値にはOpenAIのAPIキーを入力します。設定が終わったら、「スクリプト プロパティを保存」ボタンを押します。

スクリプトエディタの左のメニューから「エディタ」を選択します。

スクリプトエディタ上部の「デバッグ」と「実行ログ」の間の文字列が「startConversation」と表示されていることを確認してから「実行」を押して実行します。

「承認が必要です」と表示された場合は「権限を確認」を押します。

スクリプトの実行が1回目の場合に表示されます。


自分のGoogleアカウントを選択します。

スクリプトの実行が1回目の場合に表示されます。

左下の「詳細」を選択します。

スクリプトの実行が1回目の場合に表示されます。


さらに下に表示される「xxx(安全ではないページ)に移動」を選択します。

スクリプトの実行が1回目の場合に表示されます。

「許可」を押します。

スクリプトの実行が1回目の場合に表示されます。


これにより、スプレッドシートの「Output」シートに設定したプロンプトに基づいた会話が生成されます。

戦闘員たちの会話

会話を止める際はスクリプトエディタ上部の「停止」を選択します。
なお、会話はだいたい2レスポンスを1ターン換算で10ターン程で収束してしまうのでスクリプト内のCOUNT変数を小さくすることで停止をしなくても勝手に停止します。Google Apps Scriptのスクリプト最大実行時間は6分なため、COUNT値を大幅に増やしたとしても6分で停止します。

二回目を始めるときはスプレッドシートの「Output」シートの会話を削除してスクリプトエディタの「実行」を押してください。

まとめ


2つのプロンプトが相互に会話するChatGPTスクリプトは、スプレッドシートとGoogle Apps Scriptを活用して簡単に実現できる方法です。さまざまなシーンでの活用が期待されるこの方法は、AI技術を用いたコンテンツ生成や意見交換などに新たな可能性をもたらします。特に、複数のキャラクターや視点が関与するシナリオにおいては、このスクリプトを活用することで効率的かつ自然な対話の生成が期待できます。

今回紹介したスクリプトは、すでに用意されているため、誰でも簡単に試すことができます。ぜひ、あなた自身のプロジェクトや研究において、このスクリプトを活用して、新しい形の対話生成を体験してみてください。AI技術の進化により、今後もさらなる応用例や発展が期待されますので、最新の情報にも注目しておくことが重要です。

改良版スクリプトの配信について

改良版スクリプトの配信を始めました。こちらは有料記事として掲載しています。これ以上の機能が不要な方、自身で改良が可能な方は参照不要です。


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