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,1206 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
|
|
3
|
+
from typing import Any, Generic, Literal, TypeVar
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field, model_validator
|
|
6
|
+
|
|
7
|
+
# Import message types from core types module
|
|
8
|
+
from memos.log import get_logger
|
|
9
|
+
from memos.types import MessageList, MessagesType, PermissionDict, SearchMode
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
logger = get_logger(__name__)
|
|
13
|
+
T = TypeVar("T")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BaseRequest(BaseModel):
|
|
17
|
+
"""Base model for all requests."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class BaseResponse(BaseModel, Generic[T]):
|
|
21
|
+
"""Base model for all responses."""
|
|
22
|
+
|
|
23
|
+
code: int = Field(200, description="Response status code")
|
|
24
|
+
message: str = Field(..., description="Response message")
|
|
25
|
+
data: T | None = Field(None, description="Response data")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# Product API Models
|
|
29
|
+
class UserRegisterRequest(BaseRequest):
|
|
30
|
+
"""Request model for user registration."""
|
|
31
|
+
|
|
32
|
+
user_id: str = Field(
|
|
33
|
+
default_factory=lambda: str(uuid.uuid4()), description="User ID for registration"
|
|
34
|
+
)
|
|
35
|
+
mem_cube_id: str | None = Field(None, description="Cube ID for registration")
|
|
36
|
+
user_name: str | None = Field(None, description="User name for registration")
|
|
37
|
+
interests: str | None = Field(None, description="User interests")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class GetMemoryPlaygroundRequest(BaseRequest):
|
|
41
|
+
"""Request model for getting memories."""
|
|
42
|
+
|
|
43
|
+
user_id: str = Field(..., description="User ID")
|
|
44
|
+
memory_type: Literal["text_mem", "act_mem", "param_mem", "para_mem"] = Field(
|
|
45
|
+
..., description="Memory type"
|
|
46
|
+
)
|
|
47
|
+
mem_cube_ids: list[str] | None = Field(None, description="Cube IDs")
|
|
48
|
+
search_query: str | None = Field(None, description="Search query")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# Start API Models
|
|
52
|
+
class Message(BaseModel):
|
|
53
|
+
role: str = Field(..., description="Role of the message (user or assistant).")
|
|
54
|
+
content: str = Field(..., description="Message content.")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class MemoryCreate(BaseRequest):
|
|
58
|
+
user_id: str = Field(..., description="User ID")
|
|
59
|
+
messages: MessageList | None = Field(None, description="List of messages to store.")
|
|
60
|
+
memory_content: str | None = Field(None, description="Content to store as memory")
|
|
61
|
+
doc_path: str | None = Field(None, description="Path to document to store")
|
|
62
|
+
mem_cube_id: str | None = Field(None, description="ID of the memory cube")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class MemCubeRegister(BaseRequest):
|
|
66
|
+
mem_cube_name_or_path: str = Field(..., description="Name or path of the MemCube to register.")
|
|
67
|
+
mem_cube_id: str | None = Field(None, description="ID for the MemCube")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class ChatRequest(BaseRequest):
|
|
71
|
+
"""Request model for chat operations.
|
|
72
|
+
|
|
73
|
+
This model is used as the algorithm-facing chat interface, while also
|
|
74
|
+
remaining backward compatible with older developer-facing APIs.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
# ==== Basic identifiers ====
|
|
78
|
+
user_id: str = Field(..., description="User ID")
|
|
79
|
+
query: str = Field(..., description="Chat query message")
|
|
80
|
+
readable_cube_ids: list[str] | None = Field(
|
|
81
|
+
None, description="List of cube IDs user can read for multi-cube chat"
|
|
82
|
+
)
|
|
83
|
+
writable_cube_ids: list[str] | None = Field(
|
|
84
|
+
None, description="List of cube IDs user can write for multi-cube chat"
|
|
85
|
+
)
|
|
86
|
+
history: MessageList | None = Field(None, description="Chat history")
|
|
87
|
+
mode: SearchMode = Field(SearchMode.FAST, description="search mode: fast, fine, or mixture")
|
|
88
|
+
system_prompt: str | None = Field(None, description="Base system prompt to use for chat")
|
|
89
|
+
top_k: int = Field(10, description="Number of results to return")
|
|
90
|
+
session_id: str | None = Field(None, description="Session ID for soft-filtering memories")
|
|
91
|
+
include_preference: bool = Field(True, description="Whether to handle preference memory")
|
|
92
|
+
pref_top_k: int = Field(6, description="Number of preference results to return")
|
|
93
|
+
model_name_or_path: str | None = Field(None, description="Model name to use for chat")
|
|
94
|
+
max_tokens: int | None = Field(None, description="Max tokens to generate")
|
|
95
|
+
temperature: float | None = Field(None, description="Temperature for sampling")
|
|
96
|
+
top_p: float | None = Field(None, description="Top-p (nucleus) sampling parameter")
|
|
97
|
+
add_message_on_answer: bool = Field(True, description="Add dialogs to memory after chat")
|
|
98
|
+
|
|
99
|
+
# ==== Filter conditions ====
|
|
100
|
+
filter: dict[str, Any] | None = Field(
|
|
101
|
+
None,
|
|
102
|
+
description="""
|
|
103
|
+
Filter for the memory, example:
|
|
104
|
+
{
|
|
105
|
+
"`and` or `or`": [
|
|
106
|
+
{"id": "uuid-xxx"},
|
|
107
|
+
{"created_at": {"gt": "2024-01-01"}},
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
""",
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# ==== Extended capabilities ====
|
|
114
|
+
internet_search: bool = Field(False, description="Whether to use internet search")
|
|
115
|
+
threshold: float = Field(0.5, description="Threshold for filtering references")
|
|
116
|
+
|
|
117
|
+
# ==== Backward compatibility ====
|
|
118
|
+
moscube: bool = Field(
|
|
119
|
+
False,
|
|
120
|
+
description="(Deprecated) Whether to use legacy MemOSCube pipeline.",
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
mem_cube_id: str | None = Field(
|
|
124
|
+
None,
|
|
125
|
+
description=(
|
|
126
|
+
"(Deprecated) Single cube ID to use for chat. "
|
|
127
|
+
"Prefer `readable_cube_ids` / `writable_cube_ids` for multi-cube chat."
|
|
128
|
+
),
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
@model_validator(mode="after")
|
|
132
|
+
def _convert_deprecated_fields(self):
|
|
133
|
+
"""
|
|
134
|
+
Normalize fields for algorithm interface while preserving backward compatibility.
|
|
135
|
+
|
|
136
|
+
Rules:
|
|
137
|
+
- mem_cube_id → readable_cube_ids / writable_cube_ids if they are missing
|
|
138
|
+
- moscube: log warning when True (deprecated)
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
# ---- mem_cube_id backward compatibility ----
|
|
142
|
+
if self.mem_cube_id is not None:
|
|
143
|
+
logger.warning(
|
|
144
|
+
"ChatRequest.mem_cube_id is deprecated and will be removed in a future version. "
|
|
145
|
+
"Please migrate to `readable_cube_ids` / `writable_cube_ids`."
|
|
146
|
+
)
|
|
147
|
+
if not self.readable_cube_ids:
|
|
148
|
+
self.readable_cube_ids = [self.mem_cube_id]
|
|
149
|
+
if not self.writable_cube_ids:
|
|
150
|
+
self.writable_cube_ids = [self.mem_cube_id]
|
|
151
|
+
|
|
152
|
+
# ---- Deprecated moscube flag ----
|
|
153
|
+
if self.moscube:
|
|
154
|
+
logger.warning(
|
|
155
|
+
"ChatRequest.moscube is deprecated. Legacy MemOSCube pipeline "
|
|
156
|
+
"will be removed in a future version."
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
return self
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class ChatPlaygroundRequest(ChatRequest):
|
|
163
|
+
"""Request model for chat operations in playground."""
|
|
164
|
+
|
|
165
|
+
beginner_guide_step: str | None = Field(
|
|
166
|
+
None, description="Whether to use beginner guide, option: [first, second]"
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class ChatCompleteRequest(BaseRequest):
|
|
171
|
+
"""Request model for chat operations. will (Deprecated), instead use APIChatCompleteRequest."""
|
|
172
|
+
|
|
173
|
+
user_id: str = Field(..., description="User ID")
|
|
174
|
+
query: str = Field(..., description="Chat query message")
|
|
175
|
+
mem_cube_id: str | None = Field(None, description="Cube ID to use for chat")
|
|
176
|
+
history: MessageList | None = Field(None, description="Chat history")
|
|
177
|
+
internet_search: bool = Field(False, description="Whether to use internet search")
|
|
178
|
+
system_prompt: str | None = Field(None, description="Base prompt to use for chat")
|
|
179
|
+
top_k: int = Field(10, description="Number of results to return")
|
|
180
|
+
threshold: float = Field(0.5, description="Threshold for filtering references")
|
|
181
|
+
session_id: str | None = Field(None, description="Session ID for soft-filtering memories")
|
|
182
|
+
include_preference: bool = Field(True, description="Whether to handle preference memory")
|
|
183
|
+
pref_top_k: int = Field(6, description="Number of preference results to return")
|
|
184
|
+
filter: dict[str, Any] | None = Field(None, description="Filter for the memory")
|
|
185
|
+
model_name_or_path: str | None = Field(None, description="Model name to use for chat")
|
|
186
|
+
max_tokens: int | None = Field(None, description="Max tokens to generate")
|
|
187
|
+
temperature: float | None = Field(None, description="Temperature for sampling")
|
|
188
|
+
top_p: float | None = Field(None, description="Top-p (nucleus) sampling parameter")
|
|
189
|
+
add_message_on_answer: bool = Field(True, description="Add dialogs to memory after chat")
|
|
190
|
+
|
|
191
|
+
base_prompt: str | None = Field(None, description="(Deprecated) Base prompt alias")
|
|
192
|
+
moscube: bool = Field(
|
|
193
|
+
False, description="(Deprecated) Whether to use legacy MemOSCube pipeline"
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class UserCreate(BaseRequest):
|
|
198
|
+
user_name: str | None = Field(None, description="Name of the user")
|
|
199
|
+
role: str = Field("USER", description="Role of the user")
|
|
200
|
+
user_id: str = Field(..., description="User ID")
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
class CubeShare(BaseRequest):
|
|
204
|
+
target_user_id: str = Field(..., description="Target user ID to share with")
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
# Response Models
|
|
208
|
+
class SimpleResponse(BaseResponse[None]):
|
|
209
|
+
"""Simple response model for operations without data return."""
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class UserRegisterResponse(BaseResponse[dict]):
|
|
213
|
+
"""Response model for user registration."""
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class MemoryResponse(BaseResponse[list]):
|
|
217
|
+
"""Response model for memory operations."""
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class SuggestionResponse(BaseResponse[list]):
|
|
221
|
+
"""Response model for suggestion operations."""
|
|
222
|
+
|
|
223
|
+
data: dict[str, list[str]] | None = Field(None, description="Response data")
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class AddStatusResponse(BaseResponse[dict]):
|
|
227
|
+
"""Response model for add status operations."""
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class ConfigResponse(BaseResponse[None]):
|
|
231
|
+
"""Response model for configuration endpoint."""
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class SearchResponse(BaseResponse[dict]):
|
|
235
|
+
"""Response model for search operations."""
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
class ChatResponse(BaseResponse[str]):
|
|
239
|
+
"""Response model for chat operations."""
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
class GetMemoryResponse(BaseResponse[dict]):
|
|
243
|
+
"""Response model for getting memories."""
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
class DeleteMemoryResponse(BaseResponse[dict]):
|
|
247
|
+
"""Response model for deleting memories."""
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
class UserResponse(BaseResponse[dict]):
|
|
251
|
+
"""Response model for user operations."""
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class UserListResponse(BaseResponse[list]):
|
|
255
|
+
"""Response model for user list operations."""
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
class MemoryCreateRequest(BaseRequest):
|
|
259
|
+
"""Request model for creating memories."""
|
|
260
|
+
|
|
261
|
+
user_id: str = Field(..., description="User ID")
|
|
262
|
+
messages: str | MessagesType | None = Field(None, description="List of messages to store.")
|
|
263
|
+
memory_content: str | None = Field(None, description="Memory content to store")
|
|
264
|
+
doc_path: str | None = Field(None, description="Path to document to store")
|
|
265
|
+
mem_cube_id: str | None = Field(None, description="Cube ID")
|
|
266
|
+
source: str | None = Field(None, description="Source of the memory")
|
|
267
|
+
user_profile: bool = Field(False, description="User profile memory")
|
|
268
|
+
session_id: str | None = Field(None, description="Session id")
|
|
269
|
+
task_id: str | None = Field(None, description="Task ID for monitoring async tasks")
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
class SearchRequest(BaseRequest):
|
|
273
|
+
"""Request model for searching memories."""
|
|
274
|
+
|
|
275
|
+
user_id: str = Field(..., description="User ID")
|
|
276
|
+
query: str = Field(..., description="Search query")
|
|
277
|
+
mem_cube_id: str | None = Field(None, description="Cube ID to search in")
|
|
278
|
+
top_k: int = Field(10, description="Number of results to return")
|
|
279
|
+
session_id: str | None = Field(None, description="Session ID for soft-filtering memories")
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
class APISearchRequest(BaseRequest):
|
|
283
|
+
"""Request model for searching memories."""
|
|
284
|
+
|
|
285
|
+
# ==== Basic inputs ====
|
|
286
|
+
query: str = Field(
|
|
287
|
+
...,
|
|
288
|
+
description="User search query",
|
|
289
|
+
)
|
|
290
|
+
user_id: str = Field(..., description="User ID")
|
|
291
|
+
|
|
292
|
+
# ==== Cube scoping ====
|
|
293
|
+
readable_cube_ids: list[str] | None = Field(
|
|
294
|
+
None,
|
|
295
|
+
description=(
|
|
296
|
+
"List of cube IDs that are readable for this request. "
|
|
297
|
+
"Required for algorithm-facing API; optional for developer-facing API."
|
|
298
|
+
),
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
# ==== Search mode ====
|
|
302
|
+
mode: SearchMode = Field(
|
|
303
|
+
SearchMode.FAST,
|
|
304
|
+
description="Search mode: fast, fine, or mixture.",
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
session_id: str | None = Field(
|
|
308
|
+
None,
|
|
309
|
+
description=(
|
|
310
|
+
"Session ID used as a soft signal to prioritize more relevant memories. "
|
|
311
|
+
"Only used for weighting, not as a hard filter."
|
|
312
|
+
),
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
# ==== Result control ====
|
|
316
|
+
top_k: int = Field(
|
|
317
|
+
10,
|
|
318
|
+
ge=1,
|
|
319
|
+
description="Number of textual memories to retrieve (top-K). Default: 10.",
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
dedup: Literal["no", "sim"] | None = Field(
|
|
323
|
+
None,
|
|
324
|
+
description=(
|
|
325
|
+
"Optional dedup option for textual memories. "
|
|
326
|
+
"Use 'no' for no dedup, 'sim' for similarity dedup. "
|
|
327
|
+
"If None, default exact-text dedup is applied."
|
|
328
|
+
),
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
pref_top_k: int = Field(
|
|
332
|
+
6,
|
|
333
|
+
ge=0,
|
|
334
|
+
description="Number of preference memories to retrieve (top-K). Default: 6.",
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
include_preference: bool = Field(
|
|
338
|
+
True,
|
|
339
|
+
description=(
|
|
340
|
+
"Whether to retrieve preference memories along with general memories. "
|
|
341
|
+
"If enabled, the system will automatically recall user preferences "
|
|
342
|
+
"relevant to the query. Default: True."
|
|
343
|
+
),
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
search_tool_memory: bool = Field(
|
|
347
|
+
True,
|
|
348
|
+
description=(
|
|
349
|
+
"Whether to retrieve tool memories along with general memories. "
|
|
350
|
+
"If enabled, the system will automatically recall tool memories "
|
|
351
|
+
"relevant to the query. Default: True."
|
|
352
|
+
),
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
tool_mem_top_k: int = Field(
|
|
356
|
+
6,
|
|
357
|
+
ge=0,
|
|
358
|
+
description="Number of tool memories to retrieve (top-K). Default: 6.",
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
# ==== Filter conditions ====
|
|
362
|
+
# TODO: maybe add detailed description later
|
|
363
|
+
filter: dict[str, Any] | None = Field(
|
|
364
|
+
None,
|
|
365
|
+
description="""
|
|
366
|
+
Filter for the memory, example:
|
|
367
|
+
{
|
|
368
|
+
"`and` or `or`": [
|
|
369
|
+
{"id": "uuid-xxx"},
|
|
370
|
+
{"created_at": {"gt": "2024-01-01"}},
|
|
371
|
+
]
|
|
372
|
+
}
|
|
373
|
+
""",
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
# ==== Extended capabilities ====
|
|
377
|
+
internet_search: bool = Field(
|
|
378
|
+
False,
|
|
379
|
+
description=(
|
|
380
|
+
"Whether to enable internet search in addition to memory search. "
|
|
381
|
+
"Primarily used by internal algorithms. Default: False."
|
|
382
|
+
),
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
# Inner user, not supported in API yet
|
|
386
|
+
threshold: float | None = Field(
|
|
387
|
+
None,
|
|
388
|
+
description=(
|
|
389
|
+
"Internal similarity threshold for searching plaintext memories. "
|
|
390
|
+
"If None, default thresholds will be applied."
|
|
391
|
+
),
|
|
392
|
+
)
|
|
393
|
+
# Internal field for search memory type
|
|
394
|
+
search_memory_type: str = Field(
|
|
395
|
+
"All",
|
|
396
|
+
description="Type of memory to search: All, WorkingMemory, LongTermMemory, UserMemory, OuterMemory, ToolSchemaMemory, ToolTrajectoryMemory",
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
# ==== Context ====
|
|
400
|
+
chat_history: MessageList | None = Field(
|
|
401
|
+
None,
|
|
402
|
+
description=(
|
|
403
|
+
"Historical chat messages used internally by algorithms. "
|
|
404
|
+
"If None, internal stored history may be used; "
|
|
405
|
+
"if provided (even an empty list), this value will be used as-is."
|
|
406
|
+
),
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
# ==== Backward compatibility ====
|
|
410
|
+
mem_cube_id: str | None = Field(
|
|
411
|
+
None,
|
|
412
|
+
description=(
|
|
413
|
+
"(Deprecated) Single cube ID to search in. "
|
|
414
|
+
"Prefer `readable_cube_ids` for multi-cube search."
|
|
415
|
+
),
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
moscube: bool = Field(
|
|
419
|
+
False,
|
|
420
|
+
description="(Deprecated / internal) Whether to use legacy MemOSCube path.",
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
operation: list[PermissionDict] | None = Field(
|
|
424
|
+
None,
|
|
425
|
+
description="(Internal) Operation definitions for multi-cube read permissions.",
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
# ==== Source for plugin ====
|
|
429
|
+
source: str | None = Field(
|
|
430
|
+
None,
|
|
431
|
+
description="Source of the search query [plugin will router diff search]",
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
@model_validator(mode="after")
|
|
435
|
+
def _convert_deprecated_fields(self) -> "APISearchRequest":
|
|
436
|
+
"""
|
|
437
|
+
Convert deprecated fields to new fields for backward compatibility.
|
|
438
|
+
Ensures full backward compatibility:
|
|
439
|
+
- mem_cube_id → readable_cube_ids
|
|
440
|
+
- moscube is ignored with warning
|
|
441
|
+
- operation ignored
|
|
442
|
+
"""
|
|
443
|
+
# Convert mem_cube_id to readable_cube_ids (new field takes priority)
|
|
444
|
+
if self.mem_cube_id is not None:
|
|
445
|
+
if not self.readable_cube_ids:
|
|
446
|
+
self.readable_cube_ids = [self.mem_cube_id]
|
|
447
|
+
logger.warning(
|
|
448
|
+
"Deprecated field `mem_cube_id` is used in APISearchRequest. "
|
|
449
|
+
"It will be removed in a future version. "
|
|
450
|
+
"Please migrate to `readable_cube_ids`."
|
|
451
|
+
)
|
|
452
|
+
|
|
453
|
+
# Reject moscube if set to True (no longer supported)
|
|
454
|
+
if self.moscube:
|
|
455
|
+
logger.warning(
|
|
456
|
+
"Deprecated field `moscube` is used in APISearchRequest. "
|
|
457
|
+
"Legacy MemOSCube pipeline will be removed soon."
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
# Warn about operation (internal)
|
|
461
|
+
if self.operation:
|
|
462
|
+
logger.warning(
|
|
463
|
+
"Internal field `operation` is provided in APISearchRequest. "
|
|
464
|
+
"This field is deprecated and ignored."
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
return self
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
class APIADDRequest(BaseRequest):
|
|
471
|
+
"""Request model for creating memories."""
|
|
472
|
+
|
|
473
|
+
# ==== Basic identifiers ====
|
|
474
|
+
user_id: str = Field(None, description="User ID")
|
|
475
|
+
session_id: str | None = Field(
|
|
476
|
+
None,
|
|
477
|
+
description="Session ID. If not provided, a default session will be used.",
|
|
478
|
+
)
|
|
479
|
+
task_id: str | None = Field(None, description="Task ID for monitering async tasks")
|
|
480
|
+
|
|
481
|
+
# ==== Multi-cube writing ====
|
|
482
|
+
writable_cube_ids: list[str] | None = Field(
|
|
483
|
+
None, description="List of cube IDs user can write for multi-cube add"
|
|
484
|
+
)
|
|
485
|
+
|
|
486
|
+
# ==== Async control ====
|
|
487
|
+
async_mode: Literal["async", "sync"] = Field(
|
|
488
|
+
"async",
|
|
489
|
+
description=(
|
|
490
|
+
"Whether to add memory in async mode. "
|
|
491
|
+
"Use 'async' to enqueue background add (non-blocking), "
|
|
492
|
+
"or 'sync' to add memories in the current call. "
|
|
493
|
+
"Default: 'async'."
|
|
494
|
+
),
|
|
495
|
+
)
|
|
496
|
+
|
|
497
|
+
mode: Literal["fast", "fine"] | None = Field(
|
|
498
|
+
None,
|
|
499
|
+
description=(
|
|
500
|
+
"(Internal) Add mode used only when async_mode='sync'. "
|
|
501
|
+
"If set to 'fast', the handler will use a fast add pipeline. "
|
|
502
|
+
"Ignored when async_mode='async'."
|
|
503
|
+
),
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
# ==== Business tags & info ====
|
|
507
|
+
custom_tags: list[str] | None = Field(
|
|
508
|
+
None,
|
|
509
|
+
description=(
|
|
510
|
+
"Custom tags for this add request, e.g. ['Travel', 'family']. "
|
|
511
|
+
"These tags can be used as filters in search."
|
|
512
|
+
),
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
info: dict[str, Any] | None = Field(
|
|
516
|
+
None,
|
|
517
|
+
description=(
|
|
518
|
+
"Additional metadata for the add request. "
|
|
519
|
+
"All keys can be used as filters in search. "
|
|
520
|
+
"Example: "
|
|
521
|
+
"{'agent_id': 'xxxxxx', "
|
|
522
|
+
"'app_id': 'xxxx', "
|
|
523
|
+
"'source_type': 'web', "
|
|
524
|
+
"'source_url': 'https://www.baidu.com', "
|
|
525
|
+
"'source_content': '西湖是杭州最著名的景点'}."
|
|
526
|
+
),
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
# ==== Input content ====
|
|
530
|
+
messages: MessagesType | None = Field(
|
|
531
|
+
None,
|
|
532
|
+
description=(
|
|
533
|
+
"List of messages to store. Supports: "
|
|
534
|
+
"- system / user / assistant messages with 'content' and 'chat_time'; "
|
|
535
|
+
"- tool messages including: "
|
|
536
|
+
" * tool_description (name, description, parameters), "
|
|
537
|
+
" * tool_input (call_id, name, argument), "
|
|
538
|
+
" * raw tool messages where content is str or list[str], "
|
|
539
|
+
" * tool_output with structured output items "
|
|
540
|
+
" (input_text / input_image / input_file, etc.). "
|
|
541
|
+
"Also supports pure input items when there is no dialog."
|
|
542
|
+
),
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
# ==== Chat history ====
|
|
546
|
+
chat_history: MessageList | None = Field(
|
|
547
|
+
None,
|
|
548
|
+
description=(
|
|
549
|
+
"Historical chat messages used internally by algorithms. "
|
|
550
|
+
"If None, internal stored history will be used; "
|
|
551
|
+
"if provided (even an empty list), this value will be used as-is."
|
|
552
|
+
),
|
|
553
|
+
)
|
|
554
|
+
|
|
555
|
+
# ==== Feedback flag ====
|
|
556
|
+
is_feedback: bool = Field(
|
|
557
|
+
False,
|
|
558
|
+
description=("Whether this request represents user feedback. Default: False."),
|
|
559
|
+
)
|
|
560
|
+
|
|
561
|
+
# ==== Backward compatibility fields (will delete later) ====
|
|
562
|
+
mem_cube_id: str | None = Field(
|
|
563
|
+
None,
|
|
564
|
+
description="(Deprecated) Target cube ID for this add request (optional for developer API).",
|
|
565
|
+
)
|
|
566
|
+
|
|
567
|
+
memory_content: str | None = Field(
|
|
568
|
+
None,
|
|
569
|
+
description="(Deprecated) Plain memory content to store. Prefer using `messages`.",
|
|
570
|
+
)
|
|
571
|
+
doc_path: str | None = Field(
|
|
572
|
+
None,
|
|
573
|
+
description="(Deprecated / internal) Path to document to store.",
|
|
574
|
+
)
|
|
575
|
+
source: str | None = Field(
|
|
576
|
+
None,
|
|
577
|
+
description=(
|
|
578
|
+
"(Deprecated) Simple source tag of the memory. "
|
|
579
|
+
"Prefer using `info.source_type` / `info.source_url`."
|
|
580
|
+
),
|
|
581
|
+
)
|
|
582
|
+
operation: list[PermissionDict] | None = Field(
|
|
583
|
+
None,
|
|
584
|
+
description="(Internal) Operation definitions for multi-cube write permissions.",
|
|
585
|
+
)
|
|
586
|
+
|
|
587
|
+
@model_validator(mode="after")
|
|
588
|
+
def _convert_deprecated_fields(self) -> "APIADDRequest":
|
|
589
|
+
"""
|
|
590
|
+
Convert deprecated fields to new fields for backward compatibility.
|
|
591
|
+
This keeps the API fully backward-compatible while allowing
|
|
592
|
+
internal logic to use only the new fields.
|
|
593
|
+
|
|
594
|
+
Rules:
|
|
595
|
+
- mem_cube_id → writable_cube_ids
|
|
596
|
+
- memory_content → messages
|
|
597
|
+
- doc_path → messages (input_file)
|
|
598
|
+
- source → info["source"]
|
|
599
|
+
- operation → merged into writable_cube_ids (ignored otherwise)
|
|
600
|
+
"""
|
|
601
|
+
# ---- async_mode / mode relationship ----
|
|
602
|
+
if self.async_mode == "async" and self.mode is not None:
|
|
603
|
+
logger.warning(
|
|
604
|
+
"APIADDRequest.mode is ignored when async_mode='async'. "
|
|
605
|
+
"Fast add pipeline is only available in sync mode."
|
|
606
|
+
)
|
|
607
|
+
self.mode = None
|
|
608
|
+
|
|
609
|
+
# Convert mem_cube_id to writable_cube_ids (new field takes priority)
|
|
610
|
+
if self.mem_cube_id:
|
|
611
|
+
logger.warning(
|
|
612
|
+
"APIADDRequest.mem_cube_id is deprecated and will be removed in a future version. "
|
|
613
|
+
"Please use `writable_cube_ids` instead."
|
|
614
|
+
)
|
|
615
|
+
if not self.writable_cube_ids:
|
|
616
|
+
self.writable_cube_ids = [self.mem_cube_id]
|
|
617
|
+
|
|
618
|
+
# Handle deprecated operation field
|
|
619
|
+
if self.operation:
|
|
620
|
+
logger.warning(
|
|
621
|
+
"APIADDRequest.operation is deprecated and will be removed. "
|
|
622
|
+
"Use `writable_cube_ids` for multi-cube writes."
|
|
623
|
+
)
|
|
624
|
+
|
|
625
|
+
# Convert memory_content to messages (new field takes priority)
|
|
626
|
+
if self.memory_content:
|
|
627
|
+
logger.warning(
|
|
628
|
+
"APIADDRequest.memory_content is deprecated. "
|
|
629
|
+
"Use `messages` with a structured message instead."
|
|
630
|
+
)
|
|
631
|
+
if self.messages is None:
|
|
632
|
+
self.messages = []
|
|
633
|
+
self.messages.append(
|
|
634
|
+
{
|
|
635
|
+
"type": "text",
|
|
636
|
+
"text": self.memory_content,
|
|
637
|
+
}
|
|
638
|
+
)
|
|
639
|
+
|
|
640
|
+
# Handle deprecated doc_path
|
|
641
|
+
if self.doc_path:
|
|
642
|
+
logger.warning(
|
|
643
|
+
"APIADDRequest.doc_path is deprecated. "
|
|
644
|
+
"Use `messages` with an input_file item instead."
|
|
645
|
+
)
|
|
646
|
+
if self.messages is None:
|
|
647
|
+
self.messages = []
|
|
648
|
+
self.messages.append(
|
|
649
|
+
{
|
|
650
|
+
"type": "file",
|
|
651
|
+
"file": {"path": self.doc_path},
|
|
652
|
+
}
|
|
653
|
+
)
|
|
654
|
+
|
|
655
|
+
# Convert source to info.source_type (new field takes priority)
|
|
656
|
+
if self.source:
|
|
657
|
+
logger.warning(
|
|
658
|
+
"APIADDRequest.source is deprecated. "
|
|
659
|
+
"Use `info['source_type']` / `info['source_url']` instead."
|
|
660
|
+
)
|
|
661
|
+
if self.info is None:
|
|
662
|
+
self.info = {}
|
|
663
|
+
self.info.setdefault("source", self.source)
|
|
664
|
+
|
|
665
|
+
return self
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
class APIFeedbackRequest(BaseRequest):
|
|
669
|
+
"""Request model for processing feedback info."""
|
|
670
|
+
|
|
671
|
+
user_id: str = Field(..., description="User ID")
|
|
672
|
+
session_id: str | None = Field(
|
|
673
|
+
"default_session", description="Session ID for soft-filtering memories"
|
|
674
|
+
)
|
|
675
|
+
task_id: str | None = Field(None, description="Task ID for monitering async tasks")
|
|
676
|
+
history: MessageList | None = Field(..., description="Chat history")
|
|
677
|
+
retrieved_memory_ids: list[str] | None = Field(
|
|
678
|
+
None, description="Retrieved memory ids at last turn"
|
|
679
|
+
)
|
|
680
|
+
feedback_content: str | None = Field(..., description="Feedback content to process")
|
|
681
|
+
feedback_time: str | None = Field(None, description="Feedback time")
|
|
682
|
+
writable_cube_ids: list[str] | None = Field(
|
|
683
|
+
None, description="List of cube IDs user can write for multi-cube add"
|
|
684
|
+
)
|
|
685
|
+
async_mode: Literal["sync", "async"] = Field(
|
|
686
|
+
"async", description="feedback mode: sync or async"
|
|
687
|
+
)
|
|
688
|
+
corrected_answer: bool = Field(False, description="Whether need return corrected answer")
|
|
689
|
+
info: dict[str, Any] | None = Field(
|
|
690
|
+
None,
|
|
691
|
+
description=(
|
|
692
|
+
"Additional metadata for the add request. "
|
|
693
|
+
"All keys can be used as filters in search. "
|
|
694
|
+
"Example: "
|
|
695
|
+
"{'agent_id': 'xxxxxx', "
|
|
696
|
+
"'app_id': 'xxxx', "
|
|
697
|
+
"'source_type': 'web', "
|
|
698
|
+
"'source_url': 'https://www.baidu.com', "
|
|
699
|
+
"'source_content': 'West Lake is the most famous scenic spot in Hangzhou'}."
|
|
700
|
+
),
|
|
701
|
+
)
|
|
702
|
+
# ==== mem_cube_id is NOT enabled====
|
|
703
|
+
mem_cube_id: str | None = Field(
|
|
704
|
+
None,
|
|
705
|
+
description=(
|
|
706
|
+
"(Deprecated) Single cube ID to search in. "
|
|
707
|
+
"Prefer `readable_cube_ids` for multi-cube search."
|
|
708
|
+
),
|
|
709
|
+
)
|
|
710
|
+
|
|
711
|
+
|
|
712
|
+
class APIChatCompleteRequest(BaseRequest):
|
|
713
|
+
"""Request model for chat operations."""
|
|
714
|
+
|
|
715
|
+
user_id: str = Field(..., description="User ID")
|
|
716
|
+
query: str = Field(..., description="Chat query message")
|
|
717
|
+
readable_cube_ids: list[str] | None = Field(
|
|
718
|
+
None, description="List of cube IDs user can read for multi-cube chat"
|
|
719
|
+
)
|
|
720
|
+
writable_cube_ids: list[str] | None = Field(
|
|
721
|
+
None, description="List of cube IDs user can write for multi-cube chat"
|
|
722
|
+
)
|
|
723
|
+
history: MessageList | None = Field(None, description="Chat history")
|
|
724
|
+
mode: SearchMode = Field(SearchMode.FAST, description="search mode: fast, fine, or mixture")
|
|
725
|
+
system_prompt: str | None = Field(None, description="Base system prompt to use for chat")
|
|
726
|
+
top_k: int = Field(10, description="Number of results to return")
|
|
727
|
+
session_id: str | None = Field(None, description="Session ID for soft-filtering memories")
|
|
728
|
+
include_preference: bool = Field(True, description="Whether to handle preference memory")
|
|
729
|
+
pref_top_k: int = Field(6, description="Number of preference results to return")
|
|
730
|
+
model_name_or_path: str | None = Field(None, description="Model name to use for chat")
|
|
731
|
+
max_tokens: int | None = Field(None, description="Max tokens to generate")
|
|
732
|
+
temperature: float | None = Field(None, description="Temperature for sampling")
|
|
733
|
+
top_p: float | None = Field(None, description="Top-p (nucleus) sampling parameter")
|
|
734
|
+
add_message_on_answer: bool = Field(True, description="Add dialogs to memory after chat")
|
|
735
|
+
|
|
736
|
+
# ==== Filter conditions ====
|
|
737
|
+
filter: dict[str, Any] | None = Field(
|
|
738
|
+
None,
|
|
739
|
+
description="""
|
|
740
|
+
Filter for the memory, example:
|
|
741
|
+
{
|
|
742
|
+
"`and` or `or`": [
|
|
743
|
+
{"id": "uuid-xxx"},
|
|
744
|
+
{"created_at": {"gt": "2024-01-01"}},
|
|
745
|
+
]
|
|
746
|
+
}
|
|
747
|
+
""",
|
|
748
|
+
)
|
|
749
|
+
|
|
750
|
+
# ==== Extended capabilities ====
|
|
751
|
+
internet_search: bool = Field(False, description="Whether to use internet search")
|
|
752
|
+
threshold: float = Field(0.5, description="Threshold for filtering references")
|
|
753
|
+
|
|
754
|
+
# ==== Backward compatibility ====
|
|
755
|
+
mem_cube_id: str | None = Field(None, description="Cube ID to use for chat")
|
|
756
|
+
moscube: bool = Field(
|
|
757
|
+
False, description="(Deprecated) Whether to use legacy MemOSCube pipeline"
|
|
758
|
+
)
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
class AddStatusRequest(BaseRequest):
|
|
762
|
+
"""Request model for checking add status."""
|
|
763
|
+
|
|
764
|
+
mem_cube_id: str = Field(..., description="Cube ID")
|
|
765
|
+
user_id: str | None = Field(None, description="User ID")
|
|
766
|
+
session_id: str | None = Field(None, description="Session ID")
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
class GetMemoryRequest(BaseRequest):
|
|
770
|
+
"""Request model for getting memories."""
|
|
771
|
+
|
|
772
|
+
mem_cube_id: str = Field(..., description="Cube ID")
|
|
773
|
+
user_id: str | None = Field(None, description="User ID")
|
|
774
|
+
include_preference: bool = Field(True, description="Whether to return preference memory")
|
|
775
|
+
include_tool_memory: bool = Field(False, description="Whether to return tool memory")
|
|
776
|
+
filter: dict[str, Any] | None = Field(None, description="Filter for the memory")
|
|
777
|
+
page: int | None = Field(
|
|
778
|
+
None,
|
|
779
|
+
description="Page number (starts from 1). If None, exports all data without pagination.",
|
|
780
|
+
)
|
|
781
|
+
page_size: int | None = Field(
|
|
782
|
+
None, description="Number of items per page. If None, exports all data without pagination."
|
|
783
|
+
)
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
class DeleteMemoryRequest(BaseRequest):
|
|
787
|
+
"""Request model for deleting memories."""
|
|
788
|
+
|
|
789
|
+
writable_cube_ids: list[str] = Field(None, description="Writable cube IDs")
|
|
790
|
+
memory_ids: list[str] | None = Field(None, description="Memory IDs")
|
|
791
|
+
file_ids: list[str] | None = Field(None, description="File IDs")
|
|
792
|
+
filter: dict[str, Any] | None = Field(None, description="Filter for the memory")
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
class SuggestionRequest(BaseRequest):
|
|
796
|
+
"""Request model for getting suggestion queries."""
|
|
797
|
+
|
|
798
|
+
user_id: str = Field(..., description="User ID")
|
|
799
|
+
mem_cube_id: str = Field(..., description="Cube ID")
|
|
800
|
+
language: Literal["zh", "en"] = Field("zh", description="Language for suggestions")
|
|
801
|
+
message: MessagesType | None = Field(None, description="List of messages to store.")
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
# ─── MemOS Client Response Models ──────────────────────────────────────────────
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
class MessageDetail(BaseModel):
|
|
808
|
+
"""Individual message detail model based on actual API response."""
|
|
809
|
+
|
|
810
|
+
model_config = {"extra": "allow"}
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
class MemoryDetail(BaseModel):
|
|
814
|
+
"""Individual memory detail model based on actual API response."""
|
|
815
|
+
|
|
816
|
+
model_config = {"extra": "allow"}
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
class FileDetail(BaseModel):
|
|
820
|
+
"""Individual file detail model based on actual API response."""
|
|
821
|
+
|
|
822
|
+
model_config = {"extra": "allow"}
|
|
823
|
+
|
|
824
|
+
|
|
825
|
+
class GetMessagesData(BaseModel):
|
|
826
|
+
"""Data model for get messages response based on actual API."""
|
|
827
|
+
|
|
828
|
+
message_detail_list: list[MessageDetail] = Field(
|
|
829
|
+
default_factory=list, alias="message_detail_list", description="List of message details"
|
|
830
|
+
)
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
class GetCreateKnowledgebaseData(BaseModel):
|
|
834
|
+
"""Data model for create knowledgebase response based on actual API."""
|
|
835
|
+
|
|
836
|
+
id: str = Field(..., description="Knowledgebase id")
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
class SearchMemoryData(BaseModel):
|
|
840
|
+
"""Data model for search memory response based on actual API."""
|
|
841
|
+
|
|
842
|
+
memory_detail_list: list[MemoryDetail] = Field(
|
|
843
|
+
default_factory=list, alias="memory_detail_list", description="List of memory details"
|
|
844
|
+
)
|
|
845
|
+
message_detail_list: list[MessageDetail] | None = Field(
|
|
846
|
+
None, alias="message_detail_list", description="List of message details (usually None)"
|
|
847
|
+
)
|
|
848
|
+
preference_detail_list: list[MessageDetail] | None = Field(
|
|
849
|
+
None,
|
|
850
|
+
alias="preference_detail_list",
|
|
851
|
+
description="List of preference details (usually None)",
|
|
852
|
+
)
|
|
853
|
+
tool_memory_detail_list: list[MessageDetail] | None = Field(
|
|
854
|
+
None,
|
|
855
|
+
alias="tool_memory_detail_list",
|
|
856
|
+
description="List of tool_memor details (usually None)",
|
|
857
|
+
)
|
|
858
|
+
preference_note: str = Field(
|
|
859
|
+
None, alias="preference_note", description="String of preference_note"
|
|
860
|
+
)
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
class GetKnowledgebaseFileData(BaseModel):
|
|
864
|
+
"""Data model for search memory response based on actual API."""
|
|
865
|
+
|
|
866
|
+
file_detail_list: list[FileDetail] = Field(
|
|
867
|
+
default_factory=list, alias="file_detail_list", description="List of files details"
|
|
868
|
+
)
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
class GetMemoryData(BaseModel):
|
|
872
|
+
"""Data model for search memory response based on actual API."""
|
|
873
|
+
|
|
874
|
+
memory_detail_list: list[MemoryDetail] = Field(
|
|
875
|
+
default_factory=list, alias="memory_detail_list", description="List of memory details"
|
|
876
|
+
)
|
|
877
|
+
preference_detail_list: list[MessageDetail] | None = Field(
|
|
878
|
+
None, alias="preference_detail_list", description="List of preference detail"
|
|
879
|
+
)
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
class AddMessageData(BaseModel):
|
|
883
|
+
"""Data model for add message response based on actual API."""
|
|
884
|
+
|
|
885
|
+
success: bool = Field(..., description="Operation success status")
|
|
886
|
+
task_id: str = Field(..., description="Operation task_id")
|
|
887
|
+
status: str = Field(..., description="Operation task status")
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
class DeleteMessageData(BaseModel):
|
|
891
|
+
"""Data model for delete Message based on actual API."""
|
|
892
|
+
|
|
893
|
+
success: bool = Field(..., description="Operation success status")
|
|
894
|
+
|
|
895
|
+
|
|
896
|
+
class ChatMessageData(BaseModel):
|
|
897
|
+
"""Data model for chat Message based on actual API."""
|
|
898
|
+
|
|
899
|
+
response: str = Field(..., description="Operation response")
|
|
900
|
+
|
|
901
|
+
|
|
902
|
+
class GetTaskStatusMessageData(BaseModel):
|
|
903
|
+
"""Data model for task status Message based on actual API."""
|
|
904
|
+
|
|
905
|
+
status: str = Field(..., description="Operation task status")
|
|
906
|
+
|
|
907
|
+
|
|
908
|
+
# ─── MemOS Response Models (Similar to OpenAI ChatCompletion) ──────────────────
|
|
909
|
+
|
|
910
|
+
|
|
911
|
+
class MemOSGetMessagesResponse(BaseModel):
|
|
912
|
+
"""Response model for get messages operation based on actual API."""
|
|
913
|
+
|
|
914
|
+
code: int = Field(..., description="Response status code")
|
|
915
|
+
message: str = Field(..., description="Response message")
|
|
916
|
+
data: GetMessagesData = Field(..., description="Messages data")
|
|
917
|
+
|
|
918
|
+
@property
|
|
919
|
+
def messages(self) -> list[MessageDetail]:
|
|
920
|
+
"""Convenient access to message list."""
|
|
921
|
+
return self.data.message_detail_list
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
class MemOSSearchResponse(BaseModel):
|
|
925
|
+
"""Response model for search memory operation based on actual API."""
|
|
926
|
+
|
|
927
|
+
code: int = Field(..., description="Response status code")
|
|
928
|
+
message: str = Field(..., description="Response message")
|
|
929
|
+
data: SearchMemoryData = Field(..., description="Search results data")
|
|
930
|
+
|
|
931
|
+
@property
|
|
932
|
+
def memories(self) -> list[MemoryDetail]:
|
|
933
|
+
"""Convenient access to memory list."""
|
|
934
|
+
return self.data.memory_detail_list
|
|
935
|
+
|
|
936
|
+
@property
|
|
937
|
+
def preferences(self) -> list[MemoryDetail]:
|
|
938
|
+
"""Convenient access to preference list."""
|
|
939
|
+
return self.data.preference_detail_list
|
|
940
|
+
|
|
941
|
+
@property
|
|
942
|
+
def tool_memories(self) -> list[MemoryDetail]:
|
|
943
|
+
"""Convenient access to tool_memory list."""
|
|
944
|
+
return self.data.tool_memory_detail_list
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
class MemOSDeleteKnowledgebaseResponse(BaseModel):
|
|
948
|
+
"""Response model for delete knowledgebase operation based on actual API."""
|
|
949
|
+
|
|
950
|
+
code: int = Field(..., description="Response status code")
|
|
951
|
+
message: str = Field(..., description="Response message")
|
|
952
|
+
data: DeleteMessageData = Field(..., description="delete results data")
|
|
953
|
+
|
|
954
|
+
@property
|
|
955
|
+
def success(self) -> bool:
|
|
956
|
+
"""Convenient access to success status."""
|
|
957
|
+
return self.data.success
|
|
958
|
+
|
|
959
|
+
|
|
960
|
+
class MemOSDeleteMemoryResponse(BaseModel):
|
|
961
|
+
"""Response model for delete knowledgebase operation based on actual API."""
|
|
962
|
+
|
|
963
|
+
code: int = Field(..., description="Response status code")
|
|
964
|
+
message: str = Field(..., description="Response message")
|
|
965
|
+
data: DeleteMessageData = Field(..., description="delete results data")
|
|
966
|
+
|
|
967
|
+
@property
|
|
968
|
+
def success(self) -> bool:
|
|
969
|
+
"""Convenient access to success status."""
|
|
970
|
+
return self.data.success
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
class MemOSChatResponse(BaseModel):
|
|
974
|
+
"""Response model for chat operation based on actual API."""
|
|
975
|
+
|
|
976
|
+
code: int = Field(..., description="Response status code")
|
|
977
|
+
message: str = Field(..., description="Response message")
|
|
978
|
+
data: ChatMessageData = Field(..., description="chat results data")
|
|
979
|
+
|
|
980
|
+
@property
|
|
981
|
+
def response(self) -> str:
|
|
982
|
+
"""Convenient access to success status."""
|
|
983
|
+
return self.data.response
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
class MemOSGetTaskStatusResponse(BaseModel):
|
|
987
|
+
"""Response model for get task status operation based on actual API."""
|
|
988
|
+
|
|
989
|
+
code: int = Field(..., description="Response status code")
|
|
990
|
+
message: str = Field(..., description="Response message")
|
|
991
|
+
data: list[GetTaskStatusMessageData] = Field(..., description="Task status data")
|
|
992
|
+
|
|
993
|
+
@property
|
|
994
|
+
def messages(self) -> list[GetTaskStatusMessageData]:
|
|
995
|
+
"""Convenient access to task status messages."""
|
|
996
|
+
return self.data
|
|
997
|
+
|
|
998
|
+
|
|
999
|
+
class MemOSCreateKnowledgebaseResponse(BaseModel):
|
|
1000
|
+
"""Response model for create knowledgebase operation based on actual API."""
|
|
1001
|
+
|
|
1002
|
+
code: int = Field(..., description="Response status code")
|
|
1003
|
+
message: str = Field(..., description="Response message")
|
|
1004
|
+
data: GetCreateKnowledgebaseData = Field(..., description="Messages data")
|
|
1005
|
+
|
|
1006
|
+
@property
|
|
1007
|
+
def knowledgebase_id(self) -> str:
|
|
1008
|
+
"""Convenient access to knowledgebase id."""
|
|
1009
|
+
return self.data.id
|
|
1010
|
+
|
|
1011
|
+
|
|
1012
|
+
class MemOSAddKnowledgebaseFileResponse(BaseModel):
|
|
1013
|
+
"""Response model for add knowledgebase-file operation based on actual API."""
|
|
1014
|
+
|
|
1015
|
+
code: int = Field(..., description="Response status code")
|
|
1016
|
+
message: str = Field(..., description="Response message")
|
|
1017
|
+
data: list[dict[str, Any]]
|
|
1018
|
+
|
|
1019
|
+
@property
|
|
1020
|
+
def memories(self) -> list[dict[str, Any]]:
|
|
1021
|
+
"""Convenient access to memory list."""
|
|
1022
|
+
return self.data
|
|
1023
|
+
|
|
1024
|
+
|
|
1025
|
+
class MemOSGetMemoryResponse(BaseModel):
|
|
1026
|
+
"""Response model for get memory operation based on actual API."""
|
|
1027
|
+
|
|
1028
|
+
code: int = Field(..., description="Response status code")
|
|
1029
|
+
message: str = Field(..., description="Response message")
|
|
1030
|
+
data: GetMemoryData = Field(..., description="Get results data")
|
|
1031
|
+
|
|
1032
|
+
@property
|
|
1033
|
+
def memories(self) -> list[MemoryDetail]:
|
|
1034
|
+
"""Convenient access to memory list."""
|
|
1035
|
+
return self.data.memory_detail_list
|
|
1036
|
+
|
|
1037
|
+
@property
|
|
1038
|
+
def preferences(self) -> list[MessageDetail] | None:
|
|
1039
|
+
"""Convenient access to preference list."""
|
|
1040
|
+
return self.data.preference_detail_list
|
|
1041
|
+
|
|
1042
|
+
|
|
1043
|
+
class MemOSGetKnowledgebaseFileResponse(BaseModel):
|
|
1044
|
+
"""Response model for get KnowledgebaseFile operation based on actual API."""
|
|
1045
|
+
|
|
1046
|
+
code: int = Field(..., description="Response status code")
|
|
1047
|
+
message: str = Field(..., description="Response message")
|
|
1048
|
+
data: GetKnowledgebaseFileData = Field(..., description="Get results data")
|
|
1049
|
+
|
|
1050
|
+
@property
|
|
1051
|
+
def files(self) -> list[FileDetail]:
|
|
1052
|
+
"""Convenient access to file list."""
|
|
1053
|
+
return self.data.file_detail_list
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
class MemOSAddResponse(BaseModel):
|
|
1057
|
+
"""Response model for add message operation based on actual API."""
|
|
1058
|
+
|
|
1059
|
+
code: int = Field(..., description="Response status code")
|
|
1060
|
+
message: str = Field(..., description="Response message")
|
|
1061
|
+
data: AddMessageData = Field(..., description="Add operation data")
|
|
1062
|
+
|
|
1063
|
+
@property
|
|
1064
|
+
def success(self) -> bool:
|
|
1065
|
+
"""Convenient access to success status."""
|
|
1066
|
+
return self.data.success
|
|
1067
|
+
|
|
1068
|
+
@property
|
|
1069
|
+
def task_id(self) -> str:
|
|
1070
|
+
"""Convenient access to task_id status."""
|
|
1071
|
+
return self.data.task_id
|
|
1072
|
+
|
|
1073
|
+
@property
|
|
1074
|
+
def status(self) -> str:
|
|
1075
|
+
"""Convenient access to status status."""
|
|
1076
|
+
return self.data.status
|
|
1077
|
+
|
|
1078
|
+
|
|
1079
|
+
class MemOSAddFeedBackResponse(BaseModel):
|
|
1080
|
+
"""Response model for add feedback operation based on actual API."""
|
|
1081
|
+
|
|
1082
|
+
code: int = Field(..., description="Response status code")
|
|
1083
|
+
message: str = Field(..., description="Response message")
|
|
1084
|
+
data: AddMessageData = Field(..., description="Add operation data")
|
|
1085
|
+
|
|
1086
|
+
@property
|
|
1087
|
+
def success(self) -> bool:
|
|
1088
|
+
"""Convenient access to success status."""
|
|
1089
|
+
return self.data.success
|
|
1090
|
+
|
|
1091
|
+
@property
|
|
1092
|
+
def task_id(self) -> str:
|
|
1093
|
+
"""Convenient access to task_id status."""
|
|
1094
|
+
return self.data.task_id
|
|
1095
|
+
|
|
1096
|
+
@property
|
|
1097
|
+
def status(self) -> str:
|
|
1098
|
+
"""Convenient access to status status."""
|
|
1099
|
+
return self.data.status
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
# ─── Scheduler Status Models ───────────────────────────────────────────────────
|
|
1103
|
+
|
|
1104
|
+
|
|
1105
|
+
class StatusRequest(BaseRequest):
|
|
1106
|
+
"""Request model for querying scheduler task status."""
|
|
1107
|
+
|
|
1108
|
+
user_id: str = Field(..., description="User ID")
|
|
1109
|
+
task_id: str | None = Field(None, description="Optional Task ID to query a specific task")
|
|
1110
|
+
|
|
1111
|
+
|
|
1112
|
+
class StatusResponseItem(BaseModel):
|
|
1113
|
+
"""Individual task status item."""
|
|
1114
|
+
|
|
1115
|
+
task_id: str = Field(..., description="The ID of the task")
|
|
1116
|
+
status: Literal["in_progress", "completed", "waiting", "failed", "cancelled"] = Field(
|
|
1117
|
+
..., description="The current status of the task"
|
|
1118
|
+
)
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
class StatusResponse(BaseResponse[list[StatusResponseItem]]):
|
|
1122
|
+
"""Response model for scheduler status operations."""
|
|
1123
|
+
|
|
1124
|
+
message: str = "Memory get status successfully"
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
class TaskQueueData(BaseModel):
|
|
1128
|
+
"""Queue-level metrics for scheduler tasks."""
|
|
1129
|
+
|
|
1130
|
+
user_id: str = Field(..., description="User ID the query is scoped to")
|
|
1131
|
+
user_name: str | None = Field(None, description="User name if available")
|
|
1132
|
+
mem_cube_id: str | None = Field(
|
|
1133
|
+
None, description="MemCube ID if a single cube is targeted; otherwise None"
|
|
1134
|
+
)
|
|
1135
|
+
stream_keys: list[str] = Field(..., description="Matched Redis stream keys for this user")
|
|
1136
|
+
users_count: int = Field(..., description="Distinct users currently present in queue streams")
|
|
1137
|
+
pending_tasks_count: int = Field(
|
|
1138
|
+
..., description="Count of pending (delivered, not acked) tasks"
|
|
1139
|
+
)
|
|
1140
|
+
remaining_tasks_count: int = Field(..., description="Count of enqueued tasks (xlen)")
|
|
1141
|
+
pending_tasks_detail: list[str] = Field(
|
|
1142
|
+
..., description="Per-stream pending counts, formatted as '{stream_key}:{count}'"
|
|
1143
|
+
)
|
|
1144
|
+
remaining_tasks_detail: list[str] = Field(
|
|
1145
|
+
..., description="Per-stream remaining counts, formatted as '{stream_key}:{count}'"
|
|
1146
|
+
)
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
class TaskQueueResponse(BaseResponse[TaskQueueData]):
|
|
1150
|
+
"""Response model for scheduler task queue status."""
|
|
1151
|
+
|
|
1152
|
+
message: str = "Scheduler task queue status retrieved successfully"
|
|
1153
|
+
|
|
1154
|
+
|
|
1155
|
+
class TaskSummary(BaseModel):
|
|
1156
|
+
"""Aggregated counts of tasks by status."""
|
|
1157
|
+
|
|
1158
|
+
waiting: int = Field(0, description="Number of tasks waiting to run")
|
|
1159
|
+
in_progress: int = Field(0, description="Number of tasks currently running")
|
|
1160
|
+
pending: int = Field(
|
|
1161
|
+
0, description="Number of tasks fetched by workers but not yet acknowledged"
|
|
1162
|
+
)
|
|
1163
|
+
completed: int = Field(0, description="Number of tasks completed")
|
|
1164
|
+
failed: int = Field(0, description="Number of tasks failed")
|
|
1165
|
+
cancelled: int = Field(0, description="Number of tasks cancelled")
|
|
1166
|
+
total: int = Field(0, description="Total number of tasks counted")
|
|
1167
|
+
|
|
1168
|
+
|
|
1169
|
+
class AllStatusResponseData(BaseModel):
|
|
1170
|
+
"""Aggregated scheduler status metrics."""
|
|
1171
|
+
|
|
1172
|
+
scheduler_summary: TaskSummary = Field(
|
|
1173
|
+
..., description="Aggregated status for scheduler-managed tasks"
|
|
1174
|
+
)
|
|
1175
|
+
all_tasks_summary: TaskSummary = Field(
|
|
1176
|
+
..., description="Aggregated status for all tracked tasks"
|
|
1177
|
+
)
|
|
1178
|
+
|
|
1179
|
+
|
|
1180
|
+
class AllStatusResponse(BaseResponse[AllStatusResponseData]):
|
|
1181
|
+
"""Response model for full scheduler status operations."""
|
|
1182
|
+
|
|
1183
|
+
message: str = "Scheduler status summary retrieved successfully"
|
|
1184
|
+
|
|
1185
|
+
|
|
1186
|
+
# ─── Internal API Endpoints Models (for internal use) ───────────────────────────────────────────────────
|
|
1187
|
+
|
|
1188
|
+
|
|
1189
|
+
class GetUserNamesByMemoryIdsRequest(BaseRequest):
|
|
1190
|
+
"""Request model for getting user names by memory ids."""
|
|
1191
|
+
|
|
1192
|
+
memory_ids: list[str] = Field(..., description="Memory IDs")
|
|
1193
|
+
|
|
1194
|
+
|
|
1195
|
+
class GetUserNamesByMemoryIdsResponse(BaseResponse[dict[str, str | None]]):
|
|
1196
|
+
"""Response model for getting user names by memory ids."""
|
|
1197
|
+
|
|
1198
|
+
|
|
1199
|
+
class ExistMemCubeIdRequest(BaseRequest):
|
|
1200
|
+
"""Request model for checking if mem cube id exists."""
|
|
1201
|
+
|
|
1202
|
+
mem_cube_id: str = Field(..., description="Mem cube ID")
|
|
1203
|
+
|
|
1204
|
+
|
|
1205
|
+
class ExistMemCubeIdResponse(BaseResponse[dict[str, bool]]):
|
|
1206
|
+
"""Response model for checking if mem cube id exists."""
|