STERFIELD

2023/06/30

chatGPTとGASで議事録要約ツールを作ってみた(長文対応)

chatGPTとGASで議事録要約ツールを作ってみた(長文対応)

はじめに

近年、テクノロジーの進歩により、自然言語処理の分野でも驚くべき進歩がありました。その中でも、OpenAIのChatGPTは、会話を自然な形で行い、言語モデリングの能力を備えた最新の言語モデルです。また、Google Apps Script(GAS)は、G Suiteの一部として提供されるクラウドベースのスクリプト環境です。本記事では、chatGPTとGASを組み合わせて、議事録要約ツールを作成する方法について紹介します。特に、長文に対応する機能を追加する方法に焦点を当てます。

前回は、Makeというノーコードツールを使って、chatworkにまで送信する流れを作りましたが、トークン数の制限があり、長文に対応ができないという課題が残っておりましたが、今回はその課題を克服した改良版になります。

https://sterfield.co.jp/blog/18142/

chatGPTの導入

まず、chatGPTを使って自然言語処理のパワーを手に入れましょう。OpenAIのAPIを使用すると、chatGPTを簡単に利用することができます。APIキーを取得し、適切なエンドポイントに接続します。Pythonや他のプログラミング言語を使用して、APIとのインタラクションを設定しましょう。

今回は冒頭にある通り、Google Apps Script(GAS)とモデルはgpt-3.5-turboで作成しました。

GASでの要約機能の作成

GASを使用することで、Googleドキュメントやスプレッドシートなど、G Suiteのさまざまなアプリケーションを拡張することができます。GASエディタを開き、新しいプロジェクトを作成しましょう。次に、chatGPT APIとの通信を設定するために必要なコードを追加します。これにより、議事録のテキストをchatGPTに送信し、要約を取得できるようになります。

GASのコードそのものもChatGPTに書いてもらいました。 また、プロントはPROMPTYさんの【プロンプト解説】ChatGPTで要約を作成する方法という記事を参考にさせて頂きました。
一番最初の指示文は以下です。最終形態の内容とは異なります。

書いてもらったコードをスプレッドシート>拡張機能>Apps Scriptで開いたページのコード.gs欄にベタっと貼り付けます。

その後、Apps Scriptのまま、▶︎実行を押すとスクリプトが動作し、不完全な場合、エラーが返ってくるので、そのエラーコードをChatGPTに貼り付けると修正コードを返してくれるという具合で何往復も行いました。

この工程はプロンプトエンジニアリングといって良いのでしょうか。

長文対応の実装

議事録は通常、長い文章で構成されることがあります。要約ツールをより実用的にするためには、長文にも対応する必要があります。chatGPTにはテキストのトークン制約があるため、長い文章を一度に送信することはできません。しかし、GASを使用して長文を複数のパートに分割し、chatGPTに渡すことができます。それぞれのパートの要約を取得し、最終的な要約として結合します。

以下が1024トークンごとに分割する部分のスクリプトです。

  // 1024トークンごとにテキストを分割します。
  var tokens = Math.ceil(cellContent.length / 1024);
  for (var i = 0; i < tokens; i++) {
    var part = cellContent.slice(i * 1024, (i + 1) * 1024);

    // partが空ではないことを確認します
    if (part.trim() != '') {
      var summary = sendToChatGPT(part);
      summaries += summary + "\n";
    }
  }

ユーザーインターフェースの作成

ツールを使いやすくするために、GASを使用して独自のユーザーインターフェース(UI)を作成しましょう。UIを作成するには、GASのHTMLサービスを利用します。UIにはテキストエリアやボタンを配置し、ユーザーが議事録を入力し、要約を取得できるようにします。

上図のようにメニューバーに「議事録を要約」というメニューを出すためのスクリプトです。

// スプレッドシートが開かれたときにメニューボタンを作成します。
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('議事録を要約')
    .addItem('スクリプトを実行する', 'summarizeMinutes')
    .addToUi();
}

今回できたGASの共有

上記を全て盛り込んで試行錯誤の上完成したGASの全容は以下になります。 ご利用にあたって以下の項目は各自置き換えてください。

  • YOUR_OPENAI_API_KEY→あなたのOpenAIのAPIキーを設定してください
  • シート1→ご利用されるシート名に合わせてください。
  • A2→元のテキストを置くセルに合わせてください。
  • B2→要約後のテキストを置きたいセルに合わせてください。
  • 'max_tokens': 100, → おおよそ400文字程度に要約するために設定

