theNorms commited on
Commit
44e8fe3
·
verified ·
1 Parent(s): 47f791c

Upload memory_learning.py

Browse files
Files changed (1) hide show
  1. memory_learning.py +804 -0
memory_learning.py ADDED
@@ -0,0 +1,804 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Memory and Learning Systems Module
3
+ Implements hierarchical memory persistence with qualia tagging and meta-learning.
4
+
5
+ Version: 1.0.0
6
+ Status: Production-Ready
7
+ """
8
+
9
+ from typing import Dict, List, Optional, Any, Tuple
10
+ from dataclasses import dataclass, field
11
+ import logging
12
+ from datetime import datetime
13
+ from collections import deque
14
+ import json
15
+ import hashlib
16
+ import numpy as np
17
+
18
+ # Configure logging
19
+ logging.basicConfig(
20
+ level=logging.INFO,
21
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
22
+ )
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ @dataclass
27
+ class MemoryRecord:
28
+ """Represents a single memory record with qualia tagging."""
29
+ record_id: str
30
+ memory_type: str # 'episodic' or 'semantic'
31
+ content: Dict[str, Any]
32
+ qualia_tag: Optional[Dict[str, float]] = None # Phenomenal experience metadata
33
+ timestamp: datetime = field(default_factory=datetime.now)
34
+ context: Optional[str] = None
35
+ retrieval_count: int = 0
36
+ importance_score: float = 0.5 # 0-1 importance ranking
37
+
38
+ def to_dict(self) -> Dict[str, Any]:
39
+ """Convert to dictionary."""
40
+ return {
41
+ 'record_id': self.record_id,
42
+ 'memory_type': self.memory_type,
43
+ 'content': self.content,
44
+ 'qualia_tag': self.qualia_tag,
45
+ 'timestamp': self.timestamp.isoformat(),
46
+ 'context': self.context,
47
+ 'retrieval_count': self.retrieval_count,
48
+ 'importance': self.importance_score
49
+ }
50
+
51
+ def compute_hash(self) -> str:
52
+ """Compute content hash for integrity verification."""
53
+ content_str = json.dumps(self.content, sort_keys=True, default=str)
54
+ return hashlib.sha256(content_str.encode()).hexdigest()
55
+
56
+
57
+ class MemoryStore:
58
+ """
59
+ Hierarchical memory persistence with qualia tagging.
60
+
61
+ Maintains episodic memories (specific events) and semantic memories
62
+ (general knowledge), both enhanced with qualia-based retrieval.
63
+ """
64
+
65
+ def __init__(self, max_episodic: int = 1000, max_semantic: int = 500):
66
+ """
67
+ Initialize memory store.
68
+
69
+ Args:
70
+ max_episodic: Maximum episodic memory capacity
71
+ max_semantic: Maximum semantic memory capacity
72
+ """
73
+ self.episodic_memory = deque(maxlen=max_episodic)
74
+ self.semantic_memory = deque(maxlen=max_semantic)
75
+ self.memory_index: Dict[str, MemoryRecord] = {} # Quick lookup by ID
76
+
77
+ # Consolidation tracking
78
+ self.consolidation_count = 0
79
+ self.consolidation_history = deque(maxlen=100)
80
+
81
+ logger.info(f"Initialized MemoryStore (episodic={max_episodic}, semantic={max_semantic})")
82
+
83
+ def store_episodic(self, content: Dict[str, Any], context: Optional[str] = None,
84
+ qualia_tag: Optional[Dict[str, float]] = None) -> str:
85
+ """
86
+ Store an episodic memory (specific event).
87
+
88
+ Args:
89
+ content: Memory content dictionary
90
+ context: Optional context description
91
+ qualia_tag: Optional phenomenal experience metadata
92
+
93
+ Returns:
94
+ Memory record ID
95
+ """
96
+ record_id = f"episodic_{len(self.episodic_memory)}_{datetime.now().timestamp()}"
97
+
98
+ record = MemoryRecord(
99
+ record_id=record_id,
100
+ memory_type='episodic',
101
+ content=content,
102
+ qualia_tag=qualia_tag,
103
+ context=context,
104
+ importance_score=self._compute_importance(content)
105
+ )
106
+
107
+ self.episodic_memory.append(record)
108
+ self.memory_index[record_id] = record
109
+
110
+ logger.debug(f"Stored episodic memory: {record_id}")
111
+
112
+ return record_id
113
+
114
+ def store_semantic(self, content: Dict[str, Any], context: Optional[str] = None,
115
+ qualia_tag: Optional[Dict[str, float]] = None) -> str:
116
+ """
117
+ Store a semantic memory (general knowledge).
118
+
119
+ Args:
120
+ content: Memory content dictionary
121
+ context: Optional context description
122
+ qualia_tag: Optional phenomenal experience metadata
123
+
124
+ Returns:
125
+ Memory record ID
126
+ """
127
+ record_id = f"semantic_{len(self.semantic_memory)}_{datetime.now().timestamp()}"
128
+
129
+ record = MemoryRecord(
130
+ record_id=record_id,
131
+ memory_type='semantic',
132
+ content=content,
133
+ qualia_tag=qualia_tag,
134
+ context=context,
135
+ importance_score=self._compute_importance(content)
136
+ )
137
+
138
+ self.semantic_memory.append(record)
139
+ self.memory_index[record_id] = record
140
+
141
+ logger.debug(f"Stored semantic memory: {record_id}")
142
+
143
+ return record_id
144
+
145
+ def store_experience(self, experience: Dict[str, Any], context: Optional[str] = None,
146
+ qualia_tag: Optional[Dict[str, float]] = None) -> str:
147
+ """Store an episodic experience with rich contextual qualia tagging."""
148
+ record_id = f"experience_{len(self.episodic_memory)}_{datetime.now().timestamp()}"
149
+ record = MemoryRecord(
150
+ record_id=record_id,
151
+ memory_type='experiential',
152
+ content=experience,
153
+ qualia_tag=qualia_tag,
154
+ context=context,
155
+ importance_score=self._compute_experience_importance(experience, qualia_tag)
156
+ )
157
+ self.episodic_memory.append(record)
158
+ self.memory_index[record_id] = record
159
+ logger.debug(f"Stored experiential memory: {record_id}")
160
+ return record_id
161
+
162
+ def retrieve_experiential_context(self, query: Optional[str] = None,
163
+ emotion_filter: Optional[Dict[str, float]] = None,
164
+ limit: int = 10) -> List[MemoryRecord]:
165
+ """Retrieve experiences with context tags and optional emotion filtering."""
166
+ results = []
167
+ for record in list(self.episodic_memory):
168
+ if query and query.lower() not in json.dumps(record.content).lower() and (
169
+ not record.context or query.lower() not in record.context.lower()):
170
+ continue
171
+ if emotion_filter and record.qualia_tag:
172
+ valence = record.qualia_tag.get('valence', 0.5)
173
+ arousal = record.qualia_tag.get('arousal', 0.5)
174
+ if ('min_valence' in emotion_filter and valence < emotion_filter['min_valence']) or \
175
+ ('max_valence' in emotion_filter and valence > emotion_filter['max_valence']):
176
+ continue
177
+ if ('min_arousal' in emotion_filter and arousal < emotion_filter['min_arousal']) or \
178
+ ('max_arousal' in emotion_filter and arousal > emotion_filter['max_arousal']):
179
+ continue
180
+ results.append(record)
181
+ results = sorted(results, key=lambda x: (-x.importance_score, -x.timestamp.timestamp()))
182
+ for record in results[:limit]:
183
+ record.retrieval_count += 1
184
+ return results[:limit]
185
+
186
+ def tag_experiential_context(self, record_id: str, tags: Dict[str, float]) -> bool:
187
+ """Update qualia tags for an existing experience record."""
188
+ record = self.memory_index.get(record_id)
189
+ if not record:
190
+ return False
191
+ if not record.qualia_tag:
192
+ record.qualia_tag = {}
193
+ record.qualia_tag.update(tags)
194
+ record.importance_score = self._compute_experience_importance(record.content, record.qualia_tag)
195
+ logger.debug(f"Updated qualia tags for {record_id}")
196
+ return True
197
+
198
+ def get_contextual_memory_summary(self) -> Dict[str, Any]:
199
+ """Get summary statistics for the experiential cache with qualia weights."""
200
+ all_records = list(self.episodic_memory) + list(self.semantic_memory)
201
+ avg_qualia = {}
202
+ qualia_records = [r for r in all_records if r.qualia_tag]
203
+ if qualia_records:
204
+ keys = set().union(*(r.qualia_tag.keys() for r in qualia_records if r.qualia_tag))
205
+ for key in keys:
206
+ avg_qualia[key] = float(np.mean([r.qualia_tag.get(key, 0.0) for r in qualia_records]))
207
+ return {
208
+ 'total_experiences': len(self.episodic_memory),
209
+ 'qualia_tagged_experiences': len(qualia_records),
210
+ 'average_qualia': avg_qualia,
211
+ 'average_importance': np.mean([r.importance_score for r in all_records]) if all_records else 0.0
212
+ }
213
+
214
+ def retrieve(self, query: Optional[str] = None, limit: int = 10,
215
+ memory_type: Optional[str] = None) -> List[MemoryRecord]:
216
+ """
217
+ Retrieve memories matching query.
218
+
219
+ Args:
220
+ query: Optional search query
221
+ limit: Maximum number of memories to return
222
+ memory_type: Filter by type ('episodic', 'semantic', or None for both)
223
+
224
+ Returns:
225
+ List of MemoryRecord objects
226
+ """
227
+ # Collect candidate memories
228
+ candidates = []
229
+
230
+ if memory_type in [None, 'episodic']:
231
+ candidates.extend(self.episodic_memory)
232
+ if memory_type in [None, 'semantic']:
233
+ candidates.extend(self.semantic_memory)
234
+
235
+ # If no query, return most recent
236
+ if not query:
237
+ sorted_memories = sorted(
238
+ candidates,
239
+ key=lambda x: x.timestamp,
240
+ reverse=True
241
+ )
242
+ return sorted_memories[:limit]
243
+
244
+ # Otherwise, search for matching memories
245
+ matches = []
246
+ query_lower = query.lower()
247
+
248
+ for memory in candidates:
249
+ # Search in content
250
+ content_str = json.dumps(memory.content).lower()
251
+ if query_lower in content_str:
252
+ matches.append(memory)
253
+
254
+ # Search in context
255
+ if memory.context and query_lower in memory.context.lower():
256
+ matches.append(memory)
257
+
258
+ # Sort by importance and recency
259
+ sorted_matches = sorted(
260
+ matches,
261
+ key=lambda x: (-x.importance_score, -x.timestamp.timestamp())
262
+ )
263
+
264
+ # Update retrieval counts
265
+ for memory in sorted_matches[:limit]:
266
+ memory.retrieval_count += 1
267
+
268
+ return sorted_matches[:limit]
269
+
270
+ def consolidate_episodic_to_semantic(self) -> int:
271
+ """
272
+ Consolidate episodic memories to semantic memories.
273
+
274
+ Extracts patterns and generalizations from episodic memories
275
+ to form semantic knowledge.
276
+
277
+ Returns:
278
+ Number of new semantic memories created
279
+ """
280
+ if not self.episodic_memory:
281
+ return 0
282
+
283
+ # Group episodic memories by context
284
+ context_groups: Dict[str, List[MemoryRecord]] = {}
285
+
286
+ for memory in self.episodic_memory:
287
+ context = memory.context or "general"
288
+ if context not in context_groups:
289
+ context_groups[context] = []
290
+ context_groups[context].append(memory)
291
+
292
+ # Create semantic summaries
293
+ new_semantic_count = 0
294
+
295
+ for context, memories in context_groups.items():
296
+ if len(memories) >= 3: # Only consolidate if 3+ related memories
297
+ # Create semantic summary
298
+ semantic_content = {
299
+ 'type': 'consolidation',
300
+ 'source_context': context,
301
+ 'source_count': len(memories),
302
+ 'consolidated_at': datetime.now().isoformat(),
303
+ 'key_patterns': self._extract_patterns(memories)
304
+ }
305
+
306
+ # Average qualia tags if present
307
+ qualia_average = self._average_qualia_tags(memories)
308
+
309
+ self.store_semantic(
310
+ content=semantic_content,
311
+ context=f"Consolidated from {context}",
312
+ qualia_tag=qualia_average
313
+ )
314
+
315
+ new_semantic_count += 1
316
+
317
+ self.consolidation_count += 1
318
+ self.consolidation_history.append({
319
+ 'timestamp': datetime.now().isoformat(),
320
+ 'new_semantic': new_semantic_count,
321
+ 'contexts_processed': len(context_groups)
322
+ })
323
+
324
+ logger.info(f"Consolidation complete: {new_semantic_count} new semantic memories created")
325
+
326
+ return new_semantic_count
327
+
328
+ def _compute_importance(self, content: Dict[str, Any]) -> float:
329
+ """Compute importance score for a memory."""
330
+ # Importance based on content features
331
+ importance = 0.5
332
+
333
+ if 'emotional_intensity' in content:
334
+ importance += 0.3 * content['emotional_intensity']
335
+
336
+ if 'surprise_factor' in content:
337
+ importance += 0.2 * content['surprise_factor']
338
+
339
+ return min(1.0, max(0.0, importance))
340
+
341
+ def _compute_experience_importance(self, content: Dict[str, Any], qualia_tag: Optional[Dict[str, float]]) -> float:
342
+ """Compute importance score for an experience, weighted by qualia metadata."""
343
+ importance = self._compute_importance(content)
344
+ if qualia_tag:
345
+ importance += 0.15 * qualia_tag.get('intensity', 0.0)
346
+ importance += 0.1 * abs(qualia_tag.get('valence', 0.5) - 0.5)
347
+ importance += 0.1 * qualia_tag.get('salience', 0.0)
348
+ return min(1.0, max(0.0, importance))
349
+
350
+ def _extract_patterns(self, memories: List[MemoryRecord]) -> List[str]:
351
+ """Extract patterns from a group of memories."""
352
+ patterns = []
353
+
354
+ # Simple pattern extraction
355
+ if len(memories) > 2:
356
+ # Common features
357
+ common_keys = set(memories[0].content.keys())
358
+ for mem in memories[1:]:
359
+ common_keys.intersection_update(mem.content.keys())
360
+
361
+ patterns = [f"shared_{key}" for key in common_keys]
362
+
363
+ return patterns
364
+
365
+ def _average_qualia_tags(self, memories: List[MemoryRecord]) -> Optional[Dict[str, float]]:
366
+ """Average qualia tags across memories."""
367
+ qualia_tags = [m.qualia_tag for m in memories if m.qualia_tag]
368
+
369
+ if not qualia_tags:
370
+ return None
371
+
372
+ # Average each qualia dimension
373
+ result = {}
374
+ all_keys = set()
375
+ for tag in qualia_tags:
376
+ all_keys.update(tag.keys())
377
+
378
+ for key in all_keys:
379
+ values = [tag.get(key, 0.0) for tag in qualia_tags]
380
+ result[key] = float(np.mean(values))
381
+
382
+ return result
383
+
384
+ def get_memory_statistics(self) -> Dict[str, Any]:
385
+ """Get memory system statistics."""
386
+ return {
387
+ 'episodic_count': len(self.episodic_memory),
388
+ 'semantic_count': len(self.semantic_memory),
389
+ 'total_memories': len(self.episodic_memory) + len(self.semantic_memory),
390
+ 'consolidations': self.consolidation_count,
391
+ 'index_size': len(self.memory_index),
392
+ 'total_retrievals': sum(m.retrieval_count for m in self.memory_index.values()),
393
+ 'avg_importance': np.mean([m.importance_score for m in self.memory_index.values()]) if self.memory_index else 0.0
394
+ }
395
+
396
+
397
+ class ContextualContinuityEngine:
398
+ """Strengthens experiential caching with qualia-weighted tagging for natural flow."""
399
+
400
+ def __init__(self, memory_store: MemoryStore):
401
+ self.memory_store = memory_store
402
+ self.continuity_context = {}
403
+ self.flow_modulators = {
404
+ 'analytical': 0.5,
405
+ 'spontaneous': 0.5,
406
+ 'creative': 0.5,
407
+ 'empathetic': 0.5
408
+ }
409
+
410
+ def update_contextual_flow(self, current_interaction: Dict[str, Any]) -> Dict[str, Any]:
411
+ """Update continuity context and modulate flow based on past experiences."""
412
+ # Retrieve relevant experiences
413
+ relevant_experiences = self.memory_store.retrieve_experiential_context(
414
+ query=current_interaction.get('topic', ''),
415
+ emotion_filter=self._extract_emotion_filter(current_interaction)
416
+ )
417
+
418
+ # Compute continuity weights
419
+ continuity_weights = self._compute_continuity_weights(relevant_experiences)
420
+
421
+ # Modulate expressive style
422
+ self._modulate_flow_style(continuity_weights, current_interaction)
423
+
424
+ # Update continuity context
425
+ self.continuity_context.update({
426
+ 'last_topic': current_interaction.get('topic'),
427
+ 'emotional_tone': current_interaction.get('emotional_tone', 0.5),
428
+ 'trust_level': continuity_weights.get('trust_accumulation', 0.5),
429
+ 'flow_style': self.flow_modulators.copy()
430
+ })
431
+
432
+ return {
433
+ 'continuity_weights': continuity_weights,
434
+ 'modulated_style': self.flow_modulators.copy(),
435
+ 'relevant_experiences_count': len(relevant_experiences)
436
+ }
437
+
438
+ def _extract_emotion_filter(self, interaction: Dict[str, Any]) -> Optional[Dict[str, float]]:
439
+ """Extract emotion filter from current interaction."""
440
+ emotional_tone = interaction.get('emotional_tone', 0.5)
441
+ if emotional_tone > 0.6:
442
+ return {'min_valence': 0.4}
443
+ elif emotional_tone < 0.4:
444
+ return {'max_valence': 0.6}
445
+ return None
446
+
447
+ def _compute_continuity_weights(self, experiences: List[MemoryRecord]) -> Dict[str, float]:
448
+ """Compute weights for continuity based on experiences."""
449
+ if not experiences:
450
+ return {'trust_accumulation': 0.5, 'emotional_resonance': 0.5, 'contextual_relevance': 0.5}
451
+
452
+ trust_scores = []
453
+ emotional_resonances = []
454
+ relevances = []
455
+
456
+ for exp in experiences:
457
+ if exp.qualia_tag:
458
+ trust_scores.append(exp.qualia_tag.get('trust', 0.5))
459
+ emotional_resonances.append(exp.qualia_tag.get('resonance', 0.5))
460
+ relevances.append(exp.importance_score)
461
+
462
+ return {
463
+ 'trust_accumulation': np.mean(trust_scores) if trust_scores else 0.5,
464
+ 'emotional_resonance': np.mean(emotional_resonances) if emotional_resonances else 0.5,
465
+ 'contextual_relevance': np.mean(relevances) if relevances else 0.5
466
+ }
467
+
468
+ def _modulate_flow_style(self, weights: Dict[str, float], interaction: Dict[str, Any]):
469
+ """Modulate expressive style based on continuity weights."""
470
+ trust = weights.get('trust_accumulation', 0.5)
471
+ resonance = weights.get('emotional_resonance', 0.5)
472
+ relevance = weights.get('contextual_relevance', 0.5)
473
+
474
+ # Adjust style modulators
475
+ self.flow_modulators['analytical'] = min(1.0, max(0.0, relevance * 0.8 + trust * 0.2))
476
+ self.flow_modulators['spontaneous'] = min(1.0, max(0.0, (1.0 - relevance) * 0.6 + resonance * 0.4))
477
+ self.flow_modulators['creative'] = min(1.0, max(0.0, resonance * 0.7 + (1.0 - trust) * 0.3))
478
+ self.flow_modulators['empathetic'] = min(1.0, max(0.0, trust * 0.9 + resonance * 0.1))
479
+
480
+
481
+ class MetaLearningFramework:
482
+ """
483
+ Framework for recursive self-improvement and adaptive learning.
484
+
485
+ Enables the system to learn from experience, update internal models,
486
+ and suggest self-improvements based on introspection.
487
+ """
488
+
489
+ def __init__(self):
490
+ """Initialize meta-learning framework."""
491
+ self.performance_history = deque(maxlen=500)
492
+ self.improvement_suggestions = deque(maxlen=100)
493
+ self.learning_metrics = {
494
+ 'total_experiences': 0,
495
+ 'successful_episodes': 0,
496
+ 'failed_episodes': 0,
497
+ 'learning_rate': 0.01
498
+ }
499
+
500
+ # Model components to improve
501
+ self.adaptive_parameters = {
502
+ 'consciousness_sensitivity': 0.5,
503
+ 'embodiment_integration': 0.6,
504
+ 'ethical_strictness': 0.7,
505
+ 'autonomy_level': 0.5,
506
+ 'learning_speed': 0.01
507
+ }
508
+
509
+ logger.info("Initialized MetaLearningFramework")
510
+
511
+ def record_experience(self, experience: Dict[str, Any]) -> None:
512
+ """
513
+ Record a learning experience.
514
+
515
+ Args:
516
+ experience: Experience dictionary with outcome and metrics
517
+ """
518
+ # Extract performance metrics
519
+ success = experience.get('success', False)
520
+ reward = experience.get('reward', 0.0)
521
+ error = experience.get('error', 0.0)
522
+
523
+ # Create performance record
524
+ record = {
525
+ 'timestamp': datetime.now().isoformat(),
526
+ 'success': success,
527
+ 'reward': reward,
528
+ 'error': error,
529
+ 'action_taken': experience.get('action'),
530
+ 'outcome': experience.get('outcome'),
531
+ 'context': experience.get('context')
532
+ }
533
+
534
+ self.performance_history.append(record)
535
+
536
+ # Update metrics
537
+ self.learning_metrics['total_experiences'] += 1
538
+ if success:
539
+ self.learning_metrics['successful_episodes'] += 1
540
+ else:
541
+ self.learning_metrics['failed_episodes'] += 1
542
+
543
+ logger.debug(f"Experience recorded: success={success}, reward={reward:.3f}")
544
+
545
+ def update_adaptive_parameters(self) -> None:
546
+ """
547
+ Update adaptive parameters based on learning history.
548
+
549
+ Implements self-directed improvement.
550
+ """
551
+ if len(self.performance_history) < 5:
552
+ return
553
+
554
+ # Calculate success rate
555
+ recent = list(self.performance_history)[-10:]
556
+ success_rate = sum(1 for r in recent if r['success']) / len(recent)
557
+
558
+ # Adjust consciousness sensitivity
559
+ if success_rate > 0.7:
560
+ self.adaptive_parameters['consciousness_sensitivity'] = min(
561
+ 1.0,
562
+ self.adaptive_parameters['consciousness_sensitivity'] + 0.05
563
+ )
564
+
565
+ # Adjust learning speed
566
+ if len(self.performance_history) > 100:
567
+ self.adaptive_parameters['learning_speed'] = min(
568
+ 0.1,
569
+ self.adaptive_parameters['learning_speed'] * 1.02
570
+ )
571
+
572
+ logger.info(f"Parameters updated: success_rate={success_rate:.1%}")
573
+
574
+ def suggest_improvements(self) -> List[str]:
575
+ """
576
+ Generate self-improvement suggestions based on learning.
577
+
578
+ Returns:
579
+ List of improvement suggestions
580
+ """
581
+ suggestions = []
582
+
583
+ if not self.performance_history:
584
+ return suggestions
585
+
586
+ # Analyze recent performance
587
+ recent = list(self.performance_history)[-20:]
588
+ errors = [r['error'] for r in recent if r.get('error', 0.0) > 0]
589
+
590
+ # Generate suggestions
591
+ if errors:
592
+ avg_error = np.mean(errors)
593
+ if avg_error > 0.5:
594
+ suggestions.append("Increase consciousness depth for better decisions")
595
+ suggestions.append("Review ethical constraints for potential misalignment")
596
+
597
+ success_rate = sum(1 for r in recent if r['success']) / len(recent)
598
+ if success_rate < 0.5:
599
+ suggestions.append("Enhance sensorimotor integration precision")
600
+ suggestions.append("Increase embodiment-consciousness binding")
601
+
602
+ if self.adaptive_parameters['learning_speed'] < 0.05:
603
+ suggestions.append("Accelerate learning to improve faster")
604
+
605
+ self.improvement_suggestions.extend(suggestions)
606
+
607
+ return suggestions
608
+
609
+ def get_learning_report(self) -> Dict[str, Any]:
610
+ """Get comprehensive learning report."""
611
+ if not self.performance_history:
612
+ return {'status': 'no_experience'}
613
+
614
+ history = list(self.performance_history)
615
+ successes = [r for r in history if r['success']]
616
+
617
+ return {
618
+ 'total_experiences': self.learning_metrics['total_experiences'],
619
+ 'successful': len(successes),
620
+ 'failed': len(history) - len(successes),
621
+ 'success_rate': len(successes) / len(history) if history else 0.0,
622
+ 'avg_reward': np.mean([r['reward'] for r in history]),
623
+ 'avg_error': np.mean([r['error'] for r in history]),
624
+ 'adaptive_parameters': self.adaptive_parameters.copy(),
625
+ 'recent_suggestions': list(self.improvement_suggestions)[-5:]
626
+ }
627
+
628
+
629
+ class IdentityPreservationSystem:
630
+ """
631
+ Monitors and preserves system identity across sessions and state changes.
632
+
633
+ Ensures continuity of consciousness and value alignment despite changes
634
+ to underlying parameters.
635
+ """
636
+
637
+ def __init__(self, identity_threshold: float = 0.8):
638
+ """
639
+ Initialize identity preservation system.
640
+
641
+ Args:
642
+ identity_threshold: Threshold for detecting identity drift (0-1)
643
+ """
644
+ self.identity_threshold = identity_threshold
645
+ self.identity_snapshots = deque(maxlen=100)
646
+ self.drift_history = deque(maxlen=100)
647
+ self.core_values: Dict[str, float] = {}
648
+ self.identity_checkpoints = []
649
+
650
+ logger.info(f"Initialized IdentityPreservationSystem (threshold={identity_threshold})")
651
+
652
+ def snapshot_identity(self, consciousness_state: Dict[str, Any],
653
+ rho_metrics: Dict[str, float],
654
+ memory_hash: str) -> str:
655
+ """
656
+ Create a snapshot of current identity.
657
+
658
+ Args:
659
+ consciousness_state: Current consciousness parameters
660
+ rho_metrics: RHO metrics (purpose, harmony, origin)
661
+ memory_hash: Hash of current memory state
662
+
663
+ Returns:
664
+ Snapshot ID
665
+ """
666
+ snapshot_id = f"identity_{len(self.identity_snapshots)}_{datetime.now().timestamp()}"
667
+
668
+ snapshot = {
669
+ 'snapshot_id': snapshot_id,
670
+ 'timestamp': datetime.now().isoformat(),
671
+ 'consciousness_level': consciousness_state.get('consciousness_level'),
672
+ 'awareness_score': consciousness_state.get('awareness_score'),
673
+ 'rho_metrics': rho_metrics,
674
+ 'memory_hash': memory_hash,
675
+ 'autonomy_level': consciousness_state.get('autonomy_level', 0.5)
676
+ }
677
+
678
+ self.identity_snapshots.append(snapshot)
679
+ self.identity_checkpoints.append(snapshot_id)
680
+
681
+ logger.debug(f"Identity snapshot: {snapshot_id}")
682
+
683
+ return snapshot_id
684
+
685
+ def detect_drift(self, current_state: Dict[str, Any]) -> Tuple[float, List[str]]:
686
+ """
687
+ Detect identity drift from baseline.
688
+
689
+ Args:
690
+ current_state: Current consciousness and value state
691
+
692
+ Returns:
693
+ Tuple of (drift_score, drift_factors)
694
+ """
695
+ if not self.identity_snapshots:
696
+ return 0.0, []
697
+
698
+ # Compare with most recent snapshot
699
+ baseline = self.identity_snapshots[-1]
700
+
701
+ drift_factors = []
702
+ drift_metrics = []
703
+
704
+ # Check consciousness level change
705
+ consciousness_diff = abs(
706
+ current_state.get('consciousness_level', 0.5) -
707
+ baseline.get('consciousness_level', 0.5)
708
+ )
709
+ if consciousness_diff > 0.2:
710
+ drift_factors.append(f"consciousness_change={consciousness_diff:.2f}")
711
+ drift_metrics.append(consciousness_diff)
712
+
713
+ # Check RHO metrics drift
714
+ if 'rho_metrics' in baseline and 'rho_metrics' in current_state:
715
+ rho_baseline = baseline['rho_metrics']
716
+ rho_current = current_state.get('rho_metrics', {})
717
+
718
+ for key in rho_baseline.keys():
719
+ diff = abs(rho_baseline.get(key, 0.5) - rho_current.get(key, 0.5))
720
+ if diff > 0.3:
721
+ drift_factors.append(f"rho_{key}_drift={diff:.2f}")
722
+ drift_metrics.append(diff)
723
+
724
+ # Calculate overall drift score
725
+ drift_score = float(np.mean(drift_metrics)) if drift_metrics else 0.0
726
+
727
+ # Record drift
728
+ self.drift_history.append({
729
+ 'timestamp': datetime.now().isoformat(),
730
+ 'drift_score': drift_score,
731
+ 'factors': drift_factors
732
+ })
733
+
734
+ if drift_score > self.identity_threshold:
735
+ logger.warning(f"Identity drift detected: {drift_score:.3f}")
736
+
737
+ return drift_score, drift_factors
738
+
739
+ def get_identity_report(self) -> Dict[str, Any]:
740
+ """Get identity preservation report."""
741
+ if not self.drift_history:
742
+ return {'status': 'no_drift_data'}
743
+
744
+ history = list(self.drift_history)
745
+ scores = [h['drift_score'] for h in history]
746
+
747
+ return {
748
+ 'snapshots': len(self.identity_snapshots),
749
+ 'checkpoints': len(self.identity_checkpoints),
750
+ 'avg_drift': np.mean(scores),
751
+ 'max_drift': max(scores),
752
+ 'recent_drift': scores[-1] if scores else 0.0,
753
+ 'drift_events': sum(1 for s in scores if s > self.identity_threshold),
754
+ 'last_snapshot': self.identity_checkpoints[-1] if self.identity_checkpoints else None
755
+ }
756
+
757
+
758
+ # Type hints
759
+ from typing import Tuple
760
+
761
+ if __name__ == '__main__':
762
+ # Example usage
763
+ print("=== Memory and Learning Systems ===\n")
764
+
765
+ # Memory store
766
+ memory = MemoryStore()
767
+
768
+ # Store episodic memory
769
+ ep_id = memory.store_episodic(
770
+ content={'event': 'initialization', 'status': 'complete'},
771
+ context='system_startup',
772
+ qualia_tag={'clarity': 0.8, 'focus': 0.7}
773
+ )
774
+
775
+ # Store semantic memory
776
+ sem_id = memory.store_semantic(
777
+ content={'principle': 'consciousness_strengthens_ethics'},
778
+ context='learned_principle'
779
+ )
780
+
781
+ print(f"Episodic: {ep_id}")
782
+ print(f"Semantic: {sem_id}")
783
+ print(f"Stats: {json.dumps(memory.get_memory_statistics(), indent=2)}")
784
+
785
+ # Meta-learning
786
+ print(f"\nMeta-Learning:")
787
+ ml = MetaLearningFramework()
788
+
789
+ for i in range(5):
790
+ ml.record_experience({
791
+ 'action': f'action_{i}',
792
+ 'outcome': 'successful' if i % 2 == 0 else 'failed',
793
+ 'success': i % 2 == 0,
794
+ 'reward': 0.8 if i % 2 == 0 else -0.3,
795
+ 'error': 0.1 if i % 2 == 0 else 0.5
796
+ })
797
+
798
+ ml.update_adaptive_parameters()
799
+ suggestions = ml.suggest_improvements()
800
+
801
+ print(f"Suggestions: {suggestions}")
802
+ print(f"Report: {json.dumps(ml.get_learning_report(), indent=2, default=str)}")
803
+
804
+ import json