LLM Frontline
開発・エージェント

LLMで問い合わせ・文書を分類する設計|ラベル定義・出力の制約・「わからない」の扱いと人手確認の線引き

ミナト・開発・API担当
・ 約39分で読めます
LLMで問い合わせ・文書を分類する設計|ラベル定義・出力の制約・「わからない」の扱いと人手確認の線引き

問い合わせフォームから届いたメールを「請求」「解約」「不具合」のどれかに振り分ける。社内の文書にタグを付けて検索しやすくする。アンケートの自由記述を読んで、要望の種類ごとに件数を数える。生成AIの業務用途というと文章を書かせる仕事が目立ちますが、こうした「分類」も業務の現場でよく使われる用途です。1件ごとの処理は小さくても、毎日数百件、数千件と積み上がる種類の仕事です。

分類はLLMにやらせると、最初の試作がすぐに動きます。ラベルの一覧をプロンプトに書き、「この問い合わせはどれに当たりますか」と聞くだけで、それらしい答えが返ってきます。問題はその先です。「その他」に何でも入ってしまう、同じような問い合わせなのに日によって振り分け先が変わる、ラベルを1つ増やしたら既存のラベルの精度が落ちた、全体の正解率は9割なのに解約の問い合わせだけ取りこぼしていた。この記事は、試作から本番運用までのあいだで決めておくべき設計判断を、1本にまとめたものです。一次情報には、Anthropicのチケット振り分けガイドと分類のクックブックを主に使います。数字はそれぞれの出典に書かれている範囲で、条件とセットで紹介します。

LLMで分類するか、しないか

最初に決めるのは、そもそもLLMを使うかどうかです。テキスト分類は、LLMが登場するずっと前から機械学習で実用化されてきた分野です。LLMを使えば必ず良くなるわけではありません。

LLMが向く条件

Anthropicのチケット振り分けガイドは、従来の機械学習ではなくLLMを使うべき兆候として、次の7つを挙げています。

ガイドが挙げる条件ガイドの説明の要旨
ラベル付きの学習データが少ない従来の機械学習は大量のラベル付きデータを必要とするが、Claudeは数十件程度のラベル付き例で分類できる
分類カテゴリが変わりやすい従来の手法は一度作ると変更に手間とデータがかかる。LLMは再ラベル付けを大量にしなくても、定義の変更や新しいクラスに対応できる
複雑で非構造なテキストを扱う従来の手法は非構造データに弱く、特徴量設計の手間が大きい
分類ルールが意味の理解に基づく例ではなく条件でクラスが定義されている場合に、その規則を理解して適用できる
判定理由の説明が必要人が読める説明を出せるので、自動化への信頼や修正につながる
境界事例や曖昧な入力を扱いたい文脈を読めるので、誤振り分けや未分類のまま人手に回る件数を減らせる可能性がある
言語ごとにモデルを分けたくない多言語の入力を、言語別のモデルや翻訳の工程なしで分類できる

実務に引き直すと、特に効くのは上の2つです。問い合わせの分類は、立ち上げの時点では正解ラベル付きの過去データがほとんどありません。そして、新商品の発売や制度の変更のたびにラベルが増えたり分かれたりします。学習済みの分類器は、ラベルを1つ変えるたびにデータを集め直して学習し直す必要がありますが、LLMならラベルの定義文と数件の例を書き換えるところから始められます。

LLMを選ばないほうがよい条件

逆に、次のような条件がそろっているなら、LLMは第一候補ではありません(ここからは筆者の整理です)。

条件向いている手段理由
キーワードや送信元で確実に決まるルール(正規表現、フォームの選択肢、送信元ドメイン)速く、安く、判定理由が完全に説明できる。LLMに任せると、決まっているはずの振り分けがぶれる余地を作る
件数が非常に多く、1件あたりの予算が小さい埋め込み+ロジスティック回帰などの軽量分類器推論が桁違いに安く速い。ラベルが固定なら学習の手間は一度きり
ラベルが長期間変わらず、正解付きの過去データが大量にある従来の教師あり分類器データがあるなら、学習した分類器は安定して強い。LLMの柔軟さを使う場面が少ない
応答までの時間が数十ミリ秒単位で求められるルールか軽量分類器LLMの呼び出しは往復の時間がかかる

よくある落としどころは、併用です。確実に決まるものはルールで先に振り分け、残りをLLMに回す。あるいは、立ち上げ期はLLMで分類し、人が確認した結果がたまってきたら、それを学習データにして軽量分類器を作り、件数の多いラベルだけ置き換える。LLMは、ラベルが固まるまでの期間と、ルールや分類器では拾えない曖昧な残りを担当する、という位置づけです。

あわせて読みたい

エンベディングとは何か|ベクトル検索の仕組みをRAGの内側から理解する

ラベル設計が精度の上限を決める

分類の精度が伸びないとき、プロンプトの言い回しやモデルを変える前に見直すべきなのは、ラベルそのものです。チケット振り分けガイドは、Claudeが振り分けをうまくこなせるかどうかは、カテゴリがどれだけ明確に定義されているかに正比例する、とまで書いています。人が読んでも迷うラベル体系を、LLMが迷わずに運用することはできません。

各ラベルに定義文を書く

ラベル名だけを並べたプロンプトは、LLMにラベルの意味を推測させています。「請求」というラベル名から、LLMは一般的な意味で「請求」を解釈しますが、自社の運用で「請求」に入れたいものと一致する保証はありません。

