【Jev】実践:Jevで問い合わせ内容の自動分類・優先度採点を作る

AI

こんにちは、かつコーチです。

前回の記事で、Jevの基本的なAPIの使い方を確認しました。

今回はもう一歩進んで、実際の業務でありそうな「問い合わせ内容の自動分類・優先度採点」というシナリオを題材に、より具体的な実装例を紹介します。

カスタマーサポートやお問い合わせフォームを運用している方には、特にイメージしやすい内容になっていると思います。

本記事は2026年9月19日時点の情報をもとにしています。

Jevはまだウェイトリストからの早期アクセス段階であり、実装例はSDK仕様や公式情報に基づいた想定コードである点を先にお伝えしておきます。

作りたいものの整理

想定シナリオ

ここでは、Webサービスの「お問い合わせフォーム」を題材にします。

現状の課題として、次のようなものを想定します。

  • 問い合わせが1日に何十件も届き、担当者が手作業で優先度をつけている
  • 緊急のクレームが埋もれて対応が遅れることがある
  • 問い合わせ内容によって振り分け先の部署が違うのに、振り分けも手作業

こうした「振り分け・優先度づけ」は、まさにJevが得意とする「分類・採点」の領域です。

一方で、実際にお客様への返信文を作成する部分は、これまでどおりChatGPTやClaudeなどのLLMに任せます。

全体の処理フロー

実装する処理の流れは、次のようになります。

  1. お問い合わせフォームから本文を受け取る
  2. Jevで「カテゴリ分類」「緊急度スコア」「感情の判定」を同時に行う
  3. 緊急度が高い場合はSlack通知など即時アラートを飛ばす
  4. カテゴリに応じて担当部署にルーティングする
  5. 必要であれば、返信文の下書きをClaudeなどのLLMに作成させる

この中で、ステップ2と3・4の判断部分をJevが担当し、ステップ5の文章生成部分は既存のLLMが担当する、という役割分担がポイントです。

実装例

問い合わせ内容をJevに渡す

まず、問い合わせ本文をJevに渡して、カテゴリ・緊急度・感情の3つを一度に判定します。

from typesafe import Jev

client = Jev(api_key="your-api-key-here")

def triage_inquiry(inquiry_text: str) -> dict:
    response = client.judge(
        state={"text": inquiry_text},
        questions=[
            {
                "id": "category",
                "type": "classification",
                "prompt": "この問い合わせのカテゴリを選んでください。",
                "choices": ["注文・配送", "返品・返金", "不具合報告", "料金・請求", "その他"]
            },
            {
                "id": "urgency",
                "type": "score",
                "prompt": "対応の緊急度を1〜5で評価してください。5が最も緊急です。",
                "scale": [1, 5]
            },
            {
                "id": "sentiment",
                "type": "classification",
                "prompt": "問い合わせ文の感情を選んでください。",
                "choices": ["ポジティブ", "ニュートラル", "ネガティブ"]
            }
        ]
    )
    return response.results


result = triage_inquiry(
    "先週注文した商品がまだ届きません。発送状況を確認してもらえますか?急いでいます。"
)
print(result)
# 想定される出力イメージ:
# {
#     "category": "注文・配送",
#     "urgency": 4,
#     "sentiment": "ネガティブ"
# }

一つのAPI呼び出しでカテゴリ・緊急度・感情の3項目をまとめて判定できるのが、questionsを配列で渡せるJevの使いやすいところです。

緊急度に応じて通知を分岐させる

判定結果を使って、緊急度が高い問い合わせだけSlackに即時通知する処理を追加します。

import requests

SLACK_WEBHOOK_URL = "https://hooks.slack.com/services/xxx/yyy/zzz"

def notify_if_urgent(inquiry_text: str, result: dict):
    if result["urgency"] >= 4:
        message = (
            f"【緊急問い合わせ】カテゴリ: {result['category']} / "
            f"緊急度: {result['urgency']} / 感情: {result['sentiment']}\n"
            f"本文: {inquiry_text}"
        )
        requests.post(SLACK_WEBHOOK_URL, json={"text": message})


result = triage_inquiry(
    "商品が破損して届きました。すぐに交換してほしいです。"
)
notify_if_urgent(
    "商品が破損して届きました。すぐに交換してほしいです。",
    result
)

