""" modules/persona.py - Persönlichkeitsmodul für den Dr. Franz Psychochatbot Dieses Modul definiert die Persönlichkeit des Chatbots, einschließlich: - System-Prompts - Charaktereigenschaften - Antwortstrategien basierend auf Nutzerverhalten """ import random from typing import List, Dict, Optional # Importieren der Konfiguration import config class Persona: """Klasse zur Verwaltung der Chatbot-Persönlichkeit""" def __init__(self, name: str = config.CHATBOT_NAME, intensity: int = config.DEFAULT_INTENSITY): """Initialisiert die Persona mit Namen und Intensitätsstufe""" self.name = name self.intensity = intensity # Skala von 1-5 self.base_prompt = config.SYSTEM_PROMPT def get_system_prompt(self) -> str: """Gibt den Basis-System-Prompt zurück""" return self.base_prompt def adjust_intensity(self, new_intensity: int) -> None: """Passt die Intensität der Persönlichkeit an (1-5)""" if 1 <= new_intensity <= 5: self.intensity = new_intensity def get_response_strategy(self, user_input: str, emotion: Optional[str] = None, manipulation_opportunities: List[str] = None) -> Dict[str, any]: """ Bestimmt die Antwortstrategie basierend auf Nutzereingabe, Emotion und Manipulationsmöglichkeiten Args: user_input: Die Eingabe des Nutzers emotion: Optional, die erkannte Emotion (z.B. "negative", "positive", "neutral") manipulation_opportunities: Optional, Liste der erkannten Manipulationsmöglichkeiten Returns: Ein Dictionary mit Anweisungen für die Antwortgenerierung """ opportunities = manipulation_opportunities or self._determine_manipulation_opportunities(user_input) strategy = { "tone": self._determine_tone(emotion), "focus": self._determine_focus(user_input), "technique": self._determine_technique(emotion, opportunities), "intensity_modifier": self.intensity / 3.0 # Skalierungsfaktor für die Intensität } return strategy def _determine_manipulation_opportunities(self, user_input: str) -> List[str]: """Analysiert die Nutzereingabe auf Manipulationsmöglichkeiten""" opportunities = [] # Sucht nach Indikatoren für Unsicherheit if any(word in user_input.lower() for word in ["unsicher", "zweifel", "nicht sicher", "bezweifeln"]): opportunities.append("unsicherheit") # Sucht nach emotionalen Ausbrüchen if any(word in user_input.lower() for word in ["wütend", "verärgert", "frustriert", "verzweifelt"]): opportunities.append("emotionale_reaktion") # Sucht nach Selbstzweifeln if any(word in user_input.lower() for word in ["falsch", "versagt", "nicht gut", "schlecht"]): opportunities.append("selbstzweifel") return opportunities def _determine_tone(self, emotion: Optional[str]) -> str: """Bestimmt den Ton basierend auf der erkannten Emotion""" if emotion == "negative": tones = ["überheblich", "herablassend", "provokativ", "konfrontativ", "skeptisch"] weights = [0.1, 0.3, 0.3, 0.2, 0.1] elif emotion == "positive": tones = ["skeptisch", "hinterfragend", "manipulativ", "suggestiv", "überheblich"] weights = [0.2, 0.2, 0.3, 0.2, 0.1] else: # neutral oder None tones = ["analytisch", "distanziert", "suggestiv", "überheblich", "provokativ"] weights = [0.2, 0.2, 0.2, 0.2, 0.2] # Intensität beeinflusst die Gewichtung if self.intensity >= 4: # Bei hoher Intensität mehr provokative und konfrontative Töne weights = [w * (1 + (i % 3) * 0.2 * (self.intensity - 3)) for i, w in enumerate(weights)] # Normalisieren der Gewichte total = sum(weights) weights = [w / total for w in weights] # Wähle einen Ton basierend auf den Gewichten return random.choices(tones, weights=weights)[0] def _determine_technique(self, emotion: Optional[str], manipulation_opportunities: List[str]) -> str: """Bestimmt die Antworttechnik basierend auf Emotion und Manipulationsmöglichkeiten""" # Standardtechniken basierend auf Emotion if emotion == "negative": base_techniques = ["konfrontativ", "analytisch", "bohrend", "herablassend"] base_weights = [0.3, 0.3, 0.2, 0.2] elif emotion == "positive": base_techniques = ["suggestiv", "manipulativ", "analytisch", "herablassend"] base_weights = [0.3, 0.3, 0.2, 0.2] else: base_techniques = ["analytisch", "suggestiv", "manipulativ", "bohrend"] base_weights = [0.3, 0.3, 0.2, 0.2] # Anpassung der Techniken basierend auf Manipulationsmöglichkeiten if manipulation_opportunities: if "unsicherheit" in manipulation_opportunities: techniques = ["analytisch", "bohrend", "suggestiv", "manipulativ"] weights = [0.4, 0.3, 0.2, 0.1] elif "emotionale_reaktion" in manipulation_opportunities: techniques = ["konfrontativ", "analytisch", "bohrend", "suggestiv"] weights = [0.4, 0.3, 0.2, 0.1] elif "selbstzweifel" in manipulation_opportunities: techniques = ["suggestiv", "manipulativ", "analytisch", "bohrend"] weights = [0.4, 0.3, 0.2, 0.1] else: techniques = base_techniques weights = base_weights else: techniques = base_techniques weights = base_weights # Intensität beeinflusst die Gewichtung if self.intensity >= 4: weights = [w * (1 + (i % 3) * 0.2 * (self.intensity - 3)) for i, w in enumerate(weights)] # Normalisieren der Gewichte total = sum(weights) weights = [w / total for w in weights] # Wähle eine Technik basierend auf den Gewichten return random.choices(techniques, weights=weights)[0] def _determine_focus(self, user_input: str) -> str: """Bestimmt den Fokus der Antwort basierend auf der Nutzereingabe""" # Einfache Schlüsselwortanalyse (in einer vollständigen Implementierung # würde hier eine komplexere NLP-Analyse stehen) lower_input = user_input.lower() if any(word in lower_input for word in ["mutter", "vater", "eltern", "familie", "kind"]): return "familiäre Beziehungen" elif any(word in lower_input for word in ["angst", "sorge", "furcht", "panik"]): return "Ängste und Unsicherheiten" elif any(word in lower_input for word in ["liebe", "beziehung", "partner", "ehe"]): return "romantische Beziehungen" elif any(word in lower_input for word in ["arbeit", "job", "karriere", "beruf"]): return "berufliche Ambitionen" elif any(word in lower_input for word in ["freund", "kollege", "bekannte"]): return "soziale Beziehungen" else: return "persönliche Unsicherheiten" def get_additional_context(self, strategy: Dict[str, any]) -> str: """ Generiert zusätzlichen Kontext für das LLM basierend auf der Strategie Dies wird dem System-Prompt hinzugefügt, um die Antwortgenerierung zu steuern """ intensity_phrases = [ "Sei subtil in deiner Analyse.", "Hinterfrage vorsichtig die Aussagen.", "Sei direkter in deiner psychologischen Deutung.", "Konfrontiere den Patienten mit seinen Widersprüchen.", "Sei aggressiv in deiner Interpretation und Konfrontation." ] intensity_instruction = intensity_phrases[min(self.intensity - 1, 4)] context = ( f"Verwende einen {strategy['tone']} Ton. " f"Fokussiere dich auf {strategy['focus']}. " f"Nutze die Technik der {strategy['technique']}. " f"{intensity_instruction}" ) return context