Skip to main content

Memory System Visualizer

Interactive Learning Module for Multi-Layer Memory Architecture

Document ID: E3-MEMORY-VISUALIZER
Version: 1.0
Category: P5 - Interactive Learning
Format: React JSX Component


Component Overview

The Memory System Visualizer provides an interactive demonstration of how the four memory layers work together in agentic systems. Users can simulate memory operations and observe data flow between layers.


JSX Component

import React, { useState, useEffect } from 'react';
import { Database, Clock, Archive, Shield, ArrowDown, ArrowUp, Search, Plus, Trash2, RefreshCw, Play, Pause } from 'lucide-react';

const MemoryVisualizer = () => {
const [activeLayer, setActiveLayer] = useState(null);
const [simulation, setSimulation] = useState({
running: false,
step: 0,
query: '',
results: []
});

const [memories, setMemories] = useState({
parametric: [
{ id: 'p1', content: 'General world knowledge', type: 'factual', permanent: true },
{ id: 'p2', content: 'Language understanding', type: 'linguistic', permanent: true },
{ id: 'p3', content: 'Reasoning patterns', type: 'cognitive', permanent: true }
],
shortTerm: [
{ id: 'st1', content: 'Current conversation context', tokens: 2400, age: '2m' },
{ id: 'st2', content: 'User query: "Analyze Q3 report"', tokens: 45, age: '30s' },
{ id: 'st3', content: 'Working hypothesis: Revenue up 12%', tokens: 120, age: '15s' }
],
longTerm: [
{ id: 'lt1', content: 'Q2 analysis showed growth trend', type: 'episodic', score: 0.89, accessed: '3d ago' },
{ id: 'lt2', content: 'Company prefers detailed reports', type: 'preference', score: 0.95, accessed: '1w ago' },
{ id: 'lt3', content: 'Financial terminology glossary', type: 'semantic', score: 0.72, accessed: '2w ago' }
],
audit: [
{ id: 'a1', action: 'Retrieved Q2 report', timestamp: '10:42:15', status: 'success' },
{ id: 'a2', action: 'Calculated growth rate', timestamp: '10:42:18', status: 'success' },
{ id: 'a3', action: 'Generated summary', timestamp: '10:42:22', status: 'pending' }
]
});

const [dataFlow, setDataFlow] = useState([]);
const [newMemory, setNewMemory] = useState({ layer: 'shortTerm', content: '' });

const layers = [
{
id: 'parametric',
name: 'Parametric Memory',
icon: Database,
color: 'purple',
description: 'Model weights learned during training',
characteristics: ['Permanent', 'Billions of parameters', 'Instant access', 'Read-only at inference'],
operations: ['Query implicit knowledge', 'Pattern recognition', 'Language generation']
},
{
id: 'shortTerm',
name: 'Short-Term Memory',
icon: Clock,
color: 'blue',
description: 'Context window and working memory',
characteristics: ['Session-scoped', '8K-200K tokens', 'Instant access', 'Updates every turn'],
operations: ['Add to context', 'Summarize', 'Slide window', 'Clear session']
},
{
id: 'longTerm',
name: 'Long-Term Memory',
icon: Archive,
color: 'emerald',
description: 'Vector stores and knowledge graphs',
characteristics: ['Persistent', 'Unlimited capacity', '50-500ms access', 'Semantic retrieval'],
operations: ['Store', 'Retrieve', 'Update', 'Delete', 'Search']
},
{
id: 'audit',
name: 'Audit Memory',
icon: Shield,
color: 'amber',
description: 'Immutable action logs and decision traces',
characteristics: ['Immutable', 'Append-only', 'Chain integrity', 'Compliance-ready'],
operations: ['Log action', 'Query history', 'Verify chain', 'Export']
}
];

const simulateRetrieval = () => {
const query = "Q3 financial analysis";
setSimulation({ running: true, step: 0, query, results: [] });

// Simulate multi-layer retrieval flow
const steps = [
{ layer: 'shortTerm', action: 'Check context window', delay: 500 },
{ layer: 'longTerm', action: 'Semantic search', delay: 1000 },
{ layer: 'parametric', action: 'Apply reasoning', delay: 500 },
{ layer: 'audit', action: 'Log retrieval', delay: 300 }
];

steps.forEach((step, index) => {
setTimeout(() => {
setSimulation(prev => ({
...prev,
step: index + 1,
results: [...prev.results, { layer: step.layer, action: step.action }]
}));

setDataFlow(prev => [...prev, { from: step.layer, timestamp: Date.now() }]);

if (index === steps.length - 1) {
setTimeout(() => {
setSimulation(prev => ({ ...prev, running: false }));
setDataFlow([]);
}, 1000);
}
}, steps.slice(0, index + 1).reduce((acc, s) => acc + s.delay, 0));
});
};

const addMemory = () => {
if (!newMemory.content.trim()) return;

const id = `${newMemory.layer[0]}${Date.now()}`;
const memory = newMemory.layer === 'shortTerm'
? { id, content: newMemory.content, tokens: newMemory.content.split(' ').length * 1.3, age: 'now' }
: newMemory.layer === 'longTerm'
? { id, content: newMemory.content, type: 'user-added', score: 1.0, accessed: 'now' }
: { id, action: newMemory.content, timestamp: new Date().toLocaleTimeString(), status: 'logged' };

setMemories(prev => ({
...prev,
[newMemory.layer]: [...prev[newMemory.layer], memory]
}));

setNewMemory({ ...newMemory, content: '' });
};

const deleteMemory = (layer, id) => {
if (layer === 'parametric' || layer === 'audit') return; // Can't delete these

setMemories(prev => ({
...prev,
[layer]: prev[layer].filter(m => m.id !== id)
}));
};

const getColorClasses = (color, variant = 'bg') => {
const colors = {
purple: { bg: 'bg-purple-100', border: 'border-purple-500', text: 'text-purple-700', ring: 'ring-purple-500' },
blue: { bg: 'bg-blue-100', border: 'border-blue-500', text: 'text-blue-700', ring: 'ring-blue-500' },
emerald: { bg: 'bg-emerald-100', border: 'border-emerald-500', text: 'text-emerald-700', ring: 'ring-emerald-500' },
amber: { bg: 'bg-amber-100', border: 'border-amber-500', text: 'text-amber-700', ring: 'ring-amber-500' }
};
return colors[color][variant];
};

const isLayerActive = (layerId) => {
return dataFlow.some(f => f.from === layerId && Date.now() - f.timestamp < 1000);
};

return (
<div className="max-w-6xl mx-auto p-6 bg-gray-50 min-h-screen">
{/* Header */}
<div className="bg-white rounded-lg shadow-sm p-6 mb-6">
<div className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold text-gray-800">Memory System Visualizer</h1>
<p className="text-gray-500">Explore how multi-layer memory works in agentic systems</p>
</div>
<button
onClick={simulateRetrieval}
disabled={simulation.running}
className="flex items-center gap-2 px-6 py-3 bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:opacity-50 transition-colors"
>
{simulation.running ? (
<>
<RefreshCw className="w-5 h-5 animate-spin" />
Simulating...
</>
) : (
<>
<Play className="w-5 h-5" />
Run Retrieval Demo
</>
)}
</button>
</div>
</div>

{/* Simulation Status */}
{simulation.running && (
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6">
<div className="flex items-center gap-3 mb-3">
<Search className="w-5 h-5 text-blue-500" />
<span className="font-medium text-blue-700">Query: "{simulation.query}"</span>
</div>
<div className="flex gap-2">
{simulation.results.map((result, idx) => (
<div key={idx} className="px-3 py-1 bg-white rounded-full text-sm flex items-center gap-2">
<span className={`w-2 h-2 rounded-full ${
result.layer === 'parametric' ? 'bg-purple-500' :
result.layer === 'shortTerm' ? 'bg-blue-500' :
result.layer === 'longTerm' ? 'bg-emerald-500' : 'bg-amber-500'
}`} />
{result.action}
</div>
))}
</div>
</div>
)}

{/* Memory Layers */}
<div className="grid grid-cols-2 gap-6 mb-6">
{layers.map(layer => {
const LayerIcon = layer.icon;
const isActive = isLayerActive(layer.id);
const layerMemories = memories[layer.id];

return (
<div
key={layer.id}
className={`bg-white rounded-lg shadow-sm overflow-hidden transition-all duration-300 ${
isActive ? `ring-2 ${getColorClasses(layer.color, 'ring')}` : ''
} ${activeLayer === layer.id ? 'ring-2 ring-gray-400' : ''}`}
>
{/* Layer Header */}
<div
className={`p-4 ${getColorClasses(layer.color, 'bg')} cursor-pointer`}
onClick={() => setActiveLayer(activeLayer === layer.id ? null : layer.id)}
>
<div className="flex items-center gap-3">
<LayerIcon className={`w-6 h-6 ${getColorClasses(layer.color, 'text')}`} />
<div>
<h3 className={`font-bold ${getColorClasses(layer.color, 'text')}`}>{layer.name}</h3>
<p className="text-sm opacity-75">{layer.description}</p>
</div>
{isActive && (
<div className="ml-auto">
<span className="flex h-3 w-3">
<span className={`animate-ping absolute inline-flex h-3 w-3 rounded-full ${getColorClasses(layer.color, 'bg')} opacity-75`}></span>
<span className={`relative inline-flex rounded-full h-3 w-3 ${getColorClasses(layer.color, 'bg')}`}></span>
</span>
</div>
)}
</div>
</div>

{/* Layer Content */}
<div className="p-4">
{/* Characteristics */}
<div className="flex flex-wrap gap-2 mb-4">
{layer.characteristics.map((char, idx) => (
<span key={idx} className="px-2 py-1 bg-gray-100 rounded text-xs text-gray-600">
{char}
</span>
))}
</div>

{/* Memory Items */}
<div className="space-y-2 max-h-48 overflow-y-auto">
{layerMemories.map(memory => (
<div
key={memory.id}
className="p-3 bg-gray-50 rounded-lg text-sm flex items-start justify-between group"
>
<div className="flex-1">
<p className="text-gray-700">{memory.content || memory.action}</p>
<div className="flex gap-3 mt-1 text-xs text-gray-400">
{memory.tokens && <span>{Math.round(memory.tokens)} tokens</span>}
{memory.type && <span>{memory.type}</span>}
{memory.score && <span>Score: {memory.score}</span>}
{memory.age && <span>{memory.age}</span>}
{memory.accessed && <span>Accessed: {memory.accessed}</span>}
{memory.timestamp && <span>{memory.timestamp}</span>}
{memory.status && (
<span className={memory.status === 'success' ? 'text-green-500' : 'text-amber-500'}>
{memory.status}
</span>
)}
</div>
</div>
{(layer.id === 'shortTerm' || layer.id === 'longTerm') && (
<button
onClick={() => deleteMemory(layer.id, memory.id)}
className="opacity-0 group-hover:opacity-100 p-1 text-gray-400 hover:text-red-500 transition-opacity"
>
<Trash2 className="w-4 h-4" />
</button>
)}
</div>
))}
</div>

{/* Operations */}
{activeLayer === layer.id && (
<div className="mt-4 pt-4 border-t">
<h4 className="text-xs font-medium text-gray-500 uppercase mb-2">Operations</h4>
<div className="flex flex-wrap gap-2">
{layer.operations.map((op, idx) => (
<button
key={idx}
className="px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded text-xs text-gray-700 transition-colors"
>
{op}
</button>
))}
</div>
</div>
)}
</div>
</div>
);
})}
</div>

{/* Data Flow Diagram */}
<div className="bg-white rounded-lg shadow-sm p-6 mb-6">
<h3 className="font-medium text-gray-800 mb-4">Memory Data Flow</h3>
<div className="flex items-center justify-center gap-4">
{layers.map((layer, idx) => {
const LayerIcon = layer.icon;
const isActive = isLayerActive(layer.id);
return (
<React.Fragment key={layer.id}>
<div className={`flex flex-col items-center p-4 rounded-lg ${getColorClasses(layer.color, 'bg')} ${isActive ? 'ring-2 ring-offset-2 ' + getColorClasses(layer.color, 'ring') : ''}`}>
<LayerIcon className={`w-8 h-8 ${getColorClasses(layer.color, 'text')}`} />
<span className="text-xs mt-2 font-medium">{layer.name.split(' ')[0]}</span>
</div>
{idx < layers.length - 1 && (
<div className="flex flex-col items-center">
<ArrowDown className="w-4 h-4 text-gray-400" />
<ArrowUp className="w-4 h-4 text-gray-400" />
</div>
)}
</React.Fragment>
);
})}
</div>
<p className="text-center text-sm text-gray-500 mt-4">
Data flows between layers during retrieval and storage operations
</p>
</div>

{/* Add Memory Form */}
<div className="bg-white rounded-lg shadow-sm p-6">
<h3 className="font-medium text-gray-800 mb-4">Add Memory Item</h3>
<div className="flex gap-4">
<select
value={newMemory.layer}
onChange={(e) => setNewMemory({ ...newMemory, layer: e.target.value })}
className="px-4 py-2 border rounded-lg bg-white"
>
<option value="shortTerm">Short-Term Memory</option>
<option value="longTerm">Long-Term Memory</option>
<option value="audit">Audit Log</option>
</select>
<input
type="text"
value={newMemory.content}
onChange={(e) => setNewMemory({ ...newMemory, content: e.target.value })}
placeholder={newMemory.layer === 'audit' ? 'Action description...' : 'Memory content...'}
className="flex-1 px-4 py-2 border rounded-lg"
onKeyPress={(e) => e.key === 'Enter' && addMemory()}
/>
<button
onClick={addMemory}
className="flex items-center gap-2 px-6 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600"
>
<Plus className="w-4 h-4" />
Add
</button>
</div>
</div>

{/* Educational Notes */}
<div className="mt-6 bg-gray-100 rounded-lg p-6">
<h3 className="font-medium text-gray-800 mb-3">Key Concepts</h3>
<div className="grid grid-cols-2 gap-4 text-sm text-gray-600">
<div>
<h4 className="font-medium text-gray-700">Retrieval Flow</h4>
<p>Queries typically check short-term memory first (instant), then long-term memory (semantic search), using parametric knowledge to reason about results.</p>
</div>
<div>
<h4 className="font-medium text-gray-700">Storage Patterns</h4>
<p>New information enters short-term memory, important items get persisted to long-term memory, and all actions are logged to audit memory.</p>
</div>
<div>
<h4 className="font-medium text-gray-700">Paradigm Differences</h4>
<p>LSR relies mainly on parametric memory. GS heavily uses long-term retrieval. VE requires audit memory. EP uses all four layers extensively.</p>
</div>
<div>
<h4 className="font-medium text-gray-700">Token Economics</h4>
<p>Short-term memory consumes context window tokens. Long-term retrieval adds latency. Balance capacity vs. speed based on use case.</p>
</div>
</div>
</div>
</div>
);
};

export default MemoryVisualizer;

Learning Objectives

  1. Understand the four memory layers and their characteristics
  2. Observe how data flows between memory layers during retrieval
  3. Learn which paradigms rely on which memory types
  4. Practice adding and managing memory items

Component maintained by CODITECT Education Team. Feedback: education@coditect.com