Spaces:
Runtime error
Runtime error
File size: 8,160 Bytes
a73fa4e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
"""
感情分析モジュール
ユーザーのメッセージから感情を分析し、好感度を更新する
"""
import logging
from typing import Optional
logger = logging.getLogger(__name__)
class SentimentAnalyzer:
"""感情分析を担当するクラス"""
def __init__(self):
self.analyzer = None
self._initialize_analyzer()
def _initialize_analyzer(self):
"""感情分析モデルの初期化"""
try:
# transformersが利用可能な場合は使用
from transformers import pipeline
self.analyzer = pipeline(
"sentiment-analysis",
model="koheiduck/bert-japanese-finetuned-sentiment"
)
logger.info("感情分析モデルのロード完了。")
except Exception as e:
logger.warning(f"感情分析モデルのロードに失敗、ルールベース分析を使用: {e}")
self.analyzer = None
def analyze_sentiment(self, message: str) -> Optional[str]:
"""メッセージの感情を分析する"""
if not isinstance(message, str) or len(message.strip()) == 0:
return None
# transformersが利用可能な場合
if self.analyzer:
try:
result = self.analyzer(message)[0]
label = result.get('label', '').upper()
# ラベルを統一形式に変換
if 'POSITIVE' in label:
return 'positive'
elif 'NEGATIVE' in label:
return 'negative'
else:
return 'neutral'
except Exception as e:
logger.error(f"感情分析エラー: {e}")
# フォールバック:ルールベース感情分析
return self._rule_based_sentiment(message)
def _rule_based_sentiment(self, message: str) -> str:
"""ルールベースの感情分析"""
positive_words = [
'ありがとう', 'うれしい', '嬉しい', '楽しい', '好き', '愛してる',
'素晴らしい', 'いい', '良い', 'すごい', '最高', '幸せ', '感謝',
'かわいい', '可愛い', '美しい', '優しい', '親切', '素敵'
]
negative_words = [
'嫌い', '悲しい', 'つらい', '辛い', '苦しい', '痛い', '怒り',
'むかつく', 'うざい', 'きらい', '最悪', 'だめ', 'ダメ',
'死ね', 'バカ', 'ばか', 'アホ', 'あほ', 'クソ', 'くそ'
]
message_lower = message.lower()
positive_count = sum(1 for word in positive_words if word in message_lower)
negative_count = sum(1 for word in negative_words if word in message_lower)
if positive_count > negative_count:
return 'positive'
elif negative_count > positive_count:
return 'negative'
else:
return 'neutral'
def update_affection(self, message: str, current_affection: int,
conversation_context: list = None) -> tuple:
"""
メッセージに基づいて好感度を更新する
Args:
message: ユーザーのメッセージ
current_affection: 現在の好感度
conversation_context: 会話の文脈(最近のメッセージ)
Returns:
(新しい好感度, 変化量, 変化理由)
"""
if not isinstance(current_affection, (int, float)):
current_affection = 30 # デフォルト値
sentiment = self.analyze_sentiment(message)
if not sentiment:
return current_affection, 0, "感情分析失敗"
# 基本的な感情に基づく変化量
base_change = 0
if sentiment == 'positive':
base_change = 3
elif sentiment == 'negative':
base_change = -3
else: # neutral
base_change = 0
# メッセージの特徴による調整
change_modifiers = []
# メッセージの長さによる調整
if len(message) > 100:
base_change = int(base_change * 1.3)
change_modifiers.append("長文")
elif len(message) > 50:
base_change = int(base_change * 1.1)
change_modifiers.append("中文")
# 特定のキーワードによる追加調整
positive_keywords = ['ありがとう', '感謝', '好き', '愛してる', '素晴らしい', 'かわいい', '美しい']
negative_keywords = ['嫌い', '死ね', 'バカ', 'アホ', 'クソ', 'うざい', 'きらい']
message_lower = message.lower()
# ポジティブキーワードのチェック
positive_count = sum(1 for word in positive_keywords if word in message_lower)
if positive_count > 0:
base_change += positive_count * 2
change_modifiers.append(f"ポジティブ語({positive_count})")
# ネガティブキーワードのチェック
negative_count = sum(1 for word in negative_keywords if word in message_lower)
if negative_count > 0:
base_change -= negative_count * 3
change_modifiers.append(f"ネガティブ語({negative_count})")
# 現在の好感度レベルによる調整
if current_affection < 20: # 敵対状態
if base_change > 0:
base_change = int(base_change * 0.5) # ポジティブな変化を抑制
change_modifiers.append("敵対状態")
elif current_affection > 80: # 親密状態
if base_change < 0:
base_change = int(base_change * 0.7) # ネガティブな変化を抑制
change_modifiers.append("親密状態")
# 会話の文脈による調整
if conversation_context and len(conversation_context) > 0:
recent_messages = conversation_context[-3:] # 最近の3メッセージ
context_sentiment_count = {'positive': 0, 'negative': 0, 'neutral': 0}
for ctx_msg in recent_messages:
if isinstance(ctx_msg, dict) and 'content' in ctx_msg:
ctx_sentiment = self.analyze_sentiment(ctx_msg['content'])
if ctx_sentiment:
context_sentiment_count[ctx_sentiment] += 1
# 連続したポジティブ/ネガティブメッセージの場合は効果を減衰
if sentiment == 'positive' and context_sentiment_count['positive'] >= 2:
base_change = int(base_change * 0.8)
change_modifiers.append("連続ポジティブ")
elif sentiment == 'negative' and context_sentiment_count['negative'] >= 2:
base_change = int(base_change * 0.8)
change_modifiers.append("連続ネガティブ")
# 最終的な好感度を計算
new_affection = current_affection + base_change
new_affection = max(0, min(100, new_affection)) # 0-100の範囲に制限
# 変化理由を生成
if base_change == 0:
reason = "中立的なメッセージ"
else:
reason = f"{sentiment}({base_change:+d})"
if change_modifiers:
reason += f" [{', '.join(change_modifiers)}]"
return new_affection, base_change, reason
def get_relationship_stage(self, affection: int) -> str:
"""好感度から関係性のステージを取得する"""
if not isinstance(affection, (int, float)):
affection = 30 # デフォルト値
if affection < 20:
return "敵対"
elif affection < 40:
return "中立"
elif affection < 60:
return "好意"
elif affection < 80:
return "親密"
else:
return "最接近" |