# 機能設計書 53-センチメント分析

## 概要

本ドキュメントは、Chatwootにおけるメッセージのセンチメント（感情）分析機能について記述する。本機能は、顧客から送信されたメッセージの感情（ポジティブ、ネガティブ、ニュートラル等）を分析し、その結果をメッセージに関連付けて保存する機能である。

### 本機能の処理概要

**業務上の目的・背景**：カスタマーサポートにおいて、顧客の感情状態を把握することは、適切な対応を行う上で重要である。ネガティブな感情を持つ顧客には迅速かつ丁寧な対応が必要であり、ポジティブな感情の顧客にはアップセルやクロスセルの機会となる場合がある。センチメント分析により、エージェントは会話の感情的なコンテキストを素早く理解でき、優先度付けや対応戦略の立案に活用できる。

**機能の利用シーン**：
- エージェントが会話を確認する際にメッセージの感情状態を視覚的に把握する
- ダッシュボードでネガティブな感情の会話を優先的に対応する
- レポートや分析で顧客満足度の傾向を把握する
- 自動化ルールでセンチメントに基づくワークフローをトリガーする

**主要な処理内容**：
1. メッセージ受信時にセンチメント分析APIを呼び出し
2. 分析結果（センチメントスコア、ラベル）をJSONB形式で保存
3. メッセージ表示時にセンチメント情報を含めて配信
4. センチメントに基づく会話のフィルタリング・ソート

**関連システム・外部連携**：外部のセンチメント分析API（Captain AI等）と連携して感情分析を実行。

**権限による制御**：センチメント分析結果の閲覧はメッセージ閲覧権限に準ずる。分析の有効化はアカウント管理者権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 11 | 会話詳細画面 | 主画面 | メッセージとともにセンチメント情報を表示 |
| 9 | ダッシュボードホーム画面 | 参照画面 | センチメントに基づく会話のフィルタリング |

## 機能種別

データ分析 / 外部API連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| message.content | String | Yes | 分析対象のメッセージテキスト | 空でないこと |

### 入力データソース

- 顧客からの受信メッセージ（incoming message）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| sentiment | JSONB | センチメント分析結果（スコア、ラベル等） |

### 出力先

- messagesテーブルのsentimentカラム

## 処理フロー

### 処理シーケンス

```
1. メッセージ受信
   └─ 顧客からのメッセージがDBに保存される
2. センチメント分析トリガー
   └─ 非同期ジョブでセンチメント分析を実行
3. 外部API呼び出し
   └─ センチメント分析サービスにテキストを送信
4. 結果の保存
   └─ 分析結果をsentimentカラムにJSONB形式で保存
5. 結果の配信
   └─ WebSocketで更新を通知
```

### フローチャート

```mermaid
flowchart TD
    A[メッセージ受信] --> B{分析対象?}
    B -->|No| Z[終了]
    B -->|Yes| C[センチメント分析ジョブ投入]
    C --> D[外部API呼び出し]
    D --> E{分析成功?}
    E -->|Yes| F[sentimentカラム更新]
    E -->|No| G[エラーログ記録]
    F --> H[MESSAGE_UPDATED イベント発行]
    G --> Z
    H --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-53-01 | 分析対象メッセージ | 顧客からの受信メッセージ（incoming）のみを分析対象とする | メッセージ作成時 |
| BR-53-02 | テキストのみ分析 | テキストコンテンツを持つメッセージのみを分析 | メッセージにcontentが存在 |
| BR-53-03 | 非同期処理 | センチメント分析は非同期で実行し、メッセージ保存をブロックしない | 常時 |

### センチメント値

| センチメントラベル | 説明 | 一般的なスコア範囲 |
|-------------------|------|-------------------|
| positive | ポジティブな感情 | 0.5 - 1.0 |
| neutral | 中立的な感情 | -0.5 - 0.5 |
| negative | ネガティブな感情 | -1.0 - -0.5 |

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| センチメント保存 | messages | UPDATE | sentimentカラムを更新 |

### テーブル別操作詳細

#### messages

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | sentiment | 分析結果のJSONB | デフォルト値: {} |

### sentimentカラムの構造

```json
{
  "label": "positive",
  "score": 0.85,
  "analyzed_at": "2024-01-29T10:30:00Z"
}
```

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | API接続エラー | センチメント分析サービスに接続できない | リトライ後、エラーログを記録 |
| - | 分析タイムアウト | 分析処理がタイムアウト | 空のsentimentを維持 |
| - | 無効なレスポンス | APIから不正なレスポンス | 空のsentimentを維持 |

### リトライ仕様

- APIエラー時は最大3回までリトライ
- リトライ間隔は指数バックオフ（1分、5分、15分）

## トランザクション仕様

センチメント更新は単独のUPDATE操作であり、トランザクション管理は不要。

## パフォーマンス要件

- センチメント分析は非同期で実行されるため、メッセージ保存のレスポンスには影響しない
- 分析処理は通常2-5秒以内に完了

## セキュリティ考慮事項

- 外部センチメント分析APIへの通信はHTTPS必須
- 顧客のメッセージ内容が外部APIに送信されるため、プライバシーポリシーへの明記が必要
- センチメントデータへのアクセスはメッセージ閲覧権限に準ずる

## 備考

- sentimentカラムはRails 7.0マイグレーション（20230706090122）で追加
- デフォルト値は空のJSONB（{}）
- Captain AI機能を使用してセンチメント分析を実行可能

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | message.rb | `app/models/message.rb` | sentimentカラムの定義とスキーマ |

**主要処理フロー**:
- **15行目**: sentimentカラムの定義（:jsonb型）
- **1-40行目**: スキーマ情報でsentimentが:jsonb型であることを確認

**読解のコツ**: Railsのスキーマ情報はファイル先頭のコメントに記載されている。sentimentカラムはjsonb型で、任意のJSON構造を保存できる。

#### Step 2: マイグレーションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | 20230706090122_sentiment_column_to_messages.rb | `db/migrate/20230706090122_sentiment_column_to_messages.rb` | sentimentカラム追加のマイグレーション |

**主要処理フロー**:
- **3行目**: add_column :messages, :sentiment, :jsonb, default: {} でカラム追加

#### Step 3: Webhook/API連携を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | message.rb | `app/models/message.rb` | webhook_dataメソッドでセンチメント情報をエクスポート |

**主要処理フロー**:
- **171-189行目**: webhook_dataメソッドでメッセージデータを構築（sentimentも含まれる可能性）

### プログラム呼び出し階層図

```
Message (create/update)
    │
    └─ Sentiment Analysis (非同期)
           │
           └─ 外部API (Captain AI等)
                  │
                  └─ Message#update(sentiment: {...})
                         │
                         └─ MESSAGE_UPDATED イベント
```

### データフロー図

```
[入力]              [処理]                    [出力]

顧客メッセージ    センチメント分析API    messages.sentiment
テキスト    ───▶  感情分析          ───▶  JSONB更新
                                           │
                                           ▼
                                      WebSocket配信
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| message.rb | `app/models/message.rb` | モデル | sentimentカラムの定義 |
| 20230706090122_sentiment_column_to_messages.rb | `db/migrate/20230706090122_sentiment_column_to_messages.rb` | マイグレーション | sentimentカラムの追加 |
