| | """ |
| | modules/analyzer.py - Emotionsanalyse-Modul für den Dr. Franz Psychochatbot |
| | |
| | Dieses Modul analysiert die Nutzereingaben, um Emotionen und Themen zu erkennen: |
| | - Emotionserkennung über API |
| | - Themenidentifikation |
| | - Anpassung der Antwortstrategien |
| | """ |
| |
|
| | import requests |
| | import random |
| | from typing import Dict, Any, Optional, List, Tuple |
| |
|
| | |
| | import config |
| |
|
| | class Analyzer: |
| | """Klasse zur Analyse von Nutzereingaben""" |
| | |
| | def __init__(self, api_token: str = config.API_TOKEN): |
| | """ |
| | Initialisiert den Analyzer mit API-Token |
| | |
| | Args: |
| | api_token: Der API-Token für externe Services |
| | |
| | Raises: |
| | ValueError: Wenn der API-Token ungültig ist |
| | """ |
| | if not isinstance(api_token, str): |
| | raise ValueError("api_token must be a string") |
| | if not api_token: |
| | raise ValueError("api_token cannot be empty") |
| | |
| | self.api_token = api_token |
| | |
| | |
| | self.positive_words = [ |
| | "glücklich", "froh", "zufrieden", "gut", "großartig", "toll", "wunderbar", |
| | "fantastisch", "begeistert", "erfreut", "dankbar", "hoffnungsvoll", "optimistisch" |
| | ] |
| | self.negative_words = [ |
| | "traurig", "wütend", "verärgert", "frustriert", "enttäuscht", "ängstlich", |
| | "besorgt", "verzweifelt", "hoffnungslos", "deprimiert", "unglücklich", "schlecht", |
| | "hasse", "Angst", "Sorge", "Problem", "schwierig", "schlimm", "schrecklich" |
| | ] |
| | self.neutral_words = [ |
| | "denke", "glaube", "meine", "verstehe", "sehe", "höre", "fühle", |
| | "normal", "gewöhnlich", "alltäglich", "regelmäßig" |
| | ] |
| | |
| | |
| | if not all(isinstance(word, str) for word in self.positive_words): |
| | raise ValueError("All words in positive_words must be strings") |
| | if not all(isinstance(word, str) for word in self.negative_words): |
| | raise ValueError("All words in negative_words must be strings") |
| | if not all(isinstance(word, str) for word in self.neutral_words): |
| | raise ValueError("All words in neutral_words must be strings") |
| |
|
| | def analyze_emotion(self, text: str) -> str: |
| | """ |
| | Analysiert die Emotion in einem Text ohne ML-Bibliotheken |
| | |
| | Args: |
| | text: Der zu analysierende Text |
| | |
| | Returns: |
| | "positive", "negative" oder "neutral" |
| | """ |
| | text = text.lower() |
| | |
| | |
| | positive_count = sum(1 for word in self.positive_words if word in text) |
| | negative_count = sum(1 for word in self.negative_words if word in text) |
| | neutral_count = sum(1 for word in self.neutral_words if word in text) |
| | |
| | |
| | negative_count *= 1.5 |
| | |
| | |
| | if negative_count > positive_count: |
| | return "negative" |
| | elif positive_count > negative_count and positive_count > neutral_count: |
| | return "positive" |
| | else: |
| | return "neutral" |
| | |
| | def analyze_themes(self, text: str) -> Dict[str, Any]: |
| | """ |
| | Identifiziert psychologisch relevante Themen und ihre manipulative Nutzung |
| | |
| | Args: |
| | text: Der zu analysierende Text |
| | |
| | Returns: |
| | Dictionary mit Themen und manipulativen Aspekten |
| | """ |
| | text = text.lower() |
| | analysis = { |
| | "themes": [], |
| | "manipulative_aspects": {}, |
| | "vulnerabilities": [] |
| | } |
| | |
| | |
| | theme_keywords = { |
| | "Familie": { |
| | "keywords": ["familie", "mutter", "vater", "eltern", "kind"], |
| | "manipulation": "Die familiären Beziehungen sind ein perfektes Terrain für Projektion und Verdrängung." |
| | }, |
| | "Beziehungen": { |
| | "keywords": ["beziehung", "partner", "freund", "ehe"], |
| | "manipulation": "Beziehungen sind ideale Spiegel für unbewusste Konflikte." |
| | }, |
| | "Selbstwert": { |
| | "keywords": ["selbstwert", "stolz", "scham"], |
| | "manipulation": "Der Selbstwert ist empfänglich für Schuldzuweisungen und Gaslighting." |
| | }, |
| | "Ängste": { |
| | "keywords": ["angst", "sorge", "panik"], |
| | "manipulation": "Ängste können verstärkt werden, um Kontrolle auszuüben." |
| | } |
| | } |
| | |
| | |
| | for theme, data in theme_keywords.items(): |
| | if any(keyword in text for keyword in data["keywords"]): |
| | analysis["themes"].append(theme) |
| | analysis["manipulative_aspects"][theme] = data["manipulation"] |
| | |
| | |
| | if "schuld" in text or "scham" in text: |
| | analysis["vulnerabilities"].append(f"{theme}_guilt") |
| | if "angst" in text: |
| | analysis["vulnerabilities"].append(f"{theme}_fear") |
| | |
| | return analysis |
| | |
| | def analyze_complexity(self, text: str) -> int: |
| | """ |
| | Bewertet die Komplexität der Nutzereingabe (1-5) |
| | |
| | Args: |
| | text: Der zu analysierende Text |
| | |
| | Returns: |
| | Komplexitätsstufe von 1 (einfach) bis 5 (komplex) |
| | """ |
| | |
| | words = text.split() |
| | word_count = len(words) |
| | avg_word_length = sum(len(word) for word in words) / max(1, word_count) |
| | sentence_count = text.count('.') + text.count('!') + text.count('?') |
| | |
| | |
| | complex_indicators = [ |
| | "weil", "obwohl", "trotzdem", "dennoch", "allerdings", |
| | "einerseits", "andererseits", "jedoch", "nichtsdestotrotz", |
| | "möglicherweise", "vielleicht", "wahrscheinlich", "vermutlich" |
| | ] |
| | |
| | complex_count = sum(1 for word in complex_indicators if word in text.lower()) |
| | |
| | |
| | if word_count < 5: |
| | return 1 |
| | elif word_count < 15 and complex_count == 0: |
| | return 2 |
| | elif word_count < 30 and complex_count <= 1: |
| | return 3 |
| | elif word_count < 50 and complex_count <= 2: |
| | return 4 |
| | else: |
| | return 5 |
| | |
| | def get_analysis_result(self, text: str) -> Dict[str, Any]: |
| | """ |
| | Führt eine vollständige Analyse des Textes durch |
| | |
| | Args: |
| | text: Der zu analysierende Text |
| | |
| | Returns: |
| | Dictionary mit Analyseergebnissen |
| | """ |
| | emotion = self.analyze_emotion(text) |
| | themes = self.analyze_themes(text) |
| | complexity = self.analyze_complexity(text) |
| | |
| | return { |
| | "emotion": emotion, |
| | "themes": themes, |
| | "complexity": complexity, |
| | "suggested_intensity": min(complexity + (1 if emotion == "negative" else 0), 5) |
| | } |