⚖️ 日本語ドキュメント
English →

⚖️判定ロジックと精度の記録

確定した判定の仕組み + 暫定の精度(Wilson 95%CI)+ 精度改善の議論の作業台。実FPRは実機テストでこれから。

判定ロジック(確定している仕組み)と、その精度(暫定・信頼区間つき)を 1 か所に記録するページ。精度を良くするための議論の作業台として使う。
⚠️FPR 規律(このページの数字の読み方)

精度の数字はすべて暫定・Wilson 95% 信頼区間つき。点推定で断言しない。 実 FPR(まっとうな電話をどれだけ誤ブロックするか)は Chris→Hide の実機テスト(n≥20)で測定する — これから。 いまある数字は半合成 gold set 上の値であり、実運用の保証ではない。

種類①: 判定の仕組み(確定)

設計は 2 段階判定: まずルール層(決定的・速い)、次に LLM 層(文脈を読む)。

ℹ️正直な現在地: 稼働しているのはルール層のみ

本線(champion)は rules 層のみ。LLM 層は実装(classify_call / 実測プローブ)は存在するが 本線ではない(棚上げ中)。昇格するときは verdict port 内部の差し替えで行い、 呼び出し側は変わらない設計になっている。

ルール層 — チェッカーの固定実行順(順序そのものが仕様)

  1. ブロックリスト照合 — 一致 → 即 blocked(allowlist より先)
  2. ホワイトリスト照合 — 一致 → 即 direct_transfer
  3. 営業時間チェック — 時間外 → after_hours
  4. 認証キーワード — 一致 → transferred(score=0.0。判定には利用者発話のみ使用)
  5. キーワードスコア — 重み high=0.3 / medium=0.15 / low=0.05 を加算(client 別上書き可)
  6. 開幕フロア(opener floor) — 権威フレームなりすまし検知で score に 0.6 を OR 合成(max)。単独では切断せず grey 帯へ引き上げ
  7. カテゴリ判定 — SpamCategory(DB)のキーワード一致 → allowed_sales / form_guided
  8. 閾値判定 — score ≥ 0.8 → form_guided / ≤ 0.3 → transferred / 中間 → grey_transferred

閾値(確定値の正は SSoT — ここは写し)

名前意味出典
block_threshold0.8(既定)これ以上で form_guided(遮断系)。EngineConfig で client 別上書き可backend/engine/scorer.py
grey_threshold0.3(既定)これ以下で transferred(取次)。中間は grey_transferred(人へ)backend/engine/scorer.py
opener floor0.6開幕なりすましの下駄。安全弁 0.8 未満なので単独では切断しない設計backend/engine/opener_floor.py
AEGIS_TERMINATE_MIN_SCORE0.8切断安全弁。スコア由来の遮断(form_guided)はこの値以上のときだけ should_terminate=trueSSoT / backend/config.py

確定値(0.8 / 0.3 / 0.6 / 安全弁 0.8)は SSoT と整合。変えるときは先に SSoT。

LLM 層 — classify_call の分類(5 値)

  • existing_contact — 既存の取引先・知人
  • new_business — 新規の商談・問い合わせ
  • sales_pitch — 営業・勧誘
  • support_request — サポート依頼
  • unknown — 上記に当てはまらない・判断不能

verdict port — 分類脳の唯一の入口(契約の要点)

  • 判定を求める全経路(transcript-tick / transcript-final / bridge の classify)は verdict_port.evaluate() を呼ぶ。champion が rules か llm かは port 内部の関心事で、呼び出し側からは不可視。
  • 正は常に action。should_terminate / should_transfer はその投影(導出値)で、port の外で独自計算しない(二重化の禁止)。
  • 遮断系 action = form_guided / after_hours / blocked。取次系 = transferred / direct_transfer / grey_transferred / allowed_sales。
  • L1 決定的ゲート由来(after_hours / blocked)は無条件で should_terminate=true。スコア由来(form_guided)は spam_score ≥ 0.8(安全弁)のときのみ true。
  • フェイルオープン: 空 transcript → pending、内部例外 → error。いずれも導出 bool は false(人へ倒す側)。
  • 判定源の名札は call_logs.score_source('rules' / 'llm' / NULL)。どちらの脳が出した値かを後から追跡できる。

種類②: 精度・eval(暫定・信頼区間つき)

