MemoryOS 1.0.0__tar.gz → 1.1.1__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.0 → memoryos-1.1.1}/PKG-INFO +8 -2
- {memoryos-1.0.0 → memoryos-1.1.1}/README.md +1 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/pyproject.toml +12 -1
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/__init__.py +1 -1
- memoryos-1.1.1/src/memos/api/client.py +109 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/api/config.py +35 -8
- memoryos-1.1.1/src/memos/api/context/dependencies.py +50 -0
- memoryos-1.1.1/src/memos/api/middleware/request_context.py +63 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/api/product_api.py +5 -2
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/api/product_models.py +107 -16
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/api/routers/product_router.py +62 -19
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/api/start_api.py +13 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/graph_db.py +4 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/mem_scheduler.py +38 -3
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/memory.py +13 -0
- memoryos-1.1.1/src/memos/configs/reranker.py +18 -0
- memoryos-1.1.1/src/memos/context/context.py +255 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/embedders/factory.py +2 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/graph_dbs/base.py +4 -2
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/graph_dbs/nebular.py +368 -223
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/graph_dbs/neo4j.py +49 -13
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/graph_dbs/neo4j_community.py +13 -3
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/llms/factory.py +2 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/llms/openai.py +74 -2
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/llms/vllm.py +2 -0
- memoryos-1.1.1/src/memos/log.py +207 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_cube/general.py +3 -1
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_os/core.py +89 -23
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_os/main.py +3 -6
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_os/product.py +418 -154
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_os/utils/reference_utils.py +20 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_reader/factory.py +2 -0
- memoryos-1.1.1/src/memos/mem_reader/simple_struct.py +376 -0
- memoryos-1.1.1/src/memos/mem_scheduler/analyzer/mos_for_test_scheduler.py +569 -0
- memoryos-1.1.1/src/memos/mem_scheduler/analyzer/scheduler_for_eval.py +280 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_scheduler/base_scheduler.py +126 -56
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_scheduler/general_modules/dispatcher.py +2 -2
- memoryos-1.1.1/src/memos/mem_scheduler/general_modules/misc.py +202 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_scheduler/general_modules/scheduler_logger.py +17 -11
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_scheduler/general_scheduler.py +40 -88
- memoryos-1.1.1/src/memos/mem_scheduler/memory_manage_modules/__init__.py +5 -0
- memoryos-1.1.1/src/memos/mem_scheduler/memory_manage_modules/memory_filter.py +308 -0
- {memoryos-1.0.0/src/memos/mem_scheduler/general_modules → memoryos-1.1.1/src/memos/mem_scheduler/memory_manage_modules}/retriever.py +34 -7
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_scheduler/monitors/dispatcher_monitor.py +9 -8
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_scheduler/monitors/general_monitor.py +119 -39
- memoryos-1.1.1/src/memos/mem_scheduler/optimized_scheduler.py +124 -0
- memoryos-1.1.1/src/memos/mem_scheduler/orm_modules/base_model.py +635 -0
- memoryos-1.1.1/src/memos/mem_scheduler/orm_modules/monitor_models.py +261 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_scheduler/scheduler_factory.py +2 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_scheduler/schemas/monitor_schemas.py +96 -29
- memoryos-1.1.1/src/memos/mem_scheduler/utils/config_utils.py +100 -0
- memoryos-1.1.1/src/memos/mem_scheduler/utils/db_utils.py +33 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_scheduler/utils/filter_utils.py +1 -1
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_user/mysql_user_manager.py +4 -2
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/activation/kv.py +2 -1
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/item.py +96 -17
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/naive.py +1 -1
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree.py +57 -3
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree_text_memory/organize/handler.py +4 -2
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree_text_memory/organize/manager.py +28 -14
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree_text_memory/organize/relation_reason_detector.py +1 -2
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree_text_memory/organize/reorganizer.py +75 -23
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree_text_memory/retrieve/bochasearch.py +10 -6
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree_text_memory/retrieve/internet_retriever.py +6 -2
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree_text_memory/retrieve/internet_retriever_factory.py +2 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree_text_memory/retrieve/recall.py +119 -21
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree_text_memory/retrieve/searcher.py +172 -44
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree_text_memory/retrieve/utils.py +6 -4
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree_text_memory/retrieve/xinyusearch.py +5 -4
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memos_tools/notification_utils.py +46 -0
- memoryos-1.1.1/src/memos/memos_tools/singleton.py +174 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memos_tools/thread_safe_dict.py +22 -0
- memoryos-1.1.1/src/memos/memos_tools/thread_safe_dict_segment.py +382 -0
- memoryos-1.1.1/src/memos/parsers/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/parsers/factory.py +2 -0
- memoryos-1.1.1/src/memos/reranker/__init__.py +4 -0
- memoryos-1.1.1/src/memos/reranker/base.py +24 -0
- memoryos-1.1.1/src/memos/reranker/concat.py +59 -0
- memoryos-1.1.1/src/memos/reranker/cosine_local.py +96 -0
- memoryos-1.1.1/src/memos/reranker/factory.py +48 -0
- memoryos-1.1.1/src/memos/reranker/http_bge.py +312 -0
- memoryos-1.1.1/src/memos/reranker/noop.py +16 -0
- memoryos-1.1.1/src/memos/templates/__init__.py +0 -0
- memoryos-1.1.1/src/memos/templates/mem_reader_prompts.py +419 -0
- memoryos-1.1.1/src/memos/templates/mem_scheduler_prompts.py +403 -0
- memoryos-1.1.1/src/memos/templates/mos_prompts.py +252 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/types.py +4 -1
- memoryos-1.1.1/src/memos/vec_dbs/__init__.py +0 -0
- memoryos-1.0.0/src/memos/api/context/context.py +0 -147
- memoryos-1.0.0/src/memos/api/context/dependencies.py +0 -101
- memoryos-1.0.0/src/memos/log.py +0 -83
- memoryos-1.0.0/src/memos/mem_reader/simple_struct.py +0 -254
- memoryos-1.0.0/src/memos/mem_scheduler/general_modules/misc.py +0 -104
- memoryos-1.0.0/src/memos/mem_scheduler/mos_for_test_scheduler.py +0 -146
- memoryos-1.0.0/src/memos/templates/mem_reader_prompts.py +0 -170
- memoryos-1.0.0/src/memos/templates/mem_scheduler_prompts.py +0 -161
- memoryos-1.0.0/src/memos/templates/mos_prompts.py +0 -179
- {memoryos-1.0.0 → memoryos-1.1.1}/LICENSE +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/api/exceptions.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/api/mcp_serve.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/api/routers/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/chunkers/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/chunkers/base.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/chunkers/factory.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/chunkers/sentence_chunker.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/cli.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/base.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/chunker.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/embedder.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/internet_retriever.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/llm.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/mem_chat.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/mem_cube.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/mem_os.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/mem_reader.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/mem_user.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/parser.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/utils.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/configs/vec_db.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/dependency.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/deprecation.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/embedders/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/embedders/ark.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/embedders/base.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/embedders/ollama.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/embedders/sentence_transformer.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/embedders/universal_api.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/exceptions.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/graph_dbs/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/graph_dbs/factory.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/graph_dbs/item.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/hello_world.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/llms/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/llms/base.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/llms/deepseek.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/llms/hf.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/llms/hf_singleton.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/llms/ollama.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/llms/qwen.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/llms/utils.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_chat/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_chat/base.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_chat/factory.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_chat/simple.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_cube/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_cube/base.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_cube/utils.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_os/client.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_os/utils/default_config.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_os/utils/format_utils.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_reader/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_reader/base.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_reader/memory.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_scheduler/__init__.py +0 -0
- {memoryos-1.0.0/src/memos/mem_scheduler/general_modules → memoryos-1.1.1/src/memos/mem_scheduler/analyzer}/__init__.py +0 -0
- {memoryos-1.0.0/src/memos/mem_scheduler/monitors → memoryos-1.1.1/src/memos/mem_scheduler/general_modules}/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_scheduler/general_modules/base.py +0 -0
- {memoryos-1.0.0/src/memos/mem_scheduler/schemas → memoryos-1.1.1/src/memos/mem_scheduler/monitors}/__init__.py +0 -0
- {memoryos-1.0.0/src/memos/mem_scheduler/utils → memoryos-1.1.1/src/memos/mem_scheduler/orm_modules}/__init__.py +0 -0
- {memoryos-1.0.0/src/memos/memories → memoryos-1.1.1/src/memos/mem_scheduler/schemas}/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_scheduler/schemas/general_schemas.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_scheduler/schemas/message_schemas.py +0 -0
- {memoryos-1.0.0/src/memos/memories/activation → memoryos-1.1.1/src/memos/mem_scheduler/utils}/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_scheduler/utils/misc_utils.py +0 -0
- {memoryos-1.0.0/src/memos/memories/parametric → memoryos-1.1.1/src/memos/mem_scheduler/webservice_modules}/__init__.py +0 -0
- {memoryos-1.0.0/src/memos/mem_scheduler/general_modules → memoryos-1.1.1/src/memos/mem_scheduler/webservice_modules}/rabbitmq_service.py +0 -0
- {memoryos-1.0.0/src/memos/mem_scheduler/general_modules → memoryos-1.1.1/src/memos/mem_scheduler/webservice_modules}/redis_service.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_user/factory.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_user/mysql_persistent_user_manager.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_user/persistent_factory.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_user/persistent_user_manager.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/mem_user/user_manager.py +0 -0
- {memoryos-1.0.0/src/memos/memories/textual → memoryos-1.1.1/src/memos/memories}/__init__.py +0 -0
- {memoryos-1.0.0/src/memos/memories/textual/tree_text_memory → memoryos-1.1.1/src/memos/memories/activation}/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/activation/base.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/activation/item.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/activation/vllmkv.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/base.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/factory.py +0 -0
- {memoryos-1.0.0/src/memos/memories/textual/tree_text_memory/organize → memoryos-1.1.1/src/memos/memories/parametric}/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/parametric/base.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/parametric/item.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/parametric/lora.py +0 -0
- {memoryos-1.0.0/src/memos/memories/textual/tree_text_memory/retrieve → memoryos-1.1.1/src/memos/memories/textual}/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/base.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/general.py +0 -0
- {memoryos-1.0.0/src/memos/parsers → memoryos-1.1.1/src/memos/memories/textual/tree_text_memory}/__init__.py +0 -0
- {memoryos-1.0.0/src/memos/templates → memoryos-1.1.1/src/memos/memories/textual/tree_text_memory/organize}/__init__.py +0 -0
- {memoryos-1.0.0/src/memos/vec_dbs → memoryos-1.1.1/src/memos/memories/textual/tree_text_memory/retrieve}/__init__.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree_text_memory/retrieve/reasoner.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree_text_memory/retrieve/reranker.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree_text_memory/retrieve/retrieval_mid_structs.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memories/textual/tree_text_memory/retrieve/task_goal_parser.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memos_tools/dinding_report_bot.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memos_tools/lockfree_dict.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/memos_tools/notification_service.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/parsers/base.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/parsers/markitdown.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/settings.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/templates/tree_reorganize_prompts.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/utils.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/vec_dbs/base.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/vec_dbs/factory.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/src/memos/vec_dbs/item.py +0 -0
- {memoryos-1.0.0 → memoryos-1.1.1}/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.1
|
|
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"
|
|
@@ -311,6 +316,7 @@ MemOS is licensed under the [Apache 2.0 License](./LICENSE).
|
|
|
311
316
|
Stay up to date with the latest MemOS announcements, releases, and community highlights.
|
|
312
317
|
|
|
313
318
|
|
|
319
|
+
- **2025-09-10** - 🎉 *MemOS v1.0.1 (Group Q&A Bot)*: Group Q&A bot based on MemOS Cube, updated KV-Cache performance comparison data across different GPU deployment schemes, optimized test benchmarks and statistics, added plaintext memory Reranker sorting, optimized plaintext memory hallucination issues, and Playground version updates. [Try PlayGround](https://memos-playground.openmem.net/login/)
|
|
314
320
|
- **2025-08-07** - 🎉 *MemOS v1.0.0 (MemCube Release)*: First MemCube with word game demo, LongMemEval evaluation, BochaAISearchRetriever integration, NebulaGraph support, enhanced search capabilities, and official Playground launch.
|
|
315
321
|
- **2025-07-29** – 🎉 *MemOS v0.2.2 (Nebula Update)*: Internet search+Nebula DB integration, refactored memory scheduler, KV Cache stress tests, MemCube Cookbook release (CN/EN), and 4b/1.7b/0.6b memory ops models.
|
|
316
322
|
- **2025-07-21** – 🎉 *MemOS v0.2.1 (Neo Release)*: Lightweight Neo version with plaintext+KV Cache functionality, Docker/multi-tenant support, MCP expansion, and new Cookbook/Mud game examples.
|
|
@@ -252,6 +252,7 @@ MemOS is licensed under the [Apache 2.0 License](./LICENSE).
|
|
|
252
252
|
Stay up to date with the latest MemOS announcements, releases, and community highlights.
|
|
253
253
|
|
|
254
254
|
|
|
255
|
+
- **2025-09-10** - 🎉 *MemOS v1.0.1 (Group Q&A Bot)*: Group Q&A bot based on MemOS Cube, updated KV-Cache performance comparison data across different GPU deployment schemes, optimized test benchmarks and statistics, added plaintext memory Reranker sorting, optimized plaintext memory hallucination issues, and Playground version updates. [Try PlayGround](https://memos-playground.openmem.net/login/)
|
|
255
256
|
- **2025-08-07** - 🎉 *MemOS v1.0.0 (MemCube Release)*: First MemCube with word game demo, LongMemEval evaluation, BochaAISearchRetriever integration, NebulaGraph support, enhanced search capabilities, and official Playground launch.
|
|
256
257
|
- **2025-07-29** – 🎉 *MemOS v0.2.2 (Nebula Update)*: Internet search+Nebula DB integration, refactored memory scheduler, KV Cache stress tests, MemCube Cookbook release (CN/EN), and 4b/1.7b/0.6b memory ops models.
|
|
257
258
|
- **2025-07-21** – 🎉 *MemOS v0.2.1 (Neo Release)*: Lightweight Neo version with plaintext+KV Cache functionality, Docker/multi-tenant support, MCP expansion, and new Cookbook/Mud game examples.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
##############################################################################
|
|
5
5
|
|
|
6
6
|
name = "MemoryOS"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.1.1"
|
|
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")),
|
|
@@ -90,6 +90,31 @@ class APIConfig:
|
|
|
90
90
|
},
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
@staticmethod
|
|
94
|
+
def get_reranker_config() -> dict[str, Any]:
|
|
95
|
+
"""Get embedder configuration."""
|
|
96
|
+
embedder_backend = os.getenv("MOS_RERANKER_BACKEND", "http_bge")
|
|
97
|
+
|
|
98
|
+
if embedder_backend == "http_bge":
|
|
99
|
+
return {
|
|
100
|
+
"backend": "http_bge",
|
|
101
|
+
"config": {
|
|
102
|
+
"url": os.getenv("MOS_RERANKER_URL"),
|
|
103
|
+
"model": os.getenv("MOS_RERANKER_MODEL", "bge-reranker-v2-m3"),
|
|
104
|
+
"timeout": 10,
|
|
105
|
+
"headers_extra": os.getenv("MOS_RERANKER_HEADERS_EXTRA"),
|
|
106
|
+
"rerank_source": os.getenv("MOS_RERANK_SOURCE"),
|
|
107
|
+
},
|
|
108
|
+
}
|
|
109
|
+
else:
|
|
110
|
+
return {
|
|
111
|
+
"backend": "cosine_local",
|
|
112
|
+
"config": {
|
|
113
|
+
"level_weights": {"topic": 1.0, "concept": 1.0, "fact": 1.0},
|
|
114
|
+
"level_field": "background",
|
|
115
|
+
},
|
|
116
|
+
}
|
|
117
|
+
|
|
93
118
|
@staticmethod
|
|
94
119
|
def get_embedder_config() -> dict[str, Any]:
|
|
95
120
|
"""Get embedder configuration."""
|
|
@@ -163,22 +188,22 @@ class APIConfig:
|
|
|
163
188
|
return {
|
|
164
189
|
"uri": os.getenv("NEO4J_URI", "bolt://localhost:7687"),
|
|
165
190
|
"user": os.getenv("NEO4J_USER", "neo4j"),
|
|
166
|
-
"db_name": os.getenv("NEO4J_DB_NAME", "
|
|
191
|
+
"db_name": os.getenv("NEO4J_DB_NAME", "neo4j"),
|
|
167
192
|
"password": os.getenv("NEO4J_PASSWORD", "12345678"),
|
|
168
193
|
"user_name": f"memos{user_id.replace('-', '')}",
|
|
169
|
-
"auto_create":
|
|
194
|
+
"auto_create": False,
|
|
170
195
|
"use_multi_db": False,
|
|
171
|
-
"embedding_dimension": int(os.getenv("EMBEDDING_DIMENSION",
|
|
196
|
+
"embedding_dimension": int(os.getenv("EMBEDDING_DIMENSION", 1024)),
|
|
172
197
|
"vec_config": {
|
|
173
198
|
# Pass nested config to initialize external vector DB
|
|
174
199
|
# If you use qdrant, please use Server instead of local mode.
|
|
175
200
|
"backend": "qdrant",
|
|
176
201
|
"config": {
|
|
177
202
|
"collection_name": "neo4j_vec_db",
|
|
178
|
-
"vector_dimension": int(os.getenv("EMBEDDING_DIMENSION",
|
|
203
|
+
"vector_dimension": int(os.getenv("EMBEDDING_DIMENSION", 1024)),
|
|
179
204
|
"distance_metric": "cosine",
|
|
180
|
-
"host": "localhost",
|
|
181
|
-
"port": 6333,
|
|
205
|
+
"host": os.getenv("QDRANT_HOST", "localhost"),
|
|
206
|
+
"port": int(os.getenv("QDRANT_PORT", "6333")),
|
|
182
207
|
},
|
|
183
208
|
},
|
|
184
209
|
}
|
|
@@ -248,7 +273,7 @@ class APIConfig:
|
|
|
248
273
|
def get_scheduler_config() -> dict[str, Any]:
|
|
249
274
|
"""Get scheduler configuration."""
|
|
250
275
|
return {
|
|
251
|
-
"backend": "
|
|
276
|
+
"backend": "optimized_scheduler",
|
|
252
277
|
"config": {
|
|
253
278
|
"top_k": int(os.getenv("MOS_SCHEDULER_TOP_K", "10")),
|
|
254
279
|
"act_mem_update_interval": int(
|
|
@@ -492,6 +517,7 @@ class APIConfig:
|
|
|
492
517
|
},
|
|
493
518
|
"embedder": APIConfig.get_embedder_config(),
|
|
494
519
|
"internet_retriever": internet_config,
|
|
520
|
+
"reranker": APIConfig.get_reranker_config(),
|
|
495
521
|
},
|
|
496
522
|
},
|
|
497
523
|
"act_mem": {}
|
|
@@ -545,6 +571,7 @@ class APIConfig:
|
|
|
545
571
|
"config": graph_db_backend_map[graph_db_backend],
|
|
546
572
|
},
|
|
547
573
|
"embedder": APIConfig.get_embedder_config(),
|
|
574
|
+
"reranker": APIConfig.get_reranker_config(),
|
|
548
575
|
"reorganize": os.getenv("MOS_ENABLE_REORGANIZE", "false").lower()
|
|
549
576
|
== "true",
|
|
550
577
|
"internet_retriever": internet_config,
|
|
@@ -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
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Request context middleware for automatic trace_id injection.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
|
|
7
|
+
from starlette.middleware.base import BaseHTTPMiddleware
|
|
8
|
+
from starlette.requests import Request
|
|
9
|
+
from starlette.responses import Response
|
|
10
|
+
|
|
11
|
+
import memos.log
|
|
12
|
+
|
|
13
|
+
from memos.context.context import RequestContext, generate_trace_id, set_request_context
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
logger = memos.log.get_logger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def extract_trace_id_from_headers(request: Request) -> str | None:
|
|
20
|
+
"""Extract trace_id from various possible headers with priority: g-trace-id > x-trace-id > trace-id."""
|
|
21
|
+
for header in ["g-trace-id", "x-trace-id", "trace-id"]:
|
|
22
|
+
if trace_id := request.headers.get(header):
|
|
23
|
+
return trace_id
|
|
24
|
+
return None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class RequestContextMiddleware(BaseHTTPMiddleware):
|
|
28
|
+
"""
|
|
29
|
+
Middleware to automatically inject request context for every HTTP request.
|
|
30
|
+
|
|
31
|
+
This middleware:
|
|
32
|
+
1. Extracts trace_id from headers or generates a new one
|
|
33
|
+
2. Creates a RequestContext and sets it globally
|
|
34
|
+
3. Ensures the context is available throughout the request lifecycle
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
async def dispatch(self, request: Request, call_next: Callable) -> Response:
|
|
38
|
+
# Extract or generate trace_id
|
|
39
|
+
trace_id = extract_trace_id_from_headers(request) or generate_trace_id()
|
|
40
|
+
|
|
41
|
+
# Create and set request context
|
|
42
|
+
context = RequestContext(trace_id=trace_id, api_path=request.url.path)
|
|
43
|
+
set_request_context(context)
|
|
44
|
+
|
|
45
|
+
# Log request start with parameters
|
|
46
|
+
params_log = {}
|
|
47
|
+
|
|
48
|
+
# Get query parameters
|
|
49
|
+
if request.query_params:
|
|
50
|
+
params_log["query_params"] = dict(request.query_params)
|
|
51
|
+
|
|
52
|
+
logger.info(f"Request started: {request.method} {request.url.path}, {params_log}")
|
|
53
|
+
|
|
54
|
+
# Process the request
|
|
55
|
+
response = await call_next(request)
|
|
56
|
+
|
|
57
|
+
# Log request completion with output
|
|
58
|
+
logger.info(f"Request completed: {request.url.path}, status: {response.status_code}")
|
|
59
|
+
|
|
60
|
+
# Add trace_id to response headers for debugging
|
|
61
|
+
response.headers["x-trace-id"] = trace_id
|
|
62
|
+
|
|
63
|
+
return response
|
|
@@ -3,6 +3,7 @@ import logging
|
|
|
3
3
|
from fastapi import FastAPI
|
|
4
4
|
|
|
5
5
|
from memos.api.exceptions import APIExceptionHandler
|
|
6
|
+
from memos.api.middleware.request_context import RequestContextMiddleware
|
|
6
7
|
from memos.api.routers.product_router import router as product_router
|
|
7
8
|
|
|
8
9
|
|
|
@@ -13,9 +14,10 @@ logger = logging.getLogger(__name__)
|
|
|
13
14
|
app = FastAPI(
|
|
14
15
|
title="MemOS Product REST APIs",
|
|
15
16
|
description="A REST API for managing multiple users with MemOS Product.",
|
|
16
|
-
version="1.0.
|
|
17
|
+
version="1.0.1",
|
|
17
18
|
)
|
|
18
19
|
|
|
20
|
+
app.add_middleware(RequestContextMiddleware)
|
|
19
21
|
# Include routers
|
|
20
22
|
app.include_router(product_router)
|
|
21
23
|
|
|
@@ -31,5 +33,6 @@ if __name__ == "__main__":
|
|
|
31
33
|
|
|
32
34
|
parser = argparse.ArgumentParser()
|
|
33
35
|
parser.add_argument("--port", type=int, default=8001)
|
|
36
|
+
parser.add_argument("--workers", type=int, default=32)
|
|
34
37
|
args = parser.parse_args()
|
|
35
|
-
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
10
|
|
|
17
|
-
|
|
18
|
-
# Message structure
|
|
19
|
-
class MessageDict(TypedDict):
|
|
20
|
-
"""Typed dictionary for chat message dictionaries."""
|
|
21
|
-
|
|
22
|
-
role: MessageRole
|
|
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
|
|
|
@@ -84,6 +73,23 @@ class ChatRequest(BaseRequest):
|
|
|
84
73
|
mem_cube_id: str | None = Field(None, description="Cube ID to use for chat")
|
|
85
74
|
history: list[MessageDict] | None = Field(None, description="Chat history")
|
|
86
75
|
internet_search: bool = Field(True, description="Whether to use internet search")
|
|
76
|
+
moscube: bool = Field(False, description="Whether to use MemOSCube")
|
|
77
|
+
session_id: str | None = Field(None, description="Session ID for soft-filtering memories")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class ChatCompleteRequest(BaseRequest):
|
|
81
|
+
"""Request model for chat operations."""
|
|
82
|
+
|
|
83
|
+
user_id: str = Field(..., description="User ID")
|
|
84
|
+
query: str = Field(..., description="Chat query message")
|
|
85
|
+
mem_cube_id: str | None = Field(None, description="Cube ID to use for chat")
|
|
86
|
+
history: list[MessageDict] | None = Field(None, description="Chat history")
|
|
87
|
+
internet_search: bool = Field(False, description="Whether to use internet search")
|
|
88
|
+
moscube: bool = Field(False, description="Whether to use MemOSCube")
|
|
89
|
+
base_prompt: str | None = Field(None, description="Base prompt to use for chat")
|
|
90
|
+
top_k: int = Field(10, description="Number of results to return")
|
|
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")
|
|
87
93
|
|
|
88
94
|
|
|
89
95
|
class UserCreate(BaseRequest):
|
|
@@ -145,6 +151,7 @@ class MemoryCreateRequest(BaseRequest):
|
|
|
145
151
|
mem_cube_id: str | None = Field(None, description="Cube ID")
|
|
146
152
|
source: str | None = Field(None, description="Source of the memory")
|
|
147
153
|
user_profile: bool = Field(False, description="User profile memory")
|
|
154
|
+
session_id: str | None = Field(None, description="Session id")
|
|
148
155
|
|
|
149
156
|
|
|
150
157
|
class SearchRequest(BaseRequest):
|
|
@@ -154,6 +161,7 @@ class SearchRequest(BaseRequest):
|
|
|
154
161
|
query: str = Field(..., description="Search query")
|
|
155
162
|
mem_cube_id: str | None = Field(None, description="Cube ID to search in")
|
|
156
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")
|
|
157
165
|
|
|
158
166
|
|
|
159
167
|
class SuggestionRequest(BaseRequest):
|
|
@@ -161,3 +169,86 @@ class SuggestionRequest(BaseRequest):
|
|
|
161
169
|
|
|
162
170
|
user_id: str = Field(..., description="User ID")
|
|
163
171
|
language: Literal["zh", "en"] = Field("zh", description="Language for suggestions")
|
|
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="memory_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
|