Rkruemmel commited on
Commit
3a70b92
·
verified ·
1 Parent(s): c36f3bc

Upload 3 files

Browse files
Files changed (3) hide show
  1. DRLCogNet.zip +3 -0
  2. gradio_app.py +314 -0
  3. requirements.txt +9 -0
DRLCogNet.zip ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0ea989215f7b0108400126a5d4fe1bc6b6e887f41c675ddf22d9ce99922e2c8f
3
+ size 779770517
gradio_app.py ADDED
@@ -0,0 +1,314 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import json
3
+ import os
4
+ from difflib import get_close_matches
5
+ import base64
6
+ from io import BytesIO
7
+ from PIL import Image
8
+ import random
9
+ import numpy as np
10
+ import gradio as gr
11
+
12
+ # Konfiguration des Loggers
13
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
14
+
15
+ # Globale Variablen
16
+ category_nodes = []
17
+ questions = []
18
+ initialized = False
19
+
20
+ def load_model_with_questions_and_answers(filename="https://drive.google.com/file/d/1Bd7ILLW8ipgoNHSYqZp97VKVt5tR75OM/view?usp=drive_link"):
21
+ """
22
+ Lädt das Modell mit Fragen und Antworten aus einer JSON-Datei.
23
+
24
+ Args:
25
+ filename (str): Der Dateiname der JSON-Datei.
26
+
27
+ Returns:
28
+ tuple: Die Liste der Kategorie-Knoten und die Liste der Fragen.
29
+ """
30
+ global initialized
31
+ if initialized:
32
+ logging.info("Modell bereits initialisiert.")
33
+ return None, None
34
+
35
+ if not os.path.exists(filename):
36
+ logging.warning(f"Datei {filename} nicht gefunden. Netzwerk wird initialisiert.")
37
+ return None, None
38
+
39
+ try:
40
+ with open(filename, "r", encoding="utf-8") as file:
41
+ model_data = json.load(file)
42
+
43
+ nodes_dict = {node_data["label"]: Node(node_data["label"]) for node_data in model_data["nodes"]}
44
+
45
+ for node_data in model_data["nodes"]:
46
+ node = nodes_dict[node_data["label"]]
47
+ node.activation = node_data.get("activation", 0.0)
48
+ node.decay_rate = float(node_data.get("decay_rate", 0.0)) # Laden der decay_rate
49
+ for conn_state in node_data["connections"]:
50
+ target_node = nodes_dict.get(conn_state["target"])
51
+ if target_node:
52
+ node.add_connection(target_node, conn_state["weight"])
53
+
54
+ questions = model_data.get("questions", [])
55
+ logging.info(f"Modell geladen mit {len(nodes_dict)} Knoten und {len(questions)} Fragen")
56
+ initialized = True
57
+ return list(nodes_dict.values()), questions
58
+
59
+ except json.JSONDecodeError as e:
60
+ logging.error(f"Fehler beim Parsen der JSON-Datei: {e}")
61
+ return None, None
62
+
63
+ def find_similar_question(questions, query):
64
+ """
65
+ Findet die ähnlichste Frage basierend auf einfachen Ähnlichkeitsmetriken.
66
+
67
+ Args:
68
+ questions (list): Liste aller Fragen.
69
+ query (str): Die Abfrage, nach der gesucht werden soll.
70
+
71
+ Returns:
72
+ dict: Die ähnlichste Frage.
73
+ """
74
+ question_texts = [q['question'] for q in questions]
75
+ closest_matches = get_close_matches(query, question_texts, n=1, cutoff=0.3)
76
+
77
+ if closest_matches:
78
+ matched_question = next((q for q in questions if q['question'] == closest_matches[0]), None)
79
+ return matched_question
80
+ else:
81
+ return {"question": "Keine passende Frage gefunden", "category": "Unbekannt"}
82
+
83
+ def find_best_answer(category_nodes, questions, query):
84
+ """
85
+ Findet die beste Antwort auf eine Abfrage.
86
+
87
+ Args:
88
+ category_nodes (list): Liste der Kategorie-Knoten.
89
+ questions (list): Liste der Fragen.
90
+ query (str): Die Abfrage.
91
+
92
+ Returns:
93
+ str: Die beste Antwort.
94
+ float: Die Aktivierung des Kategorie-Knotens.
95
+ """
96
+ matched_question = find_similar_question(questions, query)
97
+ if matched_question:
98
+ logging.info(f"Gefundene Frage: {matched_question['question']} -> Kategorie: {matched_question['category']}")
99
+ answer = matched_question.get("answer", "Keine Antwort verfügbar")
100
+ logging.info(f"Antwort: {answer}")
101
+ activation = simulate_question_answering(category_nodes, matched_question['question'], questions)
102
+ return answer, activation
103
+ else:
104
+ logging.warning("Keine passende Frage gefunden.")
105
+ return None, None
106
+
107
+ class Node:
108
+ """
109
+ Ein Knoten im Netzwerk.
110
+ """
111
+ def __init__(self, label):
112
+ self.label = label
113
+ self.connections = []
114
+ self.activation = 0.0
115
+ self.activation_history = []
116
+ self.decay_rate = 0.0 # Initialisierung der decay_rate
117
+
118
+ def add_connection(self, target_node, weight=None):
119
+ """
120
+ Fügt eine Verbindung zu einem Zielknoten hinzu.
121
+
122
+ Args:
123
+ target_node (Node): Der Zielknoten.
124
+ weight (float): Das Gewicht der Verbindung.
125
+ """
126
+ self.connections.append(Connection(target_node, weight))
127
+
128
+ def save_state(self):
129
+ """
130
+ Speichert den Zustand des Knotens.
131
+
132
+ Returns:
133
+ dict: Der gespeicherte Zustand des Knotens.
134
+ """
135
+ return {
136
+ "label": self.label,
137
+ "activation": self.activation,
138
+ "activation_history": self.activation_history,
139
+ "decay_rate": self.decay_rate, # Speichern der decay_rate
140
+ "connections": [{"target": conn.target_node.label, "weight": conn.weight} for conn in self.connections]
141
+ }
142
+
143
+ @staticmethod
144
+ def load_state(state, nodes_dict):
145
+ """
146
+ Lädt den Zustand eines Knotens.
147
+
148
+ Args:
149
+ state (dict): Der gespeicherte Zustand des Knotens.
150
+ nodes_dict (dict): Ein Dictionary der Knoten.
151
+
152
+ Returns:
153
+ Node: Der geladene Knoten.
154
+ """
155
+ node = Node(state["label"])
156
+ node.activation = state["activation"]
157
+ node.activation_history = state["activation_history"]
158
+ node.decay_rate = float(state["decay_rate"]) # Laden der decay_rate
159
+ for conn_state in state["connections"]:
160
+ target_node = nodes_dict[conn_state["target"]]
161
+ connection = Connection(target_node, conn_state["weight"])
162
+ node.connections.append(connection)
163
+ return node
164
+
165
+ class Connection:
166
+ """
167
+ Eine Verbindung zwischen zwei Knoten im Netzwerk.
168
+ """
169
+ def __init__(self, target_node, weight=None):
170
+ self.target_node = target_node
171
+ self.weight = weight if weight is not None else random.uniform(0.1, 1.0)
172
+
173
+ def simulate_question_answering(category_nodes, question, questions):
174
+ """
175
+ Simuliert die Beantwortung einer Frage im Netzwerk.
176
+
177
+ Args:
178
+ category_nodes (list): Liste der Kategorie-Knoten.
179
+ question (str): Die Frage, die beantwortet werden soll.
180
+ questions (list): Liste aller Fragen.
181
+
182
+ Returns:
183
+ float: Die Aktivierung des Kategorie-Knotens.
184
+ """
185
+ category = next((q['category'] for q in questions if q['question'] == question), None)
186
+ if not category:
187
+ logging.warning(f"Frage '{question}' nicht gefunden!")
188
+ return None
189
+
190
+ category_node = next((node for node in category_nodes if node.label == category), None)
191
+ if category_node:
192
+ propagate_signal(category_node, input_signal=0.9, emotion_weights={}, emotional_state=1.0)
193
+ activation = category_node.activation
194
+ if activation is None or activation <= 0:
195
+ logging.warning(f"Kategorie '{category}' hat eine ungültige Aktivierung: {activation}")
196
+ return 0.0 # Rückgabe von 0, falls die Aktivierung fehlschlägt
197
+ logging.info(f"Verarbeite Frage: '{question}' → Kategorie: '{category}' mit Aktivierung {activation:.4f}")
198
+ return activation # Entfernte doppelte Logging-Ausgabe
199
+ else:
200
+ logging.warning(f"Kategorie '{category}' nicht im Netzwerk gefunden. Die Kategorie wird neu hinzugefügt!")
201
+ return 0.0
202
+
203
+ def propagate_signal(node, input_signal, emotion_weights, emotional_state=1.0, context_factors=None):
204
+ """
205
+ Propagiert ein Signal durch das Netzwerk.
206
+
207
+ Args:
208
+ node (Node): Der Knoten, an dem das Signal beginnt.
209
+ input_signal (float): Das Eingangssignal.
210
+ emotion_weights (dict): Die emotionalen Gewichte.
211
+ emotional_state (float): Der emotionale Zustand.
212
+ context_factors (dict): Die kontextuellen Faktoren.
213
+ """
214
+ node.activation = add_activation_noise(sigmoid(input_signal * random.uniform(0.8, 1.2)))
215
+ node.activation_history.append(node.activation) # Aktivierung speichern
216
+ node.activation = apply_emotion_weight(node.activation, node.label, emotion_weights, emotional_state)
217
+ if context_factors:
218
+ node.activation = apply_contextual_factors(node.activation, node, context_factors)
219
+ logging.info(f"Signalpropagation für {node.label}: Eingangssignal {input_signal:.4f}")
220
+ for connection in node.connections:
221
+ logging.info(f" → Signal an {connection.target_node.label} mit Gewicht {connection.weight:.4f}")
222
+ connection.target_node.activation += node.activation * connection.weight
223
+
224
+ def add_activation_noise(activation, noise_level=0.1):
225
+ """
226
+ Fügt Rauschen zur Aktivierung hinzu.
227
+
228
+ Args:
229
+ activation (float): Die Aktivierung.
230
+ noise_level (float): Das Rausch-Level.
231
+
232
+ Returns:
233
+ float: Die Aktivierung mit Rauschen.
234
+ """
235
+ noise = np.random.normal(0, noise_level)
236
+ return np.clip(activation + noise, 0.0, 1.0)
237
+
238
+ def sigmoid(x):
239
+ """
240
+ Berechnet die Sigmoid-Funktion.
241
+
242
+ Args:
243
+ x (float): Der Eingabewert.
244
+
245
+ Returns:
246
+ float: Der Ausgabewert der Sigmoid-Funktion.
247
+ """
248
+ return 1 / (1 + np.exp(-x))
249
+
250
+ def apply_emotion_weight(activation, category_label, emotion_weights, emotional_state=1.0):
251
+ """
252
+ Wendet ein emotionales Gewicht auf die Aktivierung an.
253
+
254
+ Args:
255
+ activation (float): Die Aktivierung.
256
+ category_label (str): Das Label der Kategorie.
257
+ emotion_weights (dict): Die emotionalen Gewichte.
258
+ emotional_state (float): Der emotionale Zustand.
259
+
260
+ Returns:
261
+ float: Die gewichtete Aktivierung.
262
+ """
263
+ emotion_factor = emotion_weights.get(category_label, 1.0) * emotional_state
264
+ return activation * emotion_factor
265
+
266
+ def apply_contextual_factors(activation, node, context_factors):
267
+ """
268
+ Wendet kontextuelle Faktoren auf die Aktivierung an.
269
+
270
+ Args:
271
+ activation (float): Die Aktivierung.
272
+ node (Node): Der Knoten.
273
+ context_factors (dict): Die kontextuellen Faktoren.
274
+
275
+ Returns:
276
+ float: Die aktualisierte Aktivierung.
277
+ """
278
+ context_factor = context_factors.get(node.label, 1.0)
279
+ return activation * context_factor * random.uniform(0.9, 1.1)
280
+
281
+ def get_answer(query):
282
+ answer, activation = find_best_answer(category_nodes, questions, query)
283
+ if answer:
284
+ # Dekodieren der Base64-Bilddaten
285
+ try:
286
+ image_data = base64.b64decode(answer)
287
+ image = Image.open(BytesIO(image_data))
288
+ return image, activation, f"{activation:.2f}"
289
+ except Exception as e:
290
+ logging.error(f"Fehler beim Dekodieren des Bildes: {e}")
291
+ return None, None, "0.00"
292
+ else:
293
+ return None, None, "0.00"
294
+
295
+ # Lade das Modell und die Fragen
296
+ category_nodes, questions = load_model_with_questions_and_answers("https://drive.google.com/file/d/1Bd7ILLW8ipgoNHSYqZp97VKVt5tR75OM/view?usp=drive_link")
297
+ if category_nodes is None or questions is None:
298
+ logging.error("Fehler beim Laden des Modells. Stellen Sie sicher, dass die Datei 'model_with_qa.json' vorhanden ist.")
299
+ else:
300
+ # Erstelle die Gradio-App
301
+ with gr.Blocks(title="DRL-CogNet Dog finder") as demo: # Hinzugefügter Titel
302
+ gr.Markdown("# Frage an das Modell")
303
+ with gr.Row():
304
+ with gr.Column():
305
+ question_input = gr.Textbox(label="Frage")
306
+ submit_button = gr.Button("Antwort abrufen")
307
+ with gr.Column():
308
+ image_output = gr.Image(label="Antwortbild")
309
+ activation_output = gr.Number(label="Aktivierung")
310
+ weight_output = gr.Text(label="Gewichtung")
311
+
312
+ submit_button.click(fn=get_answer, inputs=question_input, outputs=[image_output, activation_output, weight_output])
313
+
314
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ logging
2
+ json
3
+ os
4
+ difflib
5
+ base64
6
+ pillow
7
+ random
8
+ numpy
9
+ gradio