測っているもの(gold set の現状)

  • gold set: v3(42 件 = spam 21 / not_spam 21) — feat/eval-gold-v01 ブランチ(未マージ)。main の gold_set.json は骨格 2 件のみ
  • provenance: public 10(千葉県警文字起こし等)/ synthetic-grounded 20 / synthetic 12。real は 0 件
  • プローブ: 42 件全件に llm_observed(gpt-realtime GA の実測プローブ、commit da55690)

測定値(詐欺見逃し対策 A/B・暫定)

指標beforeafter(案A)注意
詐欺(特殊詐欺 10 件)の見逃し7/103/10 [10.8%, 60.3%]n=10 なので区間は非常に広い。傾向の把握まで
FNR 全体(迷惑の見逃し率)33.3% [17.2%, 54.6%]14.3% [5.0%, 34.6%]n=21(spam 側)。区間が重なるため「改善傾向」以上は言えない
FPR(まっとうな電話の誤ブロック率)0.0% [0.0%, 15.5%]0.0% [0.0%, 15.5%](維持)n=21(not_spam 側)。0 件でも上限 15.5% — 「FPR ゼロ」とは言えない
測定の同一性: gold v3 × llm_observed(gpt-realtime GA プローブ)× feat/eval-gold-v01 commit 4be9493(A/B 比較)。before = baseline(da55690)、after = 案A(fraud enum 追加)。
⚠️この数字は LLM 層プローブの値(本線の実運用値ではない)

上の表は LLM 層(棚上げ中)の実測プローブ(llm_observed)を閾値 0.8 で block/pass 化した値。 本線 rules 層の実運用値ではない。しかも測定元は未マージのブランチ(feat/eval-gold-v01)。 n が小さく区間が重なるため、言えるのは「改善傾向」まで。

FPR 規律(eval 設計 D4 / D5)

  • FNR / FPR は必ず Wilson 95% 信頼区間つきで報告し、受入判定は区間の上限 / 下限で行う(点推定で断言しない)。
  • gold 各件は provenance(real / public / synthetic-grounded / synthetic)を持ち、全体と real-only の両方で報告する(半合成への過適合検知)。現状 real は 0 件なので real-only は測定不能。
  • 実 FPR は Chris→Hide の実機テスト(n≥20)で測定する。これから。今ある数字は半合成 gold 上の暫定値。

改善の議論の作業台

精度を良くするために、いま開いている論点。議論が動いたらこのページ(src/data/detection.ts)を更新する。

🧠 LLM 層の champion 昇格をいつ・何を根拠に判断するか

  • 現状の champion は rules 層。昇格は verdict port 内部の差し替えで行える設計(呼び出し側の改修不要)。
  • 昇格判断の材料 = gold での rules vs llm の区間比較 + 実機テストの実測。区間が重なるうちは昇格しない。

🕵️ 詐欺見逃し対策: 案A(fraud enum)と案B(unknown 帯 0.6)の選定

  • 両案とも見逃しは 7/10 → 3/10(暫定)。ただし案A は詐欺 6 件のスコアが 0.95–0.99 へ動き大マージン、案B は 0.6–0.7 に張り付き薄氷。
  • 案A 優勢だが未マージ(feat/eval-gold-v01)。マージ判断の前に実機テストの結果を待つか、が論点。

📞 real provenance の獲得(gold の最大の穴)

  • gold 42 件に real は 0 件。半合成への過適合はいま検知できない。
  • Chris→Hide 実機テスト(n≥20)の通話を、PII マスクの上で real provenance として gold へ昇格させる動線(gold_candidates キュー)が用意済み。

📏 rules 層自体の gold 実測を記録に残す

  • eval_scorer.py --source rules で本線 rules 層を同じ gold 42 件で測れるが、その数字はまだこのページに記録していない。
  • llm 層との比較を区間つきで並べるのが次の一歩(champion 昇格判断の土台になる)。

🏷️ ラベル待ちキューの消化(PII マスク必須)

  • 実文字起こしのラベル待ちキュー(git 非追跡・PII の可能性あり)が手元にある。promote 前に個人情報のマスクが必須(キュー自身にもその旨を明記済み)。
  • ラベル付けの人手(誰が・どの基準で)が未定。gold_category の付け方は taxonomy と揃える。
📌このページの更新のしかた

数字・論点は src/data/detection.ts に集約してある。新しい測定値は必ず「gold の版 × 測定対象(rules / llm)× commit」を紐づけ、Wilson 95%CI つきで追記する。実機テストの結果が出たら、暫定値と入れ替えるのではなく 並記する(半合成 gold との乖離そのものが情報)。