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,394 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Server API Router for MemOS (Class-based handlers version).
|
|
3
|
+
|
|
4
|
+
This router demonstrates the improved architecture using class-based handlers
|
|
5
|
+
with dependency injection, providing better modularity and maintainability.
|
|
6
|
+
|
|
7
|
+
Comparison with function-based approach:
|
|
8
|
+
- Cleaner code: No need to pass dependencies in every endpoint
|
|
9
|
+
- Better testability: Easy to mock handler dependencies
|
|
10
|
+
- Improved extensibility: Add new handlers or modify existing ones easily
|
|
11
|
+
- Clear separation of concerns: Router focuses on routing, handlers handle business logic
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import os
|
|
15
|
+
import random as _random
|
|
16
|
+
import socket
|
|
17
|
+
|
|
18
|
+
from fastapi import APIRouter, HTTPException, Query
|
|
19
|
+
|
|
20
|
+
from memos.api import handlers
|
|
21
|
+
from memos.api.handlers.add_handler import AddHandler
|
|
22
|
+
from memos.api.handlers.base_handler import HandlerDependencies
|
|
23
|
+
from memos.api.handlers.chat_handler import ChatHandler
|
|
24
|
+
from memos.api.handlers.feedback_handler import FeedbackHandler
|
|
25
|
+
from memos.api.handlers.search_handler import SearchHandler
|
|
26
|
+
from memos.api.product_models import (
|
|
27
|
+
AllStatusResponse,
|
|
28
|
+
APIADDRequest,
|
|
29
|
+
APIChatCompleteRequest,
|
|
30
|
+
APIFeedbackRequest,
|
|
31
|
+
APISearchRequest,
|
|
32
|
+
ChatPlaygroundRequest,
|
|
33
|
+
ChatRequest,
|
|
34
|
+
DeleteMemoryRequest,
|
|
35
|
+
DeleteMemoryResponse,
|
|
36
|
+
ExistMemCubeIdRequest,
|
|
37
|
+
ExistMemCubeIdResponse,
|
|
38
|
+
GetMemoryPlaygroundRequest,
|
|
39
|
+
GetMemoryRequest,
|
|
40
|
+
GetMemoryResponse,
|
|
41
|
+
GetUserNamesByMemoryIdsRequest,
|
|
42
|
+
GetUserNamesByMemoryIdsResponse,
|
|
43
|
+
MemoryResponse,
|
|
44
|
+
SearchResponse,
|
|
45
|
+
StatusResponse,
|
|
46
|
+
SuggestionRequest,
|
|
47
|
+
SuggestionResponse,
|
|
48
|
+
TaskQueueResponse,
|
|
49
|
+
)
|
|
50
|
+
from memos.graph_dbs.polardb import PolarDBGraphDB
|
|
51
|
+
from memos.log import get_logger
|
|
52
|
+
from memos.mem_scheduler.base_scheduler import BaseScheduler
|
|
53
|
+
from memos.mem_scheduler.utils.status_tracker import TaskStatusTracker
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
logger = get_logger(__name__)
|
|
57
|
+
|
|
58
|
+
router = APIRouter(prefix="/product", tags=["Server API"])
|
|
59
|
+
|
|
60
|
+
# Instance ID for identifying this server instance in logs and responses
|
|
61
|
+
INSTANCE_ID = f"{socket.gethostname()}:{os.getpid()}:{_random.randint(1000, 9999)}"
|
|
62
|
+
|
|
63
|
+
# Initialize all server components
|
|
64
|
+
components = handlers.init_server()
|
|
65
|
+
|
|
66
|
+
# Create dependency container
|
|
67
|
+
dependencies = HandlerDependencies.from_init_server(components)
|
|
68
|
+
|
|
69
|
+
# Initialize all handlers with dependency injection
|
|
70
|
+
search_handler = SearchHandler(dependencies)
|
|
71
|
+
add_handler = AddHandler(dependencies)
|
|
72
|
+
chat_handler = (
|
|
73
|
+
ChatHandler(
|
|
74
|
+
dependencies,
|
|
75
|
+
components["chat_llms"],
|
|
76
|
+
search_handler,
|
|
77
|
+
add_handler,
|
|
78
|
+
online_bot=components.get("online_bot"),
|
|
79
|
+
)
|
|
80
|
+
if os.getenv("ENABLE_CHAT_API", "false") == "true"
|
|
81
|
+
else None
|
|
82
|
+
)
|
|
83
|
+
feedback_handler = FeedbackHandler(dependencies)
|
|
84
|
+
# Extract commonly used components for function-based handlers
|
|
85
|
+
# (These can be accessed from the components dict without unpacking all of them)
|
|
86
|
+
mem_scheduler: BaseScheduler = components["mem_scheduler"]
|
|
87
|
+
llm = components["llm"]
|
|
88
|
+
naive_mem_cube = components["naive_mem_cube"]
|
|
89
|
+
redis_client = components["redis_client"]
|
|
90
|
+
status_tracker = TaskStatusTracker(redis_client=redis_client)
|
|
91
|
+
graph_db = components["graph_db"]
|
|
92
|
+
vector_db = components["vector_db"]
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# =============================================================================
|
|
96
|
+
# Search API Endpoints
|
|
97
|
+
# =============================================================================
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@router.post("/search", summary="Search memories", response_model=SearchResponse)
|
|
101
|
+
def search_memories(search_req: APISearchRequest):
|
|
102
|
+
"""
|
|
103
|
+
Search memories for a specific user.
|
|
104
|
+
|
|
105
|
+
This endpoint uses the class-based SearchHandler for better code organization.
|
|
106
|
+
"""
|
|
107
|
+
search_results = search_handler.handle_search_memories(search_req)
|
|
108
|
+
return search_results
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
# =============================================================================
|
|
112
|
+
# Add API Endpoints
|
|
113
|
+
# =============================================================================
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@router.post("/add", summary="Add memories", response_model=MemoryResponse)
|
|
117
|
+
def add_memories(add_req: APIADDRequest):
|
|
118
|
+
"""
|
|
119
|
+
Add memories for a specific user.
|
|
120
|
+
|
|
121
|
+
This endpoint uses the class-based AddHandler for better code organization.
|
|
122
|
+
"""
|
|
123
|
+
return add_handler.handle_add_memories(add_req)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# =============================================================================
|
|
127
|
+
# Scheduler API Endpoints
|
|
128
|
+
# =============================================================================
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@router.get( # Changed from post to get
|
|
132
|
+
"/scheduler/allstatus",
|
|
133
|
+
summary="Get detailed scheduler status",
|
|
134
|
+
response_model=AllStatusResponse,
|
|
135
|
+
)
|
|
136
|
+
def scheduler_allstatus():
|
|
137
|
+
"""Get detailed scheduler status including running tasks and queue metrics."""
|
|
138
|
+
return handlers.scheduler_handler.handle_scheduler_allstatus(
|
|
139
|
+
mem_scheduler=mem_scheduler, status_tracker=status_tracker
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@router.get( # Changed from post to get
|
|
144
|
+
"/scheduler/status", summary="Get scheduler running status", response_model=StatusResponse
|
|
145
|
+
)
|
|
146
|
+
def scheduler_status(
|
|
147
|
+
user_id: str = Query(..., description="User ID"),
|
|
148
|
+
task_id: str | None = Query(None, description="Optional Task ID to query a specific task"),
|
|
149
|
+
):
|
|
150
|
+
"""Get scheduler running status."""
|
|
151
|
+
return handlers.scheduler_handler.handle_scheduler_status(
|
|
152
|
+
user_id=user_id,
|
|
153
|
+
task_id=task_id,
|
|
154
|
+
status_tracker=status_tracker,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@router.get( # Changed from post to get
|
|
159
|
+
"/scheduler/task_queue_status",
|
|
160
|
+
summary="Get scheduler task queue status",
|
|
161
|
+
response_model=TaskQueueResponse,
|
|
162
|
+
)
|
|
163
|
+
def scheduler_task_queue_status(
|
|
164
|
+
user_id: str = Query(..., description="User ID whose queue status is requested"),
|
|
165
|
+
):
|
|
166
|
+
"""Get scheduler task queue backlog/pending status for a user."""
|
|
167
|
+
return handlers.scheduler_handler.handle_task_queue_status(
|
|
168
|
+
user_id=user_id, mem_scheduler=mem_scheduler
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
@router.post("/scheduler/wait", summary="Wait until scheduler is idle for a specific user")
|
|
173
|
+
def scheduler_wait(
|
|
174
|
+
user_name: str,
|
|
175
|
+
timeout_seconds: float = 120.0,
|
|
176
|
+
poll_interval: float = 0.5,
|
|
177
|
+
):
|
|
178
|
+
"""Wait until scheduler is idle for a specific user."""
|
|
179
|
+
return handlers.scheduler_handler.handle_scheduler_wait(
|
|
180
|
+
user_name=user_name,
|
|
181
|
+
status_tracker=status_tracker,
|
|
182
|
+
timeout_seconds=timeout_seconds,
|
|
183
|
+
poll_interval=poll_interval,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
@router.get("/scheduler/wait/stream", summary="Stream scheduler progress for a user")
|
|
188
|
+
def scheduler_wait_stream(
|
|
189
|
+
user_name: str,
|
|
190
|
+
timeout_seconds: float = 120.0,
|
|
191
|
+
poll_interval: float = 0.5,
|
|
192
|
+
):
|
|
193
|
+
"""Stream scheduler progress via Server-Sent Events (SSE)."""
|
|
194
|
+
return handlers.scheduler_handler.handle_scheduler_wait_stream(
|
|
195
|
+
user_name=user_name,
|
|
196
|
+
status_tracker=status_tracker,
|
|
197
|
+
timeout_seconds=timeout_seconds,
|
|
198
|
+
poll_interval=poll_interval,
|
|
199
|
+
instance_id=INSTANCE_ID,
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
# =============================================================================
|
|
204
|
+
# Chat API Endpoints
|
|
205
|
+
# =============================================================================
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@router.post("/chat/complete", summary="Chat with MemOS (Complete Response)")
|
|
209
|
+
def chat_complete(chat_req: APIChatCompleteRequest):
|
|
210
|
+
"""
|
|
211
|
+
Chat with MemOS for a specific user. Returns complete response (non-streaming).
|
|
212
|
+
|
|
213
|
+
This endpoint uses the class-based ChatHandler.
|
|
214
|
+
"""
|
|
215
|
+
if chat_handler is None:
|
|
216
|
+
raise HTTPException(
|
|
217
|
+
status_code=503, detail="Chat service is not available. Chat handler not initialized."
|
|
218
|
+
)
|
|
219
|
+
return chat_handler.handle_chat_complete(chat_req)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
@router.post("/chat/stream", summary="Chat with MemOS")
|
|
223
|
+
def chat_stream(chat_req: ChatRequest):
|
|
224
|
+
"""
|
|
225
|
+
Chat with MemOS for a specific user. Returns SSE stream.
|
|
226
|
+
|
|
227
|
+
This endpoint uses the class-based ChatHandler which internally
|
|
228
|
+
composes SearchHandler and AddHandler for a clean architecture.
|
|
229
|
+
"""
|
|
230
|
+
if chat_handler is None:
|
|
231
|
+
raise HTTPException(
|
|
232
|
+
status_code=503, detail="Chat service is not available. Chat handler not initialized."
|
|
233
|
+
)
|
|
234
|
+
return chat_handler.handle_chat_stream(chat_req)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
@router.post("/chat/stream/playground", summary="Chat with MemOS playground")
|
|
238
|
+
def chat_stream_playground(chat_req: ChatPlaygroundRequest):
|
|
239
|
+
"""
|
|
240
|
+
Chat with MemOS for a specific user. Returns SSE stream.
|
|
241
|
+
|
|
242
|
+
This endpoint uses the class-based ChatHandler which internally
|
|
243
|
+
composes SearchHandler and AddHandler for a clean architecture.
|
|
244
|
+
"""
|
|
245
|
+
if chat_handler is None:
|
|
246
|
+
raise HTTPException(
|
|
247
|
+
status_code=503, detail="Chat service is not available. Chat handler not initialized."
|
|
248
|
+
)
|
|
249
|
+
return chat_handler.handle_chat_stream_playground(chat_req)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
# =============================================================================
|
|
253
|
+
# Suggestion API Endpoints
|
|
254
|
+
# =============================================================================
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
@router.post(
|
|
258
|
+
"/suggestions",
|
|
259
|
+
summary="Get suggestion queries",
|
|
260
|
+
response_model=SuggestionResponse,
|
|
261
|
+
)
|
|
262
|
+
def get_suggestion_queries(suggestion_req: SuggestionRequest):
|
|
263
|
+
"""Get suggestion queries for a specific user with language preference."""
|
|
264
|
+
return handlers.suggestion_handler.handle_get_suggestion_queries(
|
|
265
|
+
user_id=suggestion_req.mem_cube_id,
|
|
266
|
+
language=suggestion_req.language,
|
|
267
|
+
message=suggestion_req.message,
|
|
268
|
+
llm=llm,
|
|
269
|
+
naive_mem_cube=naive_mem_cube,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
# =============================================================================
|
|
274
|
+
# Memory Retrieval Delete API Endpoints
|
|
275
|
+
# =============================================================================
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
@router.post("/get_all", summary="Get all memories for user", response_model=MemoryResponse)
|
|
279
|
+
def get_all_memories(memory_req: GetMemoryPlaygroundRequest):
|
|
280
|
+
"""
|
|
281
|
+
Get all memories or subgraph for a specific user.
|
|
282
|
+
|
|
283
|
+
If search_query is provided, returns a subgraph based on the query.
|
|
284
|
+
Otherwise, returns all memories of the specified type.
|
|
285
|
+
"""
|
|
286
|
+
if memory_req.search_query:
|
|
287
|
+
return handlers.memory_handler.handle_get_subgraph(
|
|
288
|
+
user_id=memory_req.user_id,
|
|
289
|
+
mem_cube_id=(
|
|
290
|
+
memory_req.mem_cube_ids[0] if memory_req.mem_cube_ids else memory_req.user_id
|
|
291
|
+
),
|
|
292
|
+
query=memory_req.search_query,
|
|
293
|
+
top_k=20,
|
|
294
|
+
naive_mem_cube=naive_mem_cube,
|
|
295
|
+
)
|
|
296
|
+
else:
|
|
297
|
+
return handlers.memory_handler.handle_get_all_memories(
|
|
298
|
+
user_id=memory_req.user_id,
|
|
299
|
+
mem_cube_id=(
|
|
300
|
+
memory_req.mem_cube_ids[0] if memory_req.mem_cube_ids else memory_req.user_id
|
|
301
|
+
),
|
|
302
|
+
memory_type=memory_req.memory_type or "text_mem",
|
|
303
|
+
naive_mem_cube=naive_mem_cube,
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
@router.post("/get_memory", summary="Get memories for user", response_model=GetMemoryResponse)
|
|
308
|
+
def get_memories(memory_req: GetMemoryRequest):
|
|
309
|
+
return handlers.memory_handler.handle_get_memories(
|
|
310
|
+
get_mem_req=memory_req,
|
|
311
|
+
naive_mem_cube=naive_mem_cube,
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
@router.get("/get_memory/{memory_id}", summary="Get memory by id", response_model=GetMemoryResponse)
|
|
316
|
+
def get_memory_by_id(memory_id: str):
|
|
317
|
+
return handlers.memory_handler.handle_get_memory(
|
|
318
|
+
memory_id=memory_id,
|
|
319
|
+
naive_mem_cube=naive_mem_cube,
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
@router.post(
|
|
324
|
+
"/delete_memory", summary="Delete memories for user", response_model=DeleteMemoryResponse
|
|
325
|
+
)
|
|
326
|
+
def delete_memories(memory_req: DeleteMemoryRequest):
|
|
327
|
+
return handlers.memory_handler.handle_delete_memories(
|
|
328
|
+
delete_mem_req=memory_req, naive_mem_cube=naive_mem_cube
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
# =============================================================================
|
|
333
|
+
# Feedback API Endpoints
|
|
334
|
+
# =============================================================================
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
@router.post("/feedback", summary="Feedback memories", response_model=MemoryResponse)
|
|
338
|
+
def feedback_memories(feedback_req: APIFeedbackRequest):
|
|
339
|
+
"""
|
|
340
|
+
Feedback memories for a specific user.
|
|
341
|
+
|
|
342
|
+
This endpoint uses the class-based FeedbackHandler for better code organization.
|
|
343
|
+
"""
|
|
344
|
+
return feedback_handler.handle_feedback_memories(feedback_req)
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
# =============================================================================
|
|
348
|
+
# Other API Endpoints (for internal use)
|
|
349
|
+
# =============================================================================
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
@router.post(
|
|
353
|
+
"/get_user_names_by_memory_ids",
|
|
354
|
+
summary="Get user names by memory ids",
|
|
355
|
+
response_model=GetUserNamesByMemoryIdsResponse,
|
|
356
|
+
)
|
|
357
|
+
def get_user_names_by_memory_ids(request: GetUserNamesByMemoryIdsRequest):
|
|
358
|
+
"""Get user names by memory ids."""
|
|
359
|
+
if not isinstance(graph_db, PolarDBGraphDB):
|
|
360
|
+
raise HTTPException(
|
|
361
|
+
status_code=400,
|
|
362
|
+
detail=(
|
|
363
|
+
"graph_db must be an instance of PolarDBGraphDB to use "
|
|
364
|
+
"get_user_names_by_memory_ids"
|
|
365
|
+
f"current graph_db is: {graph_db.__class__.__name__}"
|
|
366
|
+
),
|
|
367
|
+
)
|
|
368
|
+
result = graph_db.get_user_names_by_memory_ids(memory_ids=request.memory_ids)
|
|
369
|
+
if vector_db:
|
|
370
|
+
prefs = []
|
|
371
|
+
for collection_name in ["explicit_preference", "implicit_preference"]:
|
|
372
|
+
prefs.extend(
|
|
373
|
+
vector_db.get_by_ids(collection_name=collection_name, ids=request.memory_ids)
|
|
374
|
+
)
|
|
375
|
+
result.update({pref.id: pref.payload.get("mem_cube_id", None) for pref in prefs})
|
|
376
|
+
return GetUserNamesByMemoryIdsResponse(
|
|
377
|
+
code=200,
|
|
378
|
+
message="Successfully",
|
|
379
|
+
data=result,
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
@router.post(
|
|
384
|
+
"/exist_mem_cube_id",
|
|
385
|
+
summary="Check if mem cube id exists",
|
|
386
|
+
response_model=ExistMemCubeIdResponse,
|
|
387
|
+
)
|
|
388
|
+
def exist_mem_cube_id(request: ExistMemCubeIdRequest):
|
|
389
|
+
"""Check if mem cube id exists."""
|
|
390
|
+
return ExistMemCubeIdResponse(
|
|
391
|
+
code=200,
|
|
392
|
+
message="Successfully",
|
|
393
|
+
data=graph_db.exist_user_name(user_name=request.mem_cube_id),
|
|
394
|
+
)
|
memos/api/server_api.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from fastapi import FastAPI, HTTPException
|
|
4
|
+
from fastapi.exceptions import RequestValidationError
|
|
5
|
+
|
|
6
|
+
from memos.api.exceptions import APIExceptionHandler
|
|
7
|
+
from memos.api.middleware.request_context import RequestContextMiddleware
|
|
8
|
+
from memos.api.routers.server_router import router as server_router
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# Configure logging
|
|
12
|
+
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
app = FastAPI(
|
|
16
|
+
title="MemOS Server REST APIs",
|
|
17
|
+
description="A REST API for managing multiple users with MemOS Server.",
|
|
18
|
+
version="1.0.1",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
app.add_middleware(RequestContextMiddleware, source="server_api")
|
|
22
|
+
# Include routers
|
|
23
|
+
app.include_router(server_router)
|
|
24
|
+
|
|
25
|
+
# Request validation failed
|
|
26
|
+
app.exception_handler(RequestValidationError)(APIExceptionHandler.validation_error_handler)
|
|
27
|
+
# Invalid business code parameters
|
|
28
|
+
app.exception_handler(ValueError)(APIExceptionHandler.value_error_handler)
|
|
29
|
+
# Business layer manual exception
|
|
30
|
+
app.exception_handler(HTTPException)(APIExceptionHandler.http_error_handler)
|
|
31
|
+
# Fallback for unknown errors
|
|
32
|
+
app.exception_handler(Exception)(APIExceptionHandler.global_exception_handler)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if __name__ == "__main__":
|
|
36
|
+
import argparse
|
|
37
|
+
|
|
38
|
+
import uvicorn
|
|
39
|
+
|
|
40
|
+
parser = argparse.ArgumentParser()
|
|
41
|
+
parser.add_argument("--port", type=int, default=8001)
|
|
42
|
+
parser.add_argument("--workers", type=int, default=1)
|
|
43
|
+
args = parser.parse_args()
|
|
44
|
+
uvicorn.run("memos.api.server_api:app", host="0.0.0.0", port=args.port, workers=args.workers)
|