From 82883a3b8e1924a2484c0d46aa8cfa878870011c Mon Sep 17 00:00:00 2001 From: fancy Date: Fri, 21 Nov 2025 15:58:38 +0800 Subject: [PATCH 1/5] docs: update .env.example with comprehensive variables and comments --- docker/.env.example | 208 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 161 insertions(+), 47 deletions(-) diff --git a/docker/.env.example b/docker/.env.example index 0f4fcb65d..037eb8db8 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -1,60 +1,174 @@ -# MemOS Environment Variables Configuration -TZ=Asia/Shanghai +# MemOS Environment Variables (core runtime) +# Legend: [required] needed for default startup; others are optional or conditional per comments. -MOS_CUBE_PATH="/tmp/data_test" # Path to memory storage (e.g. /tmp/data_test) -MOS_ENABLE_DEFAULT_CUBE_CONFIG="true" # Enable default cube config (true/false) +## Base +TZ=Asia/Shanghai +ENV_NAME=PLAYGROUND_OFFLINE # Tag shown in DingTalk notifications (e.g., PROD_ONLINE/TEST); no runtime effect unless ENABLE_DINGDING_BOT=true +MOS_CUBE_PATH=/tmp/data_test # local data path +MEMOS_BASE_PATH=. # CLI/SDK cache path +MOS_ENABLE_DEFAULT_CUBE_CONFIG=true # enable default cube config +MOS_ENABLE_REORGANIZE=false # enable memory reorg +MOS_TEXT_MEM_TYPE=general_text # general_text | tree_text +ASYNC_MODE=sync # async/sync, used in default cube config -# OpenAI Configuration -OPENAI_API_KEY="sk-xxx" # Your OpenAI API key -OPENAI_API_BASE="http://xxx" # OpenAI API base URL (default: https://api.openai.com/v1) +## User/session defaults +MOS_USER_ID=root +MOS_SESSION_ID=default_session +MOS_MAX_TURNS_WINDOW=20 +MOS_TOP_K=50 -# MemOS Chat Model Configuration +## Chat LLM (main dialogue) MOS_CHAT_MODEL=gpt-4o-mini MOS_CHAT_TEMPERATURE=0.8 MOS_MAX_TOKENS=8000 MOS_TOP_P=0.9 -MOS_TOP_K=50 -MOS_CHAT_MODEL_PROVIDER=openai - -# graph db -# neo4j -NEO4J_BACKEND=xxx -NEO4J_URI=bolt://xxx -NEO4J_USER=xxx -NEO4J_PASSWORD=xxx -MOS_NEO4J_SHARED_DB=xxx -NEO4J_DB_NAME=xxx - -# tetxmem reog -MOS_ENABLE_REORGANIZE=false - -# MemOS User Configuration -MOS_USER_ID=root -MOS_SESSION_ID=default_session -MOS_MAX_TURNS_WINDOW=20 +MOS_CHAT_MODEL_PROVIDER=openai # openai | huggingface | vllm +MOS_MODEL_SCHEMA=memos.configs.llm.VLLMLLMConfig # vllm only: config class path; keep default unless you extend it +OPENAI_API_KEY=sk-xxx # [required] when provider=openai +OPENAI_API_BASE=https://api.openai.com/v1 # [required] base for the key +OPENAI_BASE_URL= # compatibility for eval/scheduler +VLLM_API_KEY= # required when provider=vllm +VLLM_API_BASE=http://localhost:8088/v1 # required when provider=vllm -# MemRader Configuration +## MemReader / retrieval LLM MEMRADER_MODEL=gpt-4o-mini -MEMRADER_API_KEY=sk-xxx -MEMRADER_API_BASE=http://xxx:3000/v1 +MEMRADER_API_KEY=sk-xxx # [required] can reuse OPENAI_API_KEY +MEMRADER_API_BASE=http://localhost:3000/v1 # [required] base for the key MEMRADER_MAX_TOKENS=5000 -#embedding & rerank +## Embedding & rerank EMBEDDING_DIMENSION=1024 -MOS_EMBEDDER_BACKEND=universal_api -MOS_EMBEDDER_MODEL=bge-m3 -MOS_EMBEDDER_API_BASE=http://xxx -MOS_EMBEDDER_API_KEY=EMPTY -MOS_RERANKER_BACKEND=http_bge -MOS_RERANKER_URL=http://xxx -# Ollama Configuration (for embeddings) -#OLLAMA_API_BASE=http://xxx - -# milvus for pref mem -MILVUS_URI=http://xxx -MILVUS_USER_NAME=xxx -MILVUS_PASSWORD=xxx - -# pref mem +MOS_EMBEDDER_BACKEND=universal_api # universal_api | ollama +MOS_EMBEDDER_PROVIDER=openai # required when universal_api +MOS_EMBEDDER_MODEL=bge-m3 # siliconflow → use BAAI/bge-m3 +MOS_EMBEDDER_API_BASE=http://localhost:8000/v1 # required when universal_api +MOS_EMBEDDER_API_KEY=EMPTY # required when universal_api +OLLAMA_API_BASE=http://localhost:11434 # required when backend=ollama +MOS_RERANKER_BACKEND=http_bge # http_bge | http_bge_strategy | cosine_local +MOS_RERANKER_URL=http://localhost:8001 # required when backend=http_bge* +MOS_RERANKER_MODEL=bge-reranker-v2-m3 # siliconflow → use BAAI/bge-reranker-v2-m3 +MOS_RERANKER_HEADERS_EXTRA= # extra headers, JSON string +MOS_RERANKER_STRATEGY=single_turn +MOS_RERANK_SOURCE= # optional rerank scope, e.g., history/stream/custom + +## Internet search & preference memory +ENABLE_INTERNET=false +BOCHA_API_KEY= # required if ENABLE_INTERNET=true +SEARCH_MODE=fast # fast | fine | mixture +FAST_GRAPH=false +BM25_CALL=false +VEC_COT_CALL=false +FINE_STRATEGY=rewrite # rewrite | recreate | deep_search +ENABLE_ACTIVATION_MEMORY=false ENABLE_PREFERENCE_MEMORY=true -RETURN_ORIGINAL_PREF_MEM=true +PREFERENCE_ADDER_MODE=fast # fast | safe +DEDUP_PREF_EXP_BY_TEXTUAL=false + +## Reader chunking +MEM_READER_BACKEND=simple_struct # simple_struct | strategy_struct +MEM_READER_CHAT_CHUNK_TYPE=default # default | content_length +MEM_READER_CHAT_CHUNK_TOKEN_SIZE=1600 # tokens per chunk (default mode) +MEM_READER_CHAT_CHUNK_SESS_SIZE=10 # sessions per chunk (default mode) +MEM_READER_CHAT_CHUNK_OVERLAP=2 # overlap between chunks + +## Scheduler (MemScheduler / API) +MOS_ENABLE_SCHEDULER=false +MOS_SCHEDULER_TOP_K=10 +MOS_SCHEDULER_ACT_MEM_UPDATE_INTERVAL=300 +MOS_SCHEDULER_CONTEXT_WINDOW_SIZE=5 +MOS_SCHEDULER_THREAD_POOL_MAX_WORKERS=10000 +MOS_SCHEDULER_CONSUME_INTERVAL_SECONDS=0.01 +MOS_SCHEDULER_ENABLE_PARALLEL_DISPATCH=true +MOS_SCHEDULER_ENABLE_ACTIVATION_MEMORY=false +API_SCHEDULER_ON=true +API_SEARCH_WINDOW_SIZE=5 +API_SEARCH_HISTORY_TURNS=5 + +## Graph / vector stores +NEO4J_BACKEND=neo4j-community # neo4j-community | neo4j | nebular | polardb +NEO4J_URI=bolt://localhost:7687 # required when backend=neo4j* +NEO4J_USER=neo4j # required when backend=neo4j* +NEO4J_PASSWORD=12345678 # required when backend=neo4j* +NEO4J_DB_NAME=neo4j # required for shared-db mode +MOS_NEO4J_SHARED_DB=false +QDRANT_HOST=localhost +QDRANT_PORT=6333 +MILVUS_URI=http://localhost:19530 # required when ENABLE_PREFERENCE_MEMORY=true +MILVUS_USER_NAME=root # same as above +MILVUS_PASSWORD=12345678 # same as above +NEBULAR_HOSTS=["localhost"] +NEBULAR_USER=root +NEBULAR_PASSWORD=xxxxxx +NEBULAR_SPACE=shared-tree-textual-memory +NEBULAR_WORKING_MEMORY=20 +NEBULAR_LONGTERM_MEMORY=1000000 +NEBULAR_USER_MEMORY=1000000 + +## Relational DB (user manager / PolarDB) +MOS_USER_MANAGER_BACKEND=sqlite # sqlite | mysql +MYSQL_HOST=localhost # required when backend=mysql +MYSQL_PORT=3306 +MYSQL_USERNAME=root +MYSQL_PASSWORD=12345678 +MYSQL_DATABASE=memos_users +MYSQL_CHARSET=utf8mb4 +POLAR_DB_HOST=localhost +POLAR_DB_PORT=5432 +POLAR_DB_USER=root +POLAR_DB_PASSWORD=123456 +POLAR_DB_DB_NAME=shared_memos_db +POLAR_DB_USE_MULTI_DB=false + +## Redis (scheduler queue) — fill only if you want scheduler queues in Redis; otherwise in-memory queue is used +REDIS_HOST=localhost # global Redis endpoint (preferred over MEMSCHEDULER_*) +REDIS_PORT=6379 +REDIS_DB=0 +REDIS_PASSWORD= +REDIS_SOCKET_TIMEOUT= +REDIS_SOCKET_CONNECT_TIMEOUT= +MEMSCHEDULER_REDIS_HOST= # fallback keys if not using the global ones +MEMSCHEDULER_REDIS_PORT= +MEMSCHEDULER_REDIS_DB= +MEMSCHEDULER_REDIS_PASSWORD= +MEMSCHEDULER_REDIS_TIMEOUT= +MEMSCHEDULER_REDIS_CONNECT_TIMEOUT= + +## MemScheduler LLM +MEMSCHEDULER_OPENAI_API_KEY= # LLM key for scheduler’s own calls (OpenAI-compatible); leave empty if scheduler not using LLM +MEMSCHEDULER_OPENAI_BASE_URL= # Base URL for the above; can reuse OPENAI_API_BASE +MEMSCHEDULER_OPENAI_DEFAULT_MODEL=gpt-4o-mini + +## Nacos (optional config center) +NACOS_ENABLE_WATCH=false +NACOS_WATCH_INTERVAL=60 +NACOS_SERVER_ADDR= +NACOS_DATA_ID= +NACOS_GROUP=DEFAULT_GROUP +NACOS_NAMESPACE= +AK= +SK= + +## DingTalk bot & OSS upload +ENABLE_DINGDING_BOT=false # set true -> fields below required +DINGDING_ACCESS_TOKEN_USER= +DINGDING_SECRET_USER= +DINGDING_ACCESS_TOKEN_ERROR= +DINGDING_SECRET_ERROR= +DINGDING_ROBOT_CODE= +DINGDING_APP_KEY= +DINGDING_APP_SECRET= +OSS_ENDPOINT= # bot image upload depends on OSS +OSS_REGION= +OSS_BUCKET_NAME= +OSS_ACCESS_KEY_ID= +OSS_ACCESS_KEY_SECRET= +OSS_PUBLIC_BASE_URL= + +## Logging / external sink +CUSTOM_LOGGER_URL= +CUSTOM_LOGGER_TOKEN= +CUSTOM_LOGGER_WORKERS=2 + +## SDK / external client +MEMOS_API_KEY= +MEMOS_BASE_URL=https://memos.memtensor.cn/api/openmem/v1 From 439ed49e6d6fff5c63ed3576bbb7eaa3c1c915b9 Mon Sep 17 00:00:00 2001 From: fridayL Date: Fri, 21 Nov 2025 17:50:35 +0800 Subject: [PATCH 2/5] hotfix:hotfix --- src/memos/api/product_models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/memos/api/product_models.py b/src/memos/api/product_models.py index 30df150ea..f7f0304c7 100644 --- a/src/memos/api/product_models.py +++ b/src/memos/api/product_models.py @@ -201,8 +201,8 @@ class APIADDRequest(BaseRequest): operation: list[PermissionDict] | None = Field( None, description="operation ids for multi cubes" ) - async_mode: Literal["async", "sync"] = Field( - "async", description="Whether to add memory in async mode" + async_mode: Literal["async", "sync"] | None = Field( + None, description="Whether to add memory in async mode" ) From 877b9fec9ba6edddca751176b99b6ecd8cb6f5dc Mon Sep 17 00:00:00 2001 From: "yuan.wang" Date: Wed, 26 Nov 2025 19:44:51 +0800 Subject: [PATCH 3/5] fa_bu_hui pref --- src/memos/memories/textual/item.py | 1 + .../textual/prefer_text_memory/extractor.py | 29 +++++++----- .../textual/prefer_text_memory/retrievers.py | 40 ++++++++++++---- src/memos/templates/prefer_complete_prompt.py | 46 ++++++++++++------- 4 files changed, 77 insertions(+), 39 deletions(-) diff --git a/src/memos/memories/textual/item.py b/src/memos/memories/textual/item.py index e7595443d..947e73463 100644 --- a/src/memos/memories/textual/item.py +++ b/src/memos/memories/textual/item.py @@ -199,6 +199,7 @@ class PreferenceTextualMemoryMetadata(TextualMemoryMetadata): preference: str | None = Field(default=None, description="Preference.") created_at: str | None = Field(default=None, description="Timestamp of the dialog.") mem_cube_id: str | None = Field(default=None, description="ID of the MemCube.") + score: float | None = Field(default=None, description="Score of the retrieval result.") class TextualMemoryItem(BaseModel): diff --git a/src/memos/memories/textual/prefer_text_memory/extractor.py b/src/memos/memories/textual/prefer_text_memory/extractor.py index d5eab2aec..947bddf85 100644 --- a/src/memos/memories/textual/prefer_text_memory/extractor.py +++ b/src/memos/memories/textual/prefer_text_memory/extractor.py @@ -90,7 +90,8 @@ def extract_implicit_preference(self, qa_pair: MessageList | str) -> dict[str, A response = self.llm_provider.generate([{"role": "user", "content": prompt}]) response = response.strip().replace("```json", "").replace("```", "").strip() result = json.loads(response) - result["preference"] = result.pop("implicit_preference") + for d in result: + d["preference"] = d.pop("implicit_preference") return result except Exception as e: logger.error(f"Error extracting implicit preferences: {e}, return None") @@ -136,20 +137,24 @@ def _process_single_chunk_implicit( if not implicit_pref: return None - vector_info = { - "embedding": self.embedder.embed([implicit_pref["context_summary"]])[0], - } + memories = [] + for pref in implicit_pref: + vector_info = { + "embedding": self.embedder.embed([pref["context_summary"]])[0], + } - extract_info = {**basic_info, **implicit_pref, **vector_info, **info} + extract_info = {**basic_info, **pref, **vector_info, **info} - metadata = PreferenceTextualMemoryMetadata( - type=msg_type, preference_type="implicit_preference", **extract_info - ) - memory = TextualMemoryItem( - id=extract_info["dialog_id"], memory=implicit_pref["context_summary"], metadata=metadata - ) + metadata = PreferenceTextualMemoryMetadata( + type=msg_type, preference_type="implicit_preference", **extract_info + ) + memory = TextualMemoryItem( + id=str(uuid.uuid4()), memory=pref["context_summary"], metadata=metadata + ) - return memory + memories.append(memory) + + return memories def extract( self, diff --git a/src/memos/memories/textual/prefer_text_memory/retrievers.py b/src/memos/memories/textual/prefer_text_memory/retrievers.py index c3aa950e4..1fc4c19f4 100644 --- a/src/memos/memories/textual/prefer_text_memory/retrievers.py +++ b/src/memos/memories/textual/prefer_text_memory/retrievers.py @@ -1,3 +1,5 @@ +import os + from abc import ABC, abstractmethod from typing import Any @@ -34,9 +36,12 @@ def _naive_reranker( self, query: str, prefs_mem: list[TextualMemoryItem], top_k: int, **kwargs: Any ) -> list[TextualMemoryItem]: if self.reranker: - prefs_mem = self.reranker.rerank(query, prefs_mem, top_k) - return [item for item, _ in prefs_mem] - return prefs_mem + prefs_mem_reranked = [] + prefs_mem_tuple = self.reranker.rerank(query, prefs_mem, top_k) + for item, score in prefs_mem_tuple: + item.metadata.score = score + prefs_mem_reranked.append(item) + return prefs_mem_reranked def _original_text_reranker( self, @@ -52,11 +57,22 @@ def _original_text_reranker( prefs_mem_for_reranker = deepcopy(prefs_mem) for pref_mem, pref in zip(prefs_mem_for_reranker, prefs, strict=False): pref_mem.memory = pref_mem.memory + "\n" + pref.original_text - prefs_mem_for_reranker = self.reranker.rerank(query, prefs_mem_for_reranker, top_k) - prefs_mem_for_reranker = [item for item, _ in prefs_mem_for_reranker] + reranked_results = self.reranker.rerank(query, prefs_mem_for_reranker, top_k) + prefs_mem_for_reranker = [item for item, _ in reranked_results] prefs_ids = [item.id for item in prefs_mem_for_reranker] prefs_dict = {item.id: item for item in prefs_mem} - return [prefs_dict[item_id] for item_id in prefs_ids if item_id in prefs_dict] + + # Create mapping from id to score from reranked results + reranked_scores = {item.id: score for item, score in reranked_results} + + # Assign scores to the original items + result_items = [] + for item_id in prefs_ids: + if item_id in prefs_dict: + original_item = prefs_dict[item_id] + original_item.metadata.score = reranked_scores.get(item_id) + result_items.append(original_item) + return result_items return prefs_mem def retrieve( @@ -119,9 +135,6 @@ def retrieve( if pref.payload.get("preference", None) ] - # store explicit id and score, use it after reranker - explicit_id_scores = {item.id: item.score for item in explicit_prefs} - reranker_map = { "naive": self._naive_reranker, "original_text": self._original_text_reranker, @@ -136,7 +149,14 @@ def retrieve( # filter explicit mem by score bigger than threshold explicit_prefs_mem = [ - item for item in explicit_prefs_mem if explicit_id_scores.get(item.id, 0) >= 0.0 + item + for item in explicit_prefs_mem + if item.metadata.score >= float(os.getenv("PREFERENCE_SEARCH_THRESHOLD", 0.0)) + ] + implicit_prefs_mem = [ + item + for item in implicit_prefs_mem + if item.metadata.score >= float(os.getenv("PREFERENCE_SEARCH_THRESHOLD", 0.0)) ] return explicit_prefs_mem + implicit_prefs_mem diff --git a/src/memos/templates/prefer_complete_prompt.py b/src/memos/templates/prefer_complete_prompt.py index 3a468b943..3315e061e 100644 --- a/src/memos/templates/prefer_complete_prompt.py +++ b/src/memos/templates/prefer_complete_prompt.py @@ -11,7 +11,8 @@ Requirements: 1. Keep only the preferences explicitly mentioned by the user. Do not infer or assume. If the user mentions reasons for their preferences, include those reasons as well. 2. Output should be a list of entries concise natural language summaries and the corresponding context summary, context summary must contain complete information of the conversation fragment that the preference is mentioned. -3. If multiple preferences are mentioned within the same topic or domain, you MUST combine them into a single entry, keep each entry information complete. +3. If multiple preferences are mentioned within the same topic or domain, you MUST combine them into a single entry, keep each entry information complete. Different topics of preferences should be divided into multiple entries. +4. If no explicit preference can be reasonably extracted, return []. Conversation: {qa_pair} @@ -23,6 +24,7 @@ "explicit_preference": "A short natural language summary of the preferences", "context_summary": "The corresponding context summary, which is a summary of the corresponding conversation, do not lack any scenario information", "reasoning": "reasoning process to find the explicit preferences" + "topic": "preference topic, which can only belong to one topic or domain, such as: sports, hotel, education, etc.", }, ] ``` @@ -42,7 +44,8 @@ 要求: 1. 只保留用户明确提到的偏好,不要推断或假设。如果用户提到了偏好的原因,也要包含这些原因。 2. 输出应该是一个条目列表,包含简洁的自然语言摘要和相应的上下文摘要,上下文摘要必须包含提到偏好的对话片段的完整信息。 -3. 如果在同一主题或领域内提到了多个偏好,你必须将它们合并为一个条目,保持每个条目信息完整。 +3. 如果在同一主题或领域内提到了多个偏好,你必须将它们合并为一个条目,保持每个条目信息完整。不同话题的偏好要分为多个条目。 +4. 如果没有可以合理提取的显式偏好,返回[]。 对话: {qa_pair} @@ -51,9 +54,10 @@ ```json [ { - "explicit_preference": "偏好的简短自然语言摘要", + "explicit_preference": "偏好的简短自然语言摘要,需要描述为“用户偏好于/不喜欢/想要/不想要/偏好什么”", "context_summary": "对应的上下文摘要,即对应对话的摘要,不要遗漏任何场景信息", - "reasoning": "寻找显式偏好的推理过程" + "reasoning": "寻找显式偏好的推理过程", + "topic": "偏好所属的主题或领域,例如:体育、酒店、教育等, topic只能属于一个主题或领域", }, ] ``` @@ -79,18 +83,22 @@ 2. Inferred implicit preferences must not conflict with explicit preferences. 3. For implicit_preference: only output the preference statement itself; do not include any extra explanation, reasoning, or confidence information. Put all reasoning and explanation in the reasoning field. 4. In the reasoning field, explicitly explain the underlying logic and hidden motivations you identified. -5. If no implicit preference can be reasonably inferred, leave the implicit_preference field empty (do not output anything else). +5. Different topics of preferences should be divided into multiple entries. +6. If no implicit preference can be reasonably inferred, return []. Conversation: {qa_pair} Output format: -```json -{ - "implicit_preference": "A concise natural language statement of the implicit preferences reasonably inferred from the conversation, or an empty string", - "context_summary": "The corresponding context summary, which is a summary of the corresponding conversation, do not lack any scenario information", - "reasoning": "Explain the underlying logic, hidden motivations, and behavioral patterns that led to this inference" -} +[ + ```json + { + "implicit_preference": "A concise natural language statement of the implicit preferences reasonably inferred from the conversation, or an empty string", + "context_summary": "The corresponding context summary, which is a summary of the corresponding conversation, do not lack any scenario information", + "reasoning": "Explain the underlying logic, hidden motivations, and behavioral patterns that led to this inference", + "topic": "preference topic, which can only belong to one topic or domain, such as: sports, hotel, education, etc.", + } +] ``` Don't output anything except the JSON. """ @@ -115,18 +123,22 @@ 2. 推断的隐式偏好不得与显式偏好冲突。 3. 对于 implicit_preference:仅输出偏好陈述本身;不要包含任何额外的解释、推理或置信度信息。将所有推理和解释放在 reasoning 字段中。 4. 在 reasoning 字段中,明确解释你识别出的底层逻辑和隐藏动机。 -5. 如果无法合理推断出隐式偏好,则将 implicit_preference 字段留空(不要输出其他任何内容)。 +5. 如果在同一主题或领域内提到了多个偏好,你必须将它们合并为一个条目,保持每个条目信息完整。不同话题的偏好要分为多个条目。 +6. 如果没有可以合理推断的隐式偏好,返回[]。 对话: {qa_pair} 输出格式: ```json -{ - "implicit_preference": "从对话中合理推断出的隐式偏好的简洁自然语言陈述,或空字符串", - "context_summary": "对应的上下文摘要,即对应对话的摘要,不要遗漏任何场景信息", - "reasoning": "解释推断出该偏好的底层逻辑、隐藏动机和行为模式" -} +[ + { + "implicit_preference": "从对话中合理推断出的隐式偏好的简洁自然语言陈述,或空字符串", + "context_summary": "对应的上下文摘要,即对应对话的摘要,不要遗漏任何场景信息", + "reasoning": "解释推断出该偏好的底层逻辑、隐藏动机和行为模式", + "topic": "偏好所属的主题或领域,例如:体育、酒店、教育等, topic只能属于一个主题或领域", + } +] ``` 除JSON外不要输出任何其他内容。 """ From 473b501650a8b3c3025a001c7c03c0f92b854c33 Mon Sep 17 00:00:00 2001 From: "yuan.wang" Date: Thu, 27 Nov 2025 10:29:39 +0800 Subject: [PATCH 4/5] test mix reranker --- .../textual/prefer_text_memory/retrievers.py | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/memos/memories/textual/prefer_text_memory/retrievers.py b/src/memos/memories/textual/prefer_text_memory/retrievers.py index 1fc4c19f4..8db40374e 100644 --- a/src/memos/memories/textual/prefer_text_memory/retrievers.py +++ b/src/memos/memories/textual/prefer_text_memory/retrievers.py @@ -140,23 +140,18 @@ def retrieve( "original_text": self._original_text_reranker, } reranker_func = reranker_map["naive"] - explicit_prefs_mem = reranker_func( - query=query, prefs_mem=explicit_prefs_mem, prefs=explicit_prefs, top_k=top_k - ) - implicit_prefs_mem = reranker_func( - query=query, prefs_mem=implicit_prefs_mem, prefs=implicit_prefs, top_k=top_k + prefs_mem = reranker_func( + query=query, + prefs_mem=explicit_prefs_mem + implicit_prefs_mem, + prefs=explicit_prefs + implicit_prefs, + top_k=top_k, ) # filter explicit mem by score bigger than threshold - explicit_prefs_mem = [ + prefs_mem = [ item - for item in explicit_prefs_mem - if item.metadata.score >= float(os.getenv("PREFERENCE_SEARCH_THRESHOLD", 0.0)) - ] - implicit_prefs_mem = [ - item - for item in implicit_prefs_mem + for item in prefs_mem if item.metadata.score >= float(os.getenv("PREFERENCE_SEARCH_THRESHOLD", 0.0)) ] - return explicit_prefs_mem + implicit_prefs_mem + return prefs_mem From ad2b1a6630695871ba5ec90c1d34f3136e65521d Mon Sep 17 00:00:00 2001 From: "yuan.wang" Date: Fri, 28 Nov 2025 10:20:02 +0800 Subject: [PATCH 5/5] modify code --- .../textual/prefer_text_memory/retrievers.py | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/memos/memories/textual/prefer_text_memory/retrievers.py b/src/memos/memories/textual/prefer_text_memory/retrievers.py index 8db40374e..534f5d678 100644 --- a/src/memos/memories/textual/prefer_text_memory/retrievers.py +++ b/src/memos/memories/textual/prefer_text_memory/retrievers.py @@ -140,18 +140,29 @@ def retrieve( "original_text": self._original_text_reranker, } reranker_func = reranker_map["naive"] - prefs_mem = reranker_func( + prefs_mem_explicit = reranker_func( query=query, - prefs_mem=explicit_prefs_mem + implicit_prefs_mem, - prefs=explicit_prefs + implicit_prefs, + prefs_mem=explicit_prefs_mem, + prefs=explicit_prefs, + top_k=top_k, + ) + prefs_mem_implicit = reranker_func( + query=query, + prefs_mem=implicit_prefs_mem, + prefs=implicit_prefs, top_k=top_k, ) # filter explicit mem by score bigger than threshold - prefs_mem = [ + prefs_mem_explicit = [ item - for item in prefs_mem + for item in prefs_mem_explicit + if item.metadata.score >= float(os.getenv("PREFERENCE_SEARCH_THRESHOLD", 0.0)) + ] + prefs_mem_implicit = [ + item + for item in prefs_mem_implicit if item.metadata.score >= float(os.getenv("PREFERENCE_SEARCH_THRESHOLD", 0.0)) ] - return prefs_mem + return prefs_mem_explicit + prefs_mem_implicit