From 87c37fbb13ee75c9166e1926ffccb0bf434fa733 Mon Sep 17 00:00:00 2001 From: Kai Date: Thu, 11 Sep 2025 14:09:16 +0800 Subject: [PATCH 1/5] fix:#(268)https://github.com/MemTensor/MemOS/issues/286 --- pyproject.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 270fd712c..7bc02af50 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,6 +76,11 @@ mem-scheduler = [ "pika (>=1.3.2,<2.0.0)", # RabbitMQ client ] +# MemUser (MySQL support) +mem-user = [ + "pymysql (>=1.1.0,<2.0.0)", # MySQL client for SQLAlchemy +] + # MemReader mem-reader = [ "chonkie (>=1.0.7,<2.0.0)", # Sentence chunking library @@ -90,6 +95,7 @@ all = [ "schedule (>=1.2.2,<2.0.0)", "redis (>=6.2.0,<7.0.0)", "pika (>=1.3.2,<2.0.0)", + "pymysql (>=1.1.0,<2.0.0)", "chonkie (>=1.0.7,<2.0.0)", "markitdown[docx,pdf,pptx,xls,xlsx] (>=0.1.1,<0.2.0)", From a6a55584b82cdb08f5e743e0a5dbaeab397bceb3 Mon Sep 17 00:00:00 2001 From: Kai Date: Thu, 11 Sep 2025 14:16:16 +0800 Subject: [PATCH 2/5] Add pymysql dependency for MySQL user management --- poetry.lock | 23 ++++++++++++++++++++--- pyproject.toml | 4 ++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index c6b6a0ebf..2517d0b94 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand. [[package]] name = "absl-py" @@ -3773,6 +3773,22 @@ files = [ [package.extras] windows-terminal = ["colorama (>=0.4.6)"] +[[package]] +name = "pymysql" +version = "1.1.2" +description = "Pure Python MySQL Driver" +optional = false +python-versions = ">=3.8" +groups = ["main", "mem-user"] +files = [ + {file = "pymysql-1.1.2-py3-none-any.whl", hash = "sha256:e6b1d89711dd51f8f74b1631fe08f039e7d76cf67a42a323d3178f0f25762ed9"}, + {file = "pymysql-1.1.2.tar.gz", hash = "sha256:4961d3e165614ae65014e361811a724e2044ad3ea3739de9903ae7c21f539f03"}, +] + +[package.extras] +ed25519 = ["PyNaCl (>=1.4.0)"] +rsa = ["cryptography"] + [[package]] name = "pyparsing" version = "3.2.3" @@ -6285,12 +6301,13 @@ cffi = {version = ">=1.11", markers = "platform_python_implementation == \"PyPy\ cffi = ["cffi (>=1.11)"] [extras] -all = ["chonkie", "markitdown", "neo4j", "pika", "qdrant-client", "redis", "schedule", "sentence-transformers", "torch", "volcengine-python-sdk"] +all = ["chonkie", "markitdown", "neo4j", "pika", "pymysql", "qdrant-client", "redis", "schedule", "sentence-transformers", "torch", "volcengine-python-sdk"] mem-reader = ["chonkie", "markitdown"] mem-scheduler = ["pika", "redis"] +mem-user = ["pymysql"] tree-mem = ["neo4j", "schedule"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0" -content-hash = "94a3c4f97f0deda4c6ccbfd8ceda194f18dbc7525aa49004ffcc7846a1c40f7e" +content-hash = "505ab4e6784d0191c3f177fdfc1335038d80c3b03b3a711bcdd954ef89afad42" diff --git a/pyproject.toml b/pyproject.toml index 7bc02af50..e2d2e4ffd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -164,6 +164,10 @@ python-dotenv = "^1.1.1" langgraph = "^0.5.1" langmem = "^0.0.27" + +[tool.poetry.group.mem-user.dependencies] +pymysql = "^1.1.2" + [[tool.poetry.source]] name = "mirrors" url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple/" From 98dbf8aca09ff80a23d9a448c4436befd72646c2 Mon Sep 17 00:00:00 2001 From: Kai Date: Thu, 25 Sep 2025 21:14:57 +0800 Subject: [PATCH 3/5] feat:reoganize prompt with reference in user content --- src/memos/mem_os/product.py | 83 +++++++++++++++++++++++++++++++------ 1 file changed, 71 insertions(+), 12 deletions(-) diff --git a/src/memos/mem_os/product.py b/src/memos/mem_os/product.py index b6a8d8f5c..e6b6793ff 100644 --- a/src/memos/mem_os/product.py +++ b/src/memos/mem_os/product.py @@ -417,12 +417,49 @@ def _build_system_prompt( mem_block_o, mem_block_p = _format_mem_block(memories_all) mem_block = mem_block_o + "\n" + mem_block_p prefix = (base_prompt.strip() + "\n\n") if base_prompt else "" - return ( - prefix - + sys_body - + "\n\n# Memories\n## PersonalMemory & OuterMemory (ordered)\n" - + mem_block - ) + return (prefix + sys_body + + "\n\n# Memories\n## PersonalMemory & OuterMemory (ordered)\n" + + mem_block) + + def _build_base_system_prompt( + self, + base_prompt: str | None = None, + tone: str = "friendly", + verbosity: str = "mid", + mode: str = "enhance", + ) -> str: + """ + Build base system prompt without memory references. + """ + now = datetime.now() + formatted_date = now.strftime("%Y-%m-%d (%A)") + sys_body = get_memos_prompt(date=formatted_date, + tone=tone, + verbosity=verbosity, + mode=mode) + prefix = (base_prompt.strip() + "\n\n") if base_prompt else "" + return prefix + sys_body + + def _build_memory_context( + self, + memories_all: list[TextualMemoryItem], + mode: str = "enhance", + ) -> str: + """ + Build memory context to be included in user message. + """ + if not memories_all: + return "" + + mem_block_o, mem_block_p = _format_mem_block(memories_all) + + if mode == "enhance": + return ("# Memories\n## PersonalMemory (ordered)\n" + mem_block_p + + "\n## OuterMemory (ordered)\n" + mem_block_o + "\n\n") + else: + mem_block = mem_block_o + "\n" + mem_block_p + return ("# Memories\n## PersonalMemory & OuterMemory (ordered)\n" + + mem_block + "\n\n") def _build_enhance_system_prompt( self, @@ -433,6 +470,7 @@ def _build_enhance_system_prompt( ) -> str: """ Build enhance prompt for the user with memory references. + [DEPRECATED] Use _build_base_system_prompt and _build_memory_context instead. """ now = datetime.now() formatted_date = now.strftime("%Y-%m-%d (%A)") @@ -916,17 +954,29 @@ def chat( internet_search=internet_search, moscube=moscube, )["text_mem"] + memories_list = [] if memories_result: memories_list = memories_result[0]["memories"] - memories_list = self._filter_memories_by_threshold(memories_list, threshold) - system_prompt = super()._build_system_prompt(memories_list, base_prompt) + memories_list = self._filter_memories_by_threshold( + memories_list, threshold) + + # Build base system prompt without memory + system_prompt = self._build_base_system_prompt(base_prompt, + mode="base") + + # Build memory context to be included in user message + memory_context = self._build_memory_context(memories_list, mode="base") + + # Combine memory context with user query + user_content = memory_context + query if memory_context else query + history_info = [] if history: history_info = history[-20:] current_messages = [ {"role": "system", "content": system_prompt}, *history_info, - {"role": "user", "content": query}, + {"role": "user", "content": user_content}, ] response = self.chat_llm.generate(current_messages) time_end = time.time() @@ -994,8 +1044,17 @@ def chat_with_references( reference = prepare_reference_data(memories_list) yield f"data: {json.dumps({'type': 'reference', 'data': reference})}\n\n" - # Build custom system prompt with relevant memories) - system_prompt = self._build_enhance_system_prompt(user_id, memories_list) + + # Build base system prompt without memory + system_prompt = self._build_base_system_prompt(mode="enhance") + + # Build memory context to be included in user message + memory_context = self._build_memory_context(memories_list, + mode="enhance") + + # Combine memory context with user query + user_content = memory_context + query if memory_context else query + # Get chat history if user_id not in self.chat_history_manager: self._register_chat_history(user_id) @@ -1006,7 +1065,7 @@ def chat_with_references( current_messages = [ {"role": "system", "content": system_prompt}, *chat_history.chat_history, - {"role": "user", "content": query}, + {"role": "user", "content": user_content}, ] logger.info( f"user_id: {user_id}, cube_id: {cube_id}, current_system_prompt: {system_prompt}" From 7aafbd0a772c0321ae8b465c619d349dd0842287 Mon Sep 17 00:00:00 2001 From: Kai Date: Fri, 26 Sep 2025 12:06:10 +0800 Subject: [PATCH 4/5] ruff format --- src/memos/memories/activation/kv.py | 3 ++- .../memories/textual/tree_text_memory/organize/handler.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/memos/memories/activation/kv.py b/src/memos/memories/activation/kv.py index 06cef794f..2fa08590f 100644 --- a/src/memos/memories/activation/kv.py +++ b/src/memos/memories/activation/kv.py @@ -1,9 +1,10 @@ import os import pickle + from datetime import datetime from importlib.metadata import version -from packaging.version import Version +from packaging.version import Version from transformers import DynamicCache from memos.configs.memory import KVCacheMemoryConfig diff --git a/src/memos/memories/textual/tree_text_memory/organize/handler.py b/src/memos/memories/textual/tree_text_memory/organize/handler.py index a1121fcd2..271902ca0 100644 --- a/src/memos/memories/textual/tree_text_memory/organize/handler.py +++ b/src/memos/memories/textual/tree_text_memory/organize/handler.py @@ -1,5 +1,6 @@ import json import re + from datetime import datetime from dateutil import parser @@ -14,6 +15,7 @@ MEMORY_RELATION_RESOLVER_PROMPT, ) + logger = get_logger(__name__) From 04bc4fbe7d71d9e031f4a2b42502a7299b2d29eb Mon Sep 17 00:00:00 2001 From: Kai Date: Fri, 26 Sep 2025 13:00:01 +0800 Subject: [PATCH 5/5] feat:reoganize prompt with reference in user content -reformat --- src/memos/mem_os/product.py | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/memos/mem_os/product.py b/src/memos/mem_os/product.py index eb5b3a12f..6f8e8b1c1 100644 --- a/src/memos/mem_os/product.py +++ b/src/memos/mem_os/product.py @@ -417,9 +417,12 @@ def _build_system_prompt( mem_block_o, mem_block_p = _format_mem_block(memories_all) mem_block = mem_block_o + "\n" + mem_block_p prefix = (base_prompt.strip() + "\n\n") if base_prompt else "" - return (prefix + sys_body + - "\n\n# Memories\n## PersonalMemory & OuterMemory (ordered)\n" + - mem_block) + return ( + prefix + + sys_body + + "\n\n# Memories\n## PersonalMemory & OuterMemory (ordered)\n" + + mem_block + ) def _build_base_system_prompt( self, @@ -433,10 +436,7 @@ def _build_base_system_prompt( """ now = datetime.now() formatted_date = now.strftime("%Y-%m-%d (%A)") - sys_body = get_memos_prompt(date=formatted_date, - tone=tone, - verbosity=verbosity, - mode=mode) + sys_body = get_memos_prompt(date=formatted_date, tone=tone, verbosity=verbosity, mode=mode) prefix = (base_prompt.strip() + "\n\n") if base_prompt else "" return prefix + sys_body @@ -454,12 +454,16 @@ def _build_memory_context( mem_block_o, mem_block_p = _format_mem_block(memories_all) if mode == "enhance": - return ("# Memories\n## PersonalMemory (ordered)\n" + mem_block_p + - "\n## OuterMemory (ordered)\n" + mem_block_o + "\n\n") + return ( + "# Memories\n## PersonalMemory (ordered)\n" + + mem_block_p + + "\n## OuterMemory (ordered)\n" + + mem_block_o + + "\n\n" + ) else: mem_block = mem_block_o + "\n" + mem_block_p - return ("# Memories\n## PersonalMemory & OuterMemory (ordered)\n" + - mem_block + "\n\n") + return "# Memories\n## PersonalMemory & OuterMemory (ordered)\n" + mem_block + "\n\n" def _build_enhance_system_prompt( self, @@ -981,16 +985,14 @@ def chat( memories_list = [] if memories_result: memories_list = memories_result[0]["memories"] - memories_list = self._filter_memories_by_threshold( - memories_list, threshold) + memories_list = self._filter_memories_by_threshold(memories_list, threshold) new_memories_list = [] for m in memories_list: m.metadata.embedding = [] new_memories_list.append(m) memories_list = new_memories_list # Build base system prompt without memory - system_prompt = self._build_base_system_prompt(base_prompt, - mode="base") + system_prompt = self._build_base_system_prompt(base_prompt, mode="base") # Build memory context to be included in user message memory_context = self._build_memory_context(memories_list, mode="base") @@ -1077,8 +1079,7 @@ def chat_with_references( system_prompt = self._build_base_system_prompt(mode="enhance") # Build memory context to be included in user message - memory_context = self._build_memory_context(memories_list, - mode="enhance") + memory_context = self._build_memory_context(memories_list, mode="enhance") # Combine memory context with user query user_content = memory_context + query if memory_context else query