ThreadAbort commited on
Commit
f82de34
·
1 Parent(s): 701f9bf
Files changed (1) hide show
  1. app.py +85 -101
app.py CHANGED
@@ -85,21 +85,13 @@ MEMORY_DIR = "memory_snapshots"
85
  os.makedirs(MEMORY_DIR, exist_ok=True)
86
 
87
  class EmotionalContext:
88
- """
89
- Implements Mem|8's emotional context structure as described in the paper.
90
-
91
- Attributes:
92
- valence (torch.Tensor): Emotional valence (-128 to 127: negative to positive)
93
- arousal (torch.Tensor): Emotional arousal (0 to 255: intensity level)
94
- context (torch.Tensor): Contextual flags (16-bit in paper)
95
- safety (torch.Tensor): Psychological safety indicator
96
- """
97
  def __init__(self, device_str="cpu"):
98
  self.device = device_str
99
- self.valence = torch.zeros(1, device=device_str) # -128 to 127: negative to positive
100
- self.arousal = torch.zeros(1, device=device_str) # 0 to 255: intensity level
101
- self.context = torch.zeros(1, device=device_str) # Contextual flags
102
- self.safety = torch.ones(1, device=device_str) # Psychological safety indicator
103
 
104
  # Track emotional history for visualization
105
  self.history = {
@@ -109,18 +101,28 @@ class EmotionalContext:
109
  }
110
 
111
  def update(self, valence: float, arousal: Optional[float] = None):
112
- """Update emotional context with new values and record in history."""
113
- self.valence = torch.tensor([valence], device=self.device)
 
 
 
 
 
 
114
 
115
- # If arousal not provided, calculate based on valence as in the paper
116
  if arousal is None:
117
- self.arousal = torch.abs(torch.tensor([valence * 2], device=self.device))
118
  else:
119
- self.arousal = torch.tensor([arousal], device=self.device)
120
-
121
- # Update history
122
- self.history['valence'].append(float(self.valence.item()))
123
- self.history['arousal'].append(float(self.arousal.item()))
 
 
 
 
124
  self.history['timestamps'].append(time.time())
125
 
126
  # Keep history at a reasonable size
@@ -130,34 +132,36 @@ class EmotionalContext:
130
  self.history['timestamps'] = self.history['timestamps'][-100:]
131
 
132
  def get_color_mapping(self) -> Tuple[float, float, float]:
133
- """
134
- Maps emotional state to RGB color values.
 
 
135
 
136
- Returns:
137
- Tuple[float, float, float]: RGB color values (0-1 range)
138
- """
139
  # Normalize valence to 0-1 range for hue
140
- norm_valence = (self.valence.item() - EMOTION_RANGE[0]) / (EMOTION_RANGE[1] - EMOTION_RANGE[0])
141
 
142
  # Normalize arousal to 0-1 range for saturation
143
- norm_arousal = self.arousal.item() / AROUSAL_RANGE[1]
144
 
145
- # Convert HSV to RGB (hue from valence, saturation from arousal, value=1)
146
  rgb = colorsys.hsv_to_rgb(norm_valence, norm_arousal, 1.0)
147
  return rgb
148
 
149
- def __str__(self) -> str:
150
- """String representation of emotional context."""
151
- return f"EmotionalContext(valence={self.valence.item():.2f}, arousal={self.arousal.item():.2f})"
152
-
153
  def to(self, device_str):
154
  """Move the context to a different device."""
 
 
 
155
  self.device = device_str
156
  self.valence = self.valence.to(device_str)
157
  self.arousal = self.arousal.to(device_str)
158
  self.context = self.context.to(device_str)
159
  self.safety = self.safety.to(device_str)
160
  return self
 
 
 
 
161
 
162
  class MemoryWave:
163
  """
@@ -168,13 +172,13 @@ class MemoryWave:
168
  """
169
  def __init__(self,
170
  size: int = DEFAULT_GRID_SIZE,
171
- device_str: str = "cpu"): # Use global device
172
  """
173
  Initialize a memory wave system.
174
 
175
  Args:
176
  size: Size of the memory grid (NxN)
177
- device_str: Device to use for computations
178
  """
179
  self.size = size
180
  self.device = device_str
