mem-llm 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,569 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Memory Management - Mem-LLM</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
16
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
+ min-height: 100vh;
18
+ padding: 20px;
19
+ }
20
+
21
+ .container {
22
+ max-width: 1400px;
23
+ margin: 0 auto;
24
+ background: white;
25
+ border-radius: 20px;
26
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
27
+ overflow: hidden;
28
+ }
29
+
30
+ .header {
31
+ padding: 30px;
32
+ background: #2c3e50;
33
+ color: white;
34
+ display: flex;
35
+ justify-content: space-between;
36
+ align-items: center;
37
+ }
38
+
39
+ .header h1 {
40
+ font-size: 28px;
41
+ }
42
+
43
+ .nav-buttons {
44
+ display: flex;
45
+ gap: 10px;
46
+ }
47
+
48
+ .btn {
49
+ padding: 10px 20px;
50
+ background: #3498db;
51
+ color: white;
52
+ border: none;
53
+ border-radius: 5px;
54
+ cursor: pointer;
55
+ text-decoration: none;
56
+ font-size: 14px;
57
+ }
58
+
59
+ .btn:hover {
60
+ background: #2980b9;
61
+ }
62
+
63
+ .content {
64
+ padding: 30px;
65
+ }
66
+
67
+ .section {
68
+ margin-bottom: 40px;
69
+ }
70
+
71
+ .section-title {
72
+ font-size: 20px;
73
+ color: #2c3e50;
74
+ margin-bottom: 20px;
75
+ padding-bottom: 10px;
76
+ border-bottom: 2px solid #3498db;
77
+ }
78
+
79
+ .search-box {
80
+ display: flex;
81
+ gap: 10px;
82
+ margin-bottom: 20px;
83
+ }
84
+
85
+ .search-box input {
86
+ flex: 1;
87
+ padding: 12px 20px;
88
+ border: 2px solid #e9ecef;
89
+ border-radius: 25px;
90
+ font-size: 14px;
91
+ }
92
+
93
+ .search-box button {
94
+ padding: 12px 30px;
95
+ background: #3498db;
96
+ color: white;
97
+ border: none;
98
+ border-radius: 25px;
99
+ cursor: pointer;
100
+ font-size: 14px;
101
+ }
102
+
103
+ .search-box button:hover {
104
+ background: #2980b9;
105
+ }
106
+
107
+ .memory-list {
108
+ display: grid;
109
+ gap: 15px;
110
+ }
111
+
112
+ .memory-item {
113
+ background: #f8f9fa;
114
+ padding: 20px;
115
+ border-radius: 10px;
116
+ border-left: 4px solid #3498db;
117
+ }
118
+
119
+ .memory-meta {
120
+ display: flex;
121
+ justify-content: space-between;
122
+ align-items: center;
123
+ margin-bottom: 10px;
124
+ font-size: 12px;
125
+ color: #7f8c8d;
126
+ }
127
+
128
+ .memory-content {
129
+ margin-bottom: 10px;
130
+ }
131
+
132
+ .message-pair {
133
+ margin-bottom: 8px;
134
+ }
135
+
136
+ .user-msg {
137
+ color: #2c3e50;
138
+ font-weight: bold;
139
+ margin-bottom: 5px;
140
+ }
141
+
142
+ .bot-msg {
143
+ color: #7f8c8d;
144
+ padding-left: 15px;
145
+ border-left: 2px solid #e9ecef;
146
+ }
147
+
148
+ .stats-grid {
149
+ display: grid;
150
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
151
+ gap: 20px;
152
+ margin-bottom: 30px;
153
+ }
154
+
155
+ .stat-card {
156
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
157
+ color: white;
158
+ padding: 25px;
159
+ border-radius: 15px;
160
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
161
+ }
162
+
163
+ .stat-card h3 {
164
+ font-size: 14px;
165
+ opacity: 0.9;
166
+ margin-bottom: 10px;
167
+ }
168
+
169
+ .stat-card .value {
170
+ font-size: 32px;
171
+ font-weight: bold;
172
+ }
173
+
174
+ .user-profile {
175
+ background: #f8f9fa;
176
+ padding: 25px;
177
+ border-radius: 15px;
178
+ margin-bottom: 20px;
179
+ }
180
+
181
+ .profile-header {
182
+ display: flex;
183
+ justify-content: space-between;
184
+ align-items: center;
185
+ margin-bottom: 20px;
186
+ }
187
+
188
+ .profile-info {
189
+ display: grid;
190
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
191
+ gap: 15px;
192
+ }
193
+
194
+ .profile-item {
195
+ padding: 15px;
196
+ background: white;
197
+ border-radius: 8px;
198
+ }
199
+
200
+ .profile-item label {
201
+ font-size: 12px;
202
+ color: #7f8c8d;
203
+ display: block;
204
+ margin-bottom: 5px;
205
+ }
206
+
207
+ .profile-item value {
208
+ font-size: 16px;
209
+ color: #2c3e50;
210
+ font-weight: 500;
211
+ }
212
+
213
+ .loading {
214
+ text-align: center;
215
+ padding: 40px;
216
+ color: #7f8c8d;
217
+ }
218
+
219
+ .empty-state {
220
+ text-align: center;
221
+ padding: 60px 20px;
222
+ color: #7f8c8d;
223
+ }
224
+
225
+ .empty-state h3 {
226
+ font-size: 24px;
227
+ margin-bottom: 10px;
228
+ }
229
+
230
+ .btn-danger {
231
+ background: #e74c3c;
232
+ }
233
+
234
+ .btn-danger:hover {
235
+ background: #c0392b;
236
+ }
237
+
238
+ .input-group {
239
+ margin-bottom: 20px;
240
+ }
241
+
242
+ .input-group label {
243
+ display: block;
244
+ margin-bottom: 8px;
245
+ color: #2c3e50;
246
+ font-weight: 500;
247
+ }
248
+
249
+ .input-group input,
250
+ .input-group select {
251
+ width: 100%;
252
+ padding: 12px 15px;
253
+ border: 2px solid #e9ecef;
254
+ border-radius: 8px;
255
+ font-size: 14px;
256
+ }
257
+ </style>
258
+ </head>
259
+ <body>
260
+ <div class="container">
261
+ <div class="header">
262
+ <h1>🧠 Memory Management</h1>
263
+ <div class="nav-buttons">
264
+ <a href="index.html" class="btn">💬 Chat</a>
265
+ <a href="metrics.html" class="btn">📊 Metrics</a>
266
+ </div>
267
+ </div>
268
+
269
+ <div class="content">
270
+ <!-- API Settings -->
271
+ <div class="section">
272
+ <div class="section-title">⚙️ Settings</div>
273
+ <div class="input-group">
274
+ <label>User ID</label>
275
+ <input type="text" id="userId" value="user123" placeholder="User ID">
276
+ </div>
277
+ <div class="input-group">
278
+ <label>API URL</label>
279
+ <input type="text" id="apiUrl" value="http://localhost:8000" placeholder="API URL">
280
+ </div>
281
+ <button class="btn" onclick="loadUserData()">Load Data</button>
282
+ </div>
283
+
284
+ <!-- Stats -->
285
+ <div class="section">
286
+ <div class="section-title">📊 Statistics</div>
287
+ <div class="stats-grid" id="statsGrid">
288
+ <div class="loading">Loading...</div>
289
+ </div>
290
+ </div>
291
+
292
+ <!-- User Profile -->
293
+ <div class="section">
294
+ <div class="section-title">👤 User Profile</div>
295
+ <div id="userProfile" class="loading">Loading...</div>
296
+ </div>
297
+
298
+ <!-- Memory Search -->
299
+ <div class="section">
300
+ <div class="section-title">🔍 Memory Search</div>
301
+ <div class="search-box">
302
+ <input type="text" id="searchQuery" placeholder="Search in memory...">
303
+ <button onclick="searchMemories()">Search</button>
304
+ </div>
305
+ <div id="searchResults"></div>
306
+ </div>
307
+
308
+ <!-- Recent Memories -->
309
+ <div class="section">
310
+ <div class="section-title">💾 Recent Conversations</div>
311
+ <div id="memoriesList" class="loading">Loading...</div>
312
+ </div>
313
+
314
+ <!-- Actions -->
315
+ <div class="section">
316
+ <div class="section-title">🗑️ Actions</div>
317
+ <button class="btn btn-danger" onclick="clearMemory()">Clear Memory</button>
318
+ <button class="btn" onclick="exportMemory()">Export</button>
319
+ </div>
320
+ </div>
321
+ </div>
322
+
323
+ <script>
324
+ const apiUrlInput = document.getElementById('apiUrl');
325
+ const userIdInput = document.getElementById('userId');
326
+
327
+ // Load data on page load
328
+ window.onload = () => {
329
+ loadUserData();
330
+ };
331
+
332
+ async function loadUserData() {
333
+ await Promise.all([
334
+ loadStats(),
335
+ loadUserProfile(),
336
+ loadMemories()
337
+ ]);
338
+ }
339
+
340
+ async function loadStats() {
341
+ const apiUrl = apiUrlInput.value;
342
+ const statsGrid = document.getElementById('statsGrid');
343
+
344
+ try {
345
+ const response = await fetch(`${apiUrl}/api/v1/memory/stats`);
346
+ const data = await response.json();
347
+
348
+ statsGrid.innerHTML = `
349
+ <div class="stat-card">
350
+ <h3>Total Users</h3>
351
+ <div class="value">${data.total_users || 0}</div>
352
+ </div>
353
+ <div class="stat-card">
354
+ <h3>Total Memories</h3>
355
+ <div class="value">${data.total_memories || 0}</div>
356
+ </div>
357
+ <div class="stat-card">
358
+ <h3>Active Agents</h3>
359
+ <div class="value">${data.active_agents || 0}</div>
360
+ </div>
361
+ `;
362
+ } catch (error) {
363
+ statsGrid.innerHTML = `<div class="empty-state">⚠️ Could not load statistics</div>`;
364
+ console.error('Stats error:', error);
365
+ }
366
+ }
367
+
368
+ async function loadUserProfile() {
369
+ const apiUrl = apiUrlInput.value;
370
+ const userId = userIdInput.value;
371
+ const profileDiv = document.getElementById('userProfile');
372
+
373
+ try {
374
+ const response = await fetch(`${apiUrl}/api/v1/users/${userId}/profile`);
375
+ const data = await response.json();
376
+
377
+ profileDiv.innerHTML = `
378
+ <div class="user-profile">
379
+ <div class="profile-header">
380
+ <h3>👤 ${data.user_id}</h3>
381
+ </div>
382
+ <div class="profile-info">
383
+ <div class="profile-item">
384
+ <label>Name</label>
385
+ <value>${data.name || '-'}</value>
386
+ </div>
387
+ <div class="profile-item">
388
+ <label>Total Interactions</label>
389
+ <value>${data.interaction_count || 0}</value>
390
+ </div>
391
+ <div class="profile-item">
392
+ <label>Summary</label>
393
+ <value>${data.summary || 'No summary yet'}</value>
394
+ </div>
395
+ </div>
396
+ </div>
397
+ `;
398
+ } catch (error) {
399
+ profileDiv.innerHTML = `<div class="empty-state">⚠️ Could not load profile</div>`;
400
+ console.error('Profile error:', error);
401
+ }
402
+ }
403
+
404
+ async function loadMemories() {
405
+ const apiUrl = apiUrlInput.value;
406
+ const userId = userIdInput.value;
407
+ const memoriesList = document.getElementById('memoriesList');
408
+
409
+ try {
410
+ const response = await fetch(`${apiUrl}/api/v1/memory/search`, {
411
+ method: 'POST',
412
+ headers: { 'Content-Type': 'application/json' },
413
+ body: JSON.stringify({
414
+ user_id: userId,
415
+ query: '',
416
+ limit: 20
417
+ })
418
+ });
419
+
420
+ const data = await response.json();
421
+ const memories = data.results || [];
422
+
423
+ if (memories.length === 0) {
424
+ memoriesList.innerHTML = `
425
+ <div class="empty-state">
426
+ <h3>📭 No memories yet</h3>
427
+ <p>Start chatting to create memories!</p>
428
+ </div>
429
+ `;
430
+ return;
431
+ }
432
+
433
+ memoriesList.innerHTML = memories.map(mem => `
434
+ <div class="memory-item">
435
+ <div class="memory-meta">
436
+ <span>🕐 ${new Date(mem.timestamp || Date.now()).toLocaleString()}</span>
437
+ <span>💾 ${mem.id || 'N/A'}</span>
438
+ </div>
439
+ <div class="memory-content">
440
+ <div class="message-pair">
441
+ <div class="user-msg">👤 ${mem.user_message || 'N/A'}</div>
442
+ <div class="bot-msg">🤖 ${mem.bot_response || 'N/A'}</div>
443
+ </div>
444
+ </div>
445
+ </div>
446
+ `).join('');
447
+
448
+ } catch (error) {
449
+ memoriesList.innerHTML = `<div class="empty-state">⚠️ Could not load memories</div>`;
450
+ console.error('Memories error:', error);
451
+ }
452
+ }
453
+
454
+ async function searchMemories() {
455
+ const apiUrl = apiUrlInput.value;
456
+ const userId = userIdInput.value;
457
+ const query = document.getElementById('searchQuery').value;
458
+ const resultsDiv = document.getElementById('searchResults');
459
+
460
+ if (!query.trim()) {
461
+ alert('Please enter a search term');
462
+ return;
463
+ }
464
+
465
+ resultsDiv.innerHTML = '<div class="loading">Searching...</div>';
466
+
467
+ try {
468
+ const response = await fetch(`${apiUrl}/api/v1/memory/search`, {
469
+ method: 'POST',
470
+ headers: { 'Content-Type': 'application/json' },
471
+ body: JSON.stringify({
472
+ user_id: userId,
473
+ query: query,
474
+ limit: 10
475
+ })
476
+ });
477
+
478
+ const data = await response.json();
479
+ const results = data.results || [];
480
+
481
+ if (results.length === 0) {
482
+ resultsDiv.innerHTML = `<div class="empty-state">🔍 No results found</div>`;
483
+ return;
484
+ }
485
+
486
+ resultsDiv.innerHTML = `
487
+ <div style="margin-bottom: 15px; color: #7f8c8d;">
488
+ ${results.length} results found
489
+ </div>
490
+ <div class="memory-list">
491
+ ${results.map(mem => `
492
+ <div class="memory-item">
493
+ <div class="memory-meta">
494
+ <span>🕐 ${new Date(mem.timestamp || Date.now()).toLocaleString()}</span>
495
+ </div>
496
+ <div class="memory-content">
497
+ <div class="user-msg">👤 ${mem.user_message || 'N/A'}</div>
498
+ <div class="bot-msg">🤖 ${mem.bot_response || 'N/A'}</div>
499
+ </div>
500
+ </div>
501
+ `).join('')}
502
+ </div>
503
+ `;
504
+
505
+ } catch (error) {
506
+ resultsDiv.innerHTML = `<div class="empty-state">⚠️ Search failed</div>`;
507
+ console.error('Search error:', error);
508
+ }
509
+ }
510
+
511
+ async function clearMemory() {
512
+ if (!confirm('Are you sure you want to delete all memories?')) {
513
+ return;
514
+ }
515
+
516
+ const apiUrl = apiUrlInput.value;
517
+ const userId = userIdInput.value;
518
+
519
+ try {
520
+ const response = await fetch(`${apiUrl}/api/v1/users/${userId}/memory`, {
521
+ method: 'DELETE'
522
+ });
523
+
524
+ if (response.ok) {
525
+ alert('Memory cleared!');
526
+ loadUserData();
527
+ } else {
528
+ alert('Could not clear memory!');
529
+ }
530
+ } catch (error) {
531
+ alert('Error: ' + error.message);
532
+ console.error('Clear error:', error);
533
+ }
534
+ }
535
+
536
+ async function exportMemory() {
537
+ const apiUrl = apiUrlInput.value;
538
+ const userId = userIdInput.value;
539
+
540
+ try {
541
+ const response = await fetch(`${apiUrl}/api/v1/memory/search`, {
542
+ method: 'POST',
543
+ headers: { 'Content-Type': 'application/json' },
544
+ body: JSON.stringify({
545
+ user_id: userId,
546
+ query: '',
547
+ limit: 1000
548
+ })
549
+ });
550
+
551
+ const data = await response.json();
552
+ const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
553
+ const url = URL.createObjectURL(blob);
554
+ const a = document.createElement('a');
555
+ a.href = url;
556
+ a.download = `memory_${userId}_${Date.now()}.json`;
557
+ a.click();
558
+ URL.revokeObjectURL(url);
559
+
560
+ alert('Memory exported!');
561
+ } catch (error) {
562
+ alert('Export error: ' + error.message);
563
+ console.error('Export error:', error);
564
+ }
565
+ }
566
+ </script>
567
+ </body>
568
+ </html>
569
+
@@ -0,0 +1,75 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Metrics - Mem-LLM</title>
7
+ <style>
8
+ * { margin: 0; padding: 0; box-sizing: border-box; }
9
+ body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; padding: 20px; }
10
+ .container { max-width: 1400px; margin: 0 auto; background: white; border-radius: 20px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); overflow: hidden; }
11
+ .header { padding: 30px; background: #2c3e50; color: white; display: flex; justify-content: space-between; align-items: center; }
12
+ .header h1 { font-size: 28px; }
13
+ .btn { padding: 10px 20px; background: #3498db; color: white; border: none; border-radius: 5px; cursor: pointer; text-decoration: none; font-size: 14px; }
14
+ .btn:hover { background: #2980b9; }
15
+ .content { padding: 30px; }
16
+ .section { margin-bottom: 40px; }
17
+ .section-title { font-size: 20px; color: #2c3e50; margin-bottom: 20px; padding-bottom: 10px; border-bottom: 2px solid #3498db; }
18
+ .metrics-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 30px; }
19
+ .metric-card { background: white; padding: 25px; border-radius: 15px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); border-left: 4px solid #3498db; }
20
+ .metric-icon { font-size: 32px; margin-bottom: 10px; }
21
+ .metric-value { font-size: 32px; font-weight: bold; color: #2c3e50; }
22
+ .loading { text-align: center; padding: 40px; color: #7f8c8d; }
23
+ .input-group { margin-bottom: 20px; }
24
+ .input-group input { width: 100%; padding: 12px 15px; border: 2px solid #e9ecef; border-radius: 8px; font-size: 14px; }
25
+ </style>
26
+ </head>
27
+ <body>
28
+ <div class="container">
29
+ <div class="header">
30
+ <h1>📊 System Metrics</h1>
31
+ <div style="display: flex; gap: 10px;">
32
+ <a href="index.html" class="btn">💬 Chat</a>
33
+ <a href="memory.html" class="btn">🧠 Memory</a>
34
+ <button class="btn" onclick="loadMetrics()">🔄 Refresh</button>
35
+ </div>
36
+ </div>
37
+ <div class="content">
38
+ <div class="section">
39
+ <div class="input-group"><input type="text" id="apiUrl" value="http://localhost:8000" placeholder="API URL"></div>
40
+ </div>
41
+ <div class="section">
42
+ <div class="section-title">⚡ Quick Statistics</div>
43
+ <div class="metrics-grid" id="quickStats"><div class="loading">Loading...</div></div>
44
+ </div>
45
+ </div>
46
+ <div style="text-align: center; padding: 20px; color: #7f8c8d; font-size: 12px;">
47
+ Auto-refresh: Every 30 seconds • Last update: <span id="lastUpdate">-</span>
48
+ </div>
49
+ </div>
50
+ <script>
51
+ const apiUrlInput = document.getElementById('apiUrl');
52
+ window.onload = () => { loadMetrics(); setInterval(loadMetrics, 30000); };
53
+ function loadMetrics() {
54
+ document.getElementById('lastUpdate').textContent = new Date().toLocaleTimeString();
55
+ loadQuickStats();
56
+ }
57
+ async function loadQuickStats() {
58
+ const apiUrl = apiUrlInput.value;
59
+ const quickStatsDiv = document.getElementById('quickStats');
60
+ try {
61
+ const response = await fetch(`${apiUrl}/api/v1/memory/stats`);
62
+ const data = await response.json();
63
+ quickStatsDiv.innerHTML = `
64
+ <div class="metric-card"><div class="metric-icon">👥</div><div class="metric-value">${data.total_users || 0}</div><div>Total Users</div></div>
65
+ <div class="metric-card"><div class="metric-icon">💾</div><div class="metric-value">${data.total_memories || 0}</div><div>Total Memories</div></div>
66
+ <div class="metric-card"><div class="metric-icon">🤖</div><div class="metric-value">${data.active_agents || 0}</div><div>Active Agents</div></div>
67
+ `;
68
+ } catch (error) {
69
+ quickStatsDiv.innerHTML = '<div class="loading">⚠️ Could not load</div>';
70
+ }
71
+ }
72
+ </script>
73
+ </body>
74
+ </html>
75
+