見出し画像

Google SheetsとGemini APIで問い合わせを自動分類・FAQ候補を出力する方法【Apps Script実装】

Google SheetsとGemini APIで問い合わせを自動分類・FAQ候補を出力する方法【Apps Script実装】


問い合わせ対応を続けていると、Google Sheetsにはデータがどんどん積み上がっていきます。

LINEから届いた質問、Googleフォームからの問い合わせ、メール対応の履歴、営業担当が入力した顧客の要望。

でも現場では、こんな声がよく聞かれます。

「同じ質問が何度も来ている」「担当者によって回答が微妙に違う」「FAQ化したいけど、整理する時間がない」「どの質問をWebやLINEのFAQに載せるべきか分からない」

こうした状態では、問い合わせデータはただの履歴で止まってしまいます。

この記事では、Google Sheets × Apps Script × Gemini API の組み合わせで、問い合わせの自動分類とFAQ候補出力を実装する方法を、実務目線で整理します。

この仕組みで何ができるか

今回作る仕組みは、大きく2段階です。

1つ目は、問い合わせ1件ごとの自動分類。

問い合わせ内容をGemini APIに送り、次の情報を返してもらいます。

  • カテゴリ(商品、料金、納期など)

  • 要約

  • 緊急度

  • 推奨担当部署

  • FAQ化候補かどうか

  • 回答案のたたき台

  • 社内確認が必要な点

2つ目は、蓄積データからのFAQ候補出力。

複数の問い合わせをまとめてGemini APIに渡し、よくある質問を整理します。納期、返品、支払い方法など、カテゴリ別にFAQ候補を自動生成できます。

この仕組みができると、Google Sheetsに溜まった問い合わせ履歴が、FAQやマニュアルの材料として使いやすくなります。

全体構成と流れ

text

問い合わせデータをGoogle Sheetsに蓄積
↓
Apps Scriptで未分類の行を取得
↓
Gemini APIへ問い合わせ内容を送信
↓
Gemini APIが分類・要約・回答案をJSONで返す
↓
Apps Scriptで結果をGoogle Sheetsに書き戻す
↓
複数件をまとめてFAQ候補として別シートに出力
↓
人間が確認して正式FAQ化

ここで大切なのは、Gemini APIに最終回答を任せるのではなく、分類と下書き作成を任せるという設計です。

FAQや返信文は顧客対応の品質に直結します。料金・納期・返品条件・契約内容などは、必ず人間が確認する必要があります。そのため、AIの出力は「下書き」「候補」「要確認」として扱う運用にします。

シート設計|まず2つのシートを用意する

問い合わせ管理シート

シート名は 問い合わせ管理 とします。

列項目A受付日時B問い合わせ元C顧客名D問い合わせ内容E回答内容FステータスGAI分類HAI要約IFAQ化候補J推奨担当部署K緊急度L回答案たたき台M社内確認事項NAI処理済みO処理日時

FAQ候補シート

シート名は FAQ候補 とします。

列項目A作成日時BカテゴリCよくある質問D回答案たたき台E根拠となる問い合わせF社内確認事項G公開可否HステータスI確認担当J最終更新日

AIが分類した結果と、人間が確認した正式回答は分けておくことが重要です。AIの回答案をそのまま正式FAQにしないためのガードとして機能します。

APIキーの保存と基本設定

スクリプトプロパティにAPIキーを保存する

Apps Scriptに直接APIキーを書くのは避けます。スクリプトプロパティで管理します。

javascript

function setProperties() {
  PropertiesService.getScriptProperties().setProperties({
    GEMINI_API_KEY: 'ここにGemini APIキー',
    GEMINI_MODEL: 'gemini-3.5-flash'
  });
}

この関数を最初に一度だけ実行します。モデル名はAPI仕様の更新によって変わる可能性があります。動かない場合は、Google AI StudioやGemini APIの公式ドキュメントで利用可能なモデル名を確認してください。

Gemini APIへ問い合わせ内容を送る実装

問い合わせ1件を分類する関数

javascript

