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 @@
|
|
|
1
|
+
# API routers module
|
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import time
|
|
3
|
+
import traceback
|
|
4
|
+
|
|
5
|
+
from fastapi import APIRouter, HTTPException
|
|
6
|
+
from fastapi.responses import StreamingResponse
|
|
7
|
+
|
|
8
|
+
from memos.api.config import APIConfig
|
|
9
|
+
from memos.api.product_models import (
|
|
10
|
+
BaseResponse,
|
|
11
|
+
ChatCompleteRequest,
|
|
12
|
+
ChatRequest,
|
|
13
|
+
GetMemoryPlaygroundRequest,
|
|
14
|
+
MemoryCreateRequest,
|
|
15
|
+
MemoryResponse,
|
|
16
|
+
SearchRequest,
|
|
17
|
+
SearchResponse,
|
|
18
|
+
SimpleResponse,
|
|
19
|
+
SuggestionRequest,
|
|
20
|
+
SuggestionResponse,
|
|
21
|
+
UserRegisterRequest,
|
|
22
|
+
UserRegisterResponse,
|
|
23
|
+
)
|
|
24
|
+
from memos.configs.mem_os import MOSConfig
|
|
25
|
+
from memos.log import get_logger
|
|
26
|
+
from memos.mem_os.product import MOSProduct
|
|
27
|
+
from memos.memos_tools.notification_service import get_error_bot_function, get_online_bot_function
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
logger = get_logger(__name__)
|
|
31
|
+
|
|
32
|
+
router = APIRouter(prefix="/product", tags=["Product API"])
|
|
33
|
+
|
|
34
|
+
# Initialize MOSProduct instance with lazy initialization
|
|
35
|
+
MOS_PRODUCT_INSTANCE = None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get_mos_product_instance():
|
|
39
|
+
"""Get or create MOSProduct instance."""
|
|
40
|
+
global MOS_PRODUCT_INSTANCE
|
|
41
|
+
if MOS_PRODUCT_INSTANCE is None:
|
|
42
|
+
default_config = APIConfig.get_product_default_config()
|
|
43
|
+
logger.info(f"*********init_default_mos_config********* {default_config}")
|
|
44
|
+
from memos.configs.mem_os import MOSConfig
|
|
45
|
+
|
|
46
|
+
mos_config = MOSConfig(**default_config)
|
|
47
|
+
|
|
48
|
+
# Get default cube config from APIConfig (may be None if disabled)
|
|
49
|
+
default_cube_config = APIConfig.get_default_cube_config()
|
|
50
|
+
logger.info(f"*********initdefault_cube_config******** {default_cube_config}")
|
|
51
|
+
|
|
52
|
+
# Get DingDing bot functions
|
|
53
|
+
dingding_enabled = APIConfig.is_dingding_bot_enabled()
|
|
54
|
+
online_bot = get_online_bot_function() if dingding_enabled else None
|
|
55
|
+
error_bot = get_error_bot_function() if dingding_enabled else None
|
|
56
|
+
|
|
57
|
+
MOS_PRODUCT_INSTANCE = MOSProduct(
|
|
58
|
+
default_config=mos_config,
|
|
59
|
+
default_cube_config=default_cube_config,
|
|
60
|
+
online_bot=online_bot,
|
|
61
|
+
error_bot=error_bot,
|
|
62
|
+
)
|
|
63
|
+
logger.info("MOSProduct instance created successfully with inheritance architecture")
|
|
64
|
+
return MOS_PRODUCT_INSTANCE
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
get_mos_product_instance()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@router.post("/configure", summary="Configure MOSProduct", response_model=SimpleResponse)
|
|
71
|
+
def set_config(config):
|
|
72
|
+
"""Set MOSProduct configuration."""
|
|
73
|
+
global MOS_PRODUCT_INSTANCE
|
|
74
|
+
MOS_PRODUCT_INSTANCE = MOSProduct(default_config=config)
|
|
75
|
+
return SimpleResponse(message="Configuration set successfully")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@router.post("/users/register", summary="Register a new user", response_model=UserRegisterResponse)
|
|
79
|
+
def register_user(user_req: UserRegisterRequest):
|
|
80
|
+
"""Register a new user with configuration and default cube."""
|
|
81
|
+
try:
|
|
82
|
+
# Get configuration for the user
|
|
83
|
+
time_start_register = time.time()
|
|
84
|
+
user_config, default_mem_cube = APIConfig.create_user_config(
|
|
85
|
+
user_name=user_req.user_id, user_id=user_req.user_id
|
|
86
|
+
)
|
|
87
|
+
logger.info(f"user_config: {user_config.model_dump(mode='json')}")
|
|
88
|
+
logger.info(f"default_mem_cube: {default_mem_cube.config.model_dump(mode='json')}")
|
|
89
|
+
logger.info(
|
|
90
|
+
f"time register api : create user config time user_id: {user_req.user_id} time is: {time.time() - time_start_register}"
|
|
91
|
+
)
|
|
92
|
+
mos_product = get_mos_product_instance()
|
|
93
|
+
|
|
94
|
+
# Register user with default config and mem cube
|
|
95
|
+
result = mos_product.user_register(
|
|
96
|
+
user_id=user_req.user_id,
|
|
97
|
+
user_name=user_req.user_name,
|
|
98
|
+
interests=user_req.interests,
|
|
99
|
+
config=user_config,
|
|
100
|
+
default_mem_cube=default_mem_cube,
|
|
101
|
+
mem_cube_id=user_req.mem_cube_id,
|
|
102
|
+
)
|
|
103
|
+
logger.info(
|
|
104
|
+
f"time register api : register time user_id: {user_req.user_id} time is: {time.time() - time_start_register}"
|
|
105
|
+
)
|
|
106
|
+
if result["status"] == "success":
|
|
107
|
+
return UserRegisterResponse(
|
|
108
|
+
message="User registered successfully",
|
|
109
|
+
data={"user_id": result["user_id"], "mem_cube_id": result["default_cube_id"]},
|
|
110
|
+
)
|
|
111
|
+
else:
|
|
112
|
+
raise HTTPException(status_code=400, detail=result["message"])
|
|
113
|
+
|
|
114
|
+
except Exception as err:
|
|
115
|
+
logger.error(f"Failed to register user: {traceback.format_exc()}")
|
|
116
|
+
raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@router.get(
|
|
120
|
+
"/suggestions/{user_id}", summary="Get suggestion queries", response_model=SuggestionResponse
|
|
121
|
+
)
|
|
122
|
+
def get_suggestion_queries(user_id: str):
|
|
123
|
+
"""Get suggestion queries for a specific user."""
|
|
124
|
+
try:
|
|
125
|
+
mos_product = get_mos_product_instance()
|
|
126
|
+
suggestions = mos_product.get_suggestion_query(user_id)
|
|
127
|
+
return SuggestionResponse(
|
|
128
|
+
message="Suggestions retrieved successfully", data={"query": suggestions}
|
|
129
|
+
)
|
|
130
|
+
except ValueError as err:
|
|
131
|
+
raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
|
|
132
|
+
except Exception as err:
|
|
133
|
+
logger.error(f"Failed to get suggestions: {traceback.format_exc()}")
|
|
134
|
+
raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@router.post(
|
|
138
|
+
"/suggestions",
|
|
139
|
+
summary="Get suggestion queries with language",
|
|
140
|
+
response_model=SuggestionResponse,
|
|
141
|
+
)
|
|
142
|
+
def get_suggestion_queries_post(suggestion_req: SuggestionRequest):
|
|
143
|
+
"""Get suggestion queries for a specific user with language preference."""
|
|
144
|
+
try:
|
|
145
|
+
mos_product = get_mos_product_instance()
|
|
146
|
+
suggestions = mos_product.get_suggestion_query(
|
|
147
|
+
user_id=suggestion_req.user_id,
|
|
148
|
+
language=suggestion_req.language,
|
|
149
|
+
message=suggestion_req.message,
|
|
150
|
+
)
|
|
151
|
+
return SuggestionResponse(
|
|
152
|
+
message="Suggestions retrieved successfully", data={"query": suggestions}
|
|
153
|
+
)
|
|
154
|
+
except ValueError as err:
|
|
155
|
+
raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
|
|
156
|
+
except Exception as err:
|
|
157
|
+
logger.error(f"Failed to get suggestions: {traceback.format_exc()}")
|
|
158
|
+
raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@router.post("/get_all", summary="Get all memories for user", response_model=MemoryResponse)
|
|
162
|
+
def get_all_memories(memory_req: GetMemoryPlaygroundRequest):
|
|
163
|
+
"""Get all memories for a specific user."""
|
|
164
|
+
try:
|
|
165
|
+
mos_product = get_mos_product_instance()
|
|
166
|
+
if memory_req.search_query:
|
|
167
|
+
result = mos_product.get_subgraph(
|
|
168
|
+
user_id=memory_req.user_id,
|
|
169
|
+
query=memory_req.search_query,
|
|
170
|
+
mem_cube_ids=memory_req.mem_cube_ids,
|
|
171
|
+
)
|
|
172
|
+
return MemoryResponse(message="Memories retrieved successfully", data=result)
|
|
173
|
+
else:
|
|
174
|
+
result = mos_product.get_all(
|
|
175
|
+
user_id=memory_req.user_id,
|
|
176
|
+
memory_type=memory_req.memory_type,
|
|
177
|
+
mem_cube_ids=memory_req.mem_cube_ids,
|
|
178
|
+
)
|
|
179
|
+
return MemoryResponse(message="Memories retrieved successfully", data=result)
|
|
180
|
+
|
|
181
|
+
except ValueError as err:
|
|
182
|
+
raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
|
|
183
|
+
except Exception as err:
|
|
184
|
+
logger.error(f"Failed to get memories: {traceback.format_exc()}")
|
|
185
|
+
raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
@router.post("/add", summary="add a new memory", response_model=SimpleResponse)
|
|
189
|
+
def create_memory(memory_req: MemoryCreateRequest):
|
|
190
|
+
"""Create a new memory for a specific user."""
|
|
191
|
+
logger.info("DIAGNOSTIC: /product/add endpoint called. This confirms the new code is deployed.")
|
|
192
|
+
# Initialize status_tracker outside try block to avoid NameError in except blocks
|
|
193
|
+
status_tracker = None
|
|
194
|
+
|
|
195
|
+
try:
|
|
196
|
+
time_start_add = time.time()
|
|
197
|
+
mos_product = get_mos_product_instance()
|
|
198
|
+
|
|
199
|
+
# Track task if task_id is provided
|
|
200
|
+
item_id: str | None = None
|
|
201
|
+
if (
|
|
202
|
+
memory_req.task_id
|
|
203
|
+
and hasattr(mos_product, "mem_scheduler")
|
|
204
|
+
and mos_product.mem_scheduler
|
|
205
|
+
):
|
|
206
|
+
from uuid import uuid4
|
|
207
|
+
|
|
208
|
+
from memos.mem_scheduler.utils.status_tracker import TaskStatusTracker
|
|
209
|
+
|
|
210
|
+
item_id = str(uuid4()) # Generate a unique item_id for this submission
|
|
211
|
+
|
|
212
|
+
# Get Redis client from scheduler
|
|
213
|
+
if (
|
|
214
|
+
hasattr(mos_product.mem_scheduler, "redis_client")
|
|
215
|
+
and mos_product.mem_scheduler.redis_client
|
|
216
|
+
):
|
|
217
|
+
status_tracker = TaskStatusTracker(mos_product.mem_scheduler.redis_client)
|
|
218
|
+
# Submit task with "product_add" type
|
|
219
|
+
status_tracker.task_submitted(
|
|
220
|
+
task_id=item_id, # Use generated item_id for internal tracking
|
|
221
|
+
user_id=memory_req.user_id,
|
|
222
|
+
task_type="product_add",
|
|
223
|
+
mem_cube_id=memory_req.mem_cube_id or memory_req.user_id,
|
|
224
|
+
business_task_id=memory_req.task_id, # Use memory_req.task_id as business_task_id
|
|
225
|
+
)
|
|
226
|
+
status_tracker.task_started(item_id, memory_req.user_id) # Use item_id here
|
|
227
|
+
|
|
228
|
+
# Execute the add operation
|
|
229
|
+
mos_product.add(
|
|
230
|
+
user_id=memory_req.user_id,
|
|
231
|
+
memory_content=memory_req.memory_content,
|
|
232
|
+
messages=memory_req.messages,
|
|
233
|
+
doc_path=memory_req.doc_path,
|
|
234
|
+
mem_cube_id=memory_req.mem_cube_id,
|
|
235
|
+
source=memory_req.source,
|
|
236
|
+
user_profile=memory_req.user_profile,
|
|
237
|
+
session_id=memory_req.session_id,
|
|
238
|
+
task_id=memory_req.task_id,
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
# Mark task as completed
|
|
242
|
+
if status_tracker and item_id:
|
|
243
|
+
status_tracker.task_completed(item_id, memory_req.user_id)
|
|
244
|
+
|
|
245
|
+
logger.info(
|
|
246
|
+
f"time add api : add time user_id: {memory_req.user_id} time is: {time.time() - time_start_add}"
|
|
247
|
+
)
|
|
248
|
+
return SimpleResponse(message="Memory created successfully")
|
|
249
|
+
|
|
250
|
+
except ValueError as err:
|
|
251
|
+
# Mark task as failed if tracking
|
|
252
|
+
if status_tracker and item_id:
|
|
253
|
+
status_tracker.task_failed(item_id, memory_req.user_id, str(err))
|
|
254
|
+
raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
|
|
255
|
+
except Exception as err:
|
|
256
|
+
# Mark task as failed if tracking
|
|
257
|
+
if status_tracker and item_id:
|
|
258
|
+
status_tracker.task_failed(item_id, memory_req.user_id, str(err))
|
|
259
|
+
logger.error(f"Failed to create memory: {traceback.format_exc()}")
|
|
260
|
+
raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
@router.post("/search", summary="Search memories", response_model=SearchResponse)
|
|
264
|
+
def search_memories(search_req: SearchRequest):
|
|
265
|
+
"""Search memories for a specific user."""
|
|
266
|
+
try:
|
|
267
|
+
time_start_search = time.time()
|
|
268
|
+
mos_product = get_mos_product_instance()
|
|
269
|
+
result = mos_product.search(
|
|
270
|
+
query=search_req.query,
|
|
271
|
+
user_id=search_req.user_id,
|
|
272
|
+
install_cube_ids=[search_req.mem_cube_id] if search_req.mem_cube_id else None,
|
|
273
|
+
top_k=search_req.top_k,
|
|
274
|
+
session_id=search_req.session_id,
|
|
275
|
+
)
|
|
276
|
+
logger.info(
|
|
277
|
+
f"time search api : add time user_id: {search_req.user_id} time is: {time.time() - time_start_search}"
|
|
278
|
+
)
|
|
279
|
+
return SearchResponse(message="Search completed successfully", data=result)
|
|
280
|
+
|
|
281
|
+
except ValueError as err:
|
|
282
|
+
raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
|
|
283
|
+
except Exception as err:
|
|
284
|
+
logger.error(f"Failed to search memories: {traceback.format_exc()}")
|
|
285
|
+
raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
@router.post("/chat", summary="Chat with MemOS")
|
|
289
|
+
def chat(chat_req: ChatRequest):
|
|
290
|
+
"""Chat with MemOS for a specific user. Returns SSE stream."""
|
|
291
|
+
try:
|
|
292
|
+
mos_product = get_mos_product_instance()
|
|
293
|
+
|
|
294
|
+
def generate_chat_response():
|
|
295
|
+
"""Generate chat response as SSE stream."""
|
|
296
|
+
try:
|
|
297
|
+
# Directly yield from the generator without async wrapper
|
|
298
|
+
yield from mos_product.chat_with_references(
|
|
299
|
+
query=chat_req.query,
|
|
300
|
+
user_id=chat_req.user_id,
|
|
301
|
+
cube_id=chat_req.mem_cube_id,
|
|
302
|
+
history=chat_req.history,
|
|
303
|
+
internet_search=chat_req.internet_search,
|
|
304
|
+
moscube=chat_req.moscube,
|
|
305
|
+
session_id=chat_req.session_id,
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
except Exception as e:
|
|
309
|
+
logger.error(f"Error in chat stream: {e}")
|
|
310
|
+
error_data = f"data: {json.dumps({'type': 'error', 'content': str(traceback.format_exc())})}\n\n"
|
|
311
|
+
yield error_data
|
|
312
|
+
|
|
313
|
+
return StreamingResponse(
|
|
314
|
+
generate_chat_response(),
|
|
315
|
+
media_type="text/event-stream",
|
|
316
|
+
headers={
|
|
317
|
+
"Cache-Control": "no-cache",
|
|
318
|
+
"Connection": "keep-alive",
|
|
319
|
+
"Content-Type": "text/event-stream",
|
|
320
|
+
"Access-Control-Allow-Origin": "*",
|
|
321
|
+
"Access-Control-Allow-Headers": "*",
|
|
322
|
+
"Access-Control-Allow-Methods": "*",
|
|
323
|
+
},
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
except ValueError as err:
|
|
327
|
+
raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
|
|
328
|
+
except Exception as err:
|
|
329
|
+
logger.error(f"Failed to start chat: {traceback.format_exc()}")
|
|
330
|
+
raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
@router.post("/chat/complete", summary="Chat with MemOS (Complete Response)")
|
|
334
|
+
def chat_complete(chat_req: ChatCompleteRequest):
|
|
335
|
+
"""Chat with MemOS for a specific user. Returns complete response (non-streaming)."""
|
|
336
|
+
try:
|
|
337
|
+
mos_product = get_mos_product_instance()
|
|
338
|
+
|
|
339
|
+
# Collect all responses from the generator
|
|
340
|
+
content, references = mos_product.chat(
|
|
341
|
+
query=chat_req.query,
|
|
342
|
+
user_id=chat_req.user_id,
|
|
343
|
+
cube_id=chat_req.mem_cube_id,
|
|
344
|
+
history=chat_req.history,
|
|
345
|
+
internet_search=chat_req.internet_search,
|
|
346
|
+
moscube=chat_req.moscube,
|
|
347
|
+
base_prompt=chat_req.base_prompt or chat_req.system_prompt,
|
|
348
|
+
# will deprecate base_prompt in the future
|
|
349
|
+
top_k=chat_req.top_k,
|
|
350
|
+
threshold=chat_req.threshold,
|
|
351
|
+
session_id=chat_req.session_id,
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
# Return the complete response
|
|
355
|
+
return {
|
|
356
|
+
"message": "Chat completed successfully",
|
|
357
|
+
"data": {"response": content, "references": references},
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
except ValueError as err:
|
|
361
|
+
raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
|
|
362
|
+
except Exception as err:
|
|
363
|
+
logger.error(f"Failed to start chat: {traceback.format_exc()}")
|
|
364
|
+
raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
@router.get("/users", summary="List all users", response_model=BaseResponse[list])
|
|
368
|
+
def list_users():
|
|
369
|
+
"""List all registered users."""
|
|
370
|
+
try:
|
|
371
|
+
mos_product = get_mos_product_instance()
|
|
372
|
+
users = mos_product.list_users()
|
|
373
|
+
return BaseResponse(message="Users retrieved successfully", data=users)
|
|
374
|
+
except Exception as err:
|
|
375
|
+
logger.error(f"Failed to list users: {traceback.format_exc()}")
|
|
376
|
+
raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
@router.get("/users/{user_id}", summary="Get user info", response_model=BaseResponse[dict])
|
|
380
|
+
async def get_user_info(user_id: str):
|
|
381
|
+
"""Get user information including accessible cubes."""
|
|
382
|
+
try:
|
|
383
|
+
mos_product = get_mos_product_instance()
|
|
384
|
+
user_info = mos_product.get_user_info(user_id)
|
|
385
|
+
return BaseResponse(message="User info retrieved successfully", data=user_info)
|
|
386
|
+
except ValueError as err:
|
|
387
|
+
raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
|
|
388
|
+
except Exception as err:
|
|
389
|
+
logger.error(f"Failed to get user info: {traceback.format_exc()}")
|
|
390
|
+
raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
@router.get(
|
|
394
|
+
"/configure/{user_id}", summary="Get MOSProduct configuration", response_model=SimpleResponse
|
|
395
|
+
)
|
|
396
|
+
def get_config(user_id: str):
|
|
397
|
+
"""Get MOSProduct configuration."""
|
|
398
|
+
global MOS_PRODUCT_INSTANCE
|
|
399
|
+
config = MOS_PRODUCT_INSTANCE.default_config
|
|
400
|
+
return SimpleResponse(message="Configuration retrieved successfully", data=config)
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
@router.get(
|
|
404
|
+
"/users/{user_id}/config", summary="Get user configuration", response_model=BaseResponse[dict]
|
|
405
|
+
)
|
|
406
|
+
def get_user_config(user_id: str):
|
|
407
|
+
"""Get user-specific configuration."""
|
|
408
|
+
try:
|
|
409
|
+
mos_product = get_mos_product_instance()
|
|
410
|
+
config = mos_product.get_user_config(user_id)
|
|
411
|
+
if config:
|
|
412
|
+
return BaseResponse(
|
|
413
|
+
message="User configuration retrieved successfully",
|
|
414
|
+
data=config.model_dump(mode="json"),
|
|
415
|
+
)
|
|
416
|
+
else:
|
|
417
|
+
raise HTTPException(
|
|
418
|
+
status_code=404, detail=f"Configuration not found for user {user_id}"
|
|
419
|
+
)
|
|
420
|
+
except ValueError as err:
|
|
421
|
+
raise HTTPException(status_code=404, detail=str(traceback.format_exc())) from err
|
|
422
|
+
except Exception as err:
|
|
423
|
+
logger.error(f"Failed to get user config: {traceback.format_exc()}")
|
|
424
|
+
raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
@router.put(
|
|
428
|
+
"/users/{user_id}/config", summary="Update user configuration", response_model=SimpleResponse
|
|
429
|
+
)
|
|
430
|
+
def update_user_config(user_id: str, config_data: dict):
|
|
431
|
+
"""Update user-specific configuration."""
|
|
432
|
+
try:
|
|
433
|
+
mos_product = get_mos_product_instance()
|
|
434
|
+
|
|
435
|
+
# Create MOSConfig from the provided data
|
|
436
|
+
config = MOSConfig(**config_data)
|
|
437
|
+
|
|
438
|
+
# Update the configuration
|
|
439
|
+
success = mos_product.update_user_config(user_id, config)
|
|
440
|
+
if success:
|
|
441
|
+
return SimpleResponse(message="User configuration updated successfully")
|
|
442
|
+
else:
|
|
443
|
+
raise HTTPException(status_code=500, detail="Failed to update user configuration")
|
|
444
|
+
|
|
445
|
+
except ValueError as err:
|
|
446
|
+
raise HTTPException(status_code=400, detail=str(traceback.format_exc())) from err
|
|
447
|
+
except Exception as err:
|
|
448
|
+
logger.error(f"Failed to update user config: {traceback.format_exc()}")
|
|
449
|
+
raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
@router.get(
|
|
453
|
+
"/instances/status", summary="Get user configuration status", response_model=BaseResponse[dict]
|
|
454
|
+
)
|
|
455
|
+
def get_instance_status():
|
|
456
|
+
"""Get information about active user configurations in memory."""
|
|
457
|
+
try:
|
|
458
|
+
mos_product = get_mos_product_instance()
|
|
459
|
+
status_info = mos_product.get_user_instance_info()
|
|
460
|
+
return BaseResponse(
|
|
461
|
+
message="User configuration status retrieved successfully", data=status_info
|
|
462
|
+
)
|
|
463
|
+
except Exception as err:
|
|
464
|
+
logger.error(f"Failed to get user configuration status: {traceback.format_exc()}")
|
|
465
|
+
raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
@router.get("/instances/count", summary="Get active user count", response_model=BaseResponse[int])
|
|
469
|
+
def get_active_user_count():
|
|
470
|
+
"""Get the number of active user configurations in memory."""
|
|
471
|
+
try:
|
|
472
|
+
mos_product = get_mos_product_instance()
|
|
473
|
+
count = mos_product.get_active_user_count()
|
|
474
|
+
return BaseResponse(message="Active user count retrieved successfully", data=count)
|
|
475
|
+
except Exception as err:
|
|
476
|
+
logger.error(f"Failed to get active user count: {traceback.format_exc()}")
|
|
477
|
+
raise HTTPException(status_code=500, detail=str(traceback.format_exc())) from err
|