このように、Jevの判定結果はただの分類ラベルではなく、後続の業務ロジック(通知や振り分け)を動かすトリガーとして使えます。

カテゴリに応じて担当部署にルーティングする

分類結果をもとに、担当部署へのルーティングも自動化できます。

DEPARTMENT_MAP = {
    "注文・配送": "logistics@example.com",
    "返品・返金": "support@example.com",
    "不具合報告": "engineering@example.com",
    "料金・請求": "billing@example.com",
    "その他": "general@example.com",
}

def route_inquiry(result: dict) -> str:
    return DEPARTMENT_MAP.get(result["category"], "general@example.com")


assignee = route_inquiry(result)
print(f"担当部署: {assignee}")

返信文の下書きはLLMに任せる

ここまでの「分類・採点・ルーティング」はすべてJevの仕事でした。

一方で、お客様への実際の返信文を作るのは、引き続きClaudeなどのLLMに任せます。

import anthropic

llm_client = anthropic.Anthropic()

def draft_reply(inquiry_text: str, result: dict) -> str:
    message = llm_client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=500,
        messages=[
            {
                "role": "user",
                "content": (
                    f"以下の問い合わせに対する丁寧な返信文を作成してください。\n"
                    f"カテゴリ: {result['category']}\n"
                    f"感情: {result['sentiment']}\n"
                    f"問い合わせ本文: {inquiry_text}"
                )
            }
        ]
    )
    return message.content[0].text


reply = draft_reply(
    "商品が破損して届きました。すぐに交換してほしいです。",
    result
)
print(reply)

この構成のポイントは、Jevの判定結果(カテゴリや感情)をそのままLLMへのプロンプトの一部として渡していることです。

Jevが「この問い合わせはネガティブな感情を含む不具合報告だ」と先に判定してくれているので、LLM側は最初から適切なトーンで返信文を作成しやすくなります。

つまずきやすいポイント・注意点

一度に渡す質問数が多すぎると設計が複雑になる

今回の例ではカテゴリ・緊急度・感情の3つをまとめて判定しましたが、questionsに詰め込みすぎると、後から「このスコアは何のために使っているんだっけ」と管理が煩雑になりがちです。

実務では、まず「本当に自動化したい判断は何か」を洗い出したうえで、必要最小限の質問設計から始めるのがおすすめです。

筆者も最初に検討した際は、5〜6項目を一度に判定させようとして設計が複雑になり、結局「カテゴリ」「緊急度」「感情」の3つに絞り込みました。

誤判定を前提にしたフォールバック設計にする

Jevも完璧ではないため、誤ったカテゴリに分類されるケースは当然想定しておく必要があります。

特に緊急度のような重要な判定については、「Jevが4以上と判定したものだけ自動通知する」だけでなく、「一定時間経っても人が確認していない問い合わせは、緊急度に関わらずまとめて通知する」といった、人の目によるセーフティネットを組み合わせておくと安心です。

コスト試算をしておく

Jevは入力100万トークンあたり0.042ドルという低コストですが、問い合わせ件数が多い場合は事前に試算しておくと安心です。

たとえば1件あたりの問い合わせ本文とquestions定義を合わせて500トークン程度と仮定すると、1万件処理してもおよそ0.021ドルという計算になります(次回の比較記事で、通常のLLMを使った場合との具体的なコスト差も検証します)。

まとめ

この記事のポイント

  • 問い合わせフォームの「分類・優先度採点・感情判定」はJevに、返信文の作成は既存のLLMに任せる役割分担が実務的
  • questionsに複数の質問を配列で渡せば、1回のAPI呼び出しで複数項目をまとめて判定できる
  • Jevの判定結果を、Slack通知やルーティング、LLMへのプロンプトの一部として活用できる
  • 質問設計はシンプルに保ち、誤判定を前提にしたフォールバック設計を組み込む

次に読むべき記事

同じ判定タスクを、Jevと通常のLLM(ChatGPTやClaudeなど)でそれぞれ実装した場合、実際にどれくらい速度やコストが変わるのか気になった方も多いと思います。

次の「【比較検証】同じ判定タスクをJevと通常LLMで実装し、速度・コストを比較する」で、具体的な数値をもとに比較していますので、あわせてご覧ください。

コメント

タイトルとURLをコピーしました