@@ -192,23 +196,35 @@ class MemoryWave:
192
  # History of wave states for animation
193
  self.history = []
194
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  def create_wave(self,
196
  frequency: float,
197
  amplitude: float,
198
  phase: float = 0.0,
199
  direction: str = "radial") -> torch.Tensor:
200
- """
201
- Create a wave pattern as described in Mem|8 paper.
202
-
203
- Args:
204
- frequency: Wave frequency (ω in the paper)
205
- amplitude: Wave amplitude (A in the paper)
206
- phase: Initial phase offset
207
- direction: Wave direction pattern ("radial", "linear_x", "linear_y", or "spiral")
208
 
209
- Returns:
210
- torch.Tensor: The generated wave pattern
211
- """
212
  if direction == "radial":
213
  # Radial waves emanating from center (like dropping a stone in water)
214
  center_x, center_y = self.size/2, self.size/2
@@ -236,15 +252,11 @@ class MemoryWave:
236
  return wave
237
 
238
  def apply_emotional_modulation(self, wave: torch.Tensor) -> torch.Tensor:
239
- """
240
- Apply emotional modulation to a wave pattern as described in the paper.
241
-
242
- Args:
243
- wave: The input wave pattern
244
 
245
- Returns:
246
- torch.Tensor: Emotionally modulated wave
247
- """
248
  # Emotional modulation formula from paper: M = A·exp(iωt-kx)·D·E
249
  # We implement a simplified version where E is based on valence
250
  valence_factor = self.emotion.valence / 128 # Normalize to -1 to 1 range
@@ -264,17 +276,13 @@ class MemoryWave:
264
 
265
  def create_interference(self, wave1: torch.Tensor, wave2: torch.Tensor,
266
  interference_type: str = "constructive") -> torch.Tensor:
267
- """
268
- Create interference between two memory waves.
269
-
270
- Args:
271
- wave1: First wave pattern
272
- wave2: Second wave pattern
273
- interference_type: Type of interference ("constructive", "destructive", or "resonance")
274
 
275
- Returns:
276
- torch.Tensor: The resulting interference pattern
277
- """
278
  if interference_type == "constructive":
279
  # Simple addition for constructive interference
280
  return wave1 + wave2
@@ -291,20 +299,13 @@ class MemoryWave:
291
  raise ValueError(f"Unknown interference type: {interference_type}")
292
 
293
  def apply_memory_blanket(self, wave: torch.Tensor, threshold: float = 0.5) -> torch.Tensor:
294
- """
295
- Apply the memory blanket concept from the paper.
296
-
297
- The memory blanket acts as an adaptive filter that:
298
- 1. Catches significant waves (important memories)
299
- 2. Allows insignificant ripples to fade
300
-
301
- Args:
302
- wave: Input wave pattern
303
- threshold: Importance threshold
304
 
305
- Returns:
306
- torch.Tensor: Filtered wave pattern
307
- """
308
  # Calculate wave importance (amplitude)
309
  importance = torch.abs(wave)
310
 
@@ -314,21 +315,16 @@ class MemoryWave:
314
  return filtered_wave
315
 
316
  def store_memory(self, wave: torch.Tensor, memory_type: int = 0) -> None:
317
- """
318
- Store a wave pattern in the specified memory type.
319
-
320
- Args:
321
- wave: Wave pattern to store
322
- memory_type: Memory type (0-5) as described in the paper
323
- """
324
- if memory_type not in self.memory_types:
325
- raise ValueError(f"Invalid memory type: {memory_type}")
326
 
327
  # Store the wave pattern
328
  self.memory_types[memory_type] = wave
329
 
330
- # Add to history for animation
331
- self.history.append(wave.clone().cpu().numpy())
332
 
333
  # Keep history at a reasonable size
334
  if len(self.history) > 100:
@@ -834,18 +830,6 @@ class MemoryWave:
834
  print(f"❌ Error during processing: {e}")
835
  return None
836
 
837
- def to(self, device_str):
838
- """Move the wave system to a different device."""
839
- self.device = device_str
840
- self.grid = self.grid.to(device_str)
841
- self.emotion = self.emotion.to(device_str)
842
- self.x = self.x.to(device_str)
843
- self.y = self.y.to(device_str)
844
- self.X = self.X.to(device_str)
845
- self.Y = self.Y.to(device_str)
846
- self.memory_types = {k: v.to(device_str) for k, v in self.memory_types.items()}
847
- return self
848
-
849
  def generate_memory_prompt(operation: str, emotion_valence: float) -> str:
850
  """Generate an artistic prompt based on the memory operation and emotional context."""
851
 
 
85
  os.makedirs(MEMORY_DIR, exist_ok=True)
86
 
87
  class EmotionalContext:
88
+ """Implements Mem|8's emotional context structure."""
 
 
 
 
 
 
 
 
89
  def __init__(self, device_str="cpu"):
90
  self.device = device_str
91
+ self.valence = torch.zeros(1, device=device_str)
92
+ self.arousal = torch.zeros(1, device=device_str)
93
+ self.context = torch.zeros(1, device=device_str)
94
+ self.safety = torch.ones(1, device=device_str)
95
 
96
  # Track emotional history for visualization
97
  self.history = {
 
101
  }
102
 
103
  def update(self, valence: float, arousal: Optional[float] = None):
104
+ """Update emotional context with new values."""
105
+ # Convert inputs to tensors on the right device
106
+ if not isinstance(valence, torch.Tensor):
107
+ valence = torch.tensor([valence], device=self.device)
108
+ elif valence.device != self.device:
109
+ valence = valence.to(self.device)
110
+
111
+ self.valence = valence
112
 
113
+ # If arousal not provided, calculate based on valence
114
  if arousal is None:
115
+ self.arousal = torch.abs(valence * 2)
116
  else:
117
+ if not isinstance(arousal, torch.Tensor):
118
+ arousal = torch.tensor([arousal], device=self.device)
119
+ elif arousal.device != self.device:
120
+ arousal = arousal.to(self.device)
121
+ self.arousal = arousal
122
+
123
+ # Update history (use CPU values for storage)
124
+ self.history['valence'].append(float(self.valence.cpu().item()))
125
+ self.history['arousal'].append(float(self.arousal.cpu().item()))
126
  self.history['timestamps'].append(time.time())
127
 
128
  # Keep history at a reasonable size
 
132
  self.history['timestamps'] = self.history['timestamps'][-100:]
133
 
134
  def get_color_mapping(self) -> Tuple[float, float, float]:
135
+ """Maps emotional state to RGB color values."""
136
+ # Get values from tensors (move to CPU for calculations)
137
+ valence = self.valence.cpu().item()
138
+ arousal = self.arousal.cpu().item()
139
 
 
 
 
140
  # Normalize valence to 0-1 range for hue
141
+ norm_valence = (valence - EMOTION_RANGE[0]) / (EMOTION_RANGE[1] - EMOTION_RANGE[0])
142
 
143
  # Normalize arousal to 0-1 range for saturation
144
+ norm_arousal = arousal / AROUSAL_RANGE[1]
145
 
146
+ # Convert HSV to RGB
147
  rgb = colorsys.hsv_to_rgb(norm_valence, norm_arousal, 1.0)
148
  return rgb
149
 
 
 
 
 
150
  def to(self, device_str):
151
  """Move the context to a different device."""
152
+ if self.device == device_str:
153
+ return self
154
+
155
  self.device = device_str
156
  self.valence = self.valence.to(device_str)
157
  self.arousal = self.arousal.to(device_str)
158
  self.context = self.context.to(device_str)
159
  self.safety = self.safety.to(device_str)
160
  return self
161
+
162
+ def __str__(self) -> str:
163
+ """String representation of emotional context."""
164
+ return f"EmotionalContext(valence={self.valence.cpu().item():.2f}, arousal={self.arousal.cpu().item():.2f})"
165
 
166
  class MemoryWave:
167
  """
 
172
  """
173
  def __init__(self,
174
  size: int = DEFAULT_GRID_SIZE,
175
+ device_str: str = "cpu"):
176
  """
177
  Initialize a memory wave system.
178
 
179
  Args:
180
  size: Size of the memory grid (NxN)
181
+ device_str: Device to use for computations (defaults to CPU)
182
  """
183
  self.size = size
184
  self.device = device_str
 
196
  # History of wave states for animation
197
  self.history = []
198
 
199
+ def to(self, device_str):
200
+ """Move the wave system to a different device."""
201
+ if self.device == device_str:
202
+ return self
203
+
204
+ self.device = device_str
205
+ self.grid = self.grid.to(device_str)
206
+ self.emotion = self.emotion.to(device_str)
207
+ self.x = self.x.to(device_str)
208
+ self.y = self.y.to(device_str)
209
+ self.X = self.X.to(device_str)
210
+ self.Y = self.Y.to(device_str)
211
+ self.memory_types = {k: v.to(device_str) for k, v in self.memory_types.items()}
212
+ return self
213
+
214
  def create_wave(self,
215
  frequency: float,
216
  amplitude: float,
217
  phase: float = 0.0,
218
  direction: str = "radial") -> torch.Tensor:
219
+ """Create a wave pattern as described in Mem|8 paper."""
220
+ # Ensure we're on the right device
221
+ if not isinstance(frequency, torch.Tensor):
222
+ frequency = torch.tensor(frequency, device=self.device)
223
+ if not isinstance(amplitude, torch.Tensor):
224
+ amplitude = torch.tensor(amplitude, device=self.device)
225
+ if not isinstance(phase, torch.Tensor):
226
+ phase = torch.tensor(phase, device=self.device)
227
 
 
 
 
228
  if direction == "radial":
229
  # Radial waves emanating from center (like dropping a stone in water)
230
  center_x, center_y = self.size/2, self.size/2
 
252
  return wave
253
 
254
  def apply_emotional_modulation(self, wave: torch.Tensor) -> torch.Tensor:
255
+ """Apply emotional modulation to a wave pattern."""
256
+ # Ensure wave is on the right device
257
+ if wave.device != self.device:
258
+ wave = wave.to(self.device)
 
259
 
 
 
 
260
  # Emotional modulation formula from paper: M = A·exp(iωt-kx)·D·E
261
  # We implement a simplified version where E is based on valence
262
  valence_factor = self.emotion.valence / 128 # Normalize to -1 to 1 range
 
276
 
277
  def create_interference(self, wave1: torch.Tensor, wave2: torch.Tensor,
278
  interference_type: str = "constructive") -> torch.Tensor:
279
+ """Create interference between two memory waves."""
280
+ # Ensure waves are on the right device
281
+ if wave1.device != self.device:
282
+ wave1 = wave1.to(self.device)
283
+ if wave2.device != self.device:
284
+ wave2 = wave2.to(self.device)
 
285
 
 
 
 
286
  if interference_type == "constructive":
287
  # Simple addition for constructive interference
288
  return wave1 + wave2
 
299
  raise ValueError(f"Unknown interference type: {interference_type}")
300
 
301
  def apply_memory_blanket(self, wave: torch.Tensor, threshold: float = 0.5) -> torch.Tensor:
302
+ """Apply the memory blanket concept."""
303
+ # Ensure wave is on the right device
304
+ if wave.device != self.device:
305
+ wave = wave.to(self.device)
306
+ if not isinstance(threshold, torch.Tensor):
307
+ threshold = torch.tensor(threshold, device=self.device)
 
 
 
 
308
 
 
 
 
309
  # Calculate wave importance (amplitude)
310
  importance = torch.abs(wave)
311
 
 
315
  return filtered_wave
316
 
317
  def store_memory(self, wave: torch.Tensor, memory_type: int = 0) -> None:
318
+ """Store a wave pattern in memory."""
319
+ # Ensure wave is on the right device
320
+ if wave.device != self.device:
321
+ wave = wave.to(self.device)
 
 
 
 
 
322
 
323
  # Store the wave pattern
324
  self.memory_types[memory_type] = wave
325
 
326
+ # Add to history for animation (move to CPU for numpy conversion)
327
+ self.history.append(wave.cpu().numpy())
328
 
329
  # Keep history at a reasonable size
330
  if len(self.history) > 100:
 
830
  print(f"❌ Error during processing: {e}")
831
  return None
832
 
 
 
 
 
 
 
 
 
 
 
 
 
833
  def generate_memory_prompt(operation: str, emotion_valence: float) -> str:
834
  """Generate an artistic prompt based on the memory operation and emotional context."""
835