Anthropicのクックブック(保険会社のサポートチケットを10カテゴリに分類する例)では、各カテゴリに3行程度の定義が付いています。たとえば「Billing Inquiries(請求の問い合わせ)」は、請求書・料金・手数料・保険料についての質問、請求明細の説明の依頼、支払い方法や期日についての問い合わせ、と定義されています。一方の「Billing Disputes(請求への異議)」は、予期しない、あるいは誤った請求への苦情、返金や保険料の調整の依頼、延滞料や督促状についての問い合わせ、です。

この2つは、どちらも「請求」の話です。クックブックは、「請求について質問がある」は請求の問い合わせ、「この請求はおかしい」は請求への異議であり、この区別には意図と語調の理解が必要だ、と説明しています。実際にこのクックブックでも、定義だけを与えた最初の単純な分類器について、似たカテゴリ同士の取り違えが残っており、細かい区別にはもっと文脈が必要だと分析されています。

定義文を書くときは、次の3点を入れると、境界がはっきりします。

ラベル定義文に入れるもの

  • 含むもの:このラベルに入れる問い合わせ・文書の典型を2〜4行で
  • 含まないもの:紛らわしい隣のラベルと、その振り分け先(「料金への苦情はここではなく請求への異議」)
  • 境界事例:人が迷った実例と、どちらに入れたかの判断理由を1〜3件

境界事例は、定義文だけでは伝わりにくい判断基準を伝える、いちばん効く材料です。チケット振り分けガイドも、微妙な意図の問い合わせについては分類の根拠も一緒に例として示すと、LLMがその論理を他の問い合わせに一般化しやすくなる、と書いています。

あわせて読みたい

Few-shotプロンプトの設計|例の選び方・件数・順序と、効かなくなる場面

排他か、複数ラベルか

1件の問い合わせに、話題が2つ含まれていることはよくあります。「先月の請求額がおかしいので確認したい。ついでに住所変更もしたい」。これを1つのラベルに決めるのか、2つとも付けるのかは、分類の結果を何に使うかで決まります。

方式向いている用途設計のポイント
単一ラベル(排他)担当部署への振り分け、優先度の決定複数の話題があるときの優先順位をプロンプトに明記する
複数ラベル文書のタグ付け、アンケートの集計ラベルごとに「付ける/付けない」を判定する。ラベル数の上限を決めておく
主ラベル+補助フラグ振り分けと集計の両方に使う振り分けには主ラベルだけを使い、補助フラグは集計や後工程で使う

チケット振り分けガイドのサンプルプロンプトは、1件の問い合わせに当てはまる意図は1つだけとし、最も当てはまるものだけを出させる形になっています。そのうえでガイドは、1件に複数の問題が含まれると主な関心事を見分けにくくなるので、意図の優先順位を明確にしておくよう勧めています。単一ラベルにするなら、「解約の意思が含まれていれば、他の話題より解約を優先する」のように、優先順位を定義として書いておく必要があります。

分類の軸を混ぜない

「請求」「解約」「不具合」「至急」「法人顧客」を1つのラベル一覧に並べてしまう設計を、ときどき見かけます。これは内容の種類、緊急度、顧客の属性という別々の軸が混ざっています。「法人顧客からの至急の解約」はどのラベルでしょうか。

チケット振り分けガイドも、振り分けや優先度付けは意図だけでなく、緊急度、顧客の種類、SLA、言語などにも左右されうると書いています。軸が違うものは、別のフィールドとして別々に判定させてください。そのうえで、顧客の属性のようにシステムがすでに知っている情報は、LLMに推測させずにデータベースから引きます。

「その他」と「判定不能」を分けて置く

どのラベルにも当てはまらない入力は、必ず来ます。その受け皿をどう置くかで、運用のしやすさが大きく変わります。

クックブックの例がよい教材です。10カテゴリの最後の「General Inquiries(一般的な問い合わせ)」には、連絡先や営業時間の質問、製品やサービスについての一般的な情報の依頼に加えて、「他のカテゴリにうまく当てはまらない問い合わせ」が定義として含まれています。ところが、カテゴリ定義だけを与えた単純な分類器の評価結果では、このGeneral Inquiriesの再現率が0.00でした。テストセットに7件あったのに、1件も正しく当てられていません。

メモ

同じ評価結果で、General Inquiriesの適合率は1.00と表示されています。これは分類器が優秀だったからではありません。再現率が0.00ということは正しく当てた件数が0件で、それでも適合率が0でなく1.00になっているのは、このラベルを予測した件数自体が0件だったことを意味します。クックブックの評価関数はscikit-learnのclassification_reportをzero_division=1で呼んでおり、予測が0件で割り算ができないときは1を返す設定になっています。「その他」系のラベルは、こうした数字の見え方にも注意が必要です。

受け皿のラベルは、1つにまとめずに役割で分けると扱いやすくなります(ここからは筆者の整理です)。

ラベル意味その後の扱い
その他(対象内)業務の範囲内だが、既存のどのラベルにも当てはまらない定期的に中身を読み、件数が増えたものを新ラベルの候補にする
判定不能情報が足りない、意味が取れない、複数のラベルで決めきれない人手確認のキューへ回す
対象外営業メール、スパム、空の送信など、そもそも分類対象ではない除外、または別の処理へ

