mem-llm 1.0.5__py3-none-any.whl → 1.0.7__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.
Potentially problematic release.
This version of mem-llm might be problematic. Click here for more details.
- mem_llm/__init__.py +1 -1
- mem_llm/mem_agent.py +81 -24
- mem_llm/memory_manager.py +50 -0
- {mem_llm-1.0.5.dist-info → mem_llm-1.0.7.dist-info}/METADATA +1 -1
- {mem_llm-1.0.5.dist-info → mem_llm-1.0.7.dist-info}/RECORD +7 -7
- {mem_llm-1.0.5.dist-info → mem_llm-1.0.7.dist-info}/WHEEL +0 -0
- {mem_llm-1.0.5.dist-info → mem_llm-1.0.7.dist-info}/top_level.txt +0 -0
mem_llm/__init__.py
CHANGED
mem_llm/mem_agent.py
CHANGED
|
@@ -407,47 +407,76 @@ REMEMBER: Knowledge base = truth. Always use it when provided!"""
|
|
|
407
407
|
|
|
408
408
|
def _update_user_profile(self, user_id: str, message: str, response: str):
|
|
409
409
|
"""Extract user info from conversation and update profile"""
|
|
410
|
-
if not hasattr(self.memory, 'update_profile'):
|
|
411
|
-
return
|
|
412
|
-
|
|
413
410
|
msg_lower = message.lower()
|
|
414
|
-
|
|
411
|
+
|
|
412
|
+
# Extract information
|
|
413
|
+
extracted = {}
|
|
415
414
|
|
|
416
415
|
# Extract name
|
|
417
|
-
if "my name is" in msg_lower or "i am" in msg_lower or "i'm" in msg_lower:
|
|
418
|
-
|
|
419
|
-
for phrase in ["my name is ", "i am ", "i'm "]:
|
|
416
|
+
if "my name is" in msg_lower or "i am" in msg_lower or "i'm" in msg_lower or "adım" in msg_lower or "ismim" in msg_lower:
|
|
417
|
+
for phrase in ["my name is ", "i am ", "i'm ", "adım ", "ismim ", "benim adım "]:
|
|
420
418
|
if phrase in msg_lower:
|
|
421
419
|
name_part = message[msg_lower.index(phrase) + len(phrase):].strip()
|
|
422
420
|
name = name_part.split()[0] if name_part else None
|
|
423
421
|
if name and len(name) > 1:
|
|
424
|
-
|
|
422
|
+
extracted['name'] = name.strip('.,!?')
|
|
425
423
|
break
|
|
426
424
|
|
|
427
425
|
# Extract favorite food
|
|
428
|
-
if "favorite food" in msg_lower or "favourite food" in msg_lower:
|
|
429
|
-
if "is" in msg_lower:
|
|
430
|
-
food = msg_lower.split("is")[-1].strip().strip(
|
|
426
|
+
if "favorite food" in msg_lower or "favourite food" in msg_lower or "sevdiğim yemek" in msg_lower or "en sevdiğim" in msg_lower:
|
|
427
|
+
if "is" in msg_lower or ":" in msg_lower:
|
|
428
|
+
food = msg_lower.split("is")[-1].strip() if "is" in msg_lower else msg_lower.split(":")[-1].strip()
|
|
429
|
+
food = food.strip('.,!?')
|
|
431
430
|
if food and len(food) < 50:
|
|
432
|
-
|
|
431
|
+
extracted['favorite_food'] = food
|
|
433
432
|
|
|
434
433
|
# Extract location
|
|
435
|
-
if "i live in" in msg_lower or "i'm from" in msg_lower or "
|
|
436
|
-
for phrase in ["i live in ", "i'm from ", "from "]:
|
|
434
|
+
if "i live in" in msg_lower or "i'm from" in msg_lower or "yaşıyorum" in msg_lower or "yaşadığım" in msg_lower:
|
|
435
|
+
for phrase in ["i live in ", "i'm from ", "from ", "yaşıyorum", "yaşadığım yer", "yaşadığım şehir"]:
|
|
437
436
|
if phrase in msg_lower:
|
|
438
437
|
loc = message[msg_lower.index(phrase) + len(phrase):].strip()
|
|
439
438
|
location = loc.split()[0] if loc else None
|
|
440
439
|
if location and len(location) > 2:
|
|
441
|
-
|
|
440
|
+
extracted['location'] = location.strip('.,!?')
|
|
442
441
|
break
|
|
443
442
|
|
|
444
443
|
# Save updates
|
|
445
|
-
if
|
|
444
|
+
if extracted:
|
|
446
445
|
try:
|
|
447
|
-
|
|
448
|
-
self.
|
|
449
|
-
|
|
450
|
-
|
|
446
|
+
# SQL memory - store in preferences JSON
|
|
447
|
+
if hasattr(self.memory, 'update_user_profile'):
|
|
448
|
+
# Get current profile
|
|
449
|
+
profile = self.memory.get_user_profile(user_id) or {}
|
|
450
|
+
|
|
451
|
+
# Update name directly if extracted
|
|
452
|
+
updates = {}
|
|
453
|
+
if 'name' in extracted:
|
|
454
|
+
updates['name'] = extracted.pop('name')
|
|
455
|
+
|
|
456
|
+
# Store other info in preferences
|
|
457
|
+
if extracted:
|
|
458
|
+
current_prefs = profile.get('preferences')
|
|
459
|
+
if current_prefs:
|
|
460
|
+
try:
|
|
461
|
+
prefs = json.loads(current_prefs) if isinstance(current_prefs, str) else current_prefs
|
|
462
|
+
except:
|
|
463
|
+
prefs = {}
|
|
464
|
+
else:
|
|
465
|
+
prefs = {}
|
|
466
|
+
|
|
467
|
+
prefs.update(extracted)
|
|
468
|
+
updates['preferences'] = json.dumps(prefs)
|
|
469
|
+
|
|
470
|
+
if updates:
|
|
471
|
+
self.memory.update_user_profile(user_id, updates)
|
|
472
|
+
self.logger.debug(f"Profile updated for {user_id}: {extracted}")
|
|
473
|
+
|
|
474
|
+
# JSON memory - direct update
|
|
475
|
+
elif hasattr(self.memory, 'update_profile'):
|
|
476
|
+
self.memory.update_profile(user_id, extracted)
|
|
477
|
+
self.logger.debug(f"Profile updated for {user_id}: {extracted}")
|
|
478
|
+
except Exception as e:
|
|
479
|
+
self.logger.error(f"Error updating profile: {e}")
|
|
451
480
|
|
|
452
481
|
def get_user_profile(self, user_id: Optional[str] = None) -> Dict:
|
|
453
482
|
"""
|
|
@@ -457,16 +486,44 @@ REMEMBER: Knowledge base = truth. Always use it when provided!"""
|
|
|
457
486
|
user_id: User ID (uses current_user if not specified)
|
|
458
487
|
|
|
459
488
|
Returns:
|
|
460
|
-
User profile dictionary
|
|
489
|
+
User profile dictionary with all info (name, favorite_food, location, etc.)
|
|
461
490
|
"""
|
|
462
491
|
uid = user_id or self.current_user
|
|
463
492
|
if not uid:
|
|
464
493
|
return {}
|
|
465
494
|
|
|
466
495
|
try:
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
496
|
+
# Check if SQL or JSON memory
|
|
497
|
+
if hasattr(self.memory, 'get_user_profile'):
|
|
498
|
+
# SQL memory - merge preferences into main dict
|
|
499
|
+
profile = self.memory.get_user_profile(uid)
|
|
500
|
+
if not profile:
|
|
501
|
+
return {}
|
|
502
|
+
|
|
503
|
+
# Parse preferences JSON if exists
|
|
504
|
+
result = {
|
|
505
|
+
'user_id': profile.get('user_id'),
|
|
506
|
+
'name': profile.get('name'),
|
|
507
|
+
'first_seen': profile.get('first_seen'),
|
|
508
|
+
'last_interaction': profile.get('last_interaction'),
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
# Merge preferences
|
|
512
|
+
prefs_str = profile.get('preferences')
|
|
513
|
+
if prefs_str:
|
|
514
|
+
try:
|
|
515
|
+
prefs = json.loads(prefs_str) if isinstance(prefs_str, str) else prefs_str
|
|
516
|
+
result.update(prefs) # Add favorite_food, location, etc.
|
|
517
|
+
except:
|
|
518
|
+
pass
|
|
519
|
+
|
|
520
|
+
return result
|
|
521
|
+
else:
|
|
522
|
+
# JSON memory
|
|
523
|
+
memory_data = self.memory.load_memory(uid)
|
|
524
|
+
return memory_data.get('profile', {})
|
|
525
|
+
except Exception as e:
|
|
526
|
+
self.logger.error(f"Error getting user profile: {e}")
|
|
470
527
|
return {}
|
|
471
528
|
|
|
472
529
|
def add_knowledge(self, category: str, question: str, answer: str,
|
mem_llm/memory_manager.py
CHANGED
|
@@ -259,4 +259,54 @@ class MemoryManager:
|
|
|
259
259
|
self.load_memory(user_id)
|
|
260
260
|
|
|
261
261
|
return self.user_profiles.get(user_id)
|
|
262
|
+
|
|
263
|
+
def update_user_profile(self, user_id: str, updates: Dict) -> None:
|
|
264
|
+
"""
|
|
265
|
+
Update user profile (SQL-compatible alias)
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
user_id: User ID
|
|
269
|
+
updates: Fields to update
|
|
270
|
+
"""
|
|
271
|
+
return self.update_profile(user_id, updates)
|
|
272
|
+
|
|
273
|
+
def add_user(self, user_id: str, name: Optional[str] = None, metadata: Optional[Dict] = None) -> None:
|
|
274
|
+
"""
|
|
275
|
+
Add or update user (SQL-compatible method)
|
|
276
|
+
|
|
277
|
+
Args:
|
|
278
|
+
user_id: User ID
|
|
279
|
+
name: User name (optional)
|
|
280
|
+
metadata: Additional metadata (optional)
|
|
281
|
+
"""
|
|
282
|
+
self.load_memory(user_id)
|
|
283
|
+
if name and 'name' not in self.user_profiles[user_id]:
|
|
284
|
+
self.user_profiles[user_id]['name'] = name
|
|
285
|
+
if metadata:
|
|
286
|
+
self.user_profiles[user_id].update(metadata)
|
|
287
|
+
self.save_memory(user_id)
|
|
288
|
+
|
|
289
|
+
def get_statistics(self) -> Dict:
|
|
290
|
+
"""
|
|
291
|
+
Get general statistics (SQL-compatible method)
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
Statistics dictionary
|
|
295
|
+
"""
|
|
296
|
+
all_users = list(self.memory_dir.glob("*.json"))
|
|
297
|
+
total_interactions = 0
|
|
298
|
+
|
|
299
|
+
for user_file in all_users:
|
|
300
|
+
try:
|
|
301
|
+
with open(user_file, 'r', encoding='utf-8') as f:
|
|
302
|
+
data = json.load(f)
|
|
303
|
+
total_interactions += len(data.get('conversations', []))
|
|
304
|
+
except:
|
|
305
|
+
pass
|
|
306
|
+
|
|
307
|
+
return {
|
|
308
|
+
'total_users': len(all_users),
|
|
309
|
+
'total_interactions': total_interactions,
|
|
310
|
+
'knowledge_base_entries': 0 # JSON doesn't have KB
|
|
311
|
+
}
|
|
262
312
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
mem_llm/__init__.py,sha256=
|
|
1
|
+
mem_llm/__init__.py,sha256=K-nIQ-BtTJzDhgseulljOKMPXuQZS563ffED4brYFm4,920
|
|
2
2
|
mem_llm/config.yaml.example,sha256=lgmfaU5pxnIm4zYxwgCcgLSohNx1Jw6oh3Qk0Xoe2DE,917
|
|
3
3
|
mem_llm/config_from_docs.py,sha256=YFhq1SWyK63C-TNMS73ncNHg8sJ-XGOf2idWVCjxFco,4974
|
|
4
4
|
mem_llm/config_manager.py,sha256=8PIHs21jZWlI-eG9DgekjOvNxU3-U4xH7SbT8Gr-Z6M,7075
|
|
5
5
|
mem_llm/knowledge_loader.py,sha256=oSNhfYYcx7DlZLVogxnbSwaIydq_Q3__RDJFeZR2XVw,2699
|
|
6
6
|
mem_llm/llm_client.py,sha256=XW-LALYV4C-Nj2R8XYT2iT2YnTeH6_tUIldMKooY2uY,5461
|
|
7
|
-
mem_llm/mem_agent.py,sha256=
|
|
7
|
+
mem_llm/mem_agent.py,sha256=kJwlZYRIE6OI06ZG-mtQKzz1_zkjs1ss_DYr4DiaHUw,27140
|
|
8
8
|
mem_llm/memory_db.py,sha256=UzkMOw_p7svg6d4ZgpBWdPKoILWrJ2hAQSPHvAG_f4M,13563
|
|
9
|
-
mem_llm/memory_manager.py,sha256=
|
|
9
|
+
mem_llm/memory_manager.py,sha256=CZI3A8pFboHQIgeiXB1h2gZK7mgfbVSU3IxuqE-zXtc,9978
|
|
10
10
|
mem_llm/memory_tools.py,sha256=ARANFqu_bmL56SlV1RzTjfQsJj-Qe2QvqY0pF92hDxU,8678
|
|
11
11
|
mem_llm/prompt_templates.py,sha256=tCiQJw3QQKIaH8NsxEKOIaIVxw4XT43PwdmyfCINzzM,6536
|
|
12
|
-
mem_llm-1.0.
|
|
13
|
-
mem_llm-1.0.
|
|
14
|
-
mem_llm-1.0.
|
|
15
|
-
mem_llm-1.0.
|
|
12
|
+
mem_llm-1.0.7.dist-info/METADATA,sha256=K2paX5fYmv3U7BNrBbqYI3D6gwfvszaS1HyJJuIJo88,6505
|
|
13
|
+
mem_llm-1.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
14
|
+
mem_llm-1.0.7.dist-info/top_level.txt,sha256=_fU1ML-0JwkaxWdhqpwtmTNaJEOvDMQeJdA8d5WqDn8,8
|
|
15
|
+
mem_llm-1.0.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|