MemoryOS 1.0.1__tar.gz → 1.1.2__tar.gz
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.
Potentially problematic release.
This version of MemoryOS might be problematic. Click here for more details.
- {memoryos-1.0.1 → memoryos-1.1.2}/PKG-INFO +7 -2
- {memoryos-1.0.1 → memoryos-1.1.2}/pyproject.toml +12 -1
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/__init__.py +1 -1
- memoryos-1.1.2/src/memos/api/client.py +109 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/api/config.py +11 -9
- memoryos-1.1.2/src/memos/api/context/dependencies.py +50 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/api/middleware/request_context.py +9 -40
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/api/product_api.py +2 -3
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/api/product_models.py +91 -16
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/api/routers/product_router.py +23 -16
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/api/start_api.py +10 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/graph_db.py +4 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/mem_scheduler.py +38 -3
- memoryos-1.1.2/src/memos/context/context.py +255 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/embedders/factory.py +2 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/graph_dbs/nebular.py +230 -232
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/graph_dbs/neo4j.py +35 -1
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/graph_dbs/neo4j_community.py +7 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/llms/factory.py +2 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/llms/openai.py +74 -2
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/log.py +27 -15
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_cube/general.py +3 -1
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_os/core.py +60 -22
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_os/main.py +3 -6
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_os/product.py +35 -11
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_reader/factory.py +2 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_reader/simple_struct.py +127 -74
- memoryos-1.1.2/src/memos/mem_scheduler/analyzer/mos_for_test_scheduler.py +569 -0
- memoryos-1.1.2/src/memos/mem_scheduler/analyzer/scheduler_for_eval.py +280 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_scheduler/base_scheduler.py +126 -56
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_scheduler/general_modules/dispatcher.py +2 -2
- memoryos-1.1.2/src/memos/mem_scheduler/general_modules/misc.py +202 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_scheduler/general_modules/scheduler_logger.py +17 -11
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_scheduler/general_scheduler.py +40 -88
- memoryos-1.1.2/src/memos/mem_scheduler/memory_manage_modules/__init__.py +5 -0
- memoryos-1.1.2/src/memos/mem_scheduler/memory_manage_modules/memory_filter.py +308 -0
- {memoryos-1.0.1/src/memos/mem_scheduler/general_modules → memoryos-1.1.2/src/memos/mem_scheduler/memory_manage_modules}/retriever.py +34 -7
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_scheduler/monitors/dispatcher_monitor.py +9 -8
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_scheduler/monitors/general_monitor.py +119 -39
- memoryos-1.1.2/src/memos/mem_scheduler/optimized_scheduler.py +124 -0
- memoryos-1.1.2/src/memos/mem_scheduler/orm_modules/base_model.py +635 -0
- memoryos-1.1.2/src/memos/mem_scheduler/orm_modules/monitor_models.py +261 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_scheduler/scheduler_factory.py +2 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_scheduler/schemas/monitor_schemas.py +96 -29
- memoryos-1.1.2/src/memos/mem_scheduler/utils/config_utils.py +100 -0
- memoryos-1.1.2/src/memos/mem_scheduler/utils/db_utils.py +33 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_scheduler/utils/filter_utils.py +1 -1
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/activation/kv.py +2 -1
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/item.py +95 -16
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/naive.py +1 -1
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree.py +27 -3
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree_text_memory/organize/handler.py +4 -2
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree_text_memory/organize/manager.py +28 -14
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree_text_memory/organize/relation_reason_detector.py +1 -2
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree_text_memory/organize/reorganizer.py +75 -23
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree_text_memory/retrieve/bochasearch.py +7 -5
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree_text_memory/retrieve/internet_retriever.py +6 -2
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree_text_memory/retrieve/internet_retriever_factory.py +2 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree_text_memory/retrieve/recall.py +70 -22
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree_text_memory/retrieve/searcher.py +101 -33
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree_text_memory/retrieve/xinyusearch.py +5 -4
- memoryos-1.1.2/src/memos/memos_tools/singleton.py +174 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memos_tools/thread_safe_dict.py +22 -0
- memoryos-1.1.2/src/memos/memos_tools/thread_safe_dict_segment.py +382 -0
- memoryos-1.1.2/src/memos/parsers/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/parsers/factory.py +2 -0
- memoryos-1.1.2/src/memos/reranker/concat.py +59 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/reranker/cosine_local.py +1 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/reranker/factory.py +5 -0
- memoryos-1.1.2/src/memos/reranker/http_bge.py +312 -0
- memoryos-1.1.2/src/memos/templates/__init__.py +0 -0
- memoryos-1.1.2/src/memos/templates/mem_scheduler_prompts.py +403 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/types.py +4 -1
- memoryos-1.1.2/src/memos/vec_dbs/__init__.py +0 -0
- memoryos-1.0.1/src/memos/api/context/context.py +0 -147
- memoryos-1.0.1/src/memos/api/context/context_thread.py +0 -96
- memoryos-1.0.1/src/memos/api/context/dependencies.py +0 -90
- memoryos-1.0.1/src/memos/mem_scheduler/general_modules/misc.py +0 -104
- memoryos-1.0.1/src/memos/mem_scheduler/mos_for_test_scheduler.py +0 -146
- memoryos-1.0.1/src/memos/reranker/http_bge.py +0 -99
- memoryos-1.0.1/src/memos/templates/mem_scheduler_prompts.py +0 -161
- {memoryos-1.0.1 → memoryos-1.1.2}/LICENSE +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/README.md +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/api/exceptions.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/api/mcp_serve.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/api/routers/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/chunkers/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/chunkers/base.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/chunkers/factory.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/chunkers/sentence_chunker.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/cli.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/base.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/chunker.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/embedder.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/internet_retriever.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/llm.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/mem_chat.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/mem_cube.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/mem_os.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/mem_reader.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/mem_user.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/memory.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/parser.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/reranker.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/utils.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/configs/vec_db.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/dependency.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/deprecation.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/embedders/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/embedders/ark.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/embedders/base.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/embedders/ollama.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/embedders/sentence_transformer.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/embedders/universal_api.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/exceptions.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/graph_dbs/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/graph_dbs/base.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/graph_dbs/factory.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/graph_dbs/item.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/hello_world.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/llms/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/llms/base.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/llms/deepseek.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/llms/hf.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/llms/hf_singleton.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/llms/ollama.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/llms/qwen.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/llms/utils.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/llms/vllm.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_chat/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_chat/base.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_chat/factory.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_chat/simple.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_cube/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_cube/base.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_cube/utils.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_os/client.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_os/utils/default_config.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_os/utils/format_utils.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_os/utils/reference_utils.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_reader/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_reader/base.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_reader/memory.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_scheduler/__init__.py +0 -0
- {memoryos-1.0.1/src/memos/mem_scheduler/general_modules → memoryos-1.1.2/src/memos/mem_scheduler/analyzer}/__init__.py +0 -0
- {memoryos-1.0.1/src/memos/mem_scheduler/monitors → memoryos-1.1.2/src/memos/mem_scheduler/general_modules}/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_scheduler/general_modules/base.py +0 -0
- {memoryos-1.0.1/src/memos/mem_scheduler/schemas → memoryos-1.1.2/src/memos/mem_scheduler/monitors}/__init__.py +0 -0
- {memoryos-1.0.1/src/memos/mem_scheduler/utils → memoryos-1.1.2/src/memos/mem_scheduler/orm_modules}/__init__.py +0 -0
- {memoryos-1.0.1/src/memos/memories → memoryos-1.1.2/src/memos/mem_scheduler/schemas}/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_scheduler/schemas/general_schemas.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_scheduler/schemas/message_schemas.py +0 -0
- {memoryos-1.0.1/src/memos/memories/activation → memoryos-1.1.2/src/memos/mem_scheduler/utils}/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_scheduler/utils/misc_utils.py +0 -0
- {memoryos-1.0.1/src/memos/memories/parametric → memoryos-1.1.2/src/memos/mem_scheduler/webservice_modules}/__init__.py +0 -0
- {memoryos-1.0.1/src/memos/mem_scheduler/general_modules → memoryos-1.1.2/src/memos/mem_scheduler/webservice_modules}/rabbitmq_service.py +0 -0
- {memoryos-1.0.1/src/memos/mem_scheduler/general_modules → memoryos-1.1.2/src/memos/mem_scheduler/webservice_modules}/redis_service.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_user/factory.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_user/mysql_persistent_user_manager.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_user/mysql_user_manager.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_user/persistent_factory.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_user/persistent_user_manager.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/mem_user/user_manager.py +0 -0
- {memoryos-1.0.1/src/memos/memories/textual → memoryos-1.1.2/src/memos/memories}/__init__.py +0 -0
- {memoryos-1.0.1/src/memos/memories/textual/tree_text_memory → memoryos-1.1.2/src/memos/memories/activation}/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/activation/base.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/activation/item.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/activation/vllmkv.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/base.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/factory.py +0 -0
- {memoryos-1.0.1/src/memos/memories/textual/tree_text_memory/organize → memoryos-1.1.2/src/memos/memories/parametric}/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/parametric/base.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/parametric/item.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/parametric/lora.py +0 -0
- {memoryos-1.0.1/src/memos/memories/textual/tree_text_memory/retrieve → memoryos-1.1.2/src/memos/memories/textual}/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/base.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/general.py +0 -0
- {memoryos-1.0.1/src/memos/parsers → memoryos-1.1.2/src/memos/memories/textual/tree_text_memory}/__init__.py +0 -0
- {memoryos-1.0.1/src/memos/templates → memoryos-1.1.2/src/memos/memories/textual/tree_text_memory/organize}/__init__.py +0 -0
- {memoryos-1.0.1/src/memos/vec_dbs → memoryos-1.1.2/src/memos/memories/textual/tree_text_memory/retrieve}/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree_text_memory/retrieve/reasoner.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree_text_memory/retrieve/reranker.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree_text_memory/retrieve/retrieval_mid_structs.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree_text_memory/retrieve/task_goal_parser.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memories/textual/tree_text_memory/retrieve/utils.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memos_tools/dinding_report_bot.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memos_tools/lockfree_dict.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memos_tools/notification_service.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/memos_tools/notification_utils.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/parsers/base.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/parsers/markitdown.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/reranker/__init__.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/reranker/base.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/reranker/noop.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/settings.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/templates/mem_reader_prompts.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/templates/mos_prompts.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/templates/tree_reorganize_prompts.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/utils.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/vec_dbs/base.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/vec_dbs/factory.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/vec_dbs/item.py +0 -0
- {memoryos-1.0.1 → memoryos-1.1.2}/src/memos/vec_dbs/qdrant.py +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: MemoryOS
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.2
|
|
4
4
|
Summary: Intelligence Begins with Memory
|
|
5
5
|
License: Apache-2.0
|
|
6
|
+
License-File: LICENSE
|
|
6
7
|
Keywords: memory,llm,language model,memoryOS,agent,kv cache,lora
|
|
7
8
|
Author: MemTensor
|
|
8
9
|
Author-email: MemTensor@memtensor.cn
|
|
@@ -22,6 +23,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
22
23
|
Provides-Extra: all
|
|
23
24
|
Provides-Extra: mem-reader
|
|
24
25
|
Provides-Extra: mem-scheduler
|
|
26
|
+
Provides-Extra: mem-user
|
|
25
27
|
Provides-Extra: tree-mem
|
|
26
28
|
Requires-Dist: chonkie (>=1.0.7,<2.0.0) ; extra == "all"
|
|
27
29
|
Requires-Dist: chonkie (>=1.0.7,<2.0.0) ; extra == "mem-reader"
|
|
@@ -35,6 +37,9 @@ Requires-Dist: ollama (>=0.4.8,<0.5.0)
|
|
|
35
37
|
Requires-Dist: openai (>=1.77.0,<2.0.0)
|
|
36
38
|
Requires-Dist: pika (>=1.3.2,<2.0.0) ; extra == "all"
|
|
37
39
|
Requires-Dist: pika (>=1.3.2,<2.0.0) ; extra == "mem-scheduler"
|
|
40
|
+
Requires-Dist: pymysql (>=1.1.0,<2.0.0)
|
|
41
|
+
Requires-Dist: pymysql (>=1.1.0,<2.0.0) ; extra == "all"
|
|
42
|
+
Requires-Dist: pymysql (>=1.1.0,<2.0.0) ; extra == "mem-user"
|
|
38
43
|
Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
|
|
39
44
|
Requires-Dist: qdrant-client (>=1.14.2,<2.0.0) ; extra == "all"
|
|
40
45
|
Requires-Dist: redis (>=6.2.0,<7.0.0) ; extra == "all"
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
##############################################################################
|
|
5
5
|
|
|
6
6
|
name = "MemoryOS"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.1.2"
|
|
8
8
|
description = "Intelligence Begins with Memory"
|
|
9
9
|
license = {text = "Apache-2.0"}
|
|
10
10
|
readme = "README.md"
|
|
@@ -42,6 +42,7 @@ dependencies = [
|
|
|
42
42
|
"tenacity (>=9.1.2,<10.0.0)", # Error handling and retrying library
|
|
43
43
|
"fastapi[all] (>=0.115.12,<0.116.0)", # Web framework for building APIs
|
|
44
44
|
"sqlalchemy (>=2.0.41,<3.0.0)", # SQL toolkit
|
|
45
|
+
"pymysql (>=1.1.0,<2.0.0)", # MySQL Python driver
|
|
45
46
|
"scikit-learn (>=1.7.0,<2.0.0)", # Machine learning
|
|
46
47
|
"fastmcp (>=2.10.5,<3.0.0)",
|
|
47
48
|
"python-dateutil (>=2.9.0.post0,<3.0.0)",
|
|
@@ -76,6 +77,11 @@ mem-scheduler = [
|
|
|
76
77
|
"pika (>=1.3.2,<2.0.0)", # RabbitMQ client
|
|
77
78
|
]
|
|
78
79
|
|
|
80
|
+
# MemUser (MySQL support)
|
|
81
|
+
mem-user = [
|
|
82
|
+
"pymysql (>=1.1.0,<2.0.0)", # MySQL client for SQLAlchemy
|
|
83
|
+
]
|
|
84
|
+
|
|
79
85
|
# MemReader
|
|
80
86
|
mem-reader = [
|
|
81
87
|
"chonkie (>=1.0.7,<2.0.0)", # Sentence chunking library
|
|
@@ -90,6 +96,7 @@ all = [
|
|
|
90
96
|
"schedule (>=1.2.2,<2.0.0)",
|
|
91
97
|
"redis (>=6.2.0,<7.0.0)",
|
|
92
98
|
"pika (>=1.3.2,<2.0.0)",
|
|
99
|
+
"pymysql (>=1.1.0,<2.0.0)",
|
|
93
100
|
"chonkie (>=1.0.7,<2.0.0)",
|
|
94
101
|
"markitdown[docx,pdf,pptx,xls,xlsx] (>=0.1.1,<0.2.0)",
|
|
95
102
|
|
|
@@ -158,6 +165,10 @@ python-dotenv = "^1.1.1"
|
|
|
158
165
|
langgraph = "^0.5.1"
|
|
159
166
|
langmem = "^0.0.27"
|
|
160
167
|
|
|
168
|
+
|
|
169
|
+
[tool.poetry.group.mem-user.dependencies]
|
|
170
|
+
pymysql = "^1.1.2"
|
|
171
|
+
|
|
161
172
|
[[tool.poetry.source]]
|
|
162
173
|
name = "mirrors"
|
|
163
174
|
url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple/"
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
import requests
|
|
7
|
+
|
|
8
|
+
from memos.api.product_models import MemOSAddResponse, MemOSGetMessagesResponse, MemOSSearchResponse
|
|
9
|
+
from memos.log import get_logger
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
logger = get_logger(__name__)
|
|
13
|
+
|
|
14
|
+
MAX_RETRY_COUNT = 3
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class MemOSClient:
|
|
18
|
+
"""MemOS API client"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, api_key: str | None = None, base_url: str | None = None):
|
|
21
|
+
self.base_url = (
|
|
22
|
+
base_url or os.getenv("MEMOS_BASE_URL") or "https://memos.memtensor.cn/api/openmem/v1"
|
|
23
|
+
)
|
|
24
|
+
api_key = api_key or os.getenv("MEMOS_API_KEY")
|
|
25
|
+
|
|
26
|
+
if not api_key:
|
|
27
|
+
raise ValueError("MemOS API key is required")
|
|
28
|
+
|
|
29
|
+
self.headers = {"Content-Type": "application/json", "Authorization": f"Token {api_key}"}
|
|
30
|
+
|
|
31
|
+
def _validate_required_params(self, **params):
|
|
32
|
+
"""Validate required parameters - if passed, they must not be empty"""
|
|
33
|
+
for param_name, param_value in params.items():
|
|
34
|
+
if not param_value:
|
|
35
|
+
raise ValueError(f"{param_name} is required")
|
|
36
|
+
|
|
37
|
+
def get_message(
|
|
38
|
+
self, user_id: str, conversation_id: str | None = None
|
|
39
|
+
) -> MemOSGetMessagesResponse:
|
|
40
|
+
"""Get messages"""
|
|
41
|
+
# Validate required parameters
|
|
42
|
+
self._validate_required_params(user_id=user_id)
|
|
43
|
+
|
|
44
|
+
url = f"{self.base_url}/get/message"
|
|
45
|
+
payload = {"user_id": user_id, "conversation_id": conversation_id}
|
|
46
|
+
for retry in range(MAX_RETRY_COUNT):
|
|
47
|
+
try:
|
|
48
|
+
response = requests.post(
|
|
49
|
+
url, data=json.dumps(payload), headers=self.headers, timeout=30
|
|
50
|
+
)
|
|
51
|
+
response.raise_for_status()
|
|
52
|
+
response_data = response.json()
|
|
53
|
+
return MemOSGetMessagesResponse(**response_data)
|
|
54
|
+
except Exception as e:
|
|
55
|
+
logger.error(f"Failed to get messages (retry {retry + 1}/3): {e}")
|
|
56
|
+
if retry == MAX_RETRY_COUNT - 1:
|
|
57
|
+
raise
|
|
58
|
+
|
|
59
|
+
def add_message(
|
|
60
|
+
self, messages: list[dict[str, Any]], user_id: str, conversation_id: str
|
|
61
|
+
) -> MemOSAddResponse:
|
|
62
|
+
"""Add memories"""
|
|
63
|
+
# Validate required parameters
|
|
64
|
+
self._validate_required_params(
|
|
65
|
+
messages=messages, user_id=user_id, conversation_id=conversation_id
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
url = f"{self.base_url}/add/message"
|
|
69
|
+
payload = {"messages": messages, "user_id": user_id, "conversation_id": conversation_id}
|
|
70
|
+
for retry in range(MAX_RETRY_COUNT):
|
|
71
|
+
try:
|
|
72
|
+
response = requests.post(
|
|
73
|
+
url, data=json.dumps(payload), headers=self.headers, timeout=30
|
|
74
|
+
)
|
|
75
|
+
response.raise_for_status()
|
|
76
|
+
response_data = response.json()
|
|
77
|
+
return MemOSAddResponse(**response_data)
|
|
78
|
+
except Exception as e:
|
|
79
|
+
logger.error(f"Failed to add memory (retry {retry + 1}/3): {e}")
|
|
80
|
+
if retry == MAX_RETRY_COUNT - 1:
|
|
81
|
+
raise
|
|
82
|
+
|
|
83
|
+
def search_memory(
|
|
84
|
+
self, query: str, user_id: str, conversation_id: str, memory_limit_number: int = 6
|
|
85
|
+
) -> MemOSSearchResponse:
|
|
86
|
+
"""Search memories"""
|
|
87
|
+
# Validate required parameters
|
|
88
|
+
self._validate_required_params(query=query, user_id=user_id)
|
|
89
|
+
|
|
90
|
+
url = f"{self.base_url}/search/memory"
|
|
91
|
+
payload = {
|
|
92
|
+
"query": query,
|
|
93
|
+
"user_id": user_id,
|
|
94
|
+
"conversation_id": conversation_id,
|
|
95
|
+
"memory_limit_number": memory_limit_number,
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
for retry in range(MAX_RETRY_COUNT):
|
|
99
|
+
try:
|
|
100
|
+
response = requests.post(
|
|
101
|
+
url, data=json.dumps(payload), headers=self.headers, timeout=30
|
|
102
|
+
)
|
|
103
|
+
response.raise_for_status()
|
|
104
|
+
response_data = response.json()
|
|
105
|
+
return MemOSSearchResponse(**response_data)
|
|
106
|
+
except Exception as e:
|
|
107
|
+
logger.error(f"Failed to search memory (retry {retry + 1}/3): {e}")
|
|
108
|
+
if retry == MAX_RETRY_COUNT - 1:
|
|
109
|
+
raise
|
|
@@ -21,7 +21,7 @@ class APIConfig:
|
|
|
21
21
|
def get_openai_config() -> dict[str, Any]:
|
|
22
22
|
"""Get OpenAI configuration."""
|
|
23
23
|
return {
|
|
24
|
-
"model_name_or_path": os.getenv("
|
|
24
|
+
"model_name_or_path": os.getenv("MOS_CHAT_MODEL", "gpt-4o-mini"),
|
|
25
25
|
"temperature": float(os.getenv("MOS_CHAT_TEMPERATURE", "0.8")),
|
|
26
26
|
"max_tokens": int(os.getenv("MOS_MAX_TOKENS", "1024")),
|
|
27
27
|
"top_p": float(os.getenv("MOS_TOP_P", "0.9")),
|
|
@@ -100,8 +100,10 @@ class APIConfig:
|
|
|
100
100
|
"backend": "http_bge",
|
|
101
101
|
"config": {
|
|
102
102
|
"url": os.getenv("MOS_RERANKER_URL"),
|
|
103
|
-
"model": "bge-reranker-v2-m3",
|
|
103
|
+
"model": os.getenv("MOS_RERANKER_MODEL", "bge-reranker-v2-m3"),
|
|
104
104
|
"timeout": 10,
|
|
105
|
+
"headers_extra": os.getenv("MOS_RERANKER_HEADERS_EXTRA"),
|
|
106
|
+
"rerank_source": os.getenv("MOS_RERANK_SOURCE"),
|
|
105
107
|
},
|
|
106
108
|
}
|
|
107
109
|
else:
|
|
@@ -186,22 +188,22 @@ class APIConfig:
|
|
|
186
188
|
return {
|
|
187
189
|
"uri": os.getenv("NEO4J_URI", "bolt://localhost:7687"),
|
|
188
190
|
"user": os.getenv("NEO4J_USER", "neo4j"),
|
|
189
|
-
"db_name": os.getenv("NEO4J_DB_NAME", "
|
|
191
|
+
"db_name": os.getenv("NEO4J_DB_NAME", "neo4j"),
|
|
190
192
|
"password": os.getenv("NEO4J_PASSWORD", "12345678"),
|
|
191
193
|
"user_name": f"memos{user_id.replace('-', '')}",
|
|
192
|
-
"auto_create":
|
|
194
|
+
"auto_create": False,
|
|
193
195
|
"use_multi_db": False,
|
|
194
|
-
"embedding_dimension": int(os.getenv("EMBEDDING_DIMENSION",
|
|
196
|
+
"embedding_dimension": int(os.getenv("EMBEDDING_DIMENSION", 1024)),
|
|
195
197
|
"vec_config": {
|
|
196
198
|
# Pass nested config to initialize external vector DB
|
|
197
199
|
# If you use qdrant, please use Server instead of local mode.
|
|
198
200
|
"backend": "qdrant",
|
|
199
201
|
"config": {
|
|
200
202
|
"collection_name": "neo4j_vec_db",
|
|
201
|
-
"vector_dimension": int(os.getenv("EMBEDDING_DIMENSION",
|
|
203
|
+
"vector_dimension": int(os.getenv("EMBEDDING_DIMENSION", 1024)),
|
|
202
204
|
"distance_metric": "cosine",
|
|
203
|
-
"host": "localhost",
|
|
204
|
-
"port": 6333,
|
|
205
|
+
"host": os.getenv("QDRANT_HOST", "localhost"),
|
|
206
|
+
"port": int(os.getenv("QDRANT_PORT", "6333")),
|
|
205
207
|
},
|
|
206
208
|
},
|
|
207
209
|
}
|
|
@@ -271,7 +273,7 @@ class APIConfig:
|
|
|
271
273
|
def get_scheduler_config() -> dict[str, Any]:
|
|
272
274
|
"""Get scheduler configuration."""
|
|
273
275
|
return {
|
|
274
|
-
"backend": "
|
|
276
|
+
"backend": "optimized_scheduler",
|
|
275
277
|
"config": {
|
|
276
278
|
"top_k": int(os.getenv("MOS_SCHEDULER_TOP_K", "10")),
|
|
277
279
|
"act_mem_update_interval": int(
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from memos.context.context import RequestContext, get_current_context
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
# Type alias for the RequestContext from context module
|
|
9
|
+
G = RequestContext
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_g_object() -> G:
|
|
13
|
+
"""
|
|
14
|
+
Get Flask g-like object for the current request.
|
|
15
|
+
Returns the context created by middleware.
|
|
16
|
+
"""
|
|
17
|
+
ctx = get_current_context()
|
|
18
|
+
if ctx is None:
|
|
19
|
+
raise RuntimeError(
|
|
20
|
+
"No request context available. Make sure RequestContextMiddleware is properly configured."
|
|
21
|
+
)
|
|
22
|
+
return ctx
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_current_g() -> G | None:
|
|
26
|
+
"""
|
|
27
|
+
Get the current request's g object from anywhere in the application.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
The current request's g object if available, None otherwise.
|
|
31
|
+
"""
|
|
32
|
+
return get_current_context()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def require_g() -> G:
|
|
36
|
+
"""
|
|
37
|
+
Get the current request's g object, raising an error if not available.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
The current request's g object.
|
|
41
|
+
|
|
42
|
+
Raises:
|
|
43
|
+
RuntimeError: If called outside of a request context.
|
|
44
|
+
"""
|
|
45
|
+
ctx = get_current_context()
|
|
46
|
+
if ctx is None:
|
|
47
|
+
raise RuntimeError(
|
|
48
|
+
"No request context available. This function must be called within a request handler."
|
|
49
|
+
)
|
|
50
|
+
return ctx
|
|
@@ -2,40 +2,25 @@
|
|
|
2
2
|
Request context middleware for automatic trace_id injection.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
import logging
|
|
6
|
-
import os
|
|
7
|
-
|
|
8
5
|
from collections.abc import Callable
|
|
9
6
|
|
|
10
7
|
from starlette.middleware.base import BaseHTTPMiddleware
|
|
11
8
|
from starlette.requests import Request
|
|
12
9
|
from starlette.responses import Response
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
import memos.log
|
|
16
12
|
|
|
17
|
-
|
|
13
|
+
from memos.context.context import RequestContext, generate_trace_id, set_request_context
|
|
18
14
|
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
"""Generate a random trace_id."""
|
|
22
|
-
return os.urandom(16).hex()
|
|
16
|
+
logger = memos.log.get_logger(__name__)
|
|
23
17
|
|
|
24
18
|
|
|
25
19
|
def extract_trace_id_from_headers(request: Request) -> str | None:
|
|
26
20
|
"""Extract trace_id from various possible headers with priority: g-trace-id > x-trace-id > trace-id."""
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
trace_id = request.headers.get("x-trace-id")
|
|
32
|
-
if trace_id:
|
|
33
|
-
return trace_id
|
|
34
|
-
|
|
35
|
-
trace_id = request.headers.get("trace-id")
|
|
36
|
-
if trace_id:
|
|
37
|
-
return trace_id
|
|
38
|
-
|
|
21
|
+
for header in ["g-trace-id", "x-trace-id", "trace-id"]:
|
|
22
|
+
if trace_id := request.headers.get(header):
|
|
23
|
+
return trace_id
|
|
39
24
|
return None
|
|
40
25
|
|
|
41
26
|
|
|
@@ -51,19 +36,12 @@ class RequestContextMiddleware(BaseHTTPMiddleware):
|
|
|
51
36
|
|
|
52
37
|
async def dispatch(self, request: Request, call_next: Callable) -> Response:
|
|
53
38
|
# Extract or generate trace_id
|
|
54
|
-
trace_id = extract_trace_id_from_headers(request)
|
|
55
|
-
if not trace_id:
|
|
56
|
-
trace_id = generate_trace_id()
|
|
39
|
+
trace_id = extract_trace_id_from_headers(request) or generate_trace_id()
|
|
57
40
|
|
|
58
41
|
# Create and set request context
|
|
59
|
-
context = RequestContext(trace_id=trace_id)
|
|
42
|
+
context = RequestContext(trace_id=trace_id, api_path=request.url.path)
|
|
60
43
|
set_request_context(context)
|
|
61
44
|
|
|
62
|
-
# Add request metadata to context
|
|
63
|
-
context.set("method", request.method)
|
|
64
|
-
context.set("path", request.url.path)
|
|
65
|
-
context.set("client_ip", request.client.host if request.client else None)
|
|
66
|
-
|
|
67
45
|
# Log request start with parameters
|
|
68
46
|
params_log = {}
|
|
69
47
|
|
|
@@ -71,16 +49,7 @@ class RequestContextMiddleware(BaseHTTPMiddleware):
|
|
|
71
49
|
if request.query_params:
|
|
72
50
|
params_log["query_params"] = dict(request.query_params)
|
|
73
51
|
|
|
74
|
-
|
|
75
|
-
try:
|
|
76
|
-
params_log = await request.json()
|
|
77
|
-
except Exception as e:
|
|
78
|
-
logger.error(f"Error getting request body: {e}")
|
|
79
|
-
# If body is not JSON or empty, ignore it
|
|
80
|
-
|
|
81
|
-
logger.info(
|
|
82
|
-
f"Request started: {request.method} {request.url.path} - Parameters: {params_log}"
|
|
83
|
-
)
|
|
52
|
+
logger.info(f"Request started: {request.method} {request.url.path}, {params_log}")
|
|
84
53
|
|
|
85
54
|
# Process the request
|
|
86
55
|
response = await call_next(request)
|
|
@@ -17,9 +17,7 @@ app = FastAPI(
|
|
|
17
17
|
version="1.0.1",
|
|
18
18
|
)
|
|
19
19
|
|
|
20
|
-
# Add request context middleware (must be added first)
|
|
21
20
|
app.add_middleware(RequestContextMiddleware)
|
|
22
|
-
|
|
23
21
|
# Include routers
|
|
24
22
|
app.include_router(product_router)
|
|
25
23
|
|
|
@@ -35,5 +33,6 @@ if __name__ == "__main__":
|
|
|
35
33
|
|
|
36
34
|
parser = argparse.ArgumentParser()
|
|
37
35
|
parser.add_argument("--port", type=int, default=8001)
|
|
36
|
+
parser.add_argument("--workers", type=int, default=32)
|
|
38
37
|
args = parser.parse_args()
|
|
39
|
-
uvicorn.run(app, host="0.0.0.0", port=args.port)
|
|
38
|
+
uvicorn.run("memos.api.product_api:app", host="0.0.0.0", port=args.port, workers=args.workers)
|
|
@@ -1,26 +1,14 @@
|
|
|
1
1
|
import uuid
|
|
2
2
|
|
|
3
|
-
from typing import Generic, Literal,
|
|
3
|
+
from typing import Generic, Literal, TypeVar
|
|
4
4
|
|
|
5
5
|
from pydantic import BaseModel, Field
|
|
6
|
-
from typing_extensions import TypedDict
|
|
7
6
|
|
|
7
|
+
# Import message types from core types module
|
|
8
|
+
from memos.types import MessageDict
|
|
8
9
|
|
|
9
|
-
T = TypeVar("T")
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
# ─── Message Types ──────────────────────────────────────────────────────────────
|
|
13
|
-
|
|
14
|
-
# Chat message roles
|
|
15
|
-
MessageRole: TypeAlias = Literal["user", "assistant", "system"]
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
# Message structure
|
|
19
|
-
class MessageDict(TypedDict):
|
|
20
|
-
"""Typed dictionary for chat message dictionaries."""
|
|
21
10
|
|
|
22
|
-
|
|
23
|
-
content: str
|
|
11
|
+
T = TypeVar("T")
|
|
24
12
|
|
|
25
13
|
|
|
26
14
|
class BaseRequest(BaseModel):
|
|
@@ -42,6 +30,7 @@ class UserRegisterRequest(BaseRequest):
|
|
|
42
30
|
user_id: str = Field(
|
|
43
31
|
default_factory=lambda: str(uuid.uuid4()), description="User ID for registration"
|
|
44
32
|
)
|
|
33
|
+
mem_cube_id: str | None = Field(None, description="Cube ID for registration")
|
|
45
34
|
user_name: str | None = Field(None, description="User name for registration")
|
|
46
35
|
interests: str | None = Field(None, description="User interests")
|
|
47
36
|
|
|
@@ -85,6 +74,7 @@ class ChatRequest(BaseRequest):
|
|
|
85
74
|
history: list[MessageDict] | None = Field(None, description="Chat history")
|
|
86
75
|
internet_search: bool = Field(True, description="Whether to use internet search")
|
|
87
76
|
moscube: bool = Field(False, description="Whether to use MemOSCube")
|
|
77
|
+
session_id: str | None = Field(None, description="Session ID for soft-filtering memories")
|
|
88
78
|
|
|
89
79
|
|
|
90
80
|
class ChatCompleteRequest(BaseRequest):
|
|
@@ -99,6 +89,7 @@ class ChatCompleteRequest(BaseRequest):
|
|
|
99
89
|
base_prompt: str | None = Field(None, description="Base prompt to use for chat")
|
|
100
90
|
top_k: int = Field(10, description="Number of results to return")
|
|
101
91
|
threshold: float = Field(0.5, description="Threshold for filtering references")
|
|
92
|
+
session_id: str | None = Field(None, description="Session ID for soft-filtering memories")
|
|
102
93
|
|
|
103
94
|
|
|
104
95
|
class UserCreate(BaseRequest):
|
|
@@ -160,6 +151,7 @@ class MemoryCreateRequest(BaseRequest):
|
|
|
160
151
|
mem_cube_id: str | None = Field(None, description="Cube ID")
|
|
161
152
|
source: str | None = Field(None, description="Source of the memory")
|
|
162
153
|
user_profile: bool = Field(False, description="User profile memory")
|
|
154
|
+
session_id: str | None = Field(None, description="Session id")
|
|
163
155
|
|
|
164
156
|
|
|
165
157
|
class SearchRequest(BaseRequest):
|
|
@@ -169,6 +161,7 @@ class SearchRequest(BaseRequest):
|
|
|
169
161
|
query: str = Field(..., description="Search query")
|
|
170
162
|
mem_cube_id: str | None = Field(None, description="Cube ID to search in")
|
|
171
163
|
top_k: int = Field(10, description="Number of results to return")
|
|
164
|
+
session_id: str | None = Field(None, description="Session ID for soft-filtering memories")
|
|
172
165
|
|
|
173
166
|
|
|
174
167
|
class SuggestionRequest(BaseRequest):
|
|
@@ -177,3 +170,85 @@ class SuggestionRequest(BaseRequest):
|
|
|
177
170
|
user_id: str = Field(..., description="User ID")
|
|
178
171
|
language: Literal["zh", "en"] = Field("zh", description="Language for suggestions")
|
|
179
172
|
message: list[MessageDict] | None = Field(None, description="List of messages to store.")
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
# ─── MemOS Client Response Models ──────────────────────────────────────────────
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class MessageDetail(BaseModel):
|
|
179
|
+
"""Individual message detail model based on actual API response."""
|
|
180
|
+
|
|
181
|
+
model_config = {"extra": "allow"}
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class MemoryDetail(BaseModel):
|
|
185
|
+
"""Individual memory detail model based on actual API response."""
|
|
186
|
+
|
|
187
|
+
model_config = {"extra": "allow"}
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class GetMessagesData(BaseModel):
|
|
191
|
+
"""Data model for get messages response based on actual API."""
|
|
192
|
+
|
|
193
|
+
message_detail_list: list[MessageDetail] = Field(
|
|
194
|
+
default_factory=list, alias="message_detail_list", description="List of message details"
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
class SearchMemoryData(BaseModel):
|
|
199
|
+
"""Data model for search memory response based on actual API."""
|
|
200
|
+
|
|
201
|
+
memory_detail_list: list[MemoryDetail] = Field(
|
|
202
|
+
default_factory=list, alias="memory_detail_list", description="List of memory details"
|
|
203
|
+
)
|
|
204
|
+
message_detail_list: list[MessageDetail] | None = Field(
|
|
205
|
+
None, alias="message_detail_list", description="List of message details (usually None)"
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class AddMessageData(BaseModel):
|
|
210
|
+
"""Data model for add message response based on actual API."""
|
|
211
|
+
|
|
212
|
+
success: bool = Field(..., description="Operation success status")
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
# ─── MemOS Response Models (Similar to OpenAI ChatCompletion) ──────────────────
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class MemOSGetMessagesResponse(BaseModel):
|
|
219
|
+
"""Response model for get messages operation based on actual API."""
|
|
220
|
+
|
|
221
|
+
code: int = Field(..., description="Response status code")
|
|
222
|
+
message: str = Field(..., description="Response message")
|
|
223
|
+
data: GetMessagesData = Field(..., description="Messages data")
|
|
224
|
+
|
|
225
|
+
@property
|
|
226
|
+
def messages(self) -> list[MessageDetail]:
|
|
227
|
+
"""Convenient access to message list."""
|
|
228
|
+
return self.data.message_detail_list
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
class MemOSSearchResponse(BaseModel):
|
|
232
|
+
"""Response model for search memory operation based on actual API."""
|
|
233
|
+
|
|
234
|
+
code: int = Field(..., description="Response status code")
|
|
235
|
+
message: str = Field(..., description="Response message")
|
|
236
|
+
data: SearchMemoryData = Field(..., description="Search results data")
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def memories(self) -> list[MemoryDetail]:
|
|
240
|
+
"""Convenient access to memory list."""
|
|
241
|
+
return self.data.memory_detail_list
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
class MemOSAddResponse(BaseModel):
|
|
245
|
+
"""Response model for add message operation based on actual API."""
|
|
246
|
+
|
|
247
|
+
code: int = Field(..., description="Response status code")
|
|
248
|
+
message: str = Field(..., description="Response message")
|
|
249
|
+
data: AddMessageData = Field(..., description="Add operation data")
|
|
250
|
+
|
|
251
|
+
@property
|
|
252
|
+
def success(self) -> bool:
|
|
253
|
+
"""Convenient access to success status."""
|
|
254
|
+
return self.data.success
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import time
|
|
2
3
|
import traceback
|
|
3
4
|
|
|
4
|
-
from
|
|
5
|
-
from typing import Annotated
|
|
6
|
-
|
|
7
|
-
from fastapi import APIRouter, Depends, HTTPException
|
|
5
|
+
from fastapi import APIRouter, HTTPException
|
|
8
6
|
from fastapi.responses import StreamingResponse
|
|
9
7
|
|
|
10
8
|
from memos.api.config import APIConfig
|
|
11
|
-
from memos.api.context.dependencies import G, get_g_object
|
|
12
9
|
from memos.api.product_models import (
|
|
13
10
|
BaseResponse,
|
|
14
11
|
ChatCompleteRequest,
|
|
@@ -79,24 +76,19 @@ def set_config(config):
|
|
|
79
76
|
|
|
80
77
|
|
|
81
78
|
@router.post("/users/register", summary="Register a new user", response_model=UserRegisterResponse)
|
|
82
|
-
def register_user(user_req: UserRegisterRequest
|
|
79
|
+
def register_user(user_req: UserRegisterRequest):
|
|
83
80
|
"""Register a new user with configuration and default cube."""
|
|
84
81
|
try:
|
|
85
|
-
# Set request-related information in g object
|
|
86
|
-
g.user_id = user_req.user_id
|
|
87
|
-
g.action = "user_register"
|
|
88
|
-
g.timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
89
|
-
|
|
90
|
-
logger.info(f"Starting user registration for user_id: {user_req.user_id}")
|
|
91
|
-
logger.info(f"Request trace_id: {g.trace_id}")
|
|
92
|
-
logger.info(f"Request timestamp: {g.timestamp}")
|
|
93
|
-
|
|
94
82
|
# Get configuration for the user
|
|
83
|
+
time_start_register = time.time()
|
|
95
84
|
user_config, default_mem_cube = APIConfig.create_user_config(
|
|
96
85
|
user_name=user_req.user_id, user_id=user_req.user_id
|
|
97
86
|
)
|
|
98
87
|
logger.info(f"user_config: {user_config.model_dump(mode='json')}")
|
|
99
88
|
logger.info(f"default_mem_cube: {default_mem_cube.config.model_dump(mode='json')}")
|
|
89
|
+
logger.info(
|
|
90
|
+
f"time register api : create user config time user_id: {user_req.user_id} time is: {time.time() - time_start_register}"
|
|
91
|
+
)
|
|
100
92
|
mos_product = get_mos_product_instance()
|
|
101
93
|
|
|
102
94
|
# Register user with default config and mem cube
|
|
@@ -106,8 +98,11 @@ def register_user(user_req: UserRegisterRequest, g: Annotated[G, Depends(get_g_o
|
|
|
106
98
|
interests=user_req.interests,
|
|
107
99
|
config=user_config,
|
|
108
100
|
default_mem_cube=default_mem_cube,
|
|
101
|
+
mem_cube_id=user_req.mem_cube_id,
|
|
102
|
+
)
|
|
103
|
+
logger.info(
|
|
104
|
+
f"time register api : register time user_id: {user_req.user_id} time is: {time.time() - time_start_register}"
|
|
109
105
|
)
|
|
110
|
-
|
|
111
106
|
if result["status"] == "success":
|
|
112
107
|
return UserRegisterResponse(
|
|
113
108
|
message="User registered successfully",
|
|
@@ -194,6 +189,7 @@ def get_all_memories(memory_req: GetMemoryRequest):
|
|
|
194
189
|
def create_memory(memory_req: MemoryCreateRequest):
|
|
195
190
|
"""Create a new memory for a specific user."""
|
|
196
191
|
try:
|
|
192
|
+
time_start_add = time.time()
|
|
197
193
|
mos_product = get_mos_product_instance()
|
|
198
194
|
mos_product.add(
|
|
199
195
|
user_id=memory_req.user_id,
|
|
@@ -203,6 +199,10 @@ def create_memory(memory_req: MemoryCreateRequest):
|
|
|
203
199
|
mem_cube_id=memory_req.mem_cube_id,
|
|
204
200
|
source=memory_req.source,
|
|
205
201
|
user_profile=memory_req.user_profile,
|
|
202
|
+
session_id=memory_req.session_id,
|
|
203
|
+
)
|
|
204
|
+
logger.info(
|
|
205
|
+
f"time add api : add time user_id: {memory_req.user_id} time is: {time.time() - time_start_add}"
|
|
206
206
|
)
|
|
207
207
|
return SimpleResponse(message="Memory created successfully")
|
|
208
208
|
|
|
@@ -217,12 +217,17 @@ def create_memory(memory_req: MemoryCreateRequest):
|
|
|
217
217
|
def search_memories(search_req: SearchRequest):
|
|
218
218
|
"""Search memories for a specific user."""
|
|
219
219
|
try:
|
|
220
|
+
time_start_search = time.time()
|
|
220
221
|
mos_product = get_mos_product_instance()
|
|
221
222
|
result = mos_product.search(
|
|
222
223
|
query=search_req.query,
|
|
223
224
|
user_id=search_req.user_id,
|
|
224
225
|
install_cube_ids=[search_req.mem_cube_id] if search_req.mem_cube_id else None,
|
|
225
226
|
top_k=search_req.top_k,
|
|
227
|
+
session_id=search_req.session_id,
|
|
228
|
+
)
|
|
229
|
+
logger.info(
|
|
230
|
+
f"time search api : add time user_id: {search_req.user_id} time is: {time.time() - time_start_search}"
|
|
226
231
|
)
|
|
227
232
|
return SearchResponse(message="Search completed successfully", data=result)
|
|
228
233
|
|
|
@@ -250,6 +255,7 @@ def chat(chat_req: ChatRequest):
|
|
|
250
255
|
history=chat_req.history,
|
|
251
256
|
internet_search=chat_req.internet_search,
|
|
252
257
|
moscube=chat_req.moscube,
|
|
258
|
+
session_id=chat_req.session_id,
|
|
253
259
|
)
|
|
254
260
|
|
|
255
261
|
except Exception as e:
|
|
@@ -294,6 +300,7 @@ def chat_complete(chat_req: ChatCompleteRequest):
|
|
|
294
300
|
base_prompt=chat_req.base_prompt,
|
|
295
301
|
top_k=chat_req.top_k,
|
|
296
302
|
threshold=chat_req.threshold,
|
|
303
|
+
session_id=chat_req.session_id,
|
|
297
304
|
)
|
|
298
305
|
|
|
299
306
|
# Return the complete response
|