このGASのご利用により何らかの損害が生じても当社は, 一切損害を賠償しません。自己責任の元、ご利用ください。

// まず最初に、OpenAIのAPIキーを設定します。
var openaiApiKey = 'YOUR_OPENAI_API_KEY; // あなたのOpenAIのAPIキーを設定してください

// スプレッドシートが開かれたときにメニューボタンを作成します。
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('議事録を要約')
    .addItem('スクリプトを実行する', 'summarizeMinutes')
    .addToUi();
}

function summarizeMinutes() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');
  var cellContent = sheet.getRange('A2').getValue();
  var summaries = '';

  // 1024トークンごとにテキストを分割します。
  var tokens = Math.ceil(cellContent.length / 1024);
  for (var i = 0; i < tokens; i++) {
    var part = cellContent.slice(i * 1024, (i + 1) * 1024);

    // partが空ではないことを確認します
    if (part.trim() != '') {
      var summary = sendToChatGPT(part);
      summaries += summary + "\n";
    }
  }

  // 結果をB2のセルに記載します。
  sheet.getRange('B2').setValue(summaries);
}

function sendToChatGPT(text) {
  var url = 'https://api.openai.com/v1/chat/completions';
  var payload = {
    'model': 'gpt-3.5-turbo',
    'messages': [{
      'role': 'system',
      'content': 'あなたはプロの編集者です。以下の制約条件に従って、入力する文章を要約してください。\n#制約条件\n・重要なキーワードを取りこぼさない。\n・文章の意味を変更しない。\n・架空の表現や言葉を使用しない。\n・文章中の数値には変更を加えない。'
    }, {
      'role': 'user',
      'content': text
    }],
    'max_tokens': 100, // おおよそ400文字程度に要約するために設定
    'temperature': 0.5
  };
  var options = {
    'method' : 'post',
    'headers': {
      'Authorization': 'Bearer ' + openaiApiKey,
      'Content-Type': 'application/json'
    },
    'payload' : JSON.stringify(payload)
  };
  var response = UrlFetchApp.fetch(url, options);
  var data = JSON.parse(response.getContentText());
  return data['choices'][0]['message']['content'].trim();
}

テスト結果

青空文庫で著作権の切れた小説を探し、芥川龍之介の羅生門が6000字超だったので、試した結果が以下になります。 トークン数の壁を打ち破り、500文字超に要約ができています。 また、実際の1時間程度の会議を音声入力にて文字起こしした17,000文字程度も要約が動作しましたので実用的な範囲内はクリアしていると思われます。

最大、何文字まで出来るかの検証は行っておりませんが、一回の処理に6分間程度の制限があるようなので、それを超える処理となった場合はエラーとなるでしょう。

気になるAPI価格

前回の記事から期間が空いて、無料期間は過ぎていたため、課金しました。 試行錯誤中に20〜30回程度は、スクリプトを実行しましたが下記のような結果で、1ドルにも満たない金額でしたのでご参考ください。

工夫ポイント

トークン数をギリギリ攻める設定をすると引っかかってしまうので、1024トークンごとに区切るようにした。これは上限2048トークンの半分になります。

まとめ

chatGPTとGASを組み合わせて議事録要約ツールを作成することは、簡単かつ効果的な方法です。chatGPTの強力な自然言語処理能力を活用しながら、GASを使用して長文にも対応することができます。これにより、議事録を手早く要約し、重要な情報を抽出することができます。ぜひ、この記事を参考にして、自分自身の議事録要約ツールを作成してみてください。

スクリプトを全てchatGPTに書いてもらい、その内容もchatGPTのAPIに送って文章を要約してもらうというもので、ブログ記事の本文のベースもchatGPTに聞き、アイキャッチ画像も画像生成AIで作りました。つまり、この記事はほぼ生成AIで構成されています。

Author Profile

著者近影

YUJI MEZAKI代表取締役副社長

代表取締役副社長をやっています。 越境ECとWebマーケの営業担当しています。 なんでもカリカリにチューニングして生産性あげるのが好きで勉強したビジネスフレームワークの記事多め。 趣味はPC自作で会社のWindowsデスクトップはほぼ自分が組みました。 1985年生/2008年早大卒/

SHARE

合わせて読みたい