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
memos/graph_dbs/base.py
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Any, Literal
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class BaseGraphDB(ABC):
|
|
6
|
+
"""
|
|
7
|
+
Abstract base class for a graph database interface used in a memory-augmented RAG system.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# Node (Memory) Management
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def add_node(self, id: str, memory: str, metadata: dict[str, Any]) -> None:
|
|
13
|
+
"""
|
|
14
|
+
Add a memory node to the graph.
|
|
15
|
+
Args:
|
|
16
|
+
id: Unique identifier for the memory node.
|
|
17
|
+
memory: Raw memory content (e.g., text).
|
|
18
|
+
metadata: Dictionary of metadata (e.g., timestamp, tags, source).
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def update_node(self, id: str, fields: dict[str, Any], user_name: str | None = None) -> None:
|
|
23
|
+
"""
|
|
24
|
+
Update attributes of an existing node.
|
|
25
|
+
Args:
|
|
26
|
+
id: Node identifier to be updated.
|
|
27
|
+
fields: Dictionary of fields to update.
|
|
28
|
+
user_name: given user_name
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def delete_node(self, id: str) -> None:
|
|
33
|
+
"""
|
|
34
|
+
Delete a node from the graph.
|
|
35
|
+
Args:
|
|
36
|
+
id: Node identifier to delete.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
# Edge (Relationship) Management
|
|
40
|
+
@abstractmethod
|
|
41
|
+
def add_edge(self, source_id: str, target_id: str, type: str) -> None:
|
|
42
|
+
"""
|
|
43
|
+
Create an edge from source node to target node.
|
|
44
|
+
Args:
|
|
45
|
+
source_id: ID of the source node.
|
|
46
|
+
target_id: ID of the target node.
|
|
47
|
+
type: Relationship type (e.g., 'FOLLOWS', 'CAUSES', 'PARENT').
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
@abstractmethod
|
|
51
|
+
def delete_edge(self, source_id: str, target_id: str, type: str) -> None:
|
|
52
|
+
"""
|
|
53
|
+
Delete a specific edge between two nodes.
|
|
54
|
+
Args:
|
|
55
|
+
source_id: ID of the source node.
|
|
56
|
+
target_id: ID of the target node.
|
|
57
|
+
type: Relationship type to remove.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
@abstractmethod
|
|
61
|
+
def edge_exists(self, source_id: str, target_id: str, type: str) -> bool:
|
|
62
|
+
"""
|
|
63
|
+
Check if an edge exists between two nodes.
|
|
64
|
+
Args:
|
|
65
|
+
source_id: ID of the source node.
|
|
66
|
+
target_id: ID of the target node.
|
|
67
|
+
type: Relationship type.
|
|
68
|
+
Returns:
|
|
69
|
+
True if the edge exists, otherwise False.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
# Graph Query & Reasoning
|
|
73
|
+
@abstractmethod
|
|
74
|
+
def get_node(self, id: str, include_embedding: bool = False, **kwargs) -> dict[str, Any] | None:
|
|
75
|
+
"""
|
|
76
|
+
Retrieve the metadata and content of a node.
|
|
77
|
+
Args:
|
|
78
|
+
id: Node identifier.
|
|
79
|
+
include_embedding: with/without embedding
|
|
80
|
+
Returns:
|
|
81
|
+
Dictionary of node fields, or None if not found.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
@abstractmethod
|
|
85
|
+
def get_nodes(
|
|
86
|
+
self, ids: list, include_embedding: bool = False, **kwargs
|
|
87
|
+
) -> dict[str, Any] | None:
|
|
88
|
+
"""
|
|
89
|
+
Retrieve the metadata and memory of a list of nodes.
|
|
90
|
+
Args:
|
|
91
|
+
ids: List of Node identifier.
|
|
92
|
+
include_embedding: with/without embedding
|
|
93
|
+
Returns:
|
|
94
|
+
list[dict]: Parsed node records containing 'id', 'memory', and 'metadata'.
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
@abstractmethod
|
|
98
|
+
def get_neighbors(
|
|
99
|
+
self, id: str, type: str, direction: Literal["in", "out", "both"] = "out"
|
|
100
|
+
) -> list[str]:
|
|
101
|
+
"""
|
|
102
|
+
Get connected node IDs in a specific direction and relationship type.
|
|
103
|
+
Args:
|
|
104
|
+
id: Source node ID.
|
|
105
|
+
type: Relationship type.
|
|
106
|
+
direction: Edge direction to follow ('out', 'in', or 'both').
|
|
107
|
+
Returns:
|
|
108
|
+
List of neighboring node IDs.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
@abstractmethod
|
|
112
|
+
def get_path(self, source_id: str, target_id: str, max_depth: int = 3) -> list[str]:
|
|
113
|
+
"""
|
|
114
|
+
Get the path of nodes from source to target within a limited depth.
|
|
115
|
+
Args:
|
|
116
|
+
source_id: Starting node ID.
|
|
117
|
+
target_id: Target node ID.
|
|
118
|
+
max_depth: Maximum path length to traverse.
|
|
119
|
+
Returns:
|
|
120
|
+
Ordered list of node IDs along the path.
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
@abstractmethod
|
|
124
|
+
def get_subgraph(self, center_id: str, depth: int = 2) -> list[str]:
|
|
125
|
+
"""
|
|
126
|
+
Retrieve a local subgraph centered at a given node.
|
|
127
|
+
Args:
|
|
128
|
+
center_id: Center node ID.
|
|
129
|
+
depth: Radius to include neighboring nodes.
|
|
130
|
+
Returns:
|
|
131
|
+
List of node IDs in the subgraph.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
@abstractmethod
|
|
135
|
+
def get_context_chain(self, id: str, type: str = "FOLLOWS") -> list[str]:
|
|
136
|
+
"""
|
|
137
|
+
Get the ordered context chain starting from a node, following a relationship type.
|
|
138
|
+
Args:
|
|
139
|
+
id: Starting node ID.
|
|
140
|
+
type: Relationship type to follow (e.g., 'FOLLOWS').
|
|
141
|
+
Returns:
|
|
142
|
+
List of ordered node IDs in the chain.
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
# Search / recall operations
|
|
146
|
+
@abstractmethod
|
|
147
|
+
def search_by_embedding(self, vector: list[float], top_k: int = 5, **kwargs) -> list[dict]:
|
|
148
|
+
"""
|
|
149
|
+
Retrieve node IDs based on vector similarity.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
vector (list[float]): The embedding vector representing query semantics.
|
|
153
|
+
top_k (int): Number of top similar nodes to retrieve.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
list[dict]: A list of dicts with 'id' and 'score', ordered by similarity.
|
|
157
|
+
|
|
158
|
+
Notes:
|
|
159
|
+
- This method may internally call a VecDB (e.g., Qdrant) or store embeddings in the graph DB itself.
|
|
160
|
+
- Commonly used for RAG recall stage to find semantically similar memories.
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
@abstractmethod
|
|
164
|
+
def get_by_metadata(
|
|
165
|
+
self, filters: list[dict[str, Any]], status: str | None = None
|
|
166
|
+
) -> list[str]:
|
|
167
|
+
"""
|
|
168
|
+
Retrieve node IDs that match given metadata filters.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
filters (dict[str, Any]): A dictionary of attribute-value filters.
|
|
172
|
+
Example: {"topic": "psychology", "importance": 2}
|
|
173
|
+
status (str, optional): Filter by status (e.g., 'activated', 'archived').
|
|
174
|
+
If None, no status filter is applied.
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
list[str]: Node IDs whose metadata match the filter conditions.
|
|
178
|
+
|
|
179
|
+
Notes:
|
|
180
|
+
- Supports structured querying such as tag/category/importance/time filtering.
|
|
181
|
+
- Can be used for faceted recall or prefiltering before embedding rerank.
|
|
182
|
+
"""
|
|
183
|
+
|
|
184
|
+
@abstractmethod
|
|
185
|
+
def get_structure_optimization_candidates(
|
|
186
|
+
self, scope: str, include_embedding: bool = False
|
|
187
|
+
) -> list[dict]:
|
|
188
|
+
"""
|
|
189
|
+
Find nodes that are likely candidates for structure optimization:
|
|
190
|
+
- Isolated nodes, nodes with empty background, or nodes with exactly one child.
|
|
191
|
+
- Plus: the child of any parent node that has exactly one child.
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
# Structure Maintenance
|
|
195
|
+
@abstractmethod
|
|
196
|
+
def deduplicate_nodes(self) -> None:
|
|
197
|
+
"""
|
|
198
|
+
Deduplicate redundant or semantically similar nodes.
|
|
199
|
+
This typically involves identifying nodes with identical or near-identical content.
|
|
200
|
+
"""
|
|
201
|
+
|
|
202
|
+
@abstractmethod
|
|
203
|
+
def detect_conflicts(self) -> list[tuple[str, str]]:
|
|
204
|
+
"""
|
|
205
|
+
Detect conflicting nodes based on logical or semantic inconsistency.
|
|
206
|
+
Returns:
|
|
207
|
+
A list of (node_id1, node_id2) tuples that conflict.
|
|
208
|
+
"""
|
|
209
|
+
|
|
210
|
+
@abstractmethod
|
|
211
|
+
def merge_nodes(self, id1: str, id2: str) -> str:
|
|
212
|
+
"""
|
|
213
|
+
Merge two similar or duplicate nodes into one.
|
|
214
|
+
Args:
|
|
215
|
+
id1: First node ID.
|
|
216
|
+
id2: Second node ID.
|
|
217
|
+
Returns:
|
|
218
|
+
ID of the resulting merged node.
|
|
219
|
+
"""
|
|
220
|
+
|
|
221
|
+
# Utilities
|
|
222
|
+
@abstractmethod
|
|
223
|
+
def clear(self) -> None:
|
|
224
|
+
"""
|
|
225
|
+
Clear the entire graph.
|
|
226
|
+
"""
|
|
227
|
+
|
|
228
|
+
@abstractmethod
|
|
229
|
+
def export_graph(self, include_embedding: bool = False) -> dict[str, Any]:
|
|
230
|
+
"""
|
|
231
|
+
Export the entire graph as a serializable dictionary.
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
A dictionary containing all nodes and edges.
|
|
235
|
+
"""
|
|
236
|
+
|
|
237
|
+
@abstractmethod
|
|
238
|
+
def import_graph(self, data: dict[str, Any]) -> None:
|
|
239
|
+
"""
|
|
240
|
+
Import the entire graph from a serialized dictionary.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
data: A dictionary containing all nodes and edges to be loaded.
|
|
244
|
+
"""
|
|
245
|
+
|
|
246
|
+
@abstractmethod
|
|
247
|
+
def get_all_memory_items(
|
|
248
|
+
self, scope: str, include_embedding: bool = False, status: str | None = None
|
|
249
|
+
) -> list[dict]:
|
|
250
|
+
"""
|
|
251
|
+
Retrieve all memory items of a specific memory_type.
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
scope (str): Must be one of 'WorkingMemory', 'LongTermMemory', or 'UserMemory'.
|
|
255
|
+
include_embedding: with/without embedding
|
|
256
|
+
status (str, optional): Filter by status (e.g., 'activated', 'archived').
|
|
257
|
+
If None, no status filter is applied.
|
|
258
|
+
|
|
259
|
+
Returns:
|
|
260
|
+
list[dict]: Full list of memory items under this scope.
|
|
261
|
+
"""
|
|
262
|
+
|
|
263
|
+
@abstractmethod
|
|
264
|
+
def add_nodes_batch(self, nodes: list[dict[str, Any]], user_name: str | None = None) -> None:
|
|
265
|
+
"""
|
|
266
|
+
Batch add multiple memory nodes to the graph.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
nodes: List of node dictionaries, each containing:
|
|
270
|
+
- id: str - Node ID
|
|
271
|
+
- memory: str - Memory content
|
|
272
|
+
- metadata: dict[str, Any] - Node metadata
|
|
273
|
+
user_name: Optional user name (will use config default if not provided)
|
|
274
|
+
"""
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from typing import Any, ClassVar
|
|
2
|
+
|
|
3
|
+
from memos.configs.graph_db import GraphDBConfigFactory
|
|
4
|
+
from memos.graph_dbs.base import BaseGraphDB
|
|
5
|
+
from memos.graph_dbs.nebular import NebulaGraphDB
|
|
6
|
+
from memos.graph_dbs.neo4j import Neo4jGraphDB
|
|
7
|
+
from memos.graph_dbs.neo4j_community import Neo4jCommunityGraphDB
|
|
8
|
+
from memos.graph_dbs.polardb import PolarDBGraphDB
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class GraphStoreFactory(BaseGraphDB):
|
|
12
|
+
"""Factory for creating graph store instances."""
|
|
13
|
+
|
|
14
|
+
backend_to_class: ClassVar[dict[str, Any]] = {
|
|
15
|
+
"neo4j": Neo4jGraphDB,
|
|
16
|
+
"neo4j-community": Neo4jCommunityGraphDB,
|
|
17
|
+
"nebular": NebulaGraphDB,
|
|
18
|
+
"polardb": PolarDBGraphDB,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@classmethod
|
|
22
|
+
def from_config(cls, config_factory: GraphDBConfigFactory) -> BaseGraphDB:
|
|
23
|
+
backend = config_factory.backend
|
|
24
|
+
if backend not in cls.backend_to_class:
|
|
25
|
+
raise ValueError(f"Unsupported graph database backend: {backend}")
|
|
26
|
+
graph_class = cls.backend_to_class[backend]
|
|
27
|
+
return graph_class(config_factory.config)
|
memos/graph_dbs/item.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
|
|
3
|
+
from typing import Any, Literal
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
6
|
+
|
|
7
|
+
from memos.memories.textual.item import TextualMemoryItem
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class GraphDBNode(TextualMemoryItem):
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class GraphDBEdge(BaseModel):
|
|
15
|
+
"""Represents an edge in a graph database (corresponds to Neo4j relationship)."""
|
|
16
|
+
|
|
17
|
+
id: str = Field(
|
|
18
|
+
default_factory=lambda: str(uuid.uuid4()), description="Unique identifier for the edge"
|
|
19
|
+
)
|
|
20
|
+
source: str = Field(..., description="Source node ID")
|
|
21
|
+
target: str = Field(..., description="Target node ID")
|
|
22
|
+
type: Literal["RELATED", "PARENT"] = Field(
|
|
23
|
+
..., description="Relationship type (must be one of 'RELATED', 'PARENT')"
|
|
24
|
+
)
|
|
25
|
+
properties: dict[str, Any] | None = Field(
|
|
26
|
+
default=None, description="Additional properties for the edge"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
model_config = ConfigDict(extra="forbid")
|
|
30
|
+
|
|
31
|
+
@field_validator("id")
|
|
32
|
+
@classmethod
|
|
33
|
+
def validate_id(cls, v):
|
|
34
|
+
"""Validate that ID is a valid UUID."""
|
|
35
|
+
if not isinstance(v, str) or not uuid.UUID(v, version=4):
|
|
36
|
+
raise ValueError("ID must be a valid UUID string")
|
|
37
|
+
return v
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def from_dict(cls, data: dict[str, Any]) -> "GraphDBEdge":
|
|
41
|
+
"""Create GraphDBEdge from dictionary."""
|
|
42
|
+
return cls(**data)
|
|
43
|
+
|
|
44
|
+
def to_dict(self) -> dict[str, Any]:
|
|
45
|
+
"""Convert to dictionary format."""
|
|
46
|
+
return self.model_dump(exclude_none=True)
|