0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AI導入後に問い合わせが増えた時の5分類をGASで記録する

0
Posted at

AI導入の対象業務や確認ルールを変更した後、問い合わせが急に増えることがあります。

この時、届いた順に回答を増やすだけでは、FAQ・手順書・承認ルールのどこが不足しているのか分かりません。この記事では、GoogleスプレッドシートとGASで、変更後の問い合わせを5つの分類へ戻し、REPLY、HOLD、STOP の次の処理を記録する最小構成を作ります。

扱うのは問い合わせの整理と確認キューの作成です。AIによる自動返信、顧客への自動送信、契約や料金の自動判断は扱いません。

作るもの

問い合わせを5項目で分類し、人間確認へ戻す運用イメージ

CHANGE_INQUIRIES シートに、変更後の問い合わせを1件1行で記録します。

inquiry_id,received_at,question_type,impact_scope,source_of_truth,reviewer,return_route,decision,next_action,status

今回の5分類は次のとおりです。

項目 記録する内容 空欄の時の扱い
question_type 操作、入力、対象範囲、承認、例外のどれか HOLD
impact_scope 社内だけか、顧客・契約・公開情報へ影響するか HOLD
source_of_truth 最新のFAQ、手順書、フォーム、判断ログ HOLD
reviewer 通常・境界・停止を確認する役割 HOLD
return_route 保留、手動対応、変更前の手順などの戻し先 HOLD

decision は REPLY、HOLD、STOP の3値に限定します。REPLY は人が確認して案内できる状態であり、送信を自動許可する意味ではありません。

事前準備

スプレッドシートの1行目に、次のヘッダーを作ります。

inquiry_id,received_at,question_type,impact_scope,source_of_truth,reviewer,return_route,decision,next_action,status

変更後の問い合わせを取り込む前に、question_type、decision、status の許可値をチームで決めます。値が自由入力のままだと、「承認」「確認待ち」「review」のような表記揺れが発生し、集計結果をそのまま判断へ使えません。

5分類と3つの処理を固定する

const INQUIRY_TRIAGE_CONFIG = Object.freeze({
  sheetName: 'CHANGE_INQUIRIES',
  questionTypes: ['OPERATION', 'INPUT', 'SCOPE', 'APPROVAL', 'EXCEPTION'],
  decisions: ['REPLY', 'HOLD', 'STOP'],
  statuses: ['NEW', 'TRIAGED', 'REVIEWED', 'CLOSED'],
  required: [
    'inquiry_id', 'received_at', 'question_type', 'impact_scope',
    'source_of_truth', 'reviewer', 'return_route', 'decision', 'next_action',
  ],
});

function readChangeInquiries_() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName(INQUIRY_TRIAGE_CONFIG.sheetName);
  if (!sheet) throw new Error('CHANGE_INQUIRIES sheet is missing');

  const values = sheet.getDataRange().getValues();
  if (values.length < 2) return [];
  const headers = values[0].map(String);
  return values.slice(1).map((row, index) => {
    const item = { rowNumber: index + 2 };
    headers.forEach((header, column) => { item[header] = row[column]; });
    return item;
  });
}

function validateInquiry_(item) {
  INQUIRY_TRIAGE_CONFIG.required.forEach((key) => {
    if (!String(item[key] || '').trim()) {
      throw new Error(`${key} is required: ${item.inquiry_id || 'unknown'}`);
    }
  });

  const type = String(item.question_type).trim().toUpperCase();
  const decision = String(item.decision).trim().toUpperCase();
  const status = String(item.status || 'NEW').trim().toUpperCase();
  if (!INQUIRY_TRIAGE_CONFIG.questionTypes.includes(type)) {
    throw new Error(`unsupported question_type: ${item.inquiry_id}`);
  }
  if (!INQUIRY_TRIAGE_CONFIG.decisions.includes(decision)) {
    throw new Error(`unsupported decision: ${item.inquiry_id}`);
  }
  if (!INQUIRY_TRIAGE_CONFIG.statuses.includes(status)) {
    throw new Error(`unsupported status: ${item.inquiry_id}`);
  }
  return { ...item, question_type: type, decision, status };
}

必須項目の検査は入力漏れを見つける補助です。個人情報、契約条件、料金、苦情の有無をコードだけで安全に判断できるわけではありません。

問い合わせを分類する

