chatbotの瞼を感情(悲しい、嬉しい)で動きを作るための仕掛け、
Pythonで形態素解析と、事象を参照してスコア化できるライブラリがあるのでそれを使う
辞書(wago.121808.pn)はLLMが教えてくれた東北大のサイトからダウンロードしてます
<Python script : LLM会話での現在形態>
必要なライブラリは、spacy/jaconv/ja-ginzaをpip install、spacyは多言語の形態素解析のできるライブラリでラズパイ5でもそこそこの速度で動作可能、辞書のサイズはおよそ五千語です
import spacy
import jaconv
# --- 辞書ロード関数 ---
def normalize_to_hiragana(text):
"""表記をひらがなに正規化"""
return jaconv.kata2hira(jaconv.z2h(text, kana=True, digit=True, ascii=True))
def load_combined_sentiment_dict(paths):
sentiment = {}
for path in paths:
with open(path, encoding='UTF-8') as f:
for line in f:
cols = line.strip().split('\t')
if len(cols) < 2: continue label = cols[0] # "ポジ"や"ネガ"を抽出 word = cols[1] # 単語を抽出 # スコアをラベルに応じて決定 if "ネガ" in label: score = -1.0 elif "ポジ" in label: score = 1.0 else: score = 0.0 # 中立の場合 sentiment[word] = score # 単語とスコアを登録 return sentiment # --- 感情分析処理 --- def analyze_sentiment(text, sentiment_dict, nlp): doc = nlp(text) positive_count = 0 negative_count = 0 print("=== マッチ単語とスコア ===") for token in doc: lemma = token.lemma_ # 語幹 print(f"処理中: {token.text}({lemma})") # 辞書に単語がマッチした場合 if lemma in sentiment_dict: score = sentiment_dict[lemma] print(f"マッチ: {lemma} → {score:+.1f}") if score > 0:
positive_count += 1
elif score < 0: negative_count += 1 total_words = len([token for token in doc if not token.is_punct]) # 句読点を除く単語数 sentiment_score = positive_count - negative_count # ポジティブ単語数 - ネガティブ単語数 normalized_score = sentiment_score / total_words * 10 if total_words > 0 else 0 # スコアの正規化
result = "neutral"
if normalized_score > 0:
result = "positive"
elif normalized_score < 0:
result = "negative"
print(f"\n感情スコア: {normalized_score:+.1f}")
print(f"判定結果: {result}")
print(f"ポジティブ単語数: {positive_count}")
print(f"ネガティブ単語数: {negative_count}")
return {
"score": normalized_score,
"positive_count": positive_count,
"negative_count": negative_count,
"result": result
}
# --- メイン関数 ---
def main():
text = """シンドラーとはね、第二次世界大戦中に、ユダヤ人をナチスから守った人だよ。彼は、ドイツのオースヴィッツ強制収容所から、たくさんのユダヤ人を助けたんだ。すごい人だよね!"""
print("GiNZAロード中...")
nlp = spacy.load("ja_ginza")
print("辞書読み込み中...")
sentiment_dict = load_combined_sentiment_dict([
"wago.121808.pn"
])
print(f"\n分析対象: {text}\n")
analyze_sentiment(text, sentiment_dict, nlp)
if __name__ == "__main__":
main()
<実行結果>
クリスマスのことを語っている文章を入力にすると、
% python emotion.py
GiNZAロード中...
辞書読み込み中...
分析対象: うん、そうだよ!プレゼントとか、クリスマスツリーとか、すごく楽しいよね!
=== マッチ単語とスコア ===
処理中: うん(うん)
処理中: 、(、)
処理中: そう(そう)
処理中: だ(だ)
処理中: よ(よ)
処理中: !(!)
処理中: プレゼント(プレゼント)
処理中: と(と)
処理中: か(か)
処理中: 、(、)
処理中: クリスマスツリー(クリスマスツリー)
処理中: と(と)
処理中: か(か)
処理中: 、(、)
処理中: すごく(すごい)
処理中: 楽しい(楽しい)
マッチ: 楽しい → +1.0
処理中: よ(よ)
処理中: ね(ね)
処理中: !(!)
感情スコア: +0.7
判定結果: positive
ポジティブ単語数: 1
ネガティブ単語数: 0
感情スコアは+1 ~ -1の間に治るようにしたいから乗算してます、上限と下限もこの値で区切るようにした方がいいだろうね、
admin