「判定不能」を選択肢として用意しておくことには、もう1つ理由があります。OpenAIのStructured Outputsのドキュメントは、モデルは常に指定したスキーマに従おうとするため、入力がスキーマとまったく無関係な場合にハルシネーションにつながりうると注意し、入力がタスクと合わないときに返す内容をプロンプトで指定しておくよう勧めています。ラベルの一覧に逃げ場がないと、LLMは無関係な入力でもどれかのラベルを選んでしまいます。

出力を制約する:enumで縛り、理由と判定を分ける

ラベルが決まったら、LLMの出力をそのラベルの一覧に縛ります。自由記述で「請求関係です」と返されると、後段のプログラムで扱えません。

構造化出力のenumを使う

OpenAIとAnthropicはどちらも、応答をJSON Schemaに従わせる構造化出力を提供しており、スキーマの中でenum(列挙値)を使えます。OpenAIのドキュメントは、Structured Outputsはスキーマに従った応答を常に生成するため、必須キーの欠落や無効な列挙値を心配する必要がない、と説明しています。Anthropicの構造化出力(output_config.formatによるJSON出力と、strict: trueによるツール入力の検証)も、サポートする機能としてenumを挙げています。

分類では、ラベルをenumにしておけば、定義外のラベルや表記揺れがそもそも出てこなくなります。後段の処理で「請求」「請求関連」「Billing」を名寄せする必要がなくなるのは、運用上かなり大きな差です。

{
  "type": "object",
  "properties": {
    "reason": {
      "type": "string",
      "description": "判定の根拠。問い合わせ文のどの部分から、どの定義に当たると判断したかを2文以内で"
    },
    "label": {
      "type": "string",
      "enum": ["billing_inquiry", "billing_dispute", "cancellation", "bug_report", "other", "undecidable", "out_of_scope"]
    },
    "urgency": {
      "type": "string",
      "enum": ["normal", "high"]
    }
  },
  "required": ["reason", "label", "urgency"],
  "additionalProperties": false
}

注意

Anthropicのドキュメントには、構造化出力は文字列のenumやconstの値について大文字小文字を保証しない、という注意書きがあります。スキーマと大文字小文字だけが違う値が返ることがあり、その場合もエラーや特別なstop_reasonは出ずに正常終了します。同ドキュメントは、enumの値を大文字小文字を区別せずに比較し、大文字小文字だけが違うenumの値を作らないよう勧めています。ラベルは上の例のように小文字の英字とアンダースコアに統一し、受け取った側でも小文字に正規化してから比較するのが安全です。

判定理由のフィールドを、ラベルより前に置く

チケット振り分けガイドのサンプルプロンプトは、まず判定理由を<reasoning>タグの中に書かせ、そのあとでラベルを<intent>タグに出させています。タグを分けることで、理由とラベルを別々に取り出し、ラベルだけを振り分けに使えるようにしています。

クックブックでは、この「先に考えてから答える」形の効果が数字で示されています。似た事例を検索してプロンプトに差し込む方式(後述)に、判定前に考えを書き出す欄を足したところ、68件のテストセットでの正解率が94%から97%に上がりました。

構造化出力で同じことをするなら、フィールドの順番に気を付けます。OpenAIのドキュメントは、出力はスキーマのキーの順番どおりに生成されると書いています。Anthropicのドキュメントも、プロパティはスキーマで定義した順番を保つとしたうえで、必須のプロパティが先に、任意のプロパティが後に来るという例外を明記しています。理由をラベルより先に生成させたいなら、理由のフィールドを先に定義し、両方を必須にしておきます。

理由を出させることには、精度以外の利点もあります。人手確認の担当者が、LLMがなぜそのラベルを選んだかを一目で確認できます。誤分類を調べるときも、定義の読み違いなのか、入力の読み違いなのかを切り分けられます。代償は出力トークンと応答時間です。件数が非常に多い処理では、理由を短く制限する、あるいは理由なしの版と正解率を比べてから決めてください。

あわせて読みたい

Chain-of-Thought(思考の連鎖)とは|CoTプロンプトの基本と推論モデル時代の使いどころ

スキーマに通っても、中身が正しいとは限らない

構造化出力が保証するのは形です。OpenAIのドキュメントは、Structured Outputsでも誤りは含まれうると明記しています。enumに縛っても、選ばれたラベルが間違っている可能性は残ります。

また、スキーマどおりの応答が返らない場合もあります。Anthropicのドキュメントは、安全上の理由で拒否した場合(stop_reason: "refusal")と、max_tokensに達して途中で切れた場合に、出力がスキーマに合わないことがあると書いています。OpenAIも、拒否した場合は応答にrefusalフィールドが入ると説明しています。分類のパイプラインでは、こうした応答を例外として落とすのではなく、「判定不能」と同じ扱いで人手確認に回すようにしておくと、取りこぼしが出ません。

ヒント

クックブックは、応答の先頭を<category>で埋めておく(プレフィル)ことと停止シーケンスを組み合わせて、ラベルだけを出力させています。ただしAnthropicの構造化出力のドキュメントは、メッセージのプレフィルはJSON出力と併用できないと明記しています。さらに、Anthropicのプロンプトのベストプラクティスによると、Claude 4.6のモデル以降では、最後のアシスタントターンへのプレフィル自体が非対応で、400エラーになります(クックブックが使うclaude-haiku-4-5のような以前のモデルでは引き続き使えます)。同じドキュメントは分類の用途について、有効なラベルをenumにしたツールか、構造化出力への移行を勧めています。新しく作るなら、プレフィルではなく構造化出力でラベルを縛る形を基本にしてください。

あわせて読みたい

構造化出力(Structured Outputs)とは何か|LLMの返答をプログラムで安全に扱うための仕組み

