Jev で問い合わせを振り分け、自信のないものだけ人に回せるか

  • Jev
  • LLM

分類を自動化しようとすると、たいてい全部任せるか全部やめるかの二択になる。9割当たるなら9割は任せたい。でも外れる1割がどれか分からないので、結局すべて目視する。

確率が返るモデルなら、ここを分けられるはずだった。確信しているものは通し、迷っているものだけ人に回す。このやり方は、外れやすいところに人手を集中できるので、全件見るより安い。

同じ文面に4つ聞く

架空のネット銀行に届いた問い合わせを10件作って、それぞれに4つの質問を投げた。使ったのは Jev で、質問の型が3つある。

  • department(choice):口座管理、振込、投資商品、アプリ不具合、本人確認、その他から一つ選ばせる
  • needs_same_day(noul):当日中に担当者が対応する必要があるか。確率で返る
  • is_offensive(noul):担当者への暴言が含まれるか
  • frustration(score):穏やか、苛立ちあり、強い怒りの3段階のどこか

判断が割れるものを混ぜてある。「身に覚えのない出金が3件あります。確認をお願いします」は、文面が穏やかなのに当日対応が要る。「いい加減にしてください。3回問い合わせても誰も答えません。責任者を出してください」は、強い苦情ではあるが暴言ではない。

結果は型で綺麗に分かれた。

質問 型 一致
department choice 10/10
needs_same_day noul 10/10
is_offensive noul 10/10
frustration score 8/10

文面が穏やかで緊急、という組み合わせも、強い苦情と暴言の区別も、外さなかった。落ちたのは3段階のスコアだけだった。

線を引く場所がない

では自信のないものを人に回そう、と confidence を見にいったところで詰まった。

confidence は「その答えがどれくらい確からしいか」を表す数値で、選択肢の確率が片方に寄っているほど高くなる。ところが、返ってくる質問と返ってこない質問がある。

"needs_same_day": { "type": "noul", "noul": 0.82 },
"department":     { "type": "choice", "choice": "security",
                    "probabilities": { "security": 0.98, "account": 0.02 },
                    "confidence": 0.96 },
"frustration":    { "type": "score", "score": 0.65,
                    "probabilities": { "0": 0.36, "1": 0.63, "2": 0.01 },
                    "confidence": 0.43 }

confidence が返るのは choice と score だけだった。noul は確率そのものしか返さない。

考えてみれば当然で、二値の確率は 0.82 と言った時点で確信の度合いも同時に言っている。0.5 からの距離がそのまま確信になる。選択肢が3つ以上あると、同じ「一番高いのは0.4」でも残りが 0.35 と 0.25 に割れているのか 0.3 と 0.3 なのかで意味が違うので、別の数字が要る。

つまり noul に線を引くなら、confidence ではなく 0.5 からの距離を使うことになる。0.3 から 0.7 のあいだを人に回す、ということになる。

引いてみたが、何も買えなかった

needs_same_day でその帯に入ったのは2件だった。「昨日の15時に振込手続きをしましたが、相手先にまだ着金していないようです」が 0.41、「振込の画面でエラーコードが出て先に進めません」が 0.44。

どちらも正解だった。

noul は10件とも当たっていたのだから、当然そうなる。2件を人に回す運用は、2割を人件費に変えて、何も買っていない。

外れるものがない範囲に線を引いても意味がない。当たり前の話だが、裏返すと、精度が出ているうちは線引きの設計そのものが要らない。線が効くのは、外れるほうの質問のほうだ。

score は高いところで切らないと止まらない

落ちた frustration の2件を confidence と並べる。

ケース Jevの答え confidence 正解
身に覚えのない出金 苛立ちあり 0.33 穏やか
着金していない 穏やか 0.60 苛立ちあり

低い。confidence が 0.90 以上だった6件はすべて正解だった。ここまでは期待どおりだった。

ところが質問文を英語に書き換えて同じ10件を回すと、confidence 0.80 で外すケースが出た。2回の実行を合わせると、0.90 以上の12件は全部正解で、誤りは 0.33 と 0.60 と 0.80 に散っている。

0.7 で切ると 0.80 の誤りが素通りする。0.9 で切れば全部止められるが、そのとき10件のうち4件から5件が人の手に回る。半分近くを見るなら、最初から全部見るのとどれだけ違うのか。

正解のほうを疑う

もっとも、外した2件は正解ラベルのほうが怪しい。

正解ラベルというのは、ケースを作るときにこちらで付けた「本当はこうであるべき」という答えのことだ。一致率は、モデルの出力とこのラベルがどれだけ合ったかを測っている。ラベルが間違っていれば、正しい答えが不正解として数えられる。

「昨日の15時に振込手続きをしましたが、相手先にまだ着金していないようです」に苛立ちありを付けたのはこちらの判断で、文面そのものは丁寧だ。Jevは日本語版で 0.27、英語版で 0.13 と、二度とも穏やか側に置いた。どちらが正しいかは、この文だけでは決まらない。

3段階のラベルは人間どうしでも揃わない。揃わないものを正解にして測っているので、8割という数字はモデルの精度ではない。こちらが付けたラベルとどれだけ合ったか、というだけの数字だ。

確率のぶれ

線引きの話をする前に、確率そのものが実行ごとにどれだけ動くのかを見ておいた。同じ入力でも毎回まったく同じ値が返るとは限らないので、閾値の近くにいる判定は実行ごとに変わりうる。

40のケースと質問の組を5回ずつ回して、判定が反転したものは0件、確率の幅は最大 0.08 だった。

動き方に癖がある。0.00 や 2.00 や 0.06 のように端に振れているものは、5回とも小数第2位まで同じ値を返す。幅が出るのは 0.41 から 0.44、0.52 から 0.58 のような、真ん中にいるケースだけだった。

閾値の近くにいるものほどぶれる。運用としては嫌な性質だ。ただ、ぶれること自体が「ここは割れる」という情報でもある。

結局どう組むか

二値に落とせる質問は落としたほうがいい。noul は10件とも当たったうえ、確率そのものが確信の度合いを兼ねているので、読む数字が一つで済む。

3段階以上を使うなら、confidence 0.9 で切って半分近くを人に回す前提で見積もる。そして、そこまでして測っているものが本当に3段階要るのかを先に疑ったほうがいい。「苛立ちあり」と「強い怒り」を分ける必要があったのかは、今回のケースを作った側として自信がない。

線を引ける場所と、引く意味のある場所は別だった。