File size: 8,352 Bytes
b702d72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302b099
b702d72
302b099
b702d72
 
 
 
302b099
b702d72
 
 
 
302b099
b702d72
 
 
0e74190
b702d72
 
 
 
 
e1f07e0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b702d72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0e74190
 
 
cd853d1
 
 
0e74190
 
 
 
 
 
 
cd853d1
0e74190
 
 
 
 
cd853d1
 
 
 
 
 
 
 
 
 
0e74190
 
 
 
 
cd853d1
 
 
 
 
 
 
 
 
 
 
b702d72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80bdef8
b702d72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
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