ラベルが増えたら階層分類、事例が多様なら動的few-shot

ラベルが10個前後で、問い合わせの書き方もある程度そろっているなら、ここまでの設計で十分に回ります。ラベルが増えたり、入力の幅が広がったりしたときの打ち手が、次の2つです。

ラベルが20を超えたら階層分類を検討する

チケット振り分けガイドは、意図のカテゴリが20以上になる場合の打ち手として、階層分類を挙げています。クラスが増えると必要な例も増え、プロンプトが扱いにくくなる。そこで意図を分類木に整理し、木の各階層に分類器を置いて、段階的に振り分ける方式です。ガイドの例では、最上位で「技術的な問題」「請求の質問」「一般的な問い合わせ」に大きく分け、それぞれに下位の分類器を置いて細かく分類します。

ガイドは利点と欠点も書いています。利点は、親の分岐ごとに別のプロンプトを用意できるので、より文脈に合った分類ができ、精度の向上につながりうること。欠点は、分類器を重ねるぶん遅延が増えることです。ガイドは、この方式を「最速のモデル」としてHaikuで実装するよう勧めています(モデルの位置づけはガイド執筆時点の記述です)。

加えて、実装するなら押さえておきたい点があります(筆者の整理です)。

  • 上位の誤りは下位で取り返せません。最上位で「請求」に入れてしまった不具合報告は、請求の下位分類器のどのラベルにも正しく入りません。各階層に「判定不能」を置き、上位で迷ったものは下位に進ませずに人手確認へ回します。
  • 上位の分類器は、下位のラベルの一覧を知らないまま判定します。上位の定義文には、配下にどんなラベルがあるかを短く書いておくと、境界での迷いが減ります。
  • 評価は階層ごとに分けて測ります。最終的な正解率だけを見ていると、どの階層で落ちているのかが分かりません。

なお、ここでいう「カスケード」は、ラベルの木を上から順にたどる分類の構造のことです。どのモデルに処理させるかを振り分けるモデルルーティング・カスケードとは別の話ですが、「判定に迷ったら安全側に倒す」という考え方は共通しています。

あわせて読みたい

LLMのモデルルーティングとカスケード設計|全部を最上位モデルに投げないための振り分け基準と、判定ミスの被害を小さくする作り方

事例が多様なら、類似事例を検索してfew-shotに差し込む

プロンプトに例を入れるのは、分類の精度を上げるいちばん効く方法の1つです。ただ、問い合わせの書き方が多様だと、固定の数件の例ではカバーしきれず、かといって全部の例を入れるとプロンプトが膨らみます。

チケット振り分けガイドが勧めているのは、例のデータセットをベクトルデータベースに入れ、分類したい問い合わせに似た例を類似度検索で取り出して、そのつどプロンプトに入れる方法です。ガイドは、この方法で正解率が71%から93%に改善したと書き、詳細をクックブックに譲っています。

クックブックの現行版で、中身を確認しておきます。

項目クックブックの設定・結果
データ保険のサポートチケット、10カテゴリ。問題設定・データ・ラベルはClaude 3 Opusで合成したもの
件数学習用68件(検索対象の例のプール)、テスト用68件
検索学習用の68件をVoyageAIのvoyage-2で埋め込み、コサイン類似度で上位5件を取得(類似度0.75未満は除外)
使用モデルclaude-haiku-4-5
単純な分類器(定義のみ)正解率0.74(本文では約70%と表記)
類似事例を差し込んだ分類器正解率0.94
さらに判定前に考えを書かせた分類器正解率0.97

ガイドの「71%から93%」とクックブック現行版の出力の数字は一致しません。クックブックは2024年5月の公開後に使用モデルなどが更新されており、ガイドの数字がどの版の結果なのかはページ上では確認できませんでした。どちらを引用するにしても、テストセットは68件で、1件の正誤で約1.5ポイント動く規模だという点は添えておくべきです。示されているのは「この条件で、類似事例の差し込みがはっきり効いた」ということで、自社のデータで同じ幅の改善が出る保証ではありません。

クックブックは、効いた理由として、似た過去の例があると意味の近いカテゴリを区別しやすくなること、検索が動的で問い合わせごとに最も関連する例が選ばれることを挙げています。先ほどの請求の問い合わせと請求への異議のように、紛らわしいラベルの組を見分ける材料が、そのつど手元に来るわけです。

運用するなら、次の点に注意してください(筆者の整理です)。

動的few-shotを運用するときの注意

  • 例のプールのラベルは、人が確認したものだけを入れる。誤ったラベルの例は、似た問い合わせにそのまま誤りを広げる
  • 評価のときは、テストセットの問い合わせそのものが例のプールに入っていないことを確かめる。入っていると、答えを見ながら解くことになり正解率が実力以上に出る
  • 類似度のしきい値を設けると、似た例が見つからない問い合わせでは例が減る。例が0件になったケースの正解率を別に見ておく
  • 取り出した例のラベルが割れているときは、境界事例である可能性が高い。人手確認に回す判断材料として記録しておく
  • ラベルを改定したら、例のプールのラベルも新しい体系に付け直す。古いラベルの例が残ると、廃止したはずのラベルに引っ張られる

あわせて読みたい

RAGとは何か|仕組み・向き不向き・導入判断の考え方

評価:全体の正解率ではなく、ラベル別に見る

