SaaSのサポート窓口が過去の入電・チャットの数と施策の予定表から Python で2週間先の日ごと・時間帯ごとの問い合わせを見込み、席数の案を作る
過去の電話とチャットの受付数と、メール配信・キャンペーン・リリースなどの施策の予定表から、2週間先までの1時間ごとの問い合わせ数を窓口別に見込みます。見込みを必要な席数に直し、施策ごとの上乗せの内訳を添えて運用の担当に渡します。
- 連携・自動化
- Python
- 対象業界
- EC/IT・SaaS/金融
- 対象部門
- カスタマーサポート
- 対象業務
- 集計・分析
- 主な課題
- 人手が足りない/判断に時間がかかる/属人化している
- AIで行う処理
- 予測
- 主な効果
- 判断支援/対応スピード向上/工数削減
- 導入難易度
- ★★★★☆
- 実装レベル
- 本格構成
- 費用感
- 個別開発(大)
- 人間の確認
- 必須
01導入前 / 導入後の業務フロー
- 毎週、電話とチャットの仕組みから、前年の同じ週と直近4週の1時間ごとの受付数を書き出す
- 表計算で曜日・時間帯ごとの平均を出し、月末・月初の週は増やす
- マーケティングと開発の予定表を見に行き、向こう2週間に入っている施策を拾う
- 過去に似た施策があった週の受付数を探し、どれだけ増えたかを思い出して上乗せする
- 1時間ごとの受付数と平均の対応時間から、席数の計算の表で必要な席数を出す
- シフトの管理表に席数の枠を書き、責任者に見せる
- 施策の日程が変わったと連絡が来たら、その日の分を手で直す
- 人マーケティングと開発の担当が、施策を決めたら施策の予定表に1行書く(種類・日時・対象の数・窓口への影響の有無)
- 自動毎週木曜の夜と、施策の予定表が変わったときに、プログラムが動く
- 自動電話とチャットの仕組みから、直近までの1時間ごとの受付数と平均の対応時間を書き出したファイルを読み込む
- 自動暦(曜日・祝日・月末・給与の締め)と施策の予定を、1時間ごとの項目に直す
- 自動窓口ごとに、向こう2週間の1時間ごとの問い合わせ数の見込みを出す
- 自動見込みから、真ん中と多めの数を出し、施策が無かった場合の数との差を施策ごとの上乗せとして出す
- 自動多めの数と平均の対応時間から、電話は待ち時間の目標、チャットは同時に受ける数から必要な席数を出す
- 自動施策の山が大きい時間、前回から席数が大きく動いた時間、施策の種類が新しいものに印を付ける
- 人運用の担当が、印の付いた日だけを開いて見込みを確かめ、席数の枠を直す
- 人責任者が席数の枠を決め、シフトの管理表に反映する
各工程の詳しい説明を読む
- 毎週、電話とチャットの仕組みから、前年の同じ週と直近4週の1時間ごとの受付数を書き出す
- 表計算で曜日・時間帯ごとの平均を出し、月末・月初の週は増やす
- マーケティングと開発の予定表を見に行き、向こう2週間に入っている施策を拾う
- 過去に似た施策があった週の受付数を探し、どれだけ増えたかを思い出して上乗せする
- 1時間ごとの受付数と平均の対応時間から、席数の計算の表で必要な席数を出す
- シフトの管理表に席数の枠を書き、責任者に見せる
- 施策の日程が変わったと連絡が来たら、その日の分を手で直す
(a)施策の効き方が記憶にしかない。 4番目の「似た施策で何件増えたか」は、施策の記録と受付数の記録が別の場所にあるため、長く担当している1名の記憶で埋めています。 配信の対象が全利用者か一部か、件名が料金の話か機能の話かで、増え方は大きく違います。
(b)予定が直前まで届かない。 3番目で予定表を見に行っても、書かれていない施策があります。メール配信の日が前日に決まることもあり、 席数の枠を組んだ後に山が来ます。その日は電話が鳴りっぱなしになり、チャットの返事が数十分遅れます。
(c)前年の同じ週が当てにならない。 契約の利用者は1年で増えています。前年の数をそのまま使うと少なめに出ます。 かといって全体を何割か増やすと、施策が無い週が多めに出ます。
(d)見込みが1つの数しかない。 席数を平均の受付数で組むと、半分の時間は足りません。どれだけ多めに組むかは担当者ごとに違い、 その違いが週ごとのつながりやすさの違いになっています。
- 【人】 マーケティングと開発の担当が、施策を決めたら施策の予定表に1行書く(種類・日時・対象の数・窓口への影響の有無)
- 【自動】 毎週木曜の夜と、施策の予定表が変わったときに、プログラムが動く
- 【自動】 電話とチャットの仕組みから、直近までの1時間ごとの受付数と平均の対応時間を書き出したファイルを読み込む
- 【自動】 暦(曜日・祝日・月末・給与の締め)と施策の予定を、1時間ごとの項目に直す
- 【自動】 窓口ごとに、向こう2週間の1時間ごとの問い合わせ数の見込みを出す
- 【自動】 見込みから、真ん中と多めの数を出し、施策が無かった場合の数との差を施策ごとの上乗せとして出す
- 【自動】 多めの数と平均の対応時間から、電話は待ち時間の目標、チャットは同時に受ける数から必要な席数を出す
- 【自動】 施策の山が大きい時間、前回から席数が大きく動いた時間、施策の種類が新しいものに印を付ける
- 【人】 運用の担当が、印の付いた日だけを開いて見込みを確かめ、席数の枠を直す
- 【人】 責任者が席数の枠を決め、シフトの管理表に反映する
1番目が、この構成の入口です。 施策の予定表に書かれない施策は、見込みに出てきません。書く項目を4つに絞り、施策を決めた部署が書くことにしてあるのは、続けてもらうためです。
9番目で、人が見るのは印の付いた日だけです。 施策の無い平日はほぼ毎週同じ形になるので、流し見で足ります。時間を使うのは、施策の山がある日と、見込みが大きく動いた日です。
02今回想定するシステム構成
電話の受付の仕組み/チャットの受付の仕組み(1時間ごとの受付数・対応時間の書き出し) 施策の予定表(マーケティング・開発が記入) 内閣府の「国民の祝日」の表 │ ▼【トリガー】毎週木曜の夜/施策の予定表の変更 Python(pandas) ├──▶ 暦と施策の予定を、1時間ごとの項目に直す ▼ scikit-learn(HistGradientBoostingRegressor、loss="poisson") │ 窓口ごと・1時間ごとの問い合わせ数の見込み ▼ Python ── SciPy の poisson で多めの数/施策を外した場合との差で上乗せの内訳 ▼ Python ── 待ち時間の目標と同時に受ける数から、必要な席数 ▼ 【人が印の付いた日だけ確認】── 運用の担当 ▼ シフトの管理表(日 × 時間の席数の枠)── シフトの作成へ
| 役割 | 想定する製品 | 代替候補 |
|---|---|---|
| 実行環境 | Python(pandas・scikit-learn・SciPy) | R |
| 処理エンジン | scikit-learn の HistGradientBoostingRegressor(loss="poisson") | LightGBM、statsmodels の Poisson 回帰 |
| 集計 | Python(多めの数、上乗せの内訳、席数への換算) | 席数の計算の表 |
| データの取得元 | 電話とチャットの受付の仕組みの書き出し | 各仕組みの連携の機能 |
| 結果の出力先 | 共有フォルダのシフトの管理表 | 運用の連絡の場への通知 |
電話とチャットの受付の仕組み、シフトの管理表は、新しく足すものではありません。 受付の仕組みからは書き出すだけで、設定を変えることはしません。新しく作るのは施策の予定表だけです。 既存の部署ごとの予定表を1つにまとめ、書く項目をそろえます。
土台になるのは、scikit-learn の HistGradientBoostingRegressor です。 loss に "poisson" を選べ、内部で対数の結び付け(log-link)を使い、目的の値が0以上であることを求めます。 1時間ごとの問い合わせ数は0以上の数で、多い時間ほどばらつきも大きいので、この損失が合います。
欠けた値は、そのまま渡せます。 学習の際、分かれ目ごとに欠けた値を左右どちらへ送るかを、得られる改善の大きさから学ぶとされています。「直近の施策からの日数」は施策が無ければ値がありませんが、埋めずに渡せます。 カテゴリの項目は、categorical_features の既定 "from_dtype" で、データフレームの列の型がカテゴリなら、そのまま扱われます。
多めの数は、SciPy の scipy.stats.poisson で出します。 平均 μ のポアソン分布の確率と、累積の逆である ppf が使えます。見込みの平均を μ として、その分布の9割の位置を多めの数にします。
03どうやって実装するのか
処理の起点を決める
毎週木曜の夜と、施策の予定表が変わったときに動かします。 木曜に出すのは、運用の担当が金曜に翌々週のシフトの枠を組むからです。施策の予定表は共有フォルダの表なので、変更の日時を1時間ごとに見に行き、前回から変わっていれば出し直します。
出し直すのは、変わった施策の前後の日だけではなく、向こう2週間の全体です。施策が1つ増えると、近くの日の見込みも動くことがあるからです。ただし、シフトが確定済みの日の席数は書き換えず、差だけを知らせます。
月の初めには、前の月の見込みと実際の受付数の差をまとめて出します。外れた日と、その日にあった施策を並べ、施策の予定表の書き方の改善に使います。
入力データを集める
| データ | 中身 | 取得元 |
|---|---|---|
| 受付数 | 窓口(電話・チャット)、日時(1時間ごと)、受付数、平均の対応時間、放棄の数 | 電話・チャットの受付の仕組み |
| 施策の予定 | 施策の種類、開始の日時、対象の数(配信数・対象の利用者数)、窓口への影響の有無、担当部署 | 施策の予定表 |
| 暦 | 祝日、月末・月初、給与の締めの日、年末年始 | 内閣府の「国民の祝日」の表と自社の暦 |
| 利用者の数 | 月ごとの契約の利用者数 | 契約の管理の仕組みの月次の数 |
| 障害の記録 | サービスの障害の発生と復旧の日時 | 障害の報告の一覧 |
| 席の条件 | 窓口ごとの待ち時間の目標、同時に受けるチャットの数 | 運用の担当が入れる |
質を決めるのは、施策の予定表です。 施策の種類は、全利用者へのメール配信、一部の利用者へのメール配信、無料体験のキャンペーン、料金改定のお知らせ、新機能のリリース、計画的なメンテナンス、法改正への対応のアップデートの7つに分けます。種類を細かくしすぎると、1つの種類あたりの過去の例が少なくなります。
障害の記録は、学ばせない時間を決めるために使います。 サービスの障害が起きた時間の問い合わせは、施策とも暦とも関係なく跳ねます。この時間を学ばせると、同じ曜日・時刻の見込みが多めにずれます。
データの取得方法を決める
電話とチャットの受付の仕組みから、1時間ごとの受付数と平均の対応時間を、決まった列の並びで書き出す設定を作ります。多くの受付の仕組みには、時間帯ごとの集計を書き出す機能があります。連携の機能で自動化できるかは、それぞれの提供元に確かめます。 最初は担当者が週に1回書き出して共有フォルダに置く運用で始められます。
| 取るもの | どこから | 何に使うか |
|---|---|---|
| 1時間ごとの受付数 | 受付の仕組みの書き出し | 学ばせる目的の値 |
| 平均の対応時間 | 同上 | 席数への換算 |
| 放棄の数 | 同上 | つながらなかった問い合わせの補正 |
| 施策の予定 | 施策の予定表 | 施策の項目 |
| 祝日 | 内閣府の「国民の祝日」の表 | 暦の項目 |
祝日は、内閣府のページから「国民の祝日」の表を取ります。 昭和30年(1955年)から令和9年(2027年)までが表の形で載っていて、令和10年(2028年)の分は前年の2月に載せるとされています。年に1回、2月に取り直す予定を運用の手順に入れておきます。
AIへ渡す前に整形する
- 放棄の数を足す … 電話は、つながらずに切られた数を受付数に足します。席が足りなかった時間ほど受付数が少なく出るので、そのまま学ばせると少なめに見込みます
- 障害の時間を外す … 障害の記録の時間と、その後の2時間を学ばせる記録から外します
- 利用者の数で割る … 1時間ごとの受付数を、その月の契約の利用者数1万社あたりに直して学ばせ、見込みのときに戻します。利用者が増えた分を、前年の数に上乗せするためです
- 施策を項目に直す … 施策の種類ごとに、「開始からの経過時間(0〜168時間、それより後は値なし)」と「対象の数」の列を作ります
- 暦を項目に直す … 曜日、時刻、祝日、月末からの日数、給与の締めの日からの日数、年末年始の印
- 窓口を分ける … 電話とチャットで別のモデルを学ばせます。施策の効き方が窓口によって違うからです
- 受付時間外を外す … 電話の18時以降、土日を学ばせる記録と見込みの対象から外します
1番目を軽く見ないでください。 施策の山の日は、まさに席が足りずに放棄が多い日です。放棄を足さずに学ばせると、施策の効き方が小さく見え、次の山でもまた席が足りなくなります。 同じ人がかけ直した分が二重に入るので、放棄の数は半分を足す、のように自社で規則を決めます。
AIに処理させる
させるのは、窓口ごと・1時間ごとに「問い合わせが平均で何件来るか」を見込むことだけです。 多めの数、施策ごとの上乗せの内訳、席数への換算、印付けは、決まった計算で行います。
| 見込むもの | 使うもの | 判断できないときの扱い |
|---|---|---|
| 1時間ごとの問い合わせ数の平均 | 暦、施策の種類ごとの経過時間と対象の数、直近4週の同じ曜日・時刻の数 | 過去の例が3回未満の種類の施策は new_type |
| 多めの数(10時間のうち9時間はこれを下回る) | 平均と、過去の外れ方から決めた倍率 | 同上 |
| 施策ごとの上乗せ | 施策を入れた見込みと、その施策を外した見込みの差 | 施策が重なる時間は overlap |
施策ごとの上乗せは、同じモデルに「その施策が無かった場合」の項目を入れてもう一度見込み、その差で出します。 運用の担当には、「火曜10時の見込み85件のうち、料金改定のお知らせの分が30件」のように見えます。この内訳があると、マーケティングに配信の時刻をずらしてもらう相談ができます。
1日の合計を見込んでから時間に割り振る形にしないのは、意図してのことです。 施策の山は1日の中で偏ります。メール配信の山は配信から2〜3時間、リリースの山は朝の始業の時間に来ます。1日の合計を曜日ごとの時間の割合で割ると、山の時間が薄まり、 席が足りないのはまさにその時間になります。1時間ごとに直接見込めば、施策の経過時間の項目がそのまま山の形を作ります。
多めの数は、ポアソン分布の9割の位置だけでは足りません。 実際の問い合わせは、ポアソン分布の想定よりばらつきます。そのため、過去の見込みで実際に9割の時間が多めの数を下回っていたかを確かめ、 下回っていなければ、平均に掛ける倍率を足して調整します。
| させないこと | 理由 |
|---|---|
| シフトの確定と個人の勤務の割り当て | 勤務の希望と労働時間の管理は運用の担当が行う |
| 施策の日程を動かす判断 | 施策の目的と効果はマーケティングと開発が決める |
| 障害の発生の予測 | 過去の記録から見込めない。起きたら別の手順で対応する |
| 予定表に無い施策の推測 | 書かれた施策だけを使う |
| 受付時間の変更の判断 | 利用者との約束に関わる。責任者が決める |
4行目がいちばん起きやすい失敗です。 毎月同じ時期に配信があったからといって、予定表に無い配信をモデルが勝手に見込むと、施策が取りやめになった月に席が余ります。 予定表に書かれないものは見込みに入れず、代わりに予定表を書く運用を守ってもらいます。
指示内容を固定する
この構成は生成AIを使わないので、プロンプトの代わりに、モデルの設定と換算の規則を書いておきます。
【モデル(窓口ごとに1つ)】
- HistGradientBoostingRegressor(loss="poisson")
- 目的の値 = 1時間ごとの受付数(放棄の半分を足す)÷ 利用者数(1万社あたり)
- categorical_features = ["weekday", "hour", "holiday", "season_flag"]
- 施策の項目 = 種類ごとの経過時間(0〜168、範囲外は NaN)と対象の数
- monotonic_cst で「対象の数」は増える向きに制約する
(配信数が多いほど問い合わせが減る、という形を学ばせない)
- 学ばせ方と確かめ方は TimeSeriesSplit
・test_size = 2週間分、gap = 1週間分(木曜に翌々週を見込む使い方にそろえる)
【多めの数】
- 多め = poisson.ppf(0.9, 平均 × 倍率)
- 倍率の初期値 = 1.0。毎月、過去8週で実際の受付数が多めを
下回った時間の割合を数え、0.85 未満なら倍率を 0.05 ずつ上げる
【施策ごとの上乗せ】
- 上乗せ = 見込み(施策あり)− 見込み(その施策の列を NaN にしたもの)
- 同じ時間に施策が2つ以上あれば、それぞれの上乗せと、両方を外した差を並べる
【席数への換算】
- 電話 … 多めの数と平均の対応時間から、待ち行列の式(アーランC)で
「80%の電話に20秒以内に出る」を満たす最小の席数
+ 休憩・後処理の分として 1 ÷ (1 − 0.3) を掛け、切り上げ
- チャット … 多めの数 × 平均の対応時間 ÷ 60 ÷ 同時に受ける数(2)を切り上げ
【印を付ける条件】
- peak … 施策の上乗せが、その時間の見込みの3割以上
- new_type … 過去の例が3回未満の種類の施策がある
- overlap … 同じ時間に施策が2つ以上
- shift … 前回の出し直しから席数が2席以上動いた
- locked … シフトが確定済みの日に席数の差が出た(書き換えず知らせる)
- 印の無い日は、運用の担当の確認なしで席数の枠に書く
monotonic_cst を入れるのは、意図してのことです。 過去の施策の数が少ないと、「配信数が多いのに問い合わせが少なかった」1回の例を学んで、配信数が増えるほど問い合わせが減る形を作ることがあります。 増える向きに制約しておけば、その形は出ません。
電話に待ち行列の式を使い、チャットに使わないのは、待ち方が違うからです。 電話は1人のオペレーターが1本ずつ受け、空いた席が無ければ利用者は待ち続けます。1時間に来る数と1本あたりの対応時間が分かれば、「何席あれば何割の電話に何秒以内に出られるか」を式で出せます。チャットは1人が同時に複数を受けられ、返事が数分遅れても利用者は待っていてくれるので、 必要な対応の時間を同時に受ける数で割る簡単な換算で足ります。
待ち行列の式の目標(80%を20秒以内)は、自社の目標に置き換えてください。 ここは見込みの精度より、どれだけのつながりやすさにいくらの人件費をかけるかという経営の判断です。
出力形式を固定する
窓口・日・時間ごとに、次の形のJSONを作り、表にしてシフトの管理表へ渡します。
{
"channel": "phone | chat",
"date": "",
"hour": 0,
"forecast": { "mean": 0, "p90": 0 },
"baseline_without_campaigns": 0,
"campaign_uplift": [
{ "campaign_id": "", "type": "", "uplift": 0 }
],
"aht_sec": 0,
"seats": { "required": 0, "planned": null },
"flags": ["peak | new_type | overlap | shift | locked"],
"model_version": "",
"planner_override": { "seats": null, "reason": "" }
}
1つ目の理由は、baseline_without_campaigns と campaign_uplift を分けて見せられることです。 施策が無ければ何件で、どの施策で何件増えるのかが1行で分かります。マーケティングとの相談は、この2つの列だけで足ります。
2つ目は、required と planned を分けて持てることです。 required は計算で出した席数、planned は運用の担当がシフトに書いた席数です。両方を残すと、席数を削った時間に放棄が増えたかを後から確かめられます。
3つ目は、planner_override で直した記録が残ることです。 運用の担当が「この配信はいつもより反応が小さい」と判断して直したら、その理由を書きます。どちらが当たったかを、翌週に比べられます。
システムへ連携する
| つなぎ先 | 方式 | 内容 |
|---|---|---|
| 電話・チャットの受付の仕組み | 書き出したファイルの読み込み | 1時間ごとの受付数・対応時間・放棄の数 |
| 施策の予定表 | 共有フォルダの表の読み込みと、変更の検知 | 施策の種類・日時・対象の数 |
| 障害の報告の一覧 | 共有フォルダの表の読み込み | 学ばせない時間 |
| シフトの管理表 | 共有フォルダへの書き出し | 日 × 時間の席数の枠(確定済みの日は書き換えない) |
| 運用の連絡の場 | 通知 | 印の付いた日と、施策の予定表の変更による出し直し |
受付の仕組みへは書き込みません。 出すのは席数の枠の案までで、シフトを確定させるのは運用の担当です。 確定済みの日を書き換えないのは、オペレーターに伝えた勤務を勝手に変えないためです。
人が確認する
人が開くのは、印の付いた日だけです。 印の無い日は、席数の枠の表を流し見ます。全件を開く設計にすると、第10章の8.0時間には収まりません。
new_typeを先に見る … 過去の例が少ない施策は、見込みが当てになりません。施策の担当に、対象の数と案内の中身を聞いて判断しますoverlapとpeakを見る … 施策が重なる時間は、配信の時刻をずらせないかをマーケティングに相談しますshiftを見る … 席数が大きく動いた理由が、施策の予定の変更か、直近の受付数の変化かを確かめますlockedを見る … 確定済みの日に足りない席が出たら、残業や応援の手配を責任者と決めます- 直したら理由を書く …
planner_overrideに値と理由を残します
2番目が、この構成のいちばん効く使い方です。 席を増やすより、配信を1時間ずらしてもらうほうが安く済むことがあります。内訳が見えていれば、その相談を配信の前にできます。
例外に対処する
| 起きること | 対応 |
|---|---|
| 受付数の書き出しが届いていない | 前回の見込みを残し、運用の担当に知らせる。古い数で出し直さない |
| 施策の予定表に種類の無い施策が書かれた | new_type を付け、施策の担当に近い種類を聞く |
| 施策の日程が当日になって変わった | 出し直し、locked の日は差だけを知らせる |
| サービスの障害が起きた | 見込みは使わず、障害の対応の手順に切り替える。その時間は後で学ばせる記録から外す |
| 受付時間を変えた | 変えた日から別の項目を立て、変更前の記録の扱いを決める |
| 新しい窓口(メールなど)を足した | 記録が3か月たまるまでは見込みを出さない |
| 祝日の表に翌年の分が無い | 2月の更新を待ち、それまでは翌年の分を見込みに入れない |
| 多めの数を下回った時間が9割に届かない | 倍率を上げ、model_version を上げる |
上から3行目と4行目が大半を占めます。 どちらもモデルの問題ではなく、施策と障害の情報がサポートに届く速さの問題です。 施策の予定表と障害の報告を同じ連絡の場に流すほうが、精度を上げる工夫より効きます。
記録を残す
- 読み込んだ受付数の書き出しのファイルと、書き出した日時
- そのときの施策の予定表の内容(変更の前後を両方残す)
- 窓口・日・時間ごとの見込み、多めの数、施策ごとの上乗せ
- 席数の計算に使った目標と平均の対応時間
- 運用の担当が直した値と理由
- 実際の受付数と放棄の数、見込みとの差
- 多めの数の倍率と、それを決めたときの「9割を下回った時間の割合」
最後の行は、倍率を上げ下げした理由を残すためです。 倍率は席数にそのまま効くので、誰がいつ何を見て変えたかが残っていないと、人件費が増えた理由を説明できません。
2つ目で施策の予定表の変更の前後を残すのは、外れた理由を後から分けるためです。 見込みが外れた日が、モデルの外れなのか、予定表が直前に変わったのかで、直すところが違います。予定表の変更が配信の何日前だったかを数えると、マーケティングとの約束(何日前までに書くか)を決める材料になります。
04実装レベルの3段階
最小構成では、施策が重なった日が読めません。 種類ごとの差を足し合わせるだけなので、重なったときの効き方は出ません。確かめるための段階です。 半自動化で、過去の受付数を探して平均を出す時間はほぼ無くなります。 ただし、席数への換算と、施策の予定表の変更を受けた直しは手で残ります。本格構成で、運用の担当が見るのは印の付いた日だけになり、この段階が本記事の想定です。 差が大きいのは、施策の日程の変更が週に何度もあり、そのたびの直しが手作業だからです。 段階を飛ばさないでください。 半自動化の見込みを1か月並べると、外れやすい施策の種類と、予定表に書かれずに来た施策が先に分かります。そこを直してから本格構成に進むほうが、印の付く日が減ります。
05工数削減シミュレーション
導入後 60件 × 8分 ÷ 60 = 8 時間/月
自社条件で導入効果を整理したい方へ
このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。
06向いている企業・向いていない企業
- 中小企業向けのクラウドの業務ソフトなどを提供し、電話とチャットのサポート窓口を数十名で回しているSaaSの会社。メール配信、無料体験のキャンペーン、料金改定のお知らせ、新機能のリリースのたびに問い合わせが跳ね、その山を運用の担当が経験で読んでいる場合。マーケティングと開発の予定がサポートに直前まで届かず、席が足りない日と余る日が毎月出ている場合。電話とチャットの仕組みから1時間ごとの受付数と対応時間を1年以上取り出せる場合。
- サポートの担当が数名で、全員が同じ時間に勤務している場合。問い合わせの記録が1日の合計しか残っていない場合。施策の予定が事前に分からず、表に書き出す運用も作れない場合。なお、シフトを確定させる判断、個人ごとの勤務の割り当て、施策の日程を動かす判断は、この構成では代替できません。
07最小構成で試す方法
- 過去1年の1時間ごとの受付数を電話とチャットの仕組みから書き出す
- マーケティングと開発に頼んで、過去1年の施策の日時と種類と対象の数を一覧にしてもらう
- 表計算で、施策の無い日の曜日・時間帯ごとの平均を出す
- 施策のあった日について、実際の受付数と3番目の平均との差を、施策の種類ごとに並べる
- 種類ごとに、差の平均と、対象の数1万あたりの差を出す
2番目に時間がかかっても、必ずやってください。 過去の施策の一覧が作れないなら、この構成の前提である施策の予定表も続きません。 一覧を作る過程で、どの部署がどこに予定を書いているかが分かります。
| 出てきた内容 | 判断 |
|---|---|
| 施策の種類ごとに、増え方がはっきり違う | Python で見込みのモデルに進む |
| どの施策でもほとんど増えない | 問い合わせは暦で決まっている。曜日と月末の見込みで足りる |
| 過去の施策の一覧が半分も作れない | 施策の予定表の運用を作るのが先 |
3行目が出ることは珍しくありません。 失敗ではなく、山を経験で読むしかなかった理由が1つ分かったということです。 施策の予定表を先に作り、3か月たまってからもう一度試してください。
08実装時につまずきやすいポイント
| 問題 | 対策 |
|---|---|
| 施策の予定表が書かれない | 書く項目を4つに絞り、何日前までに書くかを部署の責任者と決める |
| 放棄を足さずに学ばせ、山を小さく見込む | 放棄の数を足す規則を決める |
| 障害の時間を学ばせ、同じ時刻が多めにずれる | 障害の記録の時間を外す |
| 利用者の増加を見込まない | 利用者数あたりに直して学ばせる |
| 配信数が多いほど減る形を学ぶ | monotonic_cst で増える向きに制約する |
| 多めの数がポアソン分布だけでは狭い | 実際に9割を下回ったかを数え、倍率で調整する |
| 未来の記録で学ばせて過去を確かめてしまう | TimeSeriesSplit で時間の順に分け、gap を空ける |
| 確定済みのシフトを書き換える | locked の日は差だけを知らせる |
| 施策の種類を細かく分けすぎる | 7つ程度に絞る。1種類あたりの過去の例が少なくなる |
| 予定表に無い施策を見込みたくなる | 入れない。書く運用を守ってもらう |
| 1日の合計を時間に割り振って山が薄まる | 1時間ごとに直接見込む |
| チャットに電話と同じ式を当てる | 同時に受ける数で割る換算にする |
| 祝日の表の翌年の分を取り忘れる | 毎年2月に取り直す予定を運用の手順に入れる |
上の2行が、この構成の失敗のほとんどです。 どちらも、山の日の記録が実際より小さく残ることから出てきます。山を見込むための構成で、山の記録が欠けていては意味がありません。
09セキュリティ・AIガバナンス上の注意点
この構成で扱うデータ: 窓口ごとの1時間ごとの受付数と対応時間、施策の予定、障害の記録です。利用者の氏名や問い合わせの中身は使いません。
- 施策の予定は社外秘として扱う … 料金改定や新機能のリリースの日程は、公表前の情報です。施策の予定表と見込みの表を見られる人を、サポートの運用の担当と施策の担当に絞ります
- 問い合わせの中身を入力に入れない … 見込みに要るのは数だけです。受付の仕組みの書き出しの設定から、通話の記録やチャットの本文を外します
- 計算は社内の環境で行う … 外部の生成AIのサービスに施策の予定表を貼り付けて見込ませる使い方はしません
- シフトを自動で確定しない … 出すのは席数の枠の案までです。オペレーターの勤務は、本人の希望と労働時間の管理を見て人が決めます
- 個人の対応の速さの評価に使わない … 平均の対応時間は窓口全体の数で使い、オペレーターごとの評価の材料にはしません
- 見込みを社外に出さない … 施策ごとの上乗せの内訳は、どの施策でどれだけ問い合わせが増えたかという、サービスの分かりにくさを映した数字でもあります。社内の改善の材料に限ります
誤りが起きた場合のリスクは、席が足りずに電話がつながらないことと、席が余って人件費がかかることの2つです。 前者は施策の予定表の漏れと放棄の扱いから起き、後者は多めの数の倍率を上げすぎると起きます。倍率は毎月、実際に9割を下回ったかで調整します。
10まず何から始めるか
1週目:施策の一覧を作る
マーケティングと開発に頼み、過去1年の施策の日時・種類・対象の数を一覧にしてもらいます。何割の施策が日時まで分かるかを数えます。半分に届かないなら、施策の予定表の運用から始めます。
2週目:施策の効き方を表計算で見る
第8章の手順で、施策の種類ごとの増え方を出します。種類によって増え方がはっきり違うかを見ます。
3週目:施策の予定表を作る
部署ごとの予定表を1つにまとめ、書く項目を4つ(種類・日時・対象の数・窓口への影響の有無)にそろえます。何日前までに書くかを、部署の責任者と決めます。 あわせて、放棄の数の扱いを運用の担当と決めます。
4週目:Python で見込みを出す
電話の窓口だけで、HistGradientBoostingRegressor のポアソン損失のモデルを学ばせ、向こう2週間の1時間ごとの見込みと多めの数を出します。この時点では席数には換算せず、見込みと実際の受付数を毎日並べます。
2か月目: チャットの窓口と施策ごとの上乗せの内訳、席数への換算を足し、印付けを入れます。3か月目以降: 予定表の変更での出し直しを足し、1件30分が何分になったかを実測します。多めの数を実際に9割の時間で下回るようになり、マーケティングと配信の時刻を相談できるようになった時点で、この構成は完成です。
11関連ユースケース
12この仕組みを理解するための記事
13技術仕様の確認日・参考情報
| 確認した内容 | 情報源 | 確認日 |
|---|---|---|
loss に 'squared_error'・'absolute_error'・'gamma'・'poisson'・'quantile' を選べること。'poisson' が内部で対数の結び付けを使い、目的の値が0以上であることを求めること。欠けた値をそのまま扱い、分かれ目ごとに左右どちらへ送るかを改善の大きさから学ぶこと。categorical_features の既定が "from_dtype" であること。monotonic_cst で増える向き・減る向きの制約を項目ごとに付けられること | scikit-learn: HistGradientBoostingRegressor | 2026-10-15 |
時間の順に並んだデータを分けること。n_splits・max_train_size・test_size・gap(学ばせる期間の末尾から確かめる期間の前までを除く数)の意味 | scikit-learn: TimeSeriesSplit | 2026-10-15 |
ポアソン分布の確率の式と、平均 μ が0以上であること。累積の逆である ppf が使えること | SciPy: scipy.stats.poisson | 2026-10-15 |
| 「国民の祝日」の表が昭和30年(1955年)から令和9年(2027年)まで載っていること。令和10年(2028年)の分は前年の2月に載せるとされていること | 内閣府: 国民の祝日について | 2026-10-15 |
席数の目標(待ち時間の目標と後処理の割合)は、自社のサービスの水準と人件費の判断で決めてください。 本記事の数値は設定の例で、上記の公開資料で確認できた範囲だけを扱っています。
実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。
自社の業務に使えるAI活用候補を整理します
このユースケース(UC-1747)についてのご相談はこちらから。
