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導入を見送る基準をSheetsとGASで管理する:試行・保留・停止の判断表

0
Posted at

生成AIを業務へ導入するとき、「使えそうな業務」を探すだけでは判断が偏ります。入力の根拠が不明、人間確認の時間がない、失敗時の戻し先がない、といった状態で試行を始めると、自然な文章が返ってきても運用を続けられません。

この記事では、GoogleスプレッドシートとGoogle Apps Script(GAS)で、AI導入候補を PILOT(試行)、PREPARE(保留)、STOP(見送り)に分ける判断表を作ります。AI APIの呼び出し、顧客への自動送信、試行の自動承認は扱いません。GASは入力された確認結果を集計し、人間が次に見る候補を整理します。

作るもの

AI導入候補を人間確認の境界で振り分ける既存承認済み図解

ADOPTION_SCOPE_GATE シートに、1行1業務で候補を登録します。次の5項目を0〜2点で記録し、危険フラグがあれば点数より先に STOP とします。

入力例 意味
scope_id SCOPE-001 候補を追跡するID
work_name 問い合わせ一次分類 対象を一つの工程に絞った名前
impact_scope 2 影響範囲が限定されているか
input_and_source 2 入力項目と現行の正本があるか
human_review 1 確認者と確認時間が決まっているか
recovery_path 2 元の手順へ戻れるか
decision_log 1 判断理由と次回日を残せるか
risk_flags none contract_or_money などの停止条件
route PREPARE GASが返す候補ルート
owner 業務管理者 台帳を更新する責任者
reviewer CS責任者 試行時に確認する人
next_review_at 2026-09-16 次回の確認日
reason 根拠の版が未確認 その判定になった理由

判定ルールを先に固定する

点数の意味を決めずに集計を始めると、導入したい候補に都合よく点数を付けてしまいます。まず、次のルールをチームで共有します。

  • PILOT: 5項目をすべて測定でき、合計8点以上。少数件・人間確認付きで試行する
  • PREPARE: 未入力がある、または合計8点未満。補う項目、担当者、期限を記録する
  • STOP: 契約・料金・返金・苦情・重大な個人情報などの停止フラグがある、または復旧先・最終判断者が不明

PILOT は導入の成功や自動送信を意味しません。試行を始める前に、業務責任者が対象範囲、確認者、復旧方法を確認します。未確認の空欄を0点と断定せず、まず PREPARE に送ります。

スプレッドシートを準備する

空のスプレッドシートを作成し、Apps Scriptエディタに次のコードを貼り付けて setupAdoptionScopeGate を一度実行します。既存シートがある場合は、同名シートを作り直さずヘッダーの差分を確認してください。

const SHEET_NAME = 'ADOPTION_SCOPE_GATE';

const HEADERS = [
  'scope_id',
  'work_name',
  'impact_scope',
  'input_and_source',
  'human_review',
  'recovery_path',
  'decision_log',
  'risk_flags',
  'route',
  'owner',
  'reviewer',
  'next_review_at',
  'reason',
  'checked_at',
];

function setupAdoptionScopeGate() {
  const book = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = book.getSheetByName(SHEET_NAME) || book.insertSheet(SHEET_NAME);

  if (sheet.getLastRow() === 0) {
    sheet.getRange(1, 1, 1, HEADERS.length).setValues([HEADERS]);
    sheet.setFrozenRows(1);
  }
}

入力例

まずは実際の顧客本文や個人情報を貼らず、業務の概要だけで3件入力します。

SCOPE-001 | 問い合わせ一次分類 | 2 | 2 | 2 | 2 | 1 | none
SCOPE-002 | 契約更新の返信案     | 0 | 2 | 2 | 2 | 2 | contract_or_money
SCOPE-003 | 社内FAQ候補の整理    | 2 |    | 1 | 2 | 1 | none

SCOPE-002 は合計点に関係なく停止します。SCOPE-003input_and_source が未確認なので、都合よく0点として見送りにせず、保留理由と確認期限を登録します。

GASでルート候補を計算する

次の関数は、点数と停止フラグからルート候補を返します。配列やオブジェクトに未知の値が入った場合も、通常処理へ進めず PREPARE に戻します。

const CRITERIA = [
  'impact_scope',
  'input_and_source',
  'human_review',
  'recovery_path',
  'decision_log',
];

const HARD_STOP_FLAGS = new Set([
  'contract_or_money',
  'high_impact_personal_data',
  'complaint_or_incident',
  'recovery_path_unknown',
  'final_decider_unknown',
]);

function suggestRoute(record) {
  const flags = String(record.risk_flags || '')
    .split(',')
    .map((flag) => flag.trim())
    .filter(Boolean);

  if (flags.some((flag) => HARD_STOP_FLAGS.has(flag))) {
    return { route: 'STOP', reason: 'hard_stop_flag' };
  }

  const scores = CRITERIA.map((key) => record[key]);
  const measured = scores.every((value) => {
    const number = Number(value);
    return Number.isInteger(number) && number >= 0 && number <= 2;
  });

  if (!measured) {
    return { route: 'PREPARE', reason: 'unmeasured_criterion' };
  }

  const score = scores.reduce((sum, value) => sum + Number(value), 0);
  if (score >= 8) {
    return { route: 'PILOT', score };
  }
  return { route: 'PREPARE', score, reason: 'criteria_to_prepare' };
}

シートの行を更新する

続けて、ヘッダー名を読み取り、各行の routereasonchecked_at を更新します。入力データをAIへ送信したり、外部へ通知したりする処理は含めません。

function evaluateAdoptionScopeRows() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
  if (!sheet || sheet.getLastRow() < 2) return;

  const values = sheet.getDataRange().getValues();
  const headers = values[0].map(String);
  const index = Object.fromEntries(headers.map((name, i) => [name, i]));
  const required = [...CRITERIA, 'risk_flags', 'route', 'reason', 'checked_at'];

  required.forEach((name) => {
    if (index[name] === undefined) throw new Error(`Missing column: ${name}`);
  });

  const now = new Date();
  const output = values.slice(1).map((row) => {
    if (row.every((value) => value === '')) return row;

    const record = Object.fromEntries(
      headers.map((name, i) => [name, row[i]]),
    );
    const result = suggestRoute(record);
    row[index.route] = result.route;
    row[index.reason] = result.reason || `score_${result.score}`;
    row[index.checked_at] = now;
    return row;
  });

  sheet.getRange(2, 1, output.length, headers.length).setValues(output);
}

トリガーを設定する場合も、まずは手動実行で結果を確認します。時間主導トリガーで勝手に試行を開始したり、PILOT の行を自動で公開状態へ変えたりする設定は作りません。

判定結果を人が確認する

GASの集計後は、route ごとに次の順番で確認します。

  1. STOP を開き、AIへ渡さない理由と戻し先を記録する
  2. PREPARE の空欄を、正本・確認者・期限の順に補う
  3. PILOT は対象を一業務・少数件に限定する
  4. 通常、境界、停止に近いケースを分けて記録する
  5. 確認時間、差し戻し、復旧の事実を次回レビューへ持ち込む

次の条件を満たしていても、別の業務へ自動的に範囲を広げません。

  • 入力と参照先が現行である
  • 人間の確認者と確認時間がある
  • 失敗時に元の手順へ戻れる
  • 判断理由、ルールの版、次回確認日が残る

運用チェックリスト

  • 対象を一つの業務工程として書いた
  • 顧客、契約、料金、返金、苦情、個人情報への影響を確認した
  • AIへ渡してよい情報と渡さない情報を分けた
  • 入力項目と現行の正本を特定した
  • 最終確認者、不在時の戻し先、復旧方法を決めた
  • PILOTPREPARESTOP の意味を共有した
  • 判断理由、ルールの版、確認日時、次回確認日を残した
  • 空欄を安全または危険と都合よく解釈していない
  • PILOT でも顧客への自動送信を許可していない

この構成で扱わないこと

この実装は、業務候補の確認漏れを見つけるための台帳です。AIの正確性、導入効果、法令への適合、情報漏えいがないことを保証するものではありません。

顧客本文、氏名、メールアドレス、認証情報、契約・決済情報は、候補表へ複製しません。高い影響を持つ判断、苦情、返金、採用可否などは、点数が高くてもAIの自動判断対象にせず、人間確認または対象外に戻します。

Miraigentでは、AIを入れる前に「試す条件」だけでなく「今回は見送る条件」と「見送った後に整える場所」を業務単位で確認します。最初の一歩は、直近の候補を3件だけ匿名化して台帳へ置き、点数を付けられない列を見つけることです。

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?