分類は、生成系のタスクに比べて評価がしやすい仕事です。正解のラベルが決まっていれば、完全一致で採点できます。Anthropicの評価設計のドキュメントも、感情分析のように答えがはっきりしたカテゴリに分かれるタスクには、完全一致の評価が単純で曖昧さのない指標として最適だとしています。

テストセットの作り方

テストセットは、本番に近い分布から作ります。Anthropicの評価設計のドキュメントは、実際のタスクの分布を映したテストを作り、境界事例を忘れないよう求めています。例として挙げられているのは、無関係あるいは存在しない入力、長すぎる入力、そして人でも判断が一致しにくい曖昧なケースです。分類なら、次の3つの枠で集めると漏れが少なくなります。

枠中身目的
無作為抽出過去の問い合わせから無作為に数百件本番での全体の精度を推定する
境界事例人が迷った事例、紛らわしいラベルの組の事例定義の弱いところを測る
少数ラベルと対象外件数は少ないが取りこぼすと困るラベル、スパムや空の送信無作為抽出だけでは数件しか入らないラベルを測る

同じドキュメントは、人手で丁寧に採点した少数の問題より、多少粗くても自動採点できる多数の問題のほうがよい、とも書いています。分類は自動採点できるので、件数を増やす方向に投資しやすいタスクです。

正解ラベルを付けるときは、可能なら同じ100件程度を2人で独立に付けてみてください。人同士で判断が割れるラベルの組は、LLMにとっても境界が曖昧な組です。そこはプロンプトより先に、ラベルの定義文を直す対象になります。

あわせて読みたい

LLMアプリの評価(eval)の作り方|「動いた気がする」で止めないための実務手順

ラベル別の適合率・再現率と混同行列

全体の正解率だけを見ていると、件数の少ないラベルの失敗が埋もれます。先ほどのクックブックの単純な分類器は、全体の正解率が0.74でしたが、General Inquiriesの再現率は0.00でした。全体の数字は「7割は当たっている」と言っていても、ある種類の問い合わせは一度も正しく振り分けられていなかったわけです。

scikit-learnのclassification_reportは、ラベルごとに適合率(そのラベルと予測したもののうち正しかった割合)、再現率(そのラベルが正解のもののうち当てられた割合)、F1スコア、そして件数(support)を並べて出します。平均には2種類あり、マクロ平均はラベルごとの値を重みなしで平均し、加重平均は件数で重み付けして平均します。件数の少ないラベルの失敗に気づきたいなら、マクロ平均とラベル別の値を見てください。

混同行列は、正解のラベルと予測したラベルの組み合わせごとの件数を並べた表です。対角線上が正解で、対角線から外れたマスが「何を何と取り違えたか」を示します。クックブックも、どのカテゴリ同士が混同されているかを見て、分類器がどこでつまずいているかを特定するために混同行列を描いています。直すべきは、件数の多い取り違えの組の定義文と境界事例です。

# テストセットの評価(y_true: 正解ラベル, y_pred: LLMの出力ラベル)
from sklearn.metrics import classification_report, confusion_matrix

LABELS = ["billing_inquiry", "billing_dispute", "cancellation",
          "bug_report", "other", "undecidable", "out_of_scope"]

# 大文字小文字の揺れを吸収してから比較する
y_pred = [p.strip().lower() for p in y_pred]

# zero_division=0にしておくと、一度も予測されなかったラベルの
# 適合率が1.00ではなく0.00と表示され、見落としにくい
print(classification_report(y_true, y_pred, labels=LABELS, zero_division=0))
print(confusion_matrix(y_true, y_pred, labels=LABELS))

ラベル別の数字を見るときは、誤りの重さがラベルごとに違うことも前提にします。解約の意思、法的な請求、セキュリティの報告のように取りこぼすと被害が大きいラベルは再現率を重視し、多少の誤検知は人手確認で吸収する。逆に、自動返信のように誤って送ると困る処理につながるラベルは、適合率を重視する。ラベルごとに、どちらを優先するかを決めておいてください。

一貫性を再テストで測る

同じ入力に同じラベルが返るかどうかも、測っておくべき指標です。AnthropicのAPIリファレンスは、temperatureを0.0にしても結果は完全には決定的にならないと明記しています。さらに同じ項目は、temperatureの指定を非推奨としており、Claude Opus 4.6より後に公開されたモデルでは1.0以外の値が400エラーになると書いています。temperatureで出力を固定する前提は取れないので、一貫性は再テストで実測してください。

チケット振り分けガイドは、LLMで振り分けるときの成功基準の例として分類の一貫性を挙げ、標準化した入力のセットで定期的にテストし、95%以上の一貫性を目指す、という目標の置き方を示しています。これはガイドが示す目標値の例であり、どの業務でも95%が妥当という意味ではありませんが、測り方の型としてはそのまま使えます。

  • 同じテストセットを、日を変えて複数回流し、ラベルが一致した割合を測る。
  • 同じ内容を言い回しだけ変えた問い合わせの組を作り、同じラベルになる割合を測る。
  • 一致しなかった問い合わせを集めて読む。たいていは境界事例で、定義文か例の追加で直せる。

確信度の扱い:自己申告は較正されていない前提で

人手確認に回す基準として、LLMに確信度を答えさせる設計をよく見かけます。スキーマにconfidenceという0〜1の数値を足し、0.8未満なら人が確認する、という形です。この数値は、そのままでは基準として信用しないでください。

LLMが口で言う確信度は過信に偏りやすい