function callGeminiForInquiry_(inquiryText, answerText) {
  const apiKey = PropertiesService.getScriptProperties().getProperty('GEMINI_API_KEY');
  const model = PropertiesService.getScriptProperties().getProperty('GEMINI_MODEL') || 'gemini-3.5-flash';

  const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent`;

  const prompt = `
あなたは企業の問い合わせ対応データを整理する業務アシスタントです。
以下の問い合わせ内容を、Google Sheetsに書き戻しやすいJSON形式で分類してください。

目的:
問い合わせ対応の属人化を減らし、FAQ候補や社内ナレッジとして活用するため。

分類カテゴリ候補:
- 商品について
- 料金について
- 納期について
- 注文・予約について
- 支払いについて
- 返品・交換について
- キャンセルについて
- トラブル対応
- 法人対応
- その他

条件:
- 個人情報は出力しない
- 未確認事項は断定しない
- 回答案は丁寧で簡潔にする
- 社内確認が必要な場合は明記する
- FAQ化に向いているかを判断する
- 料金、納期、返品、契約条件は特に慎重に扱う

問い合わせ内容:
${inquiryText}

既存の回答内容:
${answerText || 'なし'}
`;

  const payload = {
    contents: [{ parts: [{ text: prompt }] }],
    generationConfig: {
      responseFormat: {
        text: {
          mimeType: 'application/json',
          schema: {
            type: 'object',
            properties: {
              category: { type: 'string' },
              summary: { type: 'string' },
              faqCandidate: { type: 'boolean' },
              urgency: { type: 'string' },
              recommendedDepartment: { type: 'string' },
              draftAnswer: { type: 'string' },
              confirmationNeeded: { type: 'array', items: { type: 'string' } },
              caution: { type: 'string' }
            },
            required: ['category', 'summary', 'faqCandidate', 'urgency',
                       'recommendedDepartment', 'draftAnswer', 'confirmationNeeded', 'caution']
          }
        }
      }
    }
  };

  const options = {
    method: 'post',
    contentType: 'application/json',
    headers: { 'x-goog-api-key': apiKey },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true
  };

  const response = UrlFetchApp.fetch(url, options);
  const code = response.getResponseCode();
  const body = response.getContentText();

  if (code < 200 || code >= 300) {
    throw new Error(`Gemini API error: ${code} ${body}`);
  }

  const json = JSON.parse(body);
  const text = json.candidates?.[0]?.content?.parts?.[0]?.text;

  if (!text) throw new Error('Gemini API response does not contain text.');

  return JSON.parse(text);
}

構造化出力を使うことで、Google Sheetsへの書き戻しがスムーズになります。

未分類の問い合わせを自動処理する

未処理行を順番に処理する関数

javascript

function classifyInquiries() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName('問い合わせ管理');
  const values = sheet.getDataRange().getValues();

  for (let i = 1; i < values.length; i++) {
    const row = values[i];
    const inquiryText = row[3]; // D列:問い合わせ内容
    const answerText = row[4];  // E列:回答内容
    const processed = row[13]; // N列:AI処理済み

    if (!inquiryText) continue;
    if (processed === '済') continue;

    try {
      const result = callGeminiForInquiry_(inquiryText, answerText);

      sheet.getRange(i + 1, 7).setValue(result.category);
      sheet.getRange(i + 1, 8).setValue(result.summary);
      sheet.getRange(i + 1, 9).setValue(result.faqCandidate ? 'はい' : 'いいえ');
      sheet.getRange(i + 1, 10).setValue(result.recommendedDepartment);
      sheet.getRange(i + 1, 11).setValue(result.urgency);
      sheet.getRange(i + 1, 12).setValue(result.draftAnswer);
      sheet.getRange(i + 1, 13).setValue((result.confirmationNeeded || []).join('\n'));
      sheet.getRange(i + 1, 14).setValue('済');
      sheet.getRange(i + 1, 15).setValue(new Date());

      Utilities.sleep(1000);

    } catch (error) {
      sheet.getRange(i + 1, 14).setValue('エラー');
      sheet.getRange(i + 1, 15).setValue(new Date());
      logError_('classifyInquiries', error.message, i + 1);
    }
  }
}

AI処理済み 列がポイントです。これがないと、同じ問い合わせを何度もAPIに送ってしまいます。コストと処理時間を抑えるために、処理済み管理は必ず入れておきます。

エラーログの設計

API連携では、想定外のエラーが必ず起きます。

  • APIキーが無効

  • モデル名の変更

  • 入力データが長すぎる

  • 一時的な通信エラー

  • APIの利用制限

  • シート構成の変更

エラーが出た行をそのままにせず、後から確認できる仕組みを入れておきます。

javascript

function logError_(functionName, message, rowNumber) {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  let sheet = ss.getSheetByName('エラーログ');

  if (!sheet) {
    sheet = ss.insertSheet('エラーログ');
    sheet.appendRow(['日時', '関数名', '行番号', 'エラー内容']);
  }

  sheet.appendRow([new Date(), functionName, rowNumber || '', message]);
}

FAQ候補をまとめて生成する

FAQ化候補をまとめてGemini APIへ送る

AI分類が済んでいて、FAQ化候補が「はい」の問い合わせだけをまとめて処理します。

javascript

function generateFaqCandidates() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const inquirySheet = ss.getSheetByName('問い合わせ管理');
  const faqSheet = ss.getSheetByName('FAQ候補') || ss.insertSheet('FAQ候補');
  const values = inquirySheet.getDataRange().getValues();
  const targetRows = [];

  for (let i = 1; i < values.length; i++) {
    const row = values[i];
    if (row[13] === '済' && row[8] === 'はい') {
      targetRows.push({
        rowNumber: i + 1,
        category: row[6],
        inquiryText: row[3],
        answerText: row[4]
      });
    }
  }

  if (targetRows.length === 0) {
    SpreadsheetApp.getUi().alert('FAQ候補にできる問い合わせがありません。');
    return;
  }

  const result = callGeminiForFaqCandidates_(targetRows);

  if (faqSheet.getLastRow() === 0) {
    faqSheet.appendRow(['作成日時', 'カテゴリ', 'よくある質問', '回答案', '根拠となる問い合わせ',
                        '社内確認事項', '公開可否', 'ステータス', '確認担当', '最終更新日']);
  }

  result.faqs.forEach(function(faq) {
    faqSheet.appendRow([
      new Date(), faq.category, faq.question, faq.draftAnswer,
      (faq.sourceRows || []).join(', '),
      (faq.confirmationNeeded || []).join('\n'),
      faq.publishability, '下書き', '', ''
    ]);
  });
}

返ってきたFAQ候補は、FAQ候補 シートへ書き出します。最初はすべて「下書き」ステータスになります。

Google Sheetsメニューから実行する

毎回Apps Scriptエディタを開くのは手間です。シート上にメニューを追加して、ボタン感覚で実行できるようにします。

javascript

function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('AI問い合わせ処理')
    .addItem('未処理問い合わせをAI分類', 'classifyInquiries')
    .addItem('FAQ候補を生成', 'generateFaqCandidates')
    .addToUi();
}

Google Sheetsを開いたときにメニューが表示されるので、運用担当者もシート上から処理を実行できます。

実務での運用フロー

Step1|問い合わせをGoogle Sheetsに蓄積する

LINE公式アカウント、Googleフォーム、メール転記などで問い合わせを一元管理します。

Step2|個人情報を除外・匿名化する

AIに送る前に、氏名・電話番号・メールアドレス・住所・注文番号などは削除します。FAQ生成に必要なのは個人情報ではなく、質問の内容と回答方針です。

Step3〜7|分類から正式FAQ化まで

メニューから 未処理問い合わせをAI分類 を実行 → 分類結果を人間が確認 → FAQ候補を生成 → 担当者が回答案を確認 → 確認済みのFAQだけをWebサイト・LINE・社内マニュアルに展開。

この流れにすれば、問い合わせ履歴がFAQの材料になります。

カテゴリ設計のコツ

問い合わせ分類では、カテゴリ設計が精度に影響します。最初から細かくしすぎると、分類がぶれやすくなります。

まずは大きめのカテゴリから始めるのが現実的です。

text

商品について / 料金について / 納期について / 注文・予約について
支払いについて / 返品・交換について / キャンセルについて
トラブル対応 / 法人対応 / その他

ECサイトなら「配送」「ギフト対応」「クーポン」「領収書」、BtoBサービスなら「資料請求」「見積依頼」「セキュリティ」などを追加していきます。カテゴリは、FAQやマニュアルの構成にも影響するので、後から活用しやすい粒度にすることが大切です。

AI出力をそのまま公開しない|確認フローが品質を守る

この仕組みで最も重要なのは、AIが作ったFAQ案をそのまま公開しないことです。

特に次の内容は、必ず担当者が確認します。

  • 料金・納期・返品・キャンセル条件

  • 契約内容・法務・規約

  • 医療・金融・安全に関わる内容

  • 個人情報を含む内容

  • 保証内容・社内ルール

ステータスは次のように運用するのがおすすめです。

text

下書き → 確認中 → 修正必要 → 公開可 / 社内限定 / 非公開

FAQ候補シートでは最初はすべて「下書き」にし、担当者が確認して初めて「公開可」に変更します。この確認フローがないと、間違ったFAQが公開されるリスクが残ります。

Apps Scriptの実行制限と大量データへの対応

Apps Scriptは大量データの処理には制限があります。数十件程度なら問題になりにくいですが、数百件を一度にAPIへ送ると実行時間やAPI制限に引っかかる可能性があります。

1回の処理件数に上限を設ける方法が実用的です。

javascript

function classifyInquiriesWithLimit() {
  const limit = 30;
  let count = 0;
  // ... (通常のclassifyInquiriesと同じ処理)
  // ループ内に if (count >= limit) break; を追加
}

処理済みフラグを使い、エラー行は後で再処理する設計にすると運用しやすくなります。

この仕組みが向いている業務と向いていない業務

向いている業務

  • LINE公式アカウントの問い合わせ管理

  • Googleフォームの問い合わせ整理

  • ECサイトのFAQ作成

  • セミナー申込後の質問整理

  • 社内問い合わせのFAQ化

  • 新人教育用の対応マニュアル作成

問い合わせ件数がある程度溜まった段階で効果が出やすいです。50件、100件と蓄積されてくると、よくある質問や回答のばらつきが見えやすくなります。

注意が必要な業務

  • 即時に正確な自動返信が必要

  • 法務・医療・金融など高リスクな回答が多い

  • FAQを完全自動で公開したい

  • 大量データをリアルタイム処理したい

このような用途では、GASとGemini APIだけで完結させるのではなく、専用の問い合わせ管理システムやCRM、Cloud Runなどの活用も検討が必要です。

運用メモを必ず残す

このような自動化は、作った人しか分からない状態になりがちです。Excelマクロと同じように、GASも属人化します。

次のような運用メモをシート内や社内ドキュメントに残しておくと、引き継ぎがスムーズになります。

text

【連携名】問い合わせデータAI分類・FAQ候補生成
【目的】Google SheetsにためたデータをGemini APIで分類し、FAQ候補を作成する
【対象シート】問い合わせ管理 / 【出力先シート】FAQ候補
【実行方法】Google Sheetsメニュー「AI問い合わせ処理」から実行
【注意点】AI出力は下書き扱い。正式FAQ化前に人間が確認する。個人情報はAIに送らない
【確認担当】〇〇部 担当者名 / 【最終更新日】2026/05/20

まとめ|問い合わせデータをFAQに変えると、対応品質がそろう

問い合わせ対応は、返信して終わりではありません。一つひとつのデータには、顧客の不安や疑問が表れています。

Google SheetsとGemini APIを組み合わせることで、問い合わせ対応を社内ナレッジに変える流れが作れます。

  • 問い合わせ内容を自動分類する

  • 要約と回答案のたたき台を作る

  • FAQ化できる質問を見つける

  • FAQ候補を別シートに出力する

  • 人間が確認して正式FAQにする

ただし、AIが作るのはあくまで下書きです。料金、納期、返品、契約、規約、個人情報に関わる内容は、必ず担当者が確認します。

FAQにする、社内マニュアルにする、商品ページを改善する、新人教育に使う。この流れができると、問い合わせ対応は単なる作業ではなく、会社のナレッジづくりになります。

生成AIの先に、現場で使われるDXをつくる。

Google SheetsとGemini APIを連携させた問い合わせ分類・FAQ候補出力は、顧客対応を属人化させず、社内に知識を残すための実務的な一歩です。

私のnoteでは、企業の生成AI活用・DX推進について、実務目線で発信しています。

ChatGPT、Claude、Microsoft Copilot、Gemini、NotebookLMなどを使い、営業、会議、資料作成、Excel業務、メール対応、社内ナレッジ整理をどのように改善できるかをまとめています。

単なるAIツール紹介ではなく、「現場で使われるAI活用」「業務改善につながるDX」「属人化を減らす仕組みづくり」をテーマに、実際の仕事に落とし込みやすい活用法を発信しています。

他の記事もぜひ読んでみてください。


いいなと思ったら応援しよう!