LESSON

分類ツールの実装

「エージェントの最初のステップは、問い合わせのカテゴリ分類だ。」

田中VPoEが説明する。

「BERTモデルとFAQ検索を組み合わせて、高精度な分類ツールを実装しよう。確信度が低い場合のフォールバックも忘れるな。」

分類ツールの実装

from langchain_core.tools import tool
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification

class InquiryClassifier:
    """問い合わせ分類器"""

    def __init__(self, model_path, label_map):
        self.tokenizer = AutoTokenizer.from_pretrained(model_path)
        self.model = AutoModelForSequenceClassification.from_pretrained(model_path)
        self.label_map = label_map
        self.model.eval()

    def classify(self, text):
        """テキストを分類"""
        inputs = self.tokenizer(
            text, return_tensors='pt',
            padding=True, truncation=True, max_length=128,
        )

        with torch.no_grad():
            outputs = self.model(**inputs)
            probs = torch.softmax(outputs.logits, dim=-1)

        top_prob, top_idx = torch.max(probs, dim=-1)
        category = self.label_map[top_idx.item()]
        confidence = top_prob.item()

        # Top-3 カテゴリ
        top3 = torch.topk(probs[0], 3)
        alternatives = [
            {'category': self.label_map[idx.item()], 'confidence': round(prob.item(), 3)}
            for prob, idx in zip(top3.values, top3.indices)
        ]

        return {
            'category': category,
            'confidence': round(confidence, 3),
            'alternatives': alternatives,
        }


# ツールとして登録
classifier = InquiryClassifier(
    model_path='./models/inquiry_classifier',
    label_map={0: '商品問合せ', 1: '返品・交換', 2: '配送', 3: 'アカウント', 4: 'その他'},
)

@tool
def classify_inquiry(text: str) -> dict:
    """問い合わせのカテゴリを分類する"""
    result = classifier.classify(text)

    # 確信度が低い場合はLLMにフォールバック
    if result['confidence'] < 0.7:
        llm_result = llm_classify_fallback(text)
        result['llm_fallback'] = True
        result['llm_category'] = llm_result['category']
    else:
        result['llm_fallback'] = False

    return result

FAQ検索ツール

from sentence_transformers import SentenceTransformer
import numpy as np

class FAQSearchEngine:
    """セマンティックFAQ検索"""

    def __init__(self, faqs):
        self.model = SentenceTransformer('all-MiniLM-L6-v2')
        self.faqs = faqs
        self.faq_embeddings = self.model.encode(
            [f['question'] for f in faqs]
        )

    def search(self, query, category=None, top_k=3):
        """クエリに関連するFAQを検索"""
        query_embedding = self.model.encode([query])

        # コサイン類似度
        similarities = np.dot(self.faq_embeddings, query_embedding.T).flatten()

        # カテゴリフィルタ
        if category:
            for i, faq in enumerate(self.faqs):
                if faq.get('category') != category:
                    similarities[i] *= 0.5  # カテゴリ不一致は減衰

        # Top-K
        top_indices = np.argsort(-similarities)[:top_k]

        return [
            {
                'question': self.faqs[i]['question'],
                'answer': self.faqs[i]['answer'],
                'relevance': round(float(similarities[i]), 3),
            }
            for i in top_indices
            if similarities[i] > 0.3  # 最低閾値
        ]

faq_engine = FAQSearchEngine(faq_data)

@tool
def search_faq(query: str, category: str = "") -> list:
    """関連するFAQを検索する"""
    return faq_engine.search(query, category)

感情分析ツール

@tool
def analyze_sentiment(text: str) -> dict:
    """問い合わせの感情を分析する"""
    from langchain_openai import ChatOpenAI
    from pydantic import BaseModel, Field

    class SentimentResult(BaseModel):
        sentiment: str = Field(description="positive/neutral/negative")
        urgency: str = Field(description="low/medium/high/critical")
        frustration_level: int = Field(ge=1, le=5, description="1-5のフラストレーション度")

    llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
    structured_llm = llm.with_structured_output(SentimentResult)

    prompt = f"""
    以下のカスタマーサポート問い合わせの感情を分析してください。

    問い合わせ: {text}
    """

    result = structured_llm.invoke(prompt)
    return result.model_dump()

まとめ

項目ポイント
分類ツールBERT + LLMフォールバックの2段構え
FAQ検索SentenceTransformerでセマンティック検索
感情分析LLM構造化出力で感情・緊急度を分析
確信度管理低確信度時のフォールバック戦略

チェックリスト

  • BERT分類ツールを実装できる
  • 確信度に基づくフォールバック戦略を設計できる
  • セマンティックFAQ検索を実装できる
  • 感情分析ツールを実装できる

次のステップへ

分類ツールを実装した。次は回答生成の仕組みを学ぼう。

推定読了時間: 30分