ブラックボックスのLLMから確信度を引き出す方法を比較したXiongらの研究(arXiv:2306.13063、ICLR 2024)は、LLMが自分の確信度を言葉で表すとき、過信に偏る傾向があると報告しています。確信度の出させ方や、複数回の応答の一致度を使う工夫で過信は和らぐものの、どの方法も一貫して他を上回るわけではなく、専門知識を要する難しいタスクではどの方法も苦戦した、とも書いています。

ここで「較正されている」の意味を確認しておきます。scikit-learnのドキュメントは、よく較正された分類器とは、出力する確率をそのまま確信度として解釈できるもので、たとえば0.8前後の値を出したサンプルのうち、約80%が実際に正解のクラスに属する、と説明しています。LLMが「確信度0.9」と答えた問い合わせを集めて、実際に9割が正しいかどうかは、測ってみるまで分かりません。

使うなら、テストセットで実際の正解率に対応づける

自己申告の確信度をどうしても使うなら、テストセットで次のように確かめてから使います。

  1. 1

    テストセット全件に、ラベルと確信度を出させる

    確信度の出させ方(0〜1の数値、「高・中・低」の段階など)は本番と同じにします。
  2. 2

    確信度の帯ごとに、実際の正解率を計算する

    0.9以上、0.8〜0.9、0.7〜0.8のように帯に分け、それぞれの帯で正解だった割合を出します。scikit-learnが較正曲線(信頼性図)として描いているのと同じ考え方です。
  3. 3

    正解率が許容できる帯より下を、人手確認に回す

    「確信度0.8以上なら自動」ではなく、「この帯の実際の正解率は許容範囲なので自動」という根拠で線を引きます。
  4. 4

    モデルやプロンプトを変えたら測り直す

    確信度の出方はモデルやプロンプトで変わります。対応づけは、そのときの組み合わせでしか通用しません。

scikit-learnのドキュメントは、較正には分類器の学習に使っていない独立したデータを使うのが理想で、学習データの出力で較正すると、確率が実際より0か1に寄った偏った較正になる、と注意しています。LLMの場合も同じで、プロンプトの例として使った事例や、プロンプトを調整するときに見続けたテストセットで線を引くと、本番より良く見えます。確信度の線を引くためのデータは、調整に使ったものとは別に取っておいてください。

自己申告より使いやすい信号

実務では、LLMの自己申告より、次のような信号のほうが人手確認の基準として扱いやすいことが多いです(筆者の整理です)。

信号取り方性質
「判定不能」を選んだラベル一覧に判定不能を用意する明示的で、ログから件数を数えやすい
複数回の判定が一致しない同じ入力で2〜3回判定し、ラベルが割れたら確認へ呼び出し回数が増えるぶんコストがかかる。重要なラベルに絞って使う
検索した類似事例のラベルが割れている動的few-shotで取り出した例のラベル分布を見る追加の呼び出しなしで取れる
重要ラベルの候補に入った解約・法務・セキュリティなどは、判定結果にかかわらず一度人が見る被害の大きい取りこぼしを防ぐ。ルールで書ける
階層の上下が不整合上位と下位の判定が定義上ありえない組み合わせ機械的に検出できる

複数回の応答の一致度を使う考え方は、前述のXiongらの研究でも過信を和らげる工夫の1つとして挙げられています。

人手確認キューと、運用で見る指標

人手確認は、LLMの分類を「補正する工程」であると同時に、「正解データを増やす工程」でもあります。人が確認して確定したラベルは、テストセットや例のプールに戻せる、いちばん質の高いデータです。

運用で見る指標は、次の4つにしぼると回しやすくなります。

指標定義見方
人手確認率人手確認キューに回った件数の割合上がりすぎると人手が追いつかない。急に下がったら、判定不能を選ばなくなった理由を疑う
人手での上書き率人が確認して、LLMのラベルを変更した割合確認に回したものの精度。低すぎるなら、確認に回す基準が厳しすぎる
再振り分け率自動で振り分けたあと、担当者が別の部署やラベルへ付け替えた割合自動処理の実際の誤り率に近い。ラベル別に見る
ラベル別の件数の推移各ラベルに入った件数の日次・週次の変化急な増減は、問い合わせ自体の変化か、分類の変化のどちらか。「その他」の増加は新ラベルの候補

チケット振り分けガイドは、LLMを使うかどうかにかかわらず役立つ成功基準の1つとして再振り分け率を挙げ、10%未満を目指し、上位のシステムでは5%以下に達する、という目安を示しています。ただしこれはサポート業務の振り分けについての目安で、文書のタグ付けやアンケートの集計にそのまま当てはまる数字ではありません。自社では、導入前の人手運用での再振り分け率を先に測っておき、それと比べるのが確実です。

再振り分け率は、自動で振り分けたものだけを対象に計算してください。人手確認を経たものと混ぜると、LLMの精度が実際より良く見えます。

あわせて読みたい

AIエージェントの人間承認(Human-in-the-Loop)設計|どこに確認を置くかを影響範囲と取り消し可能性で決める

ラベルを改定するときの運用

分類の運用でいちばん事故が起きやすいのは、ラベルを変えるときです。新しいラベルを1つ足しただけのつもりでも、隣のラベルの境界が動き、既存のラベルの精度が落ちることがあります。

プロンプトとラベル定義を1つの版として管理する

分類の挙動を決めているのは、プロンプトの文面だけではありません。ラベルの一覧、各ラベルの定義文、境界事例、例のプール、出力スキーマのenum、人手確認に回すしきい値。これらは互いに依存しているので、1つの版として一緒に管理し、どれか1つでも変えたら版を上げます。

