File size: 10,880 Bytes
b702d72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8c9541f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b702d72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8c9541f
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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
"""
modules/memory.py - Gesprächsgedächtnis-Modul für den Dr. Franz Psychochatbot

Dieses Modul verwaltet die Konversationshistorie und extrahiert wichtige Informationen:
- Speichern und Abrufen der Gesprächshistorie
- Extraktion wichtiger Informationen
- Bereitstellung von Kontext für neue Antworten
"""

from typing import List, Dict, Any, Optional
import re
import random

class Memory:
    """Klasse zur Verwaltung des Gesprächsgedächtnisses"""
    
    def _extract_information(self, exchange: Dict[str, Any]) -> None:
        """
        Extrahiert wichtige Informationen aus einem Gesprächsaustausch
        
        Args:
            exchange: Dictionary mit User-Input und Bot-Response
            
        Raises:
            ValueError: Wenn der Exchange ungültig ist
        """
        if not isinstance(exchange, dict):
            raise ValueError("exchange must be a dictionary")
        if "user_input" not in exchange or not isinstance(exchange["user_input"], str):
            raise ValueError("exchange must contain valid user_input")
        
        user_input = exchange["user_input"].lower()
        analysis = exchange["analysis"]
        
        try:
            # Multi-Level Psychoanalyse
            self._analyze_defense_mechanisms(user_input)
            self._analyze_transference_patterns(user_input)
            self._analyze_symbolic_patterns(user_input)
            self._update_association_network(user_input)
            self._update_escalation_levels(analysis)
            
            # Erwähnte Personen und Ereignisse
            for word in user_input.split():
                if word not in ["ich", "du", "wir", "sie", "er", "es"]:
                    self.extracted_info["mentioned_people"].add(word)
            
        except Exception as e:
            raise ValueError(f"Failed to extract information: {str(e)}")
    
    def add_exchange(self, user_input: str, bot_response: str, analysis: Optional[Dict[str, Any]] = None) -> None:
        """
        Fügt einen Gesprächsaustausch zum Gedächtnis hinzu
        
        Args:
            user_input: Die Eingabe des Nutzers
            bot_response: Die Antwort des Chatbots
            analysis: Optional, Analyseergebnisse des Analyzers
        """
        exchange = {
            "user_input": user_input,
            "bot_response": bot_response,
            "analysis": analysis or {}
        }
        
        self.conversation_history.append(exchange)
        
        # Begrenzung der Historienlänge
        if len(self.conversation_history) > self.max_history_length:
            self.conversation_history = self.conversation_history[-self.max_history_length:]
        
        # Extraktion wichtiger Informationen
        self._extract_information(exchange)
    
    def get_history(self, limit: Optional[int] = None) -> List[Dict[str, Any]]:
        """
        Gibt die Konversationshistorie zurück
        
        Args:
            limit: Optional, maximale Anzahl der zurückzugebenden Einträge
            
        Returns:
            Liste der Gesprächsaustausche
        """
        if limit is None or limit >= len(self.conversation_history):
            return self.conversation_history
        else:
            return self.conversation_history[-limit:]
    
    def format_for_prompt(self, limit: Optional[int] = None) -> str:
        """
        Formatiert die Historie für den Prompt
        
        Args:
            limit: Optional, maximale Anzahl der zu formatierenden Einträge
            
        Returns:
            Formatierte Historie als String
        """
        history = self.get_history(limit)
        formatted = ""
        
        for exchange in history:
            formatted += f"User: {exchange['user_input']}\n"
            formatted += f"Dr. Franz: {exchange['bot_response']}\n"
        
        return formatted
    
    def get_relevant_context(self) -> str:
        """
        Generiert erweiterten psychoanalytischen Kontext für die nächste Antwort
        
        Returns:
            Detaillierte Kontextinformationen als String
        """
        context_parts = []
        
        # Wiederkehrende Themen
        if self.extracted_info["recurring_themes"]:
            top_themes = sorted(
                self.extracted_info["recurring_themes"].items(), 
                key=lambda x: x[1], 
                reverse=True
            )[:2]
            context_parts.append(f"Wiederkehrende Themen: {', '.join(theme for theme, _ in top_themes)}")
        
        # Abwehrmechanismen
        if self.extracted_info["defense_mechanisms"]:
            active_defenses = [k for k, v in self.extracted_info["defense_mechanisms"].items() if v > 0]
            if active_defenses:
                context_parts.append(f"Aktive Abwehrmechanismen: {', '.join(active_defenses)}")
                context_parts.append("Der Patient zeigt überwiegend negative Emotionen.")
            elif recent_emotions.count("positive") >= 2:
                context_parts.append("Der Patient zeigt ungewöhnlich positive Emotionen, was auf Verdrängung hindeuten könnte.")
        
        # Erwähnte Personen einbeziehen
        if self.extracted_info["mentioned_people"]:
            people = list(self.extracted_info["mentioned_people"])
            if people:
                person = random.choice(people)
                context_parts.append(f"Der Patient hat {person} erwähnt. Beziehe dich darauf, wenn passend.")
        
        # Zufällig ein früheres Thema aufgreifen
        if len(self.conversation_history) > 2:
            old_exchange = random.choice(self.conversation_history[:-2])
            if "analysis" in old_exchange and "themes" in old_exchange["analysis"]:
                old_theme = random.choice(old_exchange["analysis"]["themes"])
                context_parts.append(f"Greife bei Gelegenheit das frühere Thema '{old_theme}' wieder auf.")
        
        return " ".join(context_parts)
    
    def _analyze_defense_mechanisms(self, text: str) -> None:
        """Analysiert aktive Abwehrmechanismen im Text"""
        for mechanism, pattern in self.analysis_patterns["defense"].items():
            if re.search(pattern, text):
                self.extracted_info["defense_mechanisms"][mechanism] = self.extracted_info["defense_mechanisms"].get(mechanism, 0) + 1
                
    def _analyze_transference_patterns(self, text: str) -> None:
        """Analysiert Transfersituationen im Text"""
        for category, pattern in self.analysis_patterns["transference"].items():
            if re.search(pattern, text):
                self.extracted_info["transference_patterns"].append(category)
                
    def _analyze_symbolic_patterns(self, text: str) -> None:
        """Analysiert symbolische Muster im Text"""
        for symbol, pattern in self.analysis_patterns["symbolic"].items():
            if re.search(pattern, text):
                self.extracted_info["symbolic_patterns"][symbol] = self.extracted_info["symbolic_patterns"].get(symbol, 0) + 1
                
    def _update_association_network(self, text: str) -> None:
        """Aktualisiert das Assoziationsnetzwerk"""
        words = text.split()
        for i, word in enumerate(words):
            if word not in self.extracted_info["association_network"]:
                self.extracted_info["association_network"][word] = {}
            
            # Erstelle Assoziationen zu benachbarten Wörtern
            if i > 0:
                prev_word = words[i-1]
                self.extracted_info["association_network"][word][prev_word] = self.extracted_info["association_network"][word].get(prev_word, 0) + 1
            if i < len(words) - 1:
                next_word = words[i+1]
                self.extracted_info["association_network"][word][next_word] = self.extracted_info["association_network"][word].get(next_word, 0) + 1
                
    def _update_escalation_levels(self, analysis: Dict[str, Any]) -> None:
        """Aktualisiert die Escalation Levels basierend auf der Analyse"""
        intensity = analysis.get("intensity", 0)
        
        # Emotionale Escalation
        if analysis.get("emotion") == "negative":
            self.extracted_info["escalation_levels"]["emotional"] = min(5, self.extracted_info["escalation_levels"]["emotional"] + intensity)
        else:
            self.extracted_info["escalation_levels"]["emotional"] = max(0, self.extracted_info["escalation_levels"]["emotional"] - 1)
            
        # Kognitive Escalation
        if "defense_mechanisms" in analysis:
            self.extracted_info["escalation_levels"]["cognitive"] = min(5, self.extracted_info["escalation_levels"]["cognitive"] + len(analysis["defense_mechanisms"]))
        else:
            self.extracted_info["escalation_levels"]["cognitive"] = max(0, self.extracted_info["escalation_levels"]["cognitive"] - 1)
            
        # Verhaltensmäßige Escalation
        if "behavioral_patterns" in analysis:
            self.extracted_info["escalation_levels"]["behavioral"] = min(5, self.extracted_info["escalation_levels"]["behavioral"] + len(analysis["behavioral_patterns"]))
        else:
            self.extracted_info["escalation_levels"]["behavioral"] = max(0, self.extracted_info["escalation_levels"]["behavioral"] - 1)
            
    def _extract_information(self, exchange: Dict[str, Any]) -> None:
        """Extrahiert wichtige Informationen aus einem Gesprächsaustausch"""
        user_input = exchange["user_input"].lower()
        analysis = exchange["analysis"]
        
        # Multi-Level Psychoanalyse
        self._analyze_defense_mechanisms(user_input)
        self._analyze_transference_patterns(user_input)
        self._analyze_symbolic_patterns(user_input)
        self._update_association_network(user_input)
        self._update_escalation_levels(analysis)
        
        # Erwähnte Personen und Ereignisse
        for word in user_input.split():
            if word not in ["ich", "du", "wir", "sie", "er", "es"]:
                self.extracted_info["mentioned_people"].add(word)
        
        # Wiederkehrende Themen
        for theme in analysis.get("themes", []):
            self.extracted_info["recurring_themes"][theme] = self.extracted_info["recurring_themes"].get(theme, 0) + 1
        
        # Emotionale Muster
        emotion = analysis.get("emotion", "neutral")
        self.extracted_info["emotional_patterns"].append({
            "emotion": emotion,
            "timestamp": time.time(),
            "intensity": analysis.get("intensity", 0)
        })
        
        # Aktualisiere den letzten Austausch
        self.extracted_info["last_exchange"] = {
            "time": time.time(),
            "intensity": analysis.get("intensity", 0),
            "patterns": analysis.get("patterns", [])
        }