まずは問い合わせ本文をAIへ渡さず、担当者が5項目を記録します。分類の目的は回答を生成することではなく、どの正本と確認者へ戻すかを明らかにすることです。

function classifyInquiry_(item) {
  const values = [
    item.question_type,
    item.impact_scope,
    item.source_of_truth,
    item.reviewer,
    item.return_route,
  ].map((value) => String(value || '').trim());

  if (values.some((value) => value === '')) return 'HOLD';

  const impact = String(item.impact_scope).toUpperCase();
  const type = String(item.question_type).toUpperCase();
  if (impact.includes('CUSTOMER') || impact.includes('CONTRACT')
      || type === 'EXCEPTION') {
    return 'STOP';
  }
  return 'REPLY';
}

function triageAllChangeInquiries() {
  const items = readChangeInquiries_();
  const result = items.map((item) => {
    try {
      const valid = validateInquiry_(item);
      const decision = classifyInquiry_(valid);
      return [valid.inquiry_id, valid.question_type, decision, 'OK'];
    } catch (error) {
      return [item.inquiry_id || '', 'UNKNOWN', 'HOLD', error.message];
    }
  });
  Logger.log(JSON.stringify(result));
  return result;
}

STOP は危険だと断定するためのラベルではありません。顧客・契約・例外が関わり、通常の案内へ流す前に人が確認する境界を示します。HOLD は情報不足や正本不明で、回答を急がず不足項目を埋める状態です。

同じ質問をFAQ候補へ戻す

同じ question_type と source_of_truth の組み合わせが続く場合、個別回答を増やす前にFAQ候補として記録します。

function buildFaqCandidates_(items) {
  const counts = new Map();
  items.forEach((item) => {
    const key = [item.question_type, item.source_of_truth].join('|');
    counts.set(key, (counts.get(key) || 0) + 1);
  });

  return [...counts.entries()]
    .filter(([, count]) => count >= 2)
    .map(([key, count]) => ({
      key,
      count,
      nextAction: '人が質問文・条件・例外・戻し先を確認してFAQ候補へ記録',
    }));
}

件数だけでFAQ化を決めないでください。同じ質問が増えていても、回答の根拠が更新中なら公開を保留します。FAQには「通常時の答え」だけでなく、「情報不足ならどこへ戻すか」「顧客や契約に関わる場合は誰が見るか」も残します。

変更後の確認手順

  1. 問い合わせを10件だけ選び、本文ではなく業務IDと分類項目を記録する
  2. OPERATION、INPUT、SCOPE、APPROVAL、EXCEPTION の5分類へ分ける
  3. 正本、確認者、戻し先がない行を HOLD にする
  4. 顧客・契約・例外に関係する行を STOP にして人へ戻す
  5. 同じ質問が2件以上ある場合はFAQ候補として別に記録する
  6. FAQ・手順書・フォームのどこを更新するか決め、更新後に1件を再確認する

問い合わせの分類を自動実行する場合でも、最初はテスト用の匿名データで動作を確認します。本番の問い合わせ本文、氏名、メールアドレス、契約番号、認証情報をテストコードやログへ貼り付けないでください。

公開・運用前チェックリスト

  • 変更前と変更後の対象範囲が一文で分かる
  • 問い合わせを5分類のどれかへ戻せる
  • 最新のFAQ・手順書・フォームなど正本がある
  • 通常・境界・停止それぞれの確認者が分かる
  • 情報不足時の HOLD と戻し先がある
  • 顧客・契約・例外を STOP へ戻せる
  • 同じ質問をFAQ候補へ変換する条件がある
  • 顧客固有情報、認証情報、未確認の約束を記事やテストへ入れていない
  • GASの判定結果だけで返信送信やFAQ公開を完了扱いにしていない

まとめ

AI導入後に問い合わせが増えた時、先に回答数を増やすのではなく、次の5項目へ戻します。

  1. 質問の種類
  2. 影響範囲
  3. 最新の正本
  4. 確認者
  5. 保留・手動対応の戻し先

GASは分類値や必須項目の揺れを検出する補助に使い、顧客への返信、契約条件の解釈、FAQの公開判断は人が行います。問い合わせが増えた事実を、回答者の負担だけでなく、案内と正本を改善する運用ログへ変えるのがこの構成の目的です。

Miraigentでは、AI導入をツール選定だけでなく、変更後に「次の人がどこへ戻れるか」まで含めて整理しています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?