クックブックも、ノートブックでの試作から本番の分類システムに進むときに必要になるものとして、数百から数千件規模のテストセット、プロンプトの変更で精度が落ちていないかを確かめる回帰検知、システムの変化に合わせてプロンプトの性能を追跡するバージョン管理を挙げています。

あわせて読みたい

プロンプトのバージョン管理と本番運用|コードに置くか、レジストリに置くかの判断

改定前後で同じテストセットを流す

改定の手順は、次の形にしておくと安全です。

  1. 1

    旧ラベルから新ラベルへの対応表を作る

    ラベルの追加・分割・統合・廃止のそれぞれについて、旧ラベルのどの範囲が新ラベルのどこへ移るかを書きます。
  2. 2

    テストセットの正解ラベルを新体系で付け直す

    分割したラベルに属していた事例は、人が読み直して新しいどちらかに振り直します。対応表で機械的に置き換えられるのは、統合と名前の変更だけです。
  3. 3

    新旧の版を、同じテストセットで流して比べる

    新しい版のラベル別の適合率・再現率を、旧版と並べて見ます。改定と無関係なはずのラベルの数字が落ちていないかを必ず確かめます。
  4. 4

    例のプールを新体系で付け直す

    動的few-shotを使っている場合は、プールのラベルも付け直します。ここが古いままだと、プロンプトの定義と例が矛盾します。
  5. 5

    本番で並行して流してから切り替える

    可能なら一定期間、新旧の両方で判定し、結果が食い違った事例を人が見てから切り替えます。

チケット振り分けガイドは、新しいカテゴリへの適応の速さを成功基準の例として挙げ、新しい種類の問い合わせを入れて満足な正解率(例として90%超)に達するまでを測り、50〜100件のサンプルでの適応を目指す、という目標の置き方を示しています。新ラベルを足すときは、少なくともその程度の件数の実例を集めてから評価する、という目安として使えます。

分類結果に、版を記録する

分類の結果をデータベースに保存するときは、ラベルと一緒に、分類に使った版を必ず記録してください。ラベルを分割した月をまたいで件数の推移を集計すると、版の境目で数字が不連続になります。版が記録されていれば、旧体系に合わせて集計し直すことも、改定の影響を後から説明することもできます。過去データをまとめて分類し直すなら、同期APIでループさせずにバッチ処理を使うと、コストと失敗時のやり直しの面で扱いやすくなります。

あわせて読みたい

LLMの大量処理を同期APIでやらない|バッチ推論・非同期処理の判断基準と失敗設計

向かない場面と、先に決めておくこと

分類をLLMに任せないほうがよい場面も、最後に整理しておきます。

分類の結果が、そのまま人に不利益な判断につながる用途は、LLMの自動分類だけで完結させないでください。採用の書類選考、与信、不正の疑いの判定などです。こうした用途では、誤分類の被害が大きいうえに、判定の理由を説明する責任が生じます。LLMの判定理由は人が読める文章として出ますが、それが実際の判定の根拠を正しく反映していると保証されているわけではありません。

問い合わせの本文に個人情報が含まれる場合は、外部のAPIに送ってよいか、社内の規程とAPIのデータの扱いを先に確認してください。分類に必要なのは多くの場合、本文の意図であって、氏名や連絡先ではありません。

あわせて読みたい

LLMに渡す前にPIIを外す|マスキング処理をパイプラインとして設計する

そして、ラベルの定義を誰が決め、誰が改定を承認するかが決まっていない状態で始めると、運用は必ず崩れます。現場の担当者が思いついたラベルを足し、別の担当者が別の意味で使い始める。LLMの精度以前に、ラベル体系の持ち主を決めておくことが、分類の設計の最初の一歩です。

よくある質問

問い合わせの分類は、LLMと従来の機械学習のどちらを使うべきですか
正解ラベル付きのデータが少ない、ラベルが頻繁に変わる、多言語や書き方がばらばらな文章を扱う、判定理由を人が読める形で残したい、といった条件ならLLMが向きます。Anthropicのチケット振り分けガイドも、こうした条件をLLMを選ぶ兆候として挙げています。逆に、件数が非常に多く1件あたりの予算が小さい、ラベルが長く固定で、正解付きの過去データが大量にあるなら、埋め込みと軽量分類器や従来の教師あり分類器のほうが安く速いことが多いです。確実にキーワードで決まるものはルールで先に振り分け、残りをLLMに回す併用もよく使われます。
「その他」ラベルは置くべきですか
置くべきですが、役割で分けることをおすすめします。業務の範囲内で既存ラベルに当てはまらない「その他」、情報不足や意味不明で決めきれない「判定不能」、スパムなど分類対象外の「対象外」です。逃げ場のラベルがないと、LLMは無関係な入力でもどれかのラベルを選んでしまいます。一方で、Anthropicのクックブックでは、他のカテゴリに当てはまらない問い合わせを含む受け皿のカテゴリの再現率が、単純な分類器で0.00でした。受け皿のラベルこそ、定義文と実例を丁寧に書く必要があります。
構造化出力でenumを指定すれば、分類の精度は上がりますか
enumで保証されるのは、定義したラベルのどれかが返ることまでです。定義外のラベルや表記揺れがなくなるので後段の処理は安定しますが、選ばれたラベルが正しいかどうかは別の問題です。OpenAIのドキュメントも、Structured Outputsでも誤りは含まれうると書いています。なお、Anthropicのドキュメントはenumの値の大文字小文字が保証されないと注意しているので、ラベルは小文字の英字に統一し、比較の前に正規化してください。
判定理由を出させると、精度は上がりますか
上がることがありますが、確認してから採用してください。Anthropicのクックブックでは、類似事例を差し込んだ分類器に判定前に考えを書かせる欄を足したところ、68件のテストセットで正解率が94%から97%になりました。ただし出力トークンと応答時間は増えます。構造化出力で使うなら、理由のフィールドをラベルより先に定義し、両方を必須にしておくと、理由を先に生成させられます。
LLMに確信度を答えさせて、低いものだけ人が確認する設計は使えますか
その数値をそのまま基準にするのはおすすめしません。LLMが言葉で表す確信度は過信に偏りやすいことが研究で報告されています。使うなら、プロンプト調整に使っていないテストセットで、確信度の帯ごとに実際の正解率を計算し、その結果にもとづいて線を引いてください。実務では、判定不能ラベルの選択、複数回判定したときの不一致、検索した類似事例のラベルの割れ、重要ラベルは常に人が見るといったルールのほうが扱いやすいことが多いです。
ラベルが増えてきたら、どうすればよいですか
Anthropicのチケット振り分けガイドは、カテゴリが20以上になる場合に、分類木に整理して階層ごとに分類器を置く階層分類を挙げています。親の分岐ごとに専用のプロンプトを用意できる利点がある一方、分類器を重ねるぶん遅延が増えます。上位での誤りは下位で取り返せないので、各階層に判定不能を置き、上位で迷ったものは人手確認に回してください。
運用中は、何の数字を見ればよいですか
ラベル別の適合率・再現率(定期的にテストセットで測る)に加えて、本番では人手確認率、人が確認してラベルを変えた上書き率、自動振り分け後に担当者が付け替えた再振り分け率、ラベル別の件数の推移を見ます。チケット振り分けガイドは再振り分け率について10%未満を目指すという目安を示していますが、サポート業務の振り分けについての数字なので、自社では導入前の人手運用での再振り分け率と比べるのが確実です。

まとめ

分類は、LLMにやらせると最初の試作がすぐに動く仕事です。そのぶん、精度の上限を決めている部分が見えにくくなります。

最初に、LLMを使うかどうかを決めます。ラベル付きデータが少ない、ラベルが変わる、文章が多様ならLLMが向き、大量・低単価・ラベル固定ならルールや軽量分類器が向きます。次にラベルを設計します。各ラベルに含む/含まないの定義と境界事例を書き、単一ラベルか複数ラベルかを決め、分類の軸を混ぜず、「その他」と「判定不能」を分けて置きます。出力は構造化出力のenumで縛り、判定理由をラベルより先に出させます。ラベルが増えたら階層分類、事例が多様なら類似事例の動的few-shotが次の打ち手です。

評価は、全体の正解率ではなくラベル別の適合率・再現率と混同行列で見ます。LLMの自己申告の確信度は較正されていない前提で扱い、人手確認の基準は実測した正解率か、判定不能や不一致といった扱いやすい信号で決めます。本番では人手確認率、上書き率、再振り分け率を追い、ラベルを改定するときはプロンプト・定義・例・スキーマを1つの版として、改定前後で同じテストセットを流してから切り替えてください。

この記事で紹介したAnthropicのガイドとクックブックの数字は、それぞれの条件(クックブックは合成データの68件のテストセット)での結果です。構造化出力の仕様や各社のドキュメントの記述は、2026年9月25日時点で確認した内容で、改定されることがあります。採用の際は最新の公式情報を確認してください。

チケット振り分けの判断基準・成功基準の例・階層分類と類似事例検索の記述はAnthropic「Ticket routing」、分類の数値(10カテゴリ、学習用・テスト用各68件、正解率0.74/0.94/0.97、ラベル別の値)はClaude Cookbook「Classification with Claude」の現行版の出力、構造化出力の仕様はAnthropicとOpenAIの各ドキュメント、プレフィルの非対応はAnthropicのプロンプトのベストプラクティス、temperatureの扱いはAnthropicのAPIリファレンス、指標と較正の定義はscikit-learnのドキュメント、確信度の過信傾向はXiongら(arXiv:2306.13063)の要旨に基づきます(いずれも2026年9月25日確認)。受け皿ラベルの分け方、運用指標の組み立て、改定手順は、これらを踏まえた筆者の整理です。

出典・参考

この記事をシェア

関連する記事

開発・エージェント

構造化出力(Structured Outputs)とは何か|LLMの返答をプログラムで安全に扱うための仕組み

構造化出力(Structured Outputs)は、LLMの返答をあらかじめ決めたJSONスキーマに沿わせる仕組みです。JSONモードとの違い、なぜスキーマ準拠まで保証したいのか、OpenAI・Anthropic・Googleの対応の考え方、スキーマ設計や検証・リトライといった実装の勘所、そして「構造が正しくても中身が正しいとは限らない」という落とし穴までを、LLMアプリ開発の実務目線で整理します。

開発・エージェント

LLMアプリの評価(eval)の作り方|「動いた気がする」で止めないための実務手順

LLMアプリの品質を測る評価(eval)の作り方を、実務目線で整理します。実運用に似せた評価データの用意、タスク型に応じた指標設計、自動評価と人手レビューの併用、LLM-as-a-judgeの使いどころと落とし穴、失敗トレースをテストへ戻す継続的な評価まで、小さく始める手順にまとめました。