こんにちは、GMOメイクショップ SREグループの金井です。
私自身、常日頃から様々な情報に触れ、知識を蓄えることに努めてきました。例えば、従来のRSSリーダーやニュースアグリゲーターは情報の『インプット』には優れていましたが、能動的な『アウトプット』を促し、学習効果を測定する仕組みがありませんでした。また、多忙な業務の中で定期的に学習時間を確保し、その効果を可視化することも課題でした。このギャップを埋めるため、私たち自動化された学習サイクルの構築に着目し、GASをハブとしたシステムの開発に至りました。
この「インプットした情報がなかなか定着しない」という課題を解決するため、そして、より効率的かつ楽しく学習を習慣化できる仕組みを求めて開発したのが、今回ご紹介する「自動ニュースクイズボット」です。本記事では、最新のEC業界ニュースを自動で取得し、クイズ形式に変換してSlackで出題するこのシステムの全体像や実装の工夫、実際の運用で得られた知見を詳しく解説します。
なぜこの仕組みを作ったのか
知識の定着には「知る → やってみる → できる」というステップがあると考えています。
- 知る: ニュースを見て話題を把握する(Perplexity API)
- やってみる: 内容を咀嚼し、クイズ形式でアウトプットする(ChatGPT API, Google Forms)
- できる: 実際に知識として活用できる
この学習サイクルを自動化し、知識レベルを底上げするため、GASをハブに各種サービスを連携させたボットを構築しました。
システムの概要と全体フロー
この自動ニュースクイズボットは、主に「最新ニュースの収集」「クイズ化」「Slackでの配信」という3つのフェーズで構成されており、これらのプロセスはGoogle Apps Script(GAS)を中核として完全に自動化されています。ここでは、システムを構成する主要な技術要素と、それらがどのように連携して機能しているのかを解説します。 まずは、本システムで利用している技術・サービスとその役割を一覧にまとめました。
システム概要
| 技術・サービス | 役割・用途 |
|---|---|
| Google Apps Script | 全体のロジック・自動化の基盤 |
| Google Sheets | プロンプト・問題データ・履歴の管理 |
| Perplexity API | 最新ニュースの検索と要約 |
| OpenAI API (ChatGPT) | クイズ問題の自動生成 |
| Google Forms | クイズの出題と自動採点 |
| Slack Webhook | 各種通知と連携のハブ |
全体フロー図

機能一覧
| 機能カテゴリ | 概要 |
|---|---|
| プロンプト管理 | スプレッドシートからお題を取得し、ニュース以外のトピックも自由に指定可能 |
| ニュース・情報取得 | Perplexity APIで最新ニュースや指定テーマの要約を自動取得 |
| Slack通知 | 取得データやフォームURLをSlackに自動通知 |
| データ保存 | 取得したニュースデータを日付ごとのシートに記録 |
| 問題生成 | ChatGPT APIで4択クイズ問題を自動生成 |
| 問題保存 | 生成した問題を日付ごとの「_question」シートに保存 |
| Googleフォーム作成 | テンプレートをコピーし、問題のみを自動追加 |
| フォームURL通知 | 作成したフォームのURLをSlackに通知 |
| トリガー・自動実行 | 時間主導型トリガーで定期実行可能 |
| エラーハンドリング | JSON解析エラー時にリトライ・ログ出力 |
| セキュリティ | APIキー等の機密情報はスクリプトプロパティで管理 |
実装のハイライト(コード抜粋付き解説)
1. プロンプトシートからお題を取得
プロンプトをGASスクリプトで再デプロイすることなく自由に変更できるようにするために、Google スプレッドシート上にプロンプトを用意し、 それにより、ニュース以外のトピックや複数のお題を簡単に管理・編集でき、柔軟なクイズ生成が可能になります。
例えば、スプレッドシートには以下のようなお題と、Perplexity APIへの出力形式に関する指示(conditions)を結合したプロンプトを設定しています。
あなたは、日本のEC業界に詳しいマーケティングの専門家です。
以下の条件に基づいて、2025年06月22日~2025年06月28日に日本で注目されたEC業界のトピックスを10件挙げてください。
条件:
日本国内のEC業界に限定してください。
ECサイト運営者やプラットフォーム提供者にとって有益な内容を優先してください。
消費者行動や市場トレンド、技術革新、法規制など、幅広い観点を含めてください。
最新の情報から出力するようにお願いします。
出力に関して:
必ず、解答のみ記載し、前置きや説明文は不要です。
解答は、JavaScript オブジェクトリテラルでかつ、日本語でお願いします。
解答例を参考にしてください。
解答例:
{
"title": "AIを活用した新しい消費者行動分析ツールの登場",
"description": "AIを活用した新しい消費者行動分析ツールが日本のEC市場に登場しました。このツールは、リアルタイムで消費者のオンライン行動を追跡し、購入意欲や嗜好を高精度で予測します。これにより、ECサイト運営者はより効果的なマーケティング戦略を立案することが可能になります。特に、個々の消費者に合わせたパーソナライズされた広告配信や、リコメンデーションエンジンの最適化に大きな効果を発揮します。また、AIの導入は業務効率を大幅に向上させるため、人手不足に悩む企業にもメリットがあります。初期導入コストはかかるものの、長期的にはROIの向上が期待できるため、多くの企業が導入を検討しています。",
"url:" "https://ecommerce-ai-tools.jp/2025-launch",
"date": 2025年01月10日
}
このプロンプトは、以下の getDataFromPromptSheet 関数によってスプレッドシートから取得されます。
// 「プロンプト」シートのA列(2行目以降)の値を取得し、改行区切りの文字列として返す function getDataFromPromptSheet() { try { const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(SPREADSHEET_PROMPT); if (!sheet) { throw new Error("指定されたシートが見つかりません。"); } const lastRow = sheet.getLastRow(); if (lastRow < 2) { throw new Error("シートに有効なデータがありません。"); } return sheet.getRange(2, 1, lastRow - 1, 1) .getValues() .map(row => row[0]) .join("\n"); } catch (e) { logError("getDataFromPromptSheetエラー", e); return ""; } }
2. Perplexity APIでニュース検索
時事性の高い情報や最新ニュースの要約を正確かつ信頼性高くクイズ化するために、本システムではPerplexity APIを利用しています。 Perplexityは一般的な大規模言語モデル(LLM)とは異なり、リアルタイムでインターネット検索を行い、信頼できるソースを明示した最新情報を返すのが特長です。この特長は、私たちが知識を定着させる上で非常に重要でした。なぜなら、最新かつ正確な情報に基づいたクイズでなければ、学習効果が半減してしまうからです。 Perplexityを活用することで、変化が激しい分野のトレンドや新しい出来事にも柔軟に対応し、情報の鮮度と信頼性を両立したクイズ生成が可能となり、結果として質の高いインプットから深い知識定着へと繋げられるようになりました。
function callPerplexity(prompt) { const apiKey = getScriptProperty('PERPLEXITY_API_KEY'); // ※APIキーはセキュリティのため、スクリプトプロパティから取得しています。 const url = 'https://api.perplexity.ai/chat/completions'; // Perplexity APIのエンドポイントURL const conditions = ` 出力に関して: 必ず、解答のみ記載し、前置きや説明文は不要です。 解答は、JavaScript オブジェクトリテラルでかつ、日本語でお願いします。 解答例を参考にしてください。 解答例 { "title": "AIを活用した新しい消費者行動分析ツールの登場", "description": "AIを活用した新しい消費者行動分析ツールが日本のEC市場に登場しました。このツールは、リアルタイムで消費者のオンライン行動を追跡し、購入意欲や嗜好を高精度で予測します。これにより、ECサイト運営者はより効果的なマーケティング戦略を立案することが可能になります。特に、個々の消費者に合わせたパーソナライズされた広告配信や、リコメンデーションエンジンの最適化に大きな効果を発揮します。また、AIの導入は業務効率を大幅に向上させるため、人手不足に悩む企業にもメリットがあります。初期導入コストはかかるものの、長期的にはROIの向上が期待できるため、多くの企業が導入を検討しています。", "url": "https://ecommerce-ai-tools.jp/2025-launch", "date": "2025年01月10日" } `; prompt = prompt + conditions // ここで「お題」と「条件」を結合 const payload = { model: 'sonar', messages: [{ role: "user", content: prompt }] }; const options = { method: 'post', contentType: 'application/json', headers: { 'Authorization': 'Bearer ' + apiKey }, payload: JSON.stringify(payload), muteHttpExceptions: true }; try { const response = UrlFetchApp.fetch(url, options); const result = JSON.parse(response.getContentText()); const content = result.choices?.[0]?.message?.content || ""; const match = content.match(/```javascript\s*([\s\S]*?)\s*```/); return match ? match[1].trim() : content.trim(); } catch (e) { logError("Perplexity API呼び出しエラー", e); } return ''; }
3. ChatGPT APIでクイズ問題を生成
Perplexity APIで取得したニュースデータは、そのままでは学習に最適なクイズ形式ではありません。そこで、このニュースデータを元に、ChatGPT APIを活用して自動でクイズ問題を作成します。ChatGPT APIから返されるクイズ問題の回答はJSON文字列として受け取り、JavaScriptのJSON.parse()でオブジェクトに変換しています。 しかし、AIの出力は必ずしも厳密なJSON形式で出力されるとは限らず、パース時にエラーが発生することがあります。そこで、try-catchブロックを用いて安全にパース処理を行い、エラー時には最大2回まで再試行する仕組みを実装しています。
/** ChatGPTに質問を送り、回答を取得する関数 */ function askChatGPT(prompt) { Logger.log("ChatGPTへのプロンプト:\n" + prompt); const apiKey = getScriptProperty('OPENAI_API_KEY');// ※APIキーはセキュリティのため、スクリプトプロパティから取得しています。 if (!apiKey) { Logger.log('OpenAI API Key is not set in script properties.'); return ''; } const url = "https://api.openai.com/v1/chat/completions"; const data = { model: "gpt-4o", messages: [ {role: "system", content: "You are an excellent mentalist."}, {role: "user", content: prompt} ], max_tokens: 1000, temperature: 0.7 }; const options = { method: "post", contentType: "application/json", headers: { "Authorization": "Bearer " + apiKey }, payload: JSON.stringify(data) }; try { var response = UrlFetchApp.fetch(url, options); if (response.getResponseCode() !== 200) { Logger.log('Error from OpenAI API: ' + response.getContentText()); return ''; } var result = JSON.parse(response.getContentText()); return result.choices[0].message.content.replace(/```javascript|```/g, ''); } catch (e) { logError('ChatGPT API呼び出しエラー', e); return ''; } } function generateQuestionAndAnswer(data, retryCount = 0) { const prompt = createQuestionPrompt(data); const result = askChatGPT(prompt); try { return JSON.parse(result); } catch (error) { if (retryCount < 2) { Logger.log(`JSON解析エラーが発生しました。リトライ回数: ${retryCount + 1}`); return generateQuestionAndAnswer(data, retryCount + 1); } else { throw new Error('JSONの解析に失敗しました。'); } } }
4. Google Form 作成(採点設定の保持)
Googleフォームには「このフォームをテストにする(=テストモード/クイズモード)」という設定があります。これを有効にすることで、次のような機能が使えるようになります。 - 自動採点 - 点数配分 - 正解・不正解のフィードバック表示 - 回答後のスコア表示
しかし、Google Apps Script ではこの“テストモード/クイズモード”の設定をスクリプトから変更することができません。 そのため、フォームをスクリプトで一から新規作成すると、これらの設定を毎回手動で追加する必要があり、運用面で現実的ではありません。 この課題を解決するため、本プロジェクトでは「設定済みテンプレートフォームを .makeCopy() で複製する」方式を採用しています。これにより以下がそのまま引き継がれます。 - テストモード(クイズモード)の設定 - 設問形式(ラジオボタンなど) - スタイルやテーマ
結果として、手間なく自動採点付きの4択問題フォームを安定運用することが可能になります。
function duplicateTemplateForm() { // 事前にクイズモードや採点設定を済ませておいたテンプレートフォームのIDを指定 // ★この値は、利用するGoogleフォームのIDに置き換えてください。 // 例: '1a2b3c4d5e6f7g8h9i0jklmnopqrstuvw' のようなIDが入ります。 const TEMPLATE_FORM_ID = 'YOUR_TEMPLATE_FORM_ID_HERE'; const templateFile = DriveApp.getFileById(TEMPLATE_FORM_ID); const newFormName = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyyy-MM-dd") + " クイズ"; // 新しいフォーム名に日付とクイズを追加 const copiedFile = templateFile.makeCopy(newFormName); // テンプレートをコピーして新しいフォームを作成 const newForm = FormApp.openById(copiedFile.getId()); // 作成されたフォームオブジェクトを取得 // 回答の保存先を特定のGoogle Sheetsに設定 newForm.setDestination(FormApp.DestinationType.SPREADSHEET, SPREADSHEET_ID); // テンプレートフォームの既存の質問をクリアし、新しい問題を追加できるように準備 return clearFormItems(newForm); }
テンプレートフォームの運用ポイント
- テンプレートフォームには事前に「クイズモードON」「得点設定」「正解設定」などを済ませておく
- フォームのIDはURLから取得可能(例:
https://docs.google.com/forms/d/XXXXXXXXXXXXXXXXXXX/editの「XXX…」部分) - フォルダでテンプレートを管理すると運用が安定し、複数テンプレートも容易に切り替え可能
運用して気づいたこと・工夫点
AIの出力は揺れる
大規模言語モデル(LLM)であるChatGPTやPerplexityなどを活用する際、AIが指示通りに厳密なJSON形式で出力しないケースがしばしば発生します。たとえば「JSON形式のみで出力してください」と明確にプロンプトを与えていても、AIが人間らしく振る舞おうとし、前置きの文章を加えてしまう場合や、構文エラーを含むJSONを返すケースがあります。そこで、JSON パースに失敗した場合は最大 2 回までリトライを行う処理を実装し、安定した運用が可能となりました。情報の鮮度
プロンプトに「取得期間の日付(例:2025年06月15日〜2025年06月21日)」のように具体的な日付形式で明記することで、Perplexityからの出力内容がより鮮度の高い、関連性の強いものになります。問題数の最適化
問題数が10問あると意外と大変。毎日7問程度が集中力的にベスト
応用例:ニュース以外のテーマでの活用可能
ニュース以外にも、書籍、社内ドキュメント、ブログ記事などを対象にプロンプトを調整することで、知識定着や理解度確認に活用できます。 たとえば、以下のようなプロンプトを与えることで、AIが対象内容から重要な情報を抽出し、それを元に設問を作成することが可能となります。
あなたは「tidy first?」に詳しい専門家です。 この書籍の第22,23章で注目されるトピックスを挙げてください。
応用効果と活用パターン
技術書の理解確認:章ごとの要点整理や問題化に活用 記事やブログの内容チェック:特定記事を読んだ後の確認テストとして 教育用途:教材ベースで自動4択問題を生成し、Googleフォームで出題
まとめ
本記事では、Google Apps Script を中核とし、Perplexity API・ChatGPT API・Google Forms・Slack を連携させた「自動ニュースクイズボット」の仕組みを紹介しました。
このシステムは次のような特徴を持っています:
- 情報収集からアウトプット(クイズ化)までの学習サイクルを自動化
- 最新ニュースに対する理解を深めながら、チーム全体の知識レベルを底上げ
- プロンプトを切り替えることで、技術書・社内知識・業界トピックなど多様な用途に対応
- テンプレートフォームの活用により、採点設定を維持した安定運用が可能
AIを組み込んだこうした仕組みは、日々の情報整理やチーム内ナレッジの活用方法を見直すひとつのアプローチとして検討の余地があるかもしれません。 ご自身のユースケースに応じて、参考になれば幸いです。