生徒から質問フォームに届く質問を科目・単元・急ぎ具合で仕分けて担当講師へ回し、回答が遅れている質問を拾う
生徒から質問フォームに届いた質問を、科目・単元と、急ぎかどうかで仕分けて担当の講師へ回します。回答の期限を過ぎても答えのない質問を1時間ごとに拾い、教室長へ知らせます。
- 生成AI
- ChatGPT/Claude/Gemini
- 連携・自動化
- Google Apps Script/Make/Power Automate/Python
- 対象業界
- IT・SaaS/人材/教育
- 対象部門
- カスタマーサポート
- 対象業務
- 分類・仕分け/問い合わせ対応
- 主な課題
- 人手が足りない/問い合わせが多い/期限・対応漏れが起きる
- AIで行う処理
- 分類
- 主な効果
- 対応スピード向上/工数削減/機会損失防止
- 導入難易度
- ★☆☆☆☆
- 実装レベル
- 本格構成
- 費用感
- API連携(中)
- 人間の確認
- 条件付き
01導入前 / 導入後の業務フロー
- 生徒が質問フォームに、生徒番号、学年、科目(任意)、質問の内容、いつまでに知りたいかを書いて送る
- 運営スタッフが回答のスプレッドシートを開き、新しい質問を上から読む
- 内容から科目と単元を判断する。科目が空欄や誤りのことも多い
- 担当表を開き、その学年と科目を受け持つ講師を探す。生徒の担当講師がいればその講師にする
- 講師にメールで質問を転送し、スプレッドシートの「担当」の列に名前を書く
- 講師が回答を書き、生徒へ返す。返したら「回答済み」の列に印を付ける
- 運営スタッフが、ときどき「回答済み」の印が付いていない行を探し、講師に催促する
- 人生徒が質問フォームに質問を書いて送る(項目は今までと同じ)
- 自動フォームの送信をきっかけにスクリプトが動き、生徒番号から学年と担当講師を引く
- 自動AIが質問の文章から、勉強の質問かそれ以外の相談かを分ける
- 自動勉強の質問なら、学年の単元一覧から単元の ID を選び、期限の手がかりを書き出す
- 自動スクリプトが期限の手がかりと日付から回答の期限を計算し、担当表から講師を決める
- 自動講師へ質問と回答用のフォームのリンクをメールで送り、台帳に担当と期限を書く
- 自動勉強以外の相談と、単元を選べなかった質問は、教室長と運営スタッフに回す
- 人講師が回答を書いて生徒へ返し、回答用のフォームで「回答済み」を送る
- 自動1時間ごとに台帳を見て、期限を過ぎて回答済みでない質問を教室長へ知らせる
- 人運営スタッフが、7番目と9番目で回ってきたものだけを扱う
各工程の詳しい説明を読む
- 生徒が質問フォームに、生徒番号、学年、科目(任意)、質問の内容、いつまでに知りたいかを書いて送る
- 運営スタッフが回答のスプレッドシートを開き、新しい質問を上から読む
- 内容から科目と単元を判断する。科目が空欄や誤りのことも多い
- 担当表を開き、その学年と科目を受け持つ講師を探す。生徒の担当講師がいればその講師にする
- 講師にメールで質問を転送し、スプレッドシートの「担当」の列に名前を書く
- 講師が回答を書き、生徒へ返す。返したら「回答済み」の列に印を付ける
- 運営スタッフが、ときどき「回答済み」の印が付いていない行を探し、講師に催促する
(a)振り分けは、読む人の知識に頼っている。 3番目は、運営スタッフが科目の中身を知っていることが前提です。「三平方の定理」が中学3年の数学だと分かるスタッフと、分からないスタッフがいます。 分からなければ、科目の講師に聞いてから回すことになります。
(b)勉強以外の相談が講師に届いてしまう。 質問の内容を急いで読むと、勉強の質問に紛れて書かれた悩みの相談を、そのまま講師へ転送してしまうことがあります。講師はどう扱えばよいか分からず、返事が遅れます。
(c)急ぎかどうかが、生徒の書き方で決まる。 「いつまでに知りたいか」の欄は空欄が多く、本文に「明日テスト」と書いてあっても欄が空なら急ぎとして扱われません。 テストの前日の質問が、翌々日に答えられることがあります。
(d)遅れに気づくのが遅い。 7番目は、手が空いたときにしか行われません。テスト前のいちばん質問が多い時期ほど、催促の確認が後回しになります。
- 【人】 生徒が質問フォームに質問を書いて送る(項目は今までと同じ)
- 【自動】 フォームの送信をきっかけにスクリプトが動き、生徒番号から学年と担当講師を引く
- 【自動】 AIが質問の文章から、勉強の質問かそれ以外の相談かを分ける
- 【自動】 勉強の質問なら、学年の単元一覧から単元の ID を選び、期限の手がかりを書き出す
- 【自動】 スクリプトが期限の手がかりと日付から回答の期限を計算し、担当表から講師を決める
- 【自動】 講師へ質問と回答用のフォームのリンクをメールで送り、台帳に担当と期限を書く
- 【自動】 勉強以外の相談と、単元を選べなかった質問は、教室長と運営スタッフに回す
- 【人】 講師が回答を書いて生徒へ返し、回答用のフォームで「回答済み」を送る
- 【自動】 1時間ごとに台帳を見て、期限を過ぎて回答済みでない質問を教室長へ知らせる
- 【人】 運営スタッフが、7番目と9番目で回ってきたものだけを扱う
10番目が、この設計の分かれ目です。 運営スタッフが見るのは、AIが勉強以外と分けたもの、単元を選べなかったもの、期限を過ぎたものだけです。全件を読んでから回す形にすると、60.0時間はほとんど減りません。
5番目を規則にしているのも、意図してのことです。 単元の ID が決まれば、講師は担当表から一意に決まります。AIに講師の名前まで選ばせると、担当表が変わったときにAIの指示も直すことになります。 担当表を直せば振り分けが変わる形にしておきます。
02今回想定するシステム構成
生徒 ── 質問フォーム(Google フォーム)
│ 回答はスプレッドシートにたまる
▼【トリガー】フォーム送信
Google Apps Script
├──▶ 生徒番号から学年・担当講師を引く(生徒の一覧)
▼
Gemini API ── 分類(構造化出力)
│ ① 勉強の質問か、それ以外の相談か
│ ② 科目と単元の ID(学年の単元一覧から選ぶ)
│ ③ 期限の手がかりの書き出し
▼
Google Apps Script ── 回答の期限の計算・担当表から講師を決める
├──▶ 講師へメール(質問と回答用フォームのリンク)
├──▶ 教室長へメール(勉強以外の相談・単元不明)
▼
質問の台帳(スプレッドシート)
▲
回答用フォーム ── 講師が「回答済み」を送る
▲【トリガー】1時間ごと
期限を過ぎた質問を教室長へ知らせる| 役割 | 想定する製品 | 代替候補 |
|---|---|---|
| 実行環境 | Google Apps Script | Python、Power Automate、Make |
| 生成AI | Gemini API | OpenAI API、Claude API |
| 受付 | Google フォーム | Microsoft Forms |
| 台帳 | Google スプレッドシート(質問の台帳・担当表・単元一覧・生徒の一覧) | Microsoft Lists |
| 通知 | Gmail | Google Chat |
新しく足すのは、スクリプトと Gemini API の利用だけです。 質問フォーム、回答のスプレッドシート、担当表は今あるものを使います。最初の準備作業は、学年ごとの単元一覧に ID を振ることと、担当表を「学年×科目×講師」の形にそろえることです。
起点は、スプレッドシートのフォーム送信のトリガーです。 インストール型のトリガーにはフォームの送信で動くものがあり、Google フォーム用とスプレッドシート用の2種類があります。スプレッドシート用のトリガーでは、イベントの namedValues に質問の名前と回答の組が、values にスプレッドシートの列の順の値が入り、range で書き込まれた行が分かります。フォームの質問名をそのまま鍵にして読めるので、列の順が変わっても壊れにくくなります。
インストール型のトリガーは、作った人のアカウントで動きます。 講師へのメールも、トリガーを作った人のアカウントから送られます。運営部の共有アカウントでトリガーを作ってください。 個人のアカウントで作ると、その人が異動したときに振り分けが止まります。
03どうやって実装するのか
処理の起点を決める
質問フォームの送信を起点にします。 1件ずつ届いたその場で動かし、定時にまとめて振り分けることはしません。 テストの前日の夜に届く質問は、翌朝のまとめ処理では間に合わないことがあるからです。
遅れの検知は、別のトリガーで1時間ごとに動かします。 時間主導型のトリガーは毎分から月1回まで設定できます。質問の期限は時刻の単位で決めるので、1時間ごとにします。 回答用フォームの送信にも、もう1つトリガーを付け、台帳の「回答済み」を書き込みます。
トリガーが失敗しても、画面には何も出ません。 失敗したときは、Apps Script から失敗をまとめたメールが届きます。このメールの届き先を、運営部の共有アカウントにしておきます。 届かない人のアカウントで作ると、振り分けが止まっていることに誰も気づきません。
入力データを集める
| データ | 中身 | 取得元 |
|---|---|---|
| 質問 | 生徒番号、学年、科目(任意)、質問の本文、いつまでに知りたいか、送信日時 | フォーム送信のイベント(namedValues) |
| 生徒の情報 | 生徒番号、学年、教室、担当講師(科目ごと) | 生徒の一覧(シート) |
| 単元一覧 | 学年、科目、単元の ID、単元名、生徒が書きそうな言い方 | 単元一覧(シート) |
| 担当表 | 学年、科目、講師、受け持てる曜日、臨時の講師か | 担当表(シート) |
| 行事の予定 | 教室ごとの定期テストの日程 | 行事の予定(シート) |
質を決めるのは、単元一覧の「生徒が書きそうな言い方」の列です。 「二次関数」の単元に「放物線」「グラフの頂点」「平方完成」と書いておくと、生徒の書き方がばらばらでも単元が選べます。この列は、運営スタッフが過去の質問を見ながら埋めます。 AIの指示を直すより、この列を足すほうが早く効きます。
行事の予定は、期限の計算に使います。 「テスト前だから急ぎ」とAIに判断させるのではなく、教室の定期テストの日程をシートに持たせ、スクリプトが日付で比べます。
データの取得方法を決める
質問はフォーム送信のイベントから受け取ります。 回答のスプレッドシートを毎回上から読み直す必要はありません。
| 取るもの | どこから | 何に使うか |
|---|---|---|
| 質問の本文と項目 | イベントの namedValues | AIへ渡す本文と、生徒番号 |
| 書き込まれた行 | イベントの range | 台帳と回答のシートの行の対応 |
| 学年と担当講師 | 生徒の一覧を生徒番号で引く | 単元一覧の絞り込み、講師の決定 |
| その学年の単元 | 単元一覧を学年で絞る | AIに渡す選択肢 |
| 受け持ちの講師 | 担当表を学年と科目で引く | 割り当て |
AIへ渡す単元は、その生徒の学年のものだけに絞ります。 全学年の単元を渡すと、中学1年の生徒の「方程式」に高校の単元を選ぶことがあります。選択肢を絞るのは、AIの精度を上げるいちばん確実な方法です。
生徒の名前はAIへ渡しません。 渡すのは、学年と、本文と、絞り込んだ単元一覧だけです。分類に名前は要りません。
台帳の行と回答用フォームは、質問の ID でつなぎます。 台帳に書き込むときに「教室コード+日付+連番」の ID を振り、講師へのメールの件名と本文の先頭に書きます。講師は回答用フォームでその ID と「回答済み」を送り、スクリプトが ID で台帳の行を探して印を付けます。 行の番号でつなぐと、運営スタッフが台帳を並べ替えたときに別の質問に印が付きます。ID が台帳に見つからない送信は、運営スタッフに回します。
AIへ渡す前に整形する
- 同時の送信への備え … テスト前は質問が重なって届きます。スクリプトのロックを取ってから台帳に書き込みます
- 生徒番号の照合 … 生徒の一覧に無い番号なら、分類をせず運営スタッフに回します
- 本文の長さの確認 … 本文が極端に短い(「わかりません」だけなど)ものは、分類をせず「内容不足」として運営スタッフに回します
- 個人情報の除去 … 本文に電話番号やメールアドレスのような文字列があれば、伏せてからAIへ渡します
- 重複の検知 … 同じ生徒から同じ本文が数分以内に届いたものは、2件目を重複として印を付けます
- 単元一覧の絞り込み … 学年で絞り、フォームで科目が選ばれていれば科目でも絞ります。ただし、科目の選択が誤っていることがあるので、科目で絞った結果で選べなければ学年だけで絞り直します
1番目を軽く見ないでください。 同じ時刻に2件の送信があると、トリガーも2つ同時に動きます。ロックを取らずに台帳の最終行を書くと、片方の行が上書きされて質問が1件消えます。 消えた質問は、誰にも回らず、遅れの検知にもかかりません。
AIに処理させる
させるのは、3つの分類と、期限の手がかりの書き出しです。
| 見るもの | 判定の仕方 | 判断できないときの扱い |
|---|---|---|
| 質問の種類 | study(勉強の質問)/admin(授業の日程・振替などの事務)/consult(悩み・退塾・家庭の事情の相談)/other | 迷ったら consult |
| 単元 | 渡した単元一覧から ID を1つ選ぶ | 選べなければ unknown |
| 複数の単元 | 1つの質問に複数の単元が含まれるか | 含まれれば multi を立て、主な単元を1つ選ぶ |
| 期限の手がかり | 本文の「明日テスト」「金曜提出」などを、本文のとおり書き出す | 無ければ空 |
左上の「迷ったら consult」が、この構成でいちばん大事な決めごとです。 勉強の質問を相談と誤って分けると、教室長が1件余分に読むだけで済みます。相談を勉強の質問と誤って分けると、悩みの相談が大学生の講師に届きます。 誤りの重さが違うので、迷ったときの寄せ先を相談の側に決めます。
期限の手がかりは、日付に直させません。 「明日」が何日かは、送信日時から決まります。AIには本文の言葉のまま書き出させ、スクリプトが送信日時と行事の予定を使って日付にします。
| させないこと | 理由 |
|---|---|
| 講師を選ぶ | 担当表の規則で決める。担当表が変わればそれに従う |
| 質問に回答する | 回答は講師が書く。誤った解き方を生徒に返さない |
| 期限を日付にする | 「明日」の起点は送信日時。スクリプトが計算する |
| 単元一覧に無い単元を作る | 担当表と対応しない ID が出ると割り当てられない |
| 相談の内容を要約して講師へ渡す | 相談は教室長が直接読む |
2行目を最初から禁じておきます。 AIは質問の答えを書けてしまうので、指示が曖昧だと分類の結果に解き方を添えてきます。それをそのまま生徒に返す運用にすると、講師が確かめていない解き方が生徒に届きます。
指示内容を固定する
あなたは学習塾の質問窓口の受付係です。生徒から届いた質問を仕分けます。
質問に答えてはいけません。仕分けだけを行ってください。
【この生徒の学年】{grade}
【フォームで選ばれた科目】{subject_selected}(空欄や誤りのことがあります)
【この学年の単元一覧】{unit_list}
(ID、科目、単元名、生徒が書きそうな言い方 の順)
【質問の本文】{question_text}
【kind の選び方】
- study ..... 教科の内容についての質問
- admin ..... 授業の日程、振替、教材の受け取りなどの事務
- consult ... 塾をやめたい、学校や家庭のこと、体調や気持ちについての相談
- other ..... 上のどれにも当たらない
勉強の質問か相談か迷ったときは consult を選んでください。
【厳守事項】
- unit_id は、上の単元一覧にある ID から1つだけ選んでください。
一覧に無い単元を作らないでください。選べなければ unknown にしてください。
- フォームで選ばれた科目と本文の内容が食い違うときは、本文を優先し、
subject_mismatch を true にしてください。
- 1つの質問に複数の単元が含まれるときは multi を true にし、
いちばん中心の単元を unit_id にしてください。
- deadline_hint には、本文の中の期限を示す言葉を、本文のとおりに写してください。
「明日」を日付に直さないでください。無ければ空にしてください。
- kind が study 以外のときは、unit_id を unknown にしてください。
- 質問への回答、解き方、ヒントを書かないでください。
- evidence には、判定の根拠にした本文の言葉をそのまま写してください。
「本文を優先し、subject_mismatch を立てる」は、科目の欄の誤りを拾うために入れます。 生徒はフォームの科目を前回のまま送ってくることがよくあり、欄を信じると、数学の質問が英語の講師に届きます。 食い違いを印として残すと、運営スタッフが単元一覧の言い方の列を見直す材料にもなります。
「ヒントを書かない」まで書くのは、「回答しない」だけでは足りないからです。 回答を禁じると、AIは「ヒント:まず平方完成をしてみましょう」のような一言を evidence に混ぜてきます。
出力形式を固定する
次の形のJSONで受け取ります。
{
"kind": "study | admin | consult | other",
"unit_id": "M3-07",
"subject_mismatch": false,
"multi": false,
"deadline_hint": "明日の小テスト",
"evidence": ""
}
1つ目の理由は、単元を一覧の ID に縛れることです。 Gemini API の構造化出力では、response_format に MIME タイプ application/json とスキーマを渡します。スキーマは enum と required が使え、enum は分類の用途に挙げられています。 kind を4つに、unit_id をその学年の単元の ID と unknown に絞ったスキーマを、質問ごとにスクリプトで組み立てて渡します。
2つ目は、規則の側で期限を計算できることです。 スクリプトは次の規則で回答の期限を決めます。
| 条件 | 回答の期限 |
|---|---|
deadline_hint か「いつまでに」の欄から、2日以内の日付が出る | 送信から6時間後か、その日の21時の早いほう |
| 教室の定期テストが7日以内にある | 送信から24時間後 |
| 上のどれにも当たらない | 送信から48時間後 |
kind が consult | 期限は付けず、教室長へ即時に回す |
数字は自社の運営の取り決めで置き換えてください。 大事なのは、期限を決める規則がシートとスクリプトにあり、AIの返す値に含まれていないことです。
3つ目は、値を必ず検査できることです。 Gemini API の案内でも、構造化出力の値はアプリケーションの側で検査すべきとされています。unit_id が渡した一覧に本当にあるか、kind が study 以外なのに unit_id が入っていないかをスクリプトで確かめ、外れたものは運営スタッフに回します。
システムへ連携する
| つなぎ先 | 方式 | 内容 |
|---|---|---|
| 質問フォームの回答のシート | フォーム送信のトリガー | 質問を受け取る |
| Gemini API | UrlFetchApp.fetch | 分類を返す |
| 生徒の一覧・単元一覧・担当表 | スプレッドシートの読み取り | 学年、単元の選択肢、講師を引く |
| 講師 | Gmail からのメール | 質問の本文、単元、期限、回答用フォームのリンク |
| 教室長 | Gmail からのメール | 勉強以外の相談、単元不明、期限を過ぎた質問 |
| 回答用フォーム | フォーム送信のトリガー | 講師の「回答済み」を台帳に書く |
API の呼び出しには UrlFetchApp.fetch を使い、muteHttpExceptions を true にします。 既定では、失敗の応答で例外が投げられて処理が止まります。true にすると失敗の応答もそのまま返るので、状態の番号を見て、台帳に「分類失敗」と書いてから運営スタッフに回せます。
メールの送信数には1日の上限があります。 Google Workspace のアカウントでは、メールの受信者が1日1,500人までとされています。テスト前に1日100件を超えても、講師への1通と教室長への知らせで届く範囲です。 上限は予告なく変わりうるとされているので、送信数を台帳に記録しておきます。
生徒への回答は、この構成から送りません。 生徒へ返すのは講師で、返す手段は今までどおりです。
人が確認する
運営スタッフが見るのは、次の4つに当たったものだけです。
consultに分けられたもの … 教室長が直接読みます。講師へ回すかどうかは、教室長が決めますunit_idがunknownのもの … 運営スタッフが単元を選び、単元一覧の「生徒が書きそうな言い方」の列に、その質問の言葉を足しますsubject_mismatchが立ったもの … 割り当ては本文の科目で済んでいます。週に一度まとめて見て、誤りがあれば講師を付け替えます- 期限を過ぎて回答済みでないもの … 講師に連絡し、つかまらなければ同じ科目の別の講師に付け替えます
2番目の後半を省かないでください。 unknown が出た質問の言葉を言い方の列に足すと、同じ言い方の質問は次から自動で振り分けられます。 足さないと、毎月同じ言い方で unknown が出続けます。
目標は、1,200件をならして1件30秒です。 4つに当たるのが全体の1割前後という想定です。それより多い月は、単元一覧の言い方の列が足りていないか、担当表が新しい学期に合っていません。 講師の側にも、割り当てが担当外だと思ったら「担当外」を回答用フォームで送れるようにしておき、送られた質問は運営スタッフが付け替えます。
例外に対処する
| 起きること | 対応 |
|---|---|
| 生徒番号が生徒の一覧に無い | 分類せず、運営スタッフに回す |
| 本文が短すぎて内容が分からない | 「内容不足」として運営スタッフに回し、生徒に書き直しを頼む |
| 担当表に受け持ちの講師がいない | 教室長に回す。学期の変わり目は担当表の更新漏れを先に疑う |
| 担当講師がその曜日に受け持てない | 同じ学年と科目の別の講師に回し、担当講師にも写しを送る |
| Gemini API が応答しない、失敗する | 台帳に「分類失敗」と書き、運営スタッフに回す。質問を捨てない |
| 返ってきた ID が単元一覧に無い | unknown と同じ扱いで運営スタッフに回す |
| 1回の実行が6分に近づく | 1回の実行は6分まで。1件ずつ動かすので通常は届かないが、遅れの検知は台帳の行を区切って読む |
| 同じ質問が二度届く | 2件目を重複として印を付け、講師には送らない |
| 講師が「回答済み」を送り忘れる | 期限を過ぎた知らせが教室長に届く。講師に確かめてから印を付ける |
上から3行目と9行目が、運営の初めに多く出ます。 どちらもAIの問題ではなく、担当表と回答の記録の運用の問題です。 直すほうが、分類の精度を上げるより効きます。
記録を残す
- 質問の本文、送信日時、生徒番号(名前は台帳に持たない)
- AIが返したJSONの全文と、そのとき渡した単元一覧の版
- スクリプトが計算した回答の期限と、その根拠(手がかりの言葉・行事の予定)
- 割り当てた講師と、付け替えた記録
- 回答済みになった日時と、期限を過ぎていたか
- 単元ごとの
unknownの件数と、subject_mismatchの件数
2つ目で「そのときの単元一覧の版」を残すのは、一覧が後から増えるためです。 言い方の列を足すと、同じ本文でも選ばれる単元が変わります。当時の一覧が残っていないと、振り分けの誤りの原因が一覧にあったのかAIにあったのかが分かりません。
最後の行は、単元一覧を育てる材料になります。 特定の単元で unknown が続くなら、生徒の言い方が一覧に足りていません。
04実装レベルの3段階
最小構成では件数がさばけません。 1件ずつ貼るので、1,200件には使えません。確かめるための段階です。 半自動化で、1件3分が1分程度になります。 分類と割り当ては自動になりますが、回答の状況を見て催促する作業が残ります。本格構成で30秒になり、この段階が本記事の想定です。 差が大きいのは、遅れの確認が、台帳の全体を人が眺める作業だからです。 段階を飛ばさないでください。 半自動化を1か月回すと、unknown の多い単元と、担当表の抜けが先に分かります。そこを直してから遅れの検知を足すほうが、教室長に届く知らせが本当に遅れたものだけになります。
05工数削減シミュレーション
導入後 1,200件 × 0.5分 ÷ 60 = 10 時間/月
自社条件で導入効果を整理したい方へ
このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。
06向いている企業・向いていない企業
- 授業の外で生徒からの質問を受け付けている個別指導塾・オンライン教室・家庭教師の事業者。質問がGoogle フォームなどで月に数百件から千件を超えて届き、教室のスタッフが1件ずつ読んで講師へ回している場合。講師が科目と学年で分かれていて、担当表をスプレッドシートで持っている場合。テストの前に質問が集中し、回答の遅れに気づくのが遅い場合。
- 質問が月に数十件で、講師が直接すべて受けている場合。質問の受付がチャットのアプリの中だけで行われ、内容を取り出せない場合。問題の写真だけで質問が届き、文章がほとんど無い場合。退塾や家庭の事情の相談を、勉強の質問と同じ窓口で講師に回したい場合。
07最小構成で試す方法
- 先月の質問から50件を選ぶ(うち数件は、相談が混ざっていたものと、科目の欄が誤っていたものを入れる)
- その50件を、当時どの講師に回したか、回答までに何時間かかったかを台帳から書き出す
- 中学2年と中学3年の単元一覧を作り、言い方の列を埋める
- 手元のAIサービスの画面に、第7章の指示と単元一覧と質問を1件ずつ貼り、分類させる
- 出てきた分類を、当時の振り分けと突き合わせる
50件は必ずやってください。 スクリプトを書く前に、「単元一覧から選ばせれば振り分けられるのか」を確かめます。
| 出てきた内容 | 判断 |
|---|---|
| 当時の振り分けとほぼ同じ単元が選ばれた | フォーム送信のトリガーとの連携に進む |
unknown が多い | 言い方の列が足りない。構成は有効 |
相談を study に分けたものがある | 指示の書き方と consult の寄せ方を見直す。ここは連携に進む前に直す |
3行目は、件数が少なくても見過ごさないでください。 50件のうちの1件でも、相談が講師に届く経路が残っていることを示しています。 指示に相談の例を足し、同じ50件でもう一度確かめます。
08実装時につまずきやすいポイント
| 問題 | 対策 |
|---|---|
| 相談が勉強の質問として講師に届く | 迷ったら consult に寄せる。 試すときに相談の例を必ず入れる |
| 一覧に無い単元が返る | スキーマの enum で縛り、スクリプトで一覧と照合する |
| 科目の欄を信じて誤った講師に届く | 本文を優先し、subject_mismatch を立てる |
| 「明日」を誤った日付にする | AIに日付へ直させない。 送信日時から計算する |
| 同時の送信で質問が1件消える | ロックを取ってから台帳に書く |
| 分類の結果に解き方が混ざる | 回答とヒントの両方を禁じる |
| トリガーが個人のアカウントで動いている | 運営部の共有アカウントで作る |
| トリガーの失敗に誰も気づかない | 失敗の通知メールが届く先を共有アカウントにする |
| 学期が変わって割り当てが外れる | 担当表の更新を学期初めの作業に入れる |
unknown が減らない | 運営スタッフが言い方の列に質問の言葉を足す |
| API の失敗で質問が止まる | muteHttpExceptions を true にし、「分類失敗」として人に回す |
上の2行が、この構成の失敗のほとんどです。 どちらも、AIに選ばせる範囲を、決められた選択肢の中に閉じ込められているかという同じ問題です。迷ったときの寄せ先と、選べる ID の範囲を設計で決めておくかどうかで、運用に乗るかが決まります。
5行目は、テスト前に初めて表に出ます。 普段は質問が重ならないので、ロックの無いスクリプトでも動いてしまいます。質問がいちばん多い日に、1件消えます。
09セキュリティ・AIガバナンス上の注意点
この構成で扱うデータ: 生徒番号、学年、教室、質問の本文、そして本文に書かれることのある生徒の悩みや家庭の事情です。生徒の多くは未成年です。
- 生徒の名前をAIへ渡さない … 分類に必要なのは学年と本文だけです。生徒番号から名前を引くのはスクリプトの側で、AIへ送る内容には含めません
- 相談は講師に回さない …
consultに分けたものは教室長が直接読みます。本文を要約して講師へ渡すこともしません - Gemini API は有料の枠で使う … 無料の枠では、機密や個人の情報を送らないよう求められています。試すときも、実際の生徒の質問は有料の枠で扱います
- 本文の連絡先を伏せる … 生徒が本文に自分の電話番号やSNSの名前を書くことがあります。前処理で伏せてからAIへ渡します
- 台帳を見られる人を限る … 質問の台帳には、生徒の悩みが残ることがあります。閲覧は運営スタッフと教室長に限り、講師には自分に割り当てられた質問だけをメールで届けます
- 保護者への説明を決めておく … 質問の仕分けに外部のAIサービスを使うことを、入塾時の案内にどう書くかを、自社の個人情報の担当者と決めてください
誤りが起きた場合のリスクは、相談を講師へ回してしまうことと、急ぎの質問を急ぎでないものとして扱うことの2つです。 前者は consult への寄せ方で、後者は期限を規則で計算することで防ぎます。どちらも、AIの判断に頼らない側に決めごとを置いてあることが守りになります。
10まず何から始めるか
1週目:単元一覧と担当表をそろえる
中学2年と中学3年の単元一覧に ID を振り、言い方の列を過去の質問から埋めます。 担当表を「学年×科目×講師」の形に並べ直します。いきなり全学年はやりません。質問の多い学年から始めます。
2週目:50件で試す
先月の質問から50件を選び、手元のAIサービスで分類させます。相談を study に分けたものが無いかを最優先で見ます。
3週目:期限の規則を決める
急ぎの質問をいつまでに答えるかを、教室長と講師の代表で決めます。定期テストの日程をシートに入れます。 トリガーを作るアカウントを運営部の共有アカウントに決めます。
4週目:フォーム送信から割り当てまでをつなぐ
フォーム送信のトリガーで分類し、担当表から講師を決めてメールで回すところまで作ります。この時点では、運営スタッフが全件の割り当てを見て、誤りを数えます。
2か月目: 回答用フォームと、1時間ごとの遅れの検知を足します。3か月目以降: 残りの学年の単元一覧を整え、1件3分が何分になったかを実測します。単元ごとの unknown が月に数件まで減り、テスト前の月でも期限切れの知らせが数件に収まった時点で、この構成は完成です。
11関連ユースケース
12この仕組みを理解するための記事
13技術仕様の確認日・参考情報
| 確認した内容 | 情報源 | 確認日 |
|---|---|---|
| インストール型のトリガーに、フォーム送信(Google フォーム用とスプレッドシート用)と時間主導型があること。時間主導型が毎分から月1回まで設定できること。トリガーが作った人のアカウントで動き、メールもその人のアカウントから送られること。失敗時に失敗をまとめたメールが届くこと | Google for Developers: Installable Triggers | 2026-10-06 |
スプレッドシートのフォーム送信のイベントに、namedValues(質問の名前と値)、range、values(スプレッドシートの列の順)、triggerUid、authMode が入ること | Google for Developers: Event Objects | 2026-10-06 |
| 1回の実行が6分まで、Google Workspace のアカウントでメールの受信者が1日1,500人、URL Fetch が1日100,000回、トリガーの合計実行時間が1日6時間であること。上限が予告なく変わりうること | Google for Developers: Quotas for Google Services | 2026-10-06 |
getScriptLock で、どの利用者もコードの一部を同時に実行できないようにすること。tryLock/waitLock でロックを取ること | Google for Developers: Class LockService | 2026-10-06 |
fetch(url, params) の method・contentType・headers・payload。muteHttpExceptions を true にすると失敗の応答でも例外を投げずに応答を返すこと | Google for Developers: Class UrlFetchApp | 2026-10-06 |
response_format に MIME タイプ application/json とスキーマを渡すこと。enum・required が使え、enum が分類の用途に挙がっていること。値をアプリケーションの側で検査すべきこと | Google AI for Developers: Structured outputs | 2026-10-06 |
| 無料の枠では送った内容と応答が製品の改善に使われ、人が確認することがあり、機密や個人の情報を送らないよう求められていること。有料の枠ではプロンプトと応答を製品の改善に使わないこと | Google AI for Developers: Gemini API Additional Terms of Service | 2026-10-06 |
回答の期限の決め方と、相談をどう扱うかは、自社の教室長と運営の責任者で決めてください。 本記事は上記の公開情報で確認できた範囲だけを扱っています。生徒の質問を外部のAIサービスで扱うことの法令上の扱いと保護者への説明は、自社の個人情報の担当者と専門家に確認してください。
実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。
自社の業務に使えるAI活用候補を整理します
このユースケース(UC-0475)についてのご相談はこちらから。
