MemoryOS 2.0.3__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.
- memoryos-2.0.3.dist-info/METADATA +418 -0
- memoryos-2.0.3.dist-info/RECORD +315 -0
- memoryos-2.0.3.dist-info/WHEEL +4 -0
- memoryos-2.0.3.dist-info/entry_points.txt +3 -0
- memoryos-2.0.3.dist-info/licenses/LICENSE +201 -0
- memos/__init__.py +20 -0
- memos/api/client.py +571 -0
- memos/api/config.py +1018 -0
- memos/api/context/dependencies.py +50 -0
- memos/api/exceptions.py +53 -0
- memos/api/handlers/__init__.py +62 -0
- memos/api/handlers/add_handler.py +158 -0
- memos/api/handlers/base_handler.py +194 -0
- memos/api/handlers/chat_handler.py +1401 -0
- memos/api/handlers/component_init.py +388 -0
- memos/api/handlers/config_builders.py +190 -0
- memos/api/handlers/feedback_handler.py +93 -0
- memos/api/handlers/formatters_handler.py +237 -0
- memos/api/handlers/memory_handler.py +316 -0
- memos/api/handlers/scheduler_handler.py +497 -0
- memos/api/handlers/search_handler.py +222 -0
- memos/api/handlers/suggestion_handler.py +117 -0
- memos/api/mcp_serve.py +614 -0
- memos/api/middleware/request_context.py +101 -0
- memos/api/product_api.py +38 -0
- memos/api/product_models.py +1206 -0
- memos/api/routers/__init__.py +1 -0
- memos/api/routers/product_router.py +477 -0
- memos/api/routers/server_router.py +394 -0
- memos/api/server_api.py +44 -0
- memos/api/start_api.py +433 -0
- memos/chunkers/__init__.py +4 -0
- memos/chunkers/base.py +24 -0
- memos/chunkers/charactertext_chunker.py +41 -0
- memos/chunkers/factory.py +24 -0
- memos/chunkers/markdown_chunker.py +62 -0
- memos/chunkers/sentence_chunker.py +54 -0
- memos/chunkers/simple_chunker.py +50 -0
- memos/cli.py +113 -0
- memos/configs/__init__.py +0 -0
- memos/configs/base.py +82 -0
- memos/configs/chunker.py +59 -0
- memos/configs/embedder.py +88 -0
- memos/configs/graph_db.py +236 -0
- memos/configs/internet_retriever.py +100 -0
- memos/configs/llm.py +151 -0
- memos/configs/mem_agent.py +54 -0
- memos/configs/mem_chat.py +81 -0
- memos/configs/mem_cube.py +105 -0
- memos/configs/mem_os.py +83 -0
- memos/configs/mem_reader.py +91 -0
- memos/configs/mem_scheduler.py +385 -0
- memos/configs/mem_user.py +70 -0
- memos/configs/memory.py +324 -0
- memos/configs/parser.py +38 -0
- memos/configs/reranker.py +18 -0
- memos/configs/utils.py +8 -0
- memos/configs/vec_db.py +80 -0
- memos/context/context.py +355 -0
- memos/dependency.py +52 -0
- memos/deprecation.py +262 -0
- memos/embedders/__init__.py +0 -0
- memos/embedders/ark.py +95 -0
- memos/embedders/base.py +106 -0
- memos/embedders/factory.py +29 -0
- memos/embedders/ollama.py +77 -0
- memos/embedders/sentence_transformer.py +49 -0
- memos/embedders/universal_api.py +51 -0
- memos/exceptions.py +30 -0
- memos/graph_dbs/__init__.py +0 -0
- memos/graph_dbs/base.py +274 -0
- memos/graph_dbs/factory.py +27 -0
- memos/graph_dbs/item.py +46 -0
- memos/graph_dbs/nebular.py +1794 -0
- memos/graph_dbs/neo4j.py +1942 -0
- memos/graph_dbs/neo4j_community.py +1058 -0
- memos/graph_dbs/polardb.py +5446 -0
- memos/hello_world.py +97 -0
- memos/llms/__init__.py +0 -0
- memos/llms/base.py +25 -0
- memos/llms/deepseek.py +13 -0
- memos/llms/factory.py +38 -0
- memos/llms/hf.py +443 -0
- memos/llms/hf_singleton.py +114 -0
- memos/llms/ollama.py +135 -0
- memos/llms/openai.py +222 -0
- memos/llms/openai_new.py +198 -0
- memos/llms/qwen.py +13 -0
- memos/llms/utils.py +14 -0
- memos/llms/vllm.py +218 -0
- memos/log.py +237 -0
- memos/mem_agent/base.py +19 -0
- memos/mem_agent/deepsearch_agent.py +391 -0
- memos/mem_agent/factory.py +36 -0
- memos/mem_chat/__init__.py +0 -0
- memos/mem_chat/base.py +30 -0
- memos/mem_chat/factory.py +21 -0
- memos/mem_chat/simple.py +200 -0
- memos/mem_cube/__init__.py +0 -0
- memos/mem_cube/base.py +30 -0
- memos/mem_cube/general.py +240 -0
- memos/mem_cube/navie.py +172 -0
- memos/mem_cube/utils.py +169 -0
- memos/mem_feedback/base.py +15 -0
- memos/mem_feedback/feedback.py +1192 -0
- memos/mem_feedback/simple_feedback.py +40 -0
- memos/mem_feedback/utils.py +230 -0
- memos/mem_os/client.py +5 -0
- memos/mem_os/core.py +1203 -0
- memos/mem_os/main.py +582 -0
- memos/mem_os/product.py +1608 -0
- memos/mem_os/product_server.py +455 -0
- memos/mem_os/utils/default_config.py +359 -0
- memos/mem_os/utils/format_utils.py +1403 -0
- memos/mem_os/utils/reference_utils.py +162 -0
- memos/mem_reader/__init__.py +0 -0
- memos/mem_reader/base.py +47 -0
- memos/mem_reader/factory.py +53 -0
- memos/mem_reader/memory.py +298 -0
- memos/mem_reader/multi_modal_struct.py +965 -0
- memos/mem_reader/read_multi_modal/__init__.py +43 -0
- memos/mem_reader/read_multi_modal/assistant_parser.py +311 -0
- memos/mem_reader/read_multi_modal/base.py +273 -0
- memos/mem_reader/read_multi_modal/file_content_parser.py +826 -0
- memos/mem_reader/read_multi_modal/image_parser.py +359 -0
- memos/mem_reader/read_multi_modal/multi_modal_parser.py +252 -0
- memos/mem_reader/read_multi_modal/string_parser.py +139 -0
- memos/mem_reader/read_multi_modal/system_parser.py +327 -0
- memos/mem_reader/read_multi_modal/text_content_parser.py +131 -0
- memos/mem_reader/read_multi_modal/tool_parser.py +210 -0
- memos/mem_reader/read_multi_modal/user_parser.py +218 -0
- memos/mem_reader/read_multi_modal/utils.py +358 -0
- memos/mem_reader/simple_struct.py +912 -0
- memos/mem_reader/strategy_struct.py +163 -0
- memos/mem_reader/utils.py +157 -0
- memos/mem_scheduler/__init__.py +0 -0
- memos/mem_scheduler/analyzer/__init__.py +0 -0
- memos/mem_scheduler/analyzer/api_analyzer.py +714 -0
- memos/mem_scheduler/analyzer/eval_analyzer.py +219 -0
- memos/mem_scheduler/analyzer/mos_for_test_scheduler.py +571 -0
- memos/mem_scheduler/analyzer/scheduler_for_eval.py +280 -0
- memos/mem_scheduler/base_scheduler.py +1319 -0
- memos/mem_scheduler/general_modules/__init__.py +0 -0
- memos/mem_scheduler/general_modules/api_misc.py +137 -0
- memos/mem_scheduler/general_modules/base.py +80 -0
- memos/mem_scheduler/general_modules/init_components_for_scheduler.py +425 -0
- memos/mem_scheduler/general_modules/misc.py +313 -0
- memos/mem_scheduler/general_modules/scheduler_logger.py +389 -0
- memos/mem_scheduler/general_modules/task_threads.py +315 -0
- memos/mem_scheduler/general_scheduler.py +1495 -0
- memos/mem_scheduler/memory_manage_modules/__init__.py +5 -0
- memos/mem_scheduler/memory_manage_modules/memory_filter.py +306 -0
- memos/mem_scheduler/memory_manage_modules/retriever.py +547 -0
- memos/mem_scheduler/monitors/__init__.py +0 -0
- memos/mem_scheduler/monitors/dispatcher_monitor.py +366 -0
- memos/mem_scheduler/monitors/general_monitor.py +394 -0
- memos/mem_scheduler/monitors/task_schedule_monitor.py +254 -0
- memos/mem_scheduler/optimized_scheduler.py +410 -0
- memos/mem_scheduler/orm_modules/__init__.py +0 -0
- memos/mem_scheduler/orm_modules/api_redis_model.py +518 -0
- memos/mem_scheduler/orm_modules/base_model.py +729 -0
- memos/mem_scheduler/orm_modules/monitor_models.py +261 -0
- memos/mem_scheduler/orm_modules/redis_model.py +699 -0
- memos/mem_scheduler/scheduler_factory.py +23 -0
- memos/mem_scheduler/schemas/__init__.py +0 -0
- memos/mem_scheduler/schemas/analyzer_schemas.py +52 -0
- memos/mem_scheduler/schemas/api_schemas.py +233 -0
- memos/mem_scheduler/schemas/general_schemas.py +55 -0
- memos/mem_scheduler/schemas/message_schemas.py +173 -0
- memos/mem_scheduler/schemas/monitor_schemas.py +406 -0
- memos/mem_scheduler/schemas/task_schemas.py +132 -0
- memos/mem_scheduler/task_schedule_modules/__init__.py +0 -0
- memos/mem_scheduler/task_schedule_modules/dispatcher.py +740 -0
- memos/mem_scheduler/task_schedule_modules/local_queue.py +247 -0
- memos/mem_scheduler/task_schedule_modules/orchestrator.py +74 -0
- memos/mem_scheduler/task_schedule_modules/redis_queue.py +1385 -0
- memos/mem_scheduler/task_schedule_modules/task_queue.py +162 -0
- memos/mem_scheduler/utils/__init__.py +0 -0
- memos/mem_scheduler/utils/api_utils.py +77 -0
- memos/mem_scheduler/utils/config_utils.py +100 -0
- memos/mem_scheduler/utils/db_utils.py +50 -0
- memos/mem_scheduler/utils/filter_utils.py +176 -0
- memos/mem_scheduler/utils/metrics.py +125 -0
- memos/mem_scheduler/utils/misc_utils.py +290 -0
- memos/mem_scheduler/utils/monitor_event_utils.py +67 -0
- memos/mem_scheduler/utils/status_tracker.py +229 -0
- memos/mem_scheduler/webservice_modules/__init__.py +0 -0
- memos/mem_scheduler/webservice_modules/rabbitmq_service.py +485 -0
- memos/mem_scheduler/webservice_modules/redis_service.py +380 -0
- memos/mem_user/factory.py +94 -0
- memos/mem_user/mysql_persistent_user_manager.py +271 -0
- memos/mem_user/mysql_user_manager.py +502 -0
- memos/mem_user/persistent_factory.py +98 -0
- memos/mem_user/persistent_user_manager.py +260 -0
- memos/mem_user/redis_persistent_user_manager.py +225 -0
- memos/mem_user/user_manager.py +488 -0
- memos/memories/__init__.py +0 -0
- memos/memories/activation/__init__.py +0 -0
- memos/memories/activation/base.py +42 -0
- memos/memories/activation/item.py +56 -0
- memos/memories/activation/kv.py +292 -0
- memos/memories/activation/vllmkv.py +219 -0
- memos/memories/base.py +19 -0
- memos/memories/factory.py +42 -0
- memos/memories/parametric/__init__.py +0 -0
- memos/memories/parametric/base.py +19 -0
- memos/memories/parametric/item.py +11 -0
- memos/memories/parametric/lora.py +41 -0
- memos/memories/textual/__init__.py +0 -0
- memos/memories/textual/base.py +92 -0
- memos/memories/textual/general.py +236 -0
- memos/memories/textual/item.py +304 -0
- memos/memories/textual/naive.py +187 -0
- memos/memories/textual/prefer_text_memory/__init__.py +0 -0
- memos/memories/textual/prefer_text_memory/adder.py +504 -0
- memos/memories/textual/prefer_text_memory/config.py +106 -0
- memos/memories/textual/prefer_text_memory/extractor.py +221 -0
- memos/memories/textual/prefer_text_memory/factory.py +85 -0
- memos/memories/textual/prefer_text_memory/retrievers.py +177 -0
- memos/memories/textual/prefer_text_memory/spliter.py +132 -0
- memos/memories/textual/prefer_text_memory/utils.py +93 -0
- memos/memories/textual/preference.py +344 -0
- memos/memories/textual/simple_preference.py +161 -0
- memos/memories/textual/simple_tree.py +69 -0
- memos/memories/textual/tree.py +459 -0
- memos/memories/textual/tree_text_memory/__init__.py +0 -0
- memos/memories/textual/tree_text_memory/organize/__init__.py +0 -0
- memos/memories/textual/tree_text_memory/organize/handler.py +184 -0
- memos/memories/textual/tree_text_memory/organize/manager.py +518 -0
- memos/memories/textual/tree_text_memory/organize/relation_reason_detector.py +238 -0
- memos/memories/textual/tree_text_memory/organize/reorganizer.py +622 -0
- memos/memories/textual/tree_text_memory/retrieve/__init__.py +0 -0
- memos/memories/textual/tree_text_memory/retrieve/advanced_searcher.py +364 -0
- memos/memories/textual/tree_text_memory/retrieve/bm25_util.py +186 -0
- memos/memories/textual/tree_text_memory/retrieve/bochasearch.py +419 -0
- memos/memories/textual/tree_text_memory/retrieve/internet_retriever.py +270 -0
- memos/memories/textual/tree_text_memory/retrieve/internet_retriever_factory.py +102 -0
- memos/memories/textual/tree_text_memory/retrieve/reasoner.py +61 -0
- memos/memories/textual/tree_text_memory/retrieve/recall.py +497 -0
- memos/memories/textual/tree_text_memory/retrieve/reranker.py +111 -0
- memos/memories/textual/tree_text_memory/retrieve/retrieval_mid_structs.py +16 -0
- memos/memories/textual/tree_text_memory/retrieve/retrieve_utils.py +472 -0
- memos/memories/textual/tree_text_memory/retrieve/searcher.py +848 -0
- memos/memories/textual/tree_text_memory/retrieve/task_goal_parser.py +135 -0
- memos/memories/textual/tree_text_memory/retrieve/utils.py +54 -0
- memos/memories/textual/tree_text_memory/retrieve/xinyusearch.py +387 -0
- memos/memos_tools/dinding_report_bot.py +453 -0
- memos/memos_tools/lockfree_dict.py +120 -0
- memos/memos_tools/notification_service.py +44 -0
- memos/memos_tools/notification_utils.py +142 -0
- memos/memos_tools/singleton.py +174 -0
- memos/memos_tools/thread_safe_dict.py +310 -0
- memos/memos_tools/thread_safe_dict_segment.py +382 -0
- memos/multi_mem_cube/__init__.py +0 -0
- memos/multi_mem_cube/composite_cube.py +86 -0
- memos/multi_mem_cube/single_cube.py +874 -0
- memos/multi_mem_cube/views.py +54 -0
- memos/parsers/__init__.py +0 -0
- memos/parsers/base.py +15 -0
- memos/parsers/factory.py +21 -0
- memos/parsers/markitdown.py +28 -0
- memos/reranker/__init__.py +4 -0
- memos/reranker/base.py +25 -0
- memos/reranker/concat.py +103 -0
- memos/reranker/cosine_local.py +102 -0
- memos/reranker/factory.py +72 -0
- memos/reranker/http_bge.py +324 -0
- memos/reranker/http_bge_strategy.py +327 -0
- memos/reranker/noop.py +19 -0
- memos/reranker/strategies/__init__.py +4 -0
- memos/reranker/strategies/base.py +61 -0
- memos/reranker/strategies/concat_background.py +94 -0
- memos/reranker/strategies/concat_docsource.py +110 -0
- memos/reranker/strategies/dialogue_common.py +109 -0
- memos/reranker/strategies/factory.py +31 -0
- memos/reranker/strategies/single_turn.py +107 -0
- memos/reranker/strategies/singleturn_outmem.py +98 -0
- memos/settings.py +10 -0
- memos/templates/__init__.py +0 -0
- memos/templates/advanced_search_prompts.py +211 -0
- memos/templates/cloud_service_prompt.py +107 -0
- memos/templates/instruction_completion.py +66 -0
- memos/templates/mem_agent_prompts.py +85 -0
- memos/templates/mem_feedback_prompts.py +822 -0
- memos/templates/mem_reader_prompts.py +1096 -0
- memos/templates/mem_reader_strategy_prompts.py +238 -0
- memos/templates/mem_scheduler_prompts.py +626 -0
- memos/templates/mem_search_prompts.py +93 -0
- memos/templates/mos_prompts.py +403 -0
- memos/templates/prefer_complete_prompt.py +735 -0
- memos/templates/tool_mem_prompts.py +139 -0
- memos/templates/tree_reorganize_prompts.py +230 -0
- memos/types/__init__.py +34 -0
- memos/types/general_types.py +151 -0
- memos/types/openai_chat_completion_types/__init__.py +15 -0
- memos/types/openai_chat_completion_types/chat_completion_assistant_message_param.py +56 -0
- memos/types/openai_chat_completion_types/chat_completion_content_part_image_param.py +27 -0
- memos/types/openai_chat_completion_types/chat_completion_content_part_input_audio_param.py +23 -0
- memos/types/openai_chat_completion_types/chat_completion_content_part_param.py +43 -0
- memos/types/openai_chat_completion_types/chat_completion_content_part_refusal_param.py +16 -0
- memos/types/openai_chat_completion_types/chat_completion_content_part_text_param.py +16 -0
- memos/types/openai_chat_completion_types/chat_completion_message_custom_tool_call_param.py +27 -0
- memos/types/openai_chat_completion_types/chat_completion_message_function_tool_call_param.py +32 -0
- memos/types/openai_chat_completion_types/chat_completion_message_param.py +18 -0
- memos/types/openai_chat_completion_types/chat_completion_message_tool_call_union_param.py +15 -0
- memos/types/openai_chat_completion_types/chat_completion_system_message_param.py +36 -0
- memos/types/openai_chat_completion_types/chat_completion_tool_message_param.py +30 -0
- memos/types/openai_chat_completion_types/chat_completion_user_message_param.py +34 -0
- memos/utils.py +123 -0
- memos/vec_dbs/__init__.py +0 -0
- memos/vec_dbs/base.py +117 -0
- memos/vec_dbs/factory.py +23 -0
- memos/vec_dbs/item.py +50 -0
- memos/vec_dbs/milvus.py +654 -0
- memos/vec_dbs/qdrant.py +355 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from memos.context.context import RequestContext, get_current_context
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
# Type alias for the RequestContext from context module
|
|
9
|
+
G = RequestContext
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_g_object() -> G:
|
|
13
|
+
"""
|
|
14
|
+
Get Flask g-like object for the current request.
|
|
15
|
+
Returns the context created by middleware.
|
|
16
|
+
"""
|
|
17
|
+
ctx = get_current_context()
|
|
18
|
+
if ctx is None:
|
|
19
|
+
raise RuntimeError(
|
|
20
|
+
"No request context available. Make sure RequestContextMiddleware is properly configured."
|
|
21
|
+
)
|
|
22
|
+
return ctx
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_current_g() -> G | None:
|
|
26
|
+
"""
|
|
27
|
+
Get the current request's g object from anywhere in the application.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
The current request's g object if available, None otherwise.
|
|
31
|
+
"""
|
|
32
|
+
return get_current_context()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def require_g() -> G:
|
|
36
|
+
"""
|
|
37
|
+
Get the current request's g object, raising an error if not available.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
The current request's g object.
|
|
41
|
+
|
|
42
|
+
Raises:
|
|
43
|
+
RuntimeError: If called outside of a request context.
|
|
44
|
+
"""
|
|
45
|
+
ctx = get_current_context()
|
|
46
|
+
if ctx is None:
|
|
47
|
+
raise RuntimeError(
|
|
48
|
+
"No request context available. This function must be called within a request handler."
|
|
49
|
+
)
|
|
50
|
+
return ctx
|
memos/api/exceptions.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from fastapi.exceptions import HTTPException, RequestValidationError
|
|
4
|
+
from fastapi.requests import Request
|
|
5
|
+
from fastapi.responses import JSONResponse
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class APIExceptionHandler:
|
|
12
|
+
"""Centralized exception handling for MemOS APIs."""
|
|
13
|
+
|
|
14
|
+
@staticmethod
|
|
15
|
+
async def validation_error_handler(request: Request, exc: RequestValidationError):
|
|
16
|
+
"""Handle request validation errors."""
|
|
17
|
+
logger.error(f"Validation error: {exc.errors()}")
|
|
18
|
+
return JSONResponse(
|
|
19
|
+
status_code=422,
|
|
20
|
+
content={
|
|
21
|
+
"code": 422,
|
|
22
|
+
"message": "Parameter validation error",
|
|
23
|
+
"detail": exc.errors(),
|
|
24
|
+
"data": None,
|
|
25
|
+
},
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
@staticmethod
|
|
29
|
+
async def value_error_handler(request: Request, exc: ValueError):
|
|
30
|
+
"""Handle ValueError exceptions globally."""
|
|
31
|
+
logger.error(f"ValueError: {exc}")
|
|
32
|
+
return JSONResponse(
|
|
33
|
+
status_code=400,
|
|
34
|
+
content={"code": 400, "message": str(exc), "data": None},
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
@staticmethod
|
|
38
|
+
async def global_exception_handler(request: Request, exc: Exception):
|
|
39
|
+
"""Handle all unhandled exceptions globally."""
|
|
40
|
+
logger.error(f"Exception: {exc}")
|
|
41
|
+
return JSONResponse(
|
|
42
|
+
status_code=500,
|
|
43
|
+
content={"code": 500, "message": str(exc), "data": None},
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
@staticmethod
|
|
47
|
+
async def http_error_handler(request: Request, exc: HTTPException):
|
|
48
|
+
"""Handle HTTP exceptions globally."""
|
|
49
|
+
logger.error(f"HTTP error {exc.status_code}: {exc.detail}")
|
|
50
|
+
return JSONResponse(
|
|
51
|
+
status_code=exc.status_code,
|
|
52
|
+
content={"code": exc.status_code, "message": str(exc.detail), "data": None},
|
|
53
|
+
)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Server handlers for MemOS API routers.
|
|
3
|
+
|
|
4
|
+
This package contains modular handlers for the server_router, responsible for:
|
|
5
|
+
- Building component configurations (config_builders)
|
|
6
|
+
- Initializing server components (component_init)
|
|
7
|
+
- Formatting data for API responses (formatters)
|
|
8
|
+
- Handling search, add, scheduler, and chat operations
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# Lazy imports to avoid circular dependencies
|
|
12
|
+
from memos.api.handlers import (
|
|
13
|
+
add_handler,
|
|
14
|
+
chat_handler,
|
|
15
|
+
memory_handler,
|
|
16
|
+
scheduler_handler,
|
|
17
|
+
search_handler,
|
|
18
|
+
suggestion_handler,
|
|
19
|
+
)
|
|
20
|
+
from memos.api.handlers.component_init import init_server
|
|
21
|
+
from memos.api.handlers.config_builders import (
|
|
22
|
+
build_embedder_config,
|
|
23
|
+
build_graph_db_config,
|
|
24
|
+
build_internet_retriever_config,
|
|
25
|
+
build_llm_config,
|
|
26
|
+
build_mem_reader_config,
|
|
27
|
+
build_pref_adder_config,
|
|
28
|
+
build_pref_extractor_config,
|
|
29
|
+
build_pref_retriever_config,
|
|
30
|
+
build_reranker_config,
|
|
31
|
+
build_vec_db_config,
|
|
32
|
+
)
|
|
33
|
+
from memos.api.handlers.formatters_handler import (
|
|
34
|
+
format_memory_item,
|
|
35
|
+
post_process_pref_mem,
|
|
36
|
+
to_iter,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"add_handler",
|
|
42
|
+
"build_embedder_config",
|
|
43
|
+
"build_graph_db_config",
|
|
44
|
+
"build_internet_retriever_config",
|
|
45
|
+
"build_llm_config",
|
|
46
|
+
"build_mem_reader_config",
|
|
47
|
+
"build_pref_adder_config",
|
|
48
|
+
"build_pref_extractor_config",
|
|
49
|
+
"build_pref_retriever_config",
|
|
50
|
+
"build_reranker_config",
|
|
51
|
+
"build_vec_db_config",
|
|
52
|
+
"chat_handler",
|
|
53
|
+
"format_memory_item",
|
|
54
|
+
"formatters_handler",
|
|
55
|
+
"init_server",
|
|
56
|
+
"memory_handler",
|
|
57
|
+
"post_process_pref_mem",
|
|
58
|
+
"scheduler_handler",
|
|
59
|
+
"search_handler",
|
|
60
|
+
"suggestion_handler",
|
|
61
|
+
"to_iter",
|
|
62
|
+
]
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Add handler for memory addition functionality (Class-based version).
|
|
3
|
+
|
|
4
|
+
This module provides a class-based implementation of add handlers,
|
|
5
|
+
using dependency injection for better modularity and testability.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from pydantic import validate_call
|
|
9
|
+
|
|
10
|
+
from memos.api.handlers.base_handler import BaseHandler, HandlerDependencies
|
|
11
|
+
from memos.api.product_models import APIADDRequest, APIFeedbackRequest, MemoryResponse
|
|
12
|
+
from memos.memories.textual.item import (
|
|
13
|
+
list_all_fields,
|
|
14
|
+
)
|
|
15
|
+
from memos.multi_mem_cube.composite_cube import CompositeCubeView
|
|
16
|
+
from memos.multi_mem_cube.single_cube import SingleCubeView
|
|
17
|
+
from memos.multi_mem_cube.views import MemCubeView
|
|
18
|
+
from memos.types import MessageList
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AddHandler(BaseHandler):
|
|
22
|
+
"""
|
|
23
|
+
Handler for memory addition operations.
|
|
24
|
+
|
|
25
|
+
Handles both text and preference memory additions with sync/async support.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, dependencies: HandlerDependencies):
|
|
29
|
+
"""
|
|
30
|
+
Initialize add handler.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
dependencies: HandlerDependencies instance
|
|
34
|
+
"""
|
|
35
|
+
super().__init__(dependencies)
|
|
36
|
+
self._validate_dependencies(
|
|
37
|
+
"naive_mem_cube", "mem_reader", "mem_scheduler", "feedback_server"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def handle_add_memories(self, add_req: APIADDRequest) -> MemoryResponse:
|
|
41
|
+
"""
|
|
42
|
+
Main handler for add memories endpoint.
|
|
43
|
+
|
|
44
|
+
Orchestrates the addition of both text and preference memories,
|
|
45
|
+
supporting concurrent processing.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
add_req: Add memory request (deprecated fields are converted in model validator)
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
MemoryResponse with added memory information
|
|
52
|
+
"""
|
|
53
|
+
self.logger.info(
|
|
54
|
+
f"[DIAGNOSTIC] server_router -> add_handler.handle_add_memories called (Modified at 2025-11-29 18:46). Full request: {add_req.model_dump_json(indent=2)}"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
if add_req.info:
|
|
58
|
+
exclude_fields = list_all_fields()
|
|
59
|
+
info_len = len(add_req.info)
|
|
60
|
+
add_req.info = {k: v for k, v in add_req.info.items() if k not in exclude_fields}
|
|
61
|
+
if len(add_req.info) < info_len:
|
|
62
|
+
self.logger.warning(f"[AddHandler] info fields can not contain {exclude_fields}.")
|
|
63
|
+
|
|
64
|
+
cube_view = self._build_cube_view(add_req)
|
|
65
|
+
|
|
66
|
+
@validate_call
|
|
67
|
+
def _check_messages(messages: MessageList) -> None:
|
|
68
|
+
pass
|
|
69
|
+
|
|
70
|
+
if add_req.is_feedback:
|
|
71
|
+
try:
|
|
72
|
+
messages = add_req.messages
|
|
73
|
+
_check_messages(messages)
|
|
74
|
+
|
|
75
|
+
chat_history = add_req.chat_history if add_req.chat_history else []
|
|
76
|
+
concatenate_chat = chat_history + messages
|
|
77
|
+
|
|
78
|
+
last_user_index = max(
|
|
79
|
+
i for i, d in enumerate(concatenate_chat) if d["role"] == "user"
|
|
80
|
+
)
|
|
81
|
+
feedback_content = concatenate_chat[last_user_index]["content"]
|
|
82
|
+
feedback_history = concatenate_chat[:last_user_index]
|
|
83
|
+
|
|
84
|
+
feedback_req = APIFeedbackRequest(
|
|
85
|
+
user_id=add_req.user_id,
|
|
86
|
+
session_id=add_req.session_id,
|
|
87
|
+
task_id=add_req.task_id,
|
|
88
|
+
history=feedback_history,
|
|
89
|
+
feedback_content=feedback_content,
|
|
90
|
+
writable_cube_ids=add_req.writable_cube_ids,
|
|
91
|
+
async_mode=add_req.async_mode,
|
|
92
|
+
info=add_req.info,
|
|
93
|
+
)
|
|
94
|
+
process_record = cube_view.feedback_memories(feedback_req)
|
|
95
|
+
|
|
96
|
+
self.logger.info(
|
|
97
|
+
f"[ADDFeedbackHandler] Final feedback results count={len(process_record)}"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
return MemoryResponse(
|
|
101
|
+
message="Memory feedback successfully",
|
|
102
|
+
data=[process_record],
|
|
103
|
+
)
|
|
104
|
+
except Exception as e:
|
|
105
|
+
self.logger.warning(f"[ADDFeedbackHandler] Running error: {e}")
|
|
106
|
+
|
|
107
|
+
results = cube_view.add_memories(add_req)
|
|
108
|
+
|
|
109
|
+
self.logger.info(f"[AddHandler] Final add results count={len(results)}")
|
|
110
|
+
|
|
111
|
+
return MemoryResponse(
|
|
112
|
+
message="Memory added successfully",
|
|
113
|
+
data=results,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
def _resolve_cube_ids(self, add_req: APIADDRequest) -> list[str]:
|
|
117
|
+
"""
|
|
118
|
+
Normalize target cube ids from add_req.
|
|
119
|
+
Priority:
|
|
120
|
+
1) writable_cube_ids (deprecated mem_cube_id is converted to this in model validator)
|
|
121
|
+
2) fallback to user_id
|
|
122
|
+
"""
|
|
123
|
+
if add_req.writable_cube_ids:
|
|
124
|
+
return list(dict.fromkeys(add_req.writable_cube_ids))
|
|
125
|
+
|
|
126
|
+
return [add_req.user_id]
|
|
127
|
+
|
|
128
|
+
def _build_cube_view(self, add_req: APIADDRequest) -> MemCubeView:
|
|
129
|
+
cube_ids = self._resolve_cube_ids(add_req)
|
|
130
|
+
|
|
131
|
+
if len(cube_ids) == 1:
|
|
132
|
+
cube_id = cube_ids[0]
|
|
133
|
+
return SingleCubeView(
|
|
134
|
+
cube_id=cube_id,
|
|
135
|
+
naive_mem_cube=self.naive_mem_cube,
|
|
136
|
+
mem_reader=self.mem_reader,
|
|
137
|
+
mem_scheduler=self.mem_scheduler,
|
|
138
|
+
logger=self.logger,
|
|
139
|
+
feedback_server=self.feedback_server,
|
|
140
|
+
searcher=None,
|
|
141
|
+
)
|
|
142
|
+
else:
|
|
143
|
+
single_views = [
|
|
144
|
+
SingleCubeView(
|
|
145
|
+
cube_id=cube_id,
|
|
146
|
+
naive_mem_cube=self.naive_mem_cube,
|
|
147
|
+
mem_reader=self.mem_reader,
|
|
148
|
+
mem_scheduler=self.mem_scheduler,
|
|
149
|
+
logger=self.logger,
|
|
150
|
+
feedback_server=self.feedback_server,
|
|
151
|
+
searcher=None,
|
|
152
|
+
)
|
|
153
|
+
for cube_id in cube_ids
|
|
154
|
+
]
|
|
155
|
+
return CompositeCubeView(
|
|
156
|
+
cube_views=single_views,
|
|
157
|
+
logger=self.logger,
|
|
158
|
+
)
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base handler for MemOS API handlers.
|
|
3
|
+
|
|
4
|
+
This module provides the base class for all API handlers, implementing
|
|
5
|
+
dependency injection and common functionality.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from memos.log import get_logger
|
|
11
|
+
from memos.mem_scheduler.optimized_scheduler import OptimizedScheduler
|
|
12
|
+
from memos.memories.textual.tree_text_memory.retrieve.advanced_searcher import AdvancedSearcher
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
logger = get_logger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class HandlerDependencies:
|
|
19
|
+
"""
|
|
20
|
+
Container for handler dependencies.
|
|
21
|
+
|
|
22
|
+
This class acts as a dependency injection container, holding all
|
|
23
|
+
shared resources needed by handlers.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
llm: Any | None = None,
|
|
29
|
+
naive_mem_cube: Any | None = None,
|
|
30
|
+
mem_reader: Any | None = None,
|
|
31
|
+
mem_scheduler: Any | None = None,
|
|
32
|
+
searcher: Any | None = None,
|
|
33
|
+
embedder: Any | None = None,
|
|
34
|
+
reranker: Any | None = None,
|
|
35
|
+
graph_db: Any | None = None,
|
|
36
|
+
vector_db: Any | None = None,
|
|
37
|
+
internet_retriever: Any | None = None,
|
|
38
|
+
memory_manager: Any | None = None,
|
|
39
|
+
mos_server: Any | None = None,
|
|
40
|
+
feedback_server: Any | None = None,
|
|
41
|
+
**kwargs,
|
|
42
|
+
):
|
|
43
|
+
"""
|
|
44
|
+
Initialize handler dependencies.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
llm: Language model instance
|
|
48
|
+
naive_mem_cube: Memory cube instance
|
|
49
|
+
mem_reader: Memory reader instance
|
|
50
|
+
mem_scheduler: Scheduler instance
|
|
51
|
+
embedder: Embedder instance
|
|
52
|
+
reranker: Reranker instance
|
|
53
|
+
graph_db: Graph database instance
|
|
54
|
+
vector_db: Vector database instance
|
|
55
|
+
internet_retriever: Internet retriever instance
|
|
56
|
+
memory_manager: Memory manager instance
|
|
57
|
+
mos_server: MOS server instance
|
|
58
|
+
**kwargs: Additional dependencies
|
|
59
|
+
"""
|
|
60
|
+
self.llm = llm
|
|
61
|
+
self.naive_mem_cube = naive_mem_cube
|
|
62
|
+
self.mem_reader = mem_reader
|
|
63
|
+
self.mem_scheduler = mem_scheduler
|
|
64
|
+
self.searcher = searcher
|
|
65
|
+
self.embedder = embedder
|
|
66
|
+
self.reranker = reranker
|
|
67
|
+
self.graph_db = graph_db
|
|
68
|
+
self.vector_db = vector_db
|
|
69
|
+
self.internet_retriever = internet_retriever
|
|
70
|
+
self.memory_manager = memory_manager
|
|
71
|
+
self.mos_server = mos_server
|
|
72
|
+
self.feedback_server = feedback_server
|
|
73
|
+
|
|
74
|
+
# Store any additional dependencies
|
|
75
|
+
for key, value in kwargs.items():
|
|
76
|
+
setattr(self, key, value)
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def from_init_server(cls, components: dict[str, Any]):
|
|
80
|
+
"""
|
|
81
|
+
Create dependencies from init_server() return values.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
components: Dictionary of components returned by init_server().
|
|
85
|
+
All components will be automatically unpacked as dependencies.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
HandlerDependencies instance
|
|
89
|
+
|
|
90
|
+
Note:
|
|
91
|
+
This method uses **kwargs unpacking, so any new components added to
|
|
92
|
+
init_server() will automatically become available as dependencies
|
|
93
|
+
without modifying this code.
|
|
94
|
+
"""
|
|
95
|
+
return cls(**components)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class BaseHandler:
|
|
99
|
+
"""
|
|
100
|
+
Base class for all API handlers.
|
|
101
|
+
|
|
102
|
+
Provides common functionality and dependency injection for handlers.
|
|
103
|
+
All specific handlers should inherit from this class.
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
def __init__(self, dependencies: HandlerDependencies):
|
|
107
|
+
"""
|
|
108
|
+
Initialize base handler.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
dependencies: HandlerDependencies instance containing all shared resources
|
|
112
|
+
"""
|
|
113
|
+
self.deps = dependencies
|
|
114
|
+
self.logger = get_logger(self.__class__.__name__)
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def llm(self):
|
|
118
|
+
"""Get LLM instance."""
|
|
119
|
+
return self.deps.llm
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def naive_mem_cube(self):
|
|
123
|
+
"""Get memory cube instance."""
|
|
124
|
+
return self.deps.naive_mem_cube
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def mem_reader(self):
|
|
128
|
+
"""Get memory reader instance."""
|
|
129
|
+
return self.deps.mem_reader
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def mem_scheduler(self) -> OptimizedScheduler:
|
|
133
|
+
"""Get scheduler instance."""
|
|
134
|
+
return self.deps.mem_scheduler
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def searcher(self) -> AdvancedSearcher:
|
|
138
|
+
"""Get scheduler instance."""
|
|
139
|
+
return self.deps.searcher
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def embedder(self):
|
|
143
|
+
"""Get embedder instance."""
|
|
144
|
+
return self.deps.embedder
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def reranker(self):
|
|
148
|
+
"""Get reranker instance."""
|
|
149
|
+
return self.deps.reranker
|
|
150
|
+
|
|
151
|
+
@property
|
|
152
|
+
def graph_db(self):
|
|
153
|
+
"""Get graph database instance."""
|
|
154
|
+
return self.deps.graph_db
|
|
155
|
+
|
|
156
|
+
@property
|
|
157
|
+
def vector_db(self):
|
|
158
|
+
"""Get vector database instance."""
|
|
159
|
+
return self.deps.vector_db
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def mos_server(self):
|
|
163
|
+
"""Get MOS server instance."""
|
|
164
|
+
return self.deps.mos_server
|
|
165
|
+
|
|
166
|
+
@property
|
|
167
|
+
def deepsearch_agent(self):
|
|
168
|
+
"""Get deepsearch agent instance."""
|
|
169
|
+
return self.deps.deepsearch_agent
|
|
170
|
+
|
|
171
|
+
@property
|
|
172
|
+
def feedback_server(self):
|
|
173
|
+
"""Get feedback server instance."""
|
|
174
|
+
return self.deps.feedback_server
|
|
175
|
+
|
|
176
|
+
def _validate_dependencies(self, *required_deps: str) -> None:
|
|
177
|
+
"""
|
|
178
|
+
Validate that required dependencies are available.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
*required_deps: Names of required dependency attributes
|
|
182
|
+
|
|
183
|
+
Raises:
|
|
184
|
+
ValueError: If any required dependency is None
|
|
185
|
+
"""
|
|
186
|
+
missing = []
|
|
187
|
+
for dep_name in required_deps:
|
|
188
|
+
if not hasattr(self.deps, dep_name) or getattr(self.deps, dep_name) is None:
|
|
189
|
+
missing.append(dep_name)
|
|
190
|
+
|
|
191
|
+
if missing:
|
|
192
|
+
raise ValueError(
|
|
193
|
+
f"{self.__class__.__name__} requires the following dependencies: {', '.join(missing)}"
|
|
194
|
+
)
|