[Mem0] Update dependencies and make the package lighter (#1708)
Co-authored-by: Dev-Khant <devkhant24@gmail.com>
This commit is contained in:
@@ -28,12 +28,16 @@ setup_config()
|
||||
class Memory(MemoryBase):
|
||||
def __init__(self, config: MemoryConfig = MemoryConfig()):
|
||||
self.config = config
|
||||
self.embedding_model = EmbedderFactory.create(self.config.embedder.provider, self.config.embedder.config)
|
||||
self.vector_store = VectorStoreFactory.create(self.config.vector_store.provider, self.config.vector_store.config)
|
||||
self.embedding_model = EmbedderFactory.create(
|
||||
self.config.embedder.provider, self.config.embedder.config
|
||||
)
|
||||
self.vector_store = VectorStoreFactory.create(
|
||||
self.config.vector_store.provider, self.config.vector_store.config
|
||||
)
|
||||
self.llm = LlmFactory.create(self.config.llm.provider, self.config.llm.config)
|
||||
self.db = SQLiteManager(self.config.history_db_path)
|
||||
self.collection_name = self.config.vector_store.config.collection_name
|
||||
|
||||
|
||||
capture_event("mem0.init", self)
|
||||
|
||||
@classmethod
|
||||
@@ -171,9 +175,13 @@ class Memory(MemoryBase):
|
||||
memory = self.vector_store.get(vector_id=memory_id)
|
||||
if not memory:
|
||||
return None
|
||||
|
||||
filters = {key: memory.payload[key] for key in ["user_id", "agent_id", "run_id"] if memory.payload.get(key)}
|
||||
|
||||
|
||||
filters = {
|
||||
key: memory.payload[key]
|
||||
for key in ["user_id", "agent_id", "run_id"]
|
||||
if memory.payload.get(key)
|
||||
}
|
||||
|
||||
# Prepare base memory item
|
||||
memory_item = MemoryItem(
|
||||
id=memory.id,
|
||||
@@ -182,15 +190,25 @@ class Memory(MemoryBase):
|
||||
created_at=memory.payload.get("created_at"),
|
||||
updated_at=memory.payload.get("updated_at"),
|
||||
).model_dump(exclude={"score"})
|
||||
|
||||
|
||||
# Add metadata if there are additional keys
|
||||
excluded_keys = {"user_id", "agent_id", "run_id", "hash", "data", "created_at", "updated_at"}
|
||||
additional_metadata = {k: v for k, v in memory.payload.items() if k not in excluded_keys}
|
||||
excluded_keys = {
|
||||
"user_id",
|
||||
"agent_id",
|
||||
"run_id",
|
||||
"hash",
|
||||
"data",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
}
|
||||
additional_metadata = {
|
||||
k: v for k, v in memory.payload.items() if k not in excluded_keys
|
||||
}
|
||||
if additional_metadata:
|
||||
memory_item["metadata"] = additional_metadata
|
||||
|
||||
|
||||
result = {**memory_item, **filters}
|
||||
|
||||
|
||||
return result
|
||||
|
||||
def get_all(self, user_id=None, agent_id=None, run_id=None, limit=100):
|
||||
@@ -211,7 +229,15 @@ class Memory(MemoryBase):
|
||||
capture_event("mem0.get_all", self, {"filters": len(filters), "limit": limit})
|
||||
memories = self.vector_store.list(filters=filters, limit=limit)
|
||||
|
||||
excluded_keys = {"user_id", "agent_id", "run_id", "hash", "data", "created_at", "updated_at"}
|
||||
excluded_keys = {
|
||||
"user_id",
|
||||
"agent_id",
|
||||
"run_id",
|
||||
"hash",
|
||||
"data",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
}
|
||||
return [
|
||||
{
|
||||
**MemoryItem(
|
||||
@@ -221,9 +247,22 @@ class Memory(MemoryBase):
|
||||
created_at=mem.payload.get("created_at"),
|
||||
updated_at=mem.payload.get("updated_at"),
|
||||
).model_dump(exclude={"score"}),
|
||||
**{key: mem.payload[key] for key in ["user_id", "agent_id", "run_id"] if key in mem.payload},
|
||||
**({"metadata": {k: v for k, v in mem.payload.items() if k not in excluded_keys}}
|
||||
if any(k for k in mem.payload if k not in excluded_keys) else {})
|
||||
**{
|
||||
key: mem.payload[key]
|
||||
for key in ["user_id", "agent_id", "run_id"]
|
||||
if key in mem.payload
|
||||
},
|
||||
**(
|
||||
{
|
||||
"metadata": {
|
||||
k: v
|
||||
for k, v in mem.payload.items()
|
||||
if k not in excluded_keys
|
||||
}
|
||||
}
|
||||
if any(k for k in mem.payload if k not in excluded_keys)
|
||||
else {}
|
||||
),
|
||||
}
|
||||
for mem in memories[0]
|
||||
]
|
||||
@@ -255,9 +294,19 @@ class Memory(MemoryBase):
|
||||
|
||||
capture_event("mem0.search", self, {"filters": len(filters), "limit": limit})
|
||||
embeddings = self.embedding_model.embed(query)
|
||||
memories = self.vector_store.search(query=embeddings, limit=limit, filters=filters)
|
||||
memories = self.vector_store.search(
|
||||
query=embeddings, limit=limit, filters=filters
|
||||
)
|
||||
|
||||
excluded_keys = {"user_id", "agent_id", "run_id", "hash", "data", "created_at", "updated_at"}
|
||||
excluded_keys = {
|
||||
"user_id",
|
||||
"agent_id",
|
||||
"run_id",
|
||||
"hash",
|
||||
"data",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
@@ -269,9 +318,22 @@ class Memory(MemoryBase):
|
||||
updated_at=mem.payload.get("updated_at"),
|
||||
score=mem.score,
|
||||
).model_dump(),
|
||||
**{key: mem.payload[key] for key in ["user_id", "agent_id", "run_id"] if key in mem.payload},
|
||||
**({"metadata": {k: v for k, v in mem.payload.items() if k not in excluded_keys}}
|
||||
if any(k for k in mem.payload if k not in excluded_keys) else {})
|
||||
**{
|
||||
key: mem.payload[key]
|
||||
for key in ["user_id", "agent_id", "run_id"]
|
||||
if key in mem.payload
|
||||
},
|
||||
**(
|
||||
{
|
||||
"metadata": {
|
||||
k: v
|
||||
for k, v in mem.payload.items()
|
||||
if k not in excluded_keys
|
||||
}
|
||||
}
|
||||
if any(k for k in mem.payload if k not in excluded_keys)
|
||||
else {}
|
||||
),
|
||||
}
|
||||
for mem in memories
|
||||
]
|
||||
@@ -289,7 +351,7 @@ class Memory(MemoryBase):
|
||||
"""
|
||||
capture_event("mem0.update", self, {"memory_id": memory_id})
|
||||
self._update_memory_tool(memory_id, data)
|
||||
return {'message': 'Memory updated successfully!'}
|
||||
return {"message": "Memory updated successfully!"}
|
||||
|
||||
def delete(self, memory_id):
|
||||
"""
|
||||
@@ -300,7 +362,7 @@ class Memory(MemoryBase):
|
||||
"""
|
||||
capture_event("mem0.delete", self, {"memory_id": memory_id})
|
||||
self._delete_memory_tool(memory_id)
|
||||
return {'message': 'Memory deleted successfully!'}
|
||||
return {"message": "Memory deleted successfully!"}
|
||||
|
||||
def delete_all(self, user_id=None, agent_id=None, run_id=None):
|
||||
"""
|
||||
@@ -328,7 +390,7 @@ class Memory(MemoryBase):
|
||||
memories = self.vector_store.list(filters=filters)[0]
|
||||
for memory in memories:
|
||||
self._delete_memory_tool(memory.id)
|
||||
return {'message': 'Memories deleted successfully!'}
|
||||
return {"message": "Memories deleted successfully!"}
|
||||
|
||||
def history(self, memory_id):
|
||||
"""
|
||||
@@ -350,14 +412,16 @@ class Memory(MemoryBase):
|
||||
metadata = metadata or {}
|
||||
metadata["data"] = data
|
||||
metadata["hash"] = hashlib.md5(data.encode()).hexdigest()
|
||||
metadata["created_at"] = datetime.now(pytz.timezone('US/Pacific')).isoformat()
|
||||
metadata["created_at"] = datetime.now(pytz.timezone("US/Pacific")).isoformat()
|
||||
|
||||
self.vector_store.insert(
|
||||
vectors=[embeddings],
|
||||
ids=[memory_id],
|
||||
payloads=[metadata],
|
||||
)
|
||||
self.db.add_history(memory_id, None, data, "ADD", created_at=metadata["created_at"])
|
||||
self.db.add_history(
|
||||
memory_id, None, data, "ADD", created_at=metadata["created_at"]
|
||||
)
|
||||
return memory_id
|
||||
|
||||
def _update_memory_tool(self, memory_id, data, metadata=None):
|
||||
@@ -368,15 +432,17 @@ class Memory(MemoryBase):
|
||||
new_metadata["data"] = data
|
||||
new_metadata["hash"] = existing_memory.payload.get("hash")
|
||||
new_metadata["created_at"] = existing_memory.payload.get("created_at")
|
||||
new_metadata["updated_at"] = datetime.now(pytz.timezone('US/Pacific')).isoformat()
|
||||
|
||||
if "user_id" in existing_memory.payload:
|
||||
new_metadata["updated_at"] = datetime.now(
|
||||
pytz.timezone("US/Pacific")
|
||||
).isoformat()
|
||||
|
||||
if "user_id" in existing_memory.payload:
|
||||
new_metadata["user_id"] = existing_memory.payload["user_id"]
|
||||
if "agent_id" in existing_memory.payload:
|
||||
new_metadata["agent_id"] = existing_memory.payload["agent_id"]
|
||||
if "run_id" in existing_memory.payload:
|
||||
new_metadata["run_id"] = existing_memory.payload["run_id"]
|
||||
|
||||
|
||||
embeddings = self.embedding_model.embed(data)
|
||||
self.vector_store.update(
|
||||
vector_id=memory_id,
|
||||
@@ -384,7 +450,14 @@ class Memory(MemoryBase):
|
||||
payload=new_metadata,
|
||||
)
|
||||
logging.info(f"Updating memory with ID {memory_id=} with {data=}")
|
||||
self.db.add_history(memory_id, prev_value, data, "UPDATE", created_at=new_metadata["created_at"], updated_at=new_metadata["updated_at"])
|
||||
self.db.add_history(
|
||||
memory_id,
|
||||
prev_value,
|
||||
data,
|
||||
"UPDATE",
|
||||
created_at=new_metadata["created_at"],
|
||||
updated_at=new_metadata["updated_at"],
|
||||
)
|
||||
|
||||
def _delete_memory_tool(self, memory_id):
|
||||
logging.info(f"Deleting memory with {memory_id=}")
|
||||
|
||||
@@ -20,12 +20,12 @@ def setup_config():
|
||||
def get_user_id():
|
||||
config_path = os.path.join(mem0_dir, "config.json")
|
||||
if not os.path.exists(config_path):
|
||||
return "anonymous_user"
|
||||
|
||||
return "anonymous_user"
|
||||
|
||||
try:
|
||||
with open(config_path, "r") as config_file:
|
||||
config = json.load(config_file)
|
||||
user_id = config.get("user_id")
|
||||
return user_id
|
||||
except:
|
||||
except Exception:
|
||||
return "anonymous_user"
|
||||
|
||||
@@ -7,12 +7,14 @@ class SQLiteManager:
|
||||
self.connection = sqlite3.connect(db_path, check_same_thread=False)
|
||||
self._migrate_history_table()
|
||||
self._create_history_table()
|
||||
|
||||
|
||||
def _migrate_history_table(self):
|
||||
with self.connection:
|
||||
cursor = self.connection.cursor()
|
||||
|
||||
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='history'")
|
||||
cursor.execute(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='history'"
|
||||
)
|
||||
table_exists = cursor.fetchone() is not None
|
||||
|
||||
if table_exists:
|
||||
@@ -22,15 +24,15 @@ class SQLiteManager:
|
||||
|
||||
# Define the expected schema
|
||||
expected_schema = {
|
||||
'id': 'TEXT',
|
||||
'memory_id': 'TEXT',
|
||||
'old_memory': 'TEXT',
|
||||
'new_memory': 'TEXT',
|
||||
'new_value': 'TEXT',
|
||||
'event': 'TEXT',
|
||||
'created_at': 'DATETIME',
|
||||
'updated_at': 'DATETIME',
|
||||
'is_deleted': 'INTEGER'
|
||||
"id": "TEXT",
|
||||
"memory_id": "TEXT",
|
||||
"old_memory": "TEXT",
|
||||
"new_memory": "TEXT",
|
||||
"new_value": "TEXT",
|
||||
"event": "TEXT",
|
||||
"created_at": "DATETIME",
|
||||
"updated_at": "DATETIME",
|
||||
"is_deleted": "INTEGER",
|
||||
}
|
||||
|
||||
# Check if the schemas are the same
|
||||
@@ -38,7 +40,8 @@ class SQLiteManager:
|
||||
# Rename the old table
|
||||
cursor.execute("ALTER TABLE history RENAME TO old_history")
|
||||
|
||||
cursor.execute("""
|
||||
cursor.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS history (
|
||||
id TEXT PRIMARY KEY,
|
||||
memory_id TEXT,
|
||||
@@ -50,20 +53,22 @@ class SQLiteManager:
|
||||
updated_at DATETIME,
|
||||
is_deleted INTEGER
|
||||
)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
# Copy data from the old table to the new table
|
||||
cursor.execute("""
|
||||
cursor.execute(
|
||||
"""
|
||||
INSERT INTO history (id, memory_id, old_memory, new_memory, new_value, event, created_at, updated_at, is_deleted)
|
||||
SELECT id, memory_id, prev_value, new_value, new_value, event, timestamp, timestamp, is_deleted
|
||||
FROM old_history
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
cursor.execute("DROP TABLE old_history")
|
||||
|
||||
self.connection.commit()
|
||||
|
||||
|
||||
def _create_history_table(self):
|
||||
with self.connection:
|
||||
self.connection.execute(
|
||||
@@ -82,7 +87,16 @@ class SQLiteManager:
|
||||
"""
|
||||
)
|
||||
|
||||
def add_history(self, memory_id, old_memory, new_memory, event, created_at = None, updated_at = None, is_deleted=0):
|
||||
def add_history(
|
||||
self,
|
||||
memory_id,
|
||||
old_memory,
|
||||
new_memory,
|
||||
event,
|
||||
created_at=None,
|
||||
updated_at=None,
|
||||
is_deleted=0,
|
||||
):
|
||||
with self.connection:
|
||||
self.connection.execute(
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user