MemoryOS 2.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- memoryos-2.0.3.dist-info/METADATA +418 -0
- memoryos-2.0.3.dist-info/RECORD +315 -0
- memoryos-2.0.3.dist-info/WHEEL +4 -0
- memoryos-2.0.3.dist-info/entry_points.txt +3 -0
- memoryos-2.0.3.dist-info/licenses/LICENSE +201 -0
- memos/__init__.py +20 -0
- memos/api/client.py +571 -0
- memos/api/config.py +1018 -0
- memos/api/context/dependencies.py +50 -0
- memos/api/exceptions.py +53 -0
- memos/api/handlers/__init__.py +62 -0
- memos/api/handlers/add_handler.py +158 -0
- memos/api/handlers/base_handler.py +194 -0
- memos/api/handlers/chat_handler.py +1401 -0
- memos/api/handlers/component_init.py +388 -0
- memos/api/handlers/config_builders.py +190 -0
- memos/api/handlers/feedback_handler.py +93 -0
- memos/api/handlers/formatters_handler.py +237 -0
- memos/api/handlers/memory_handler.py +316 -0
- memos/api/handlers/scheduler_handler.py +497 -0
- memos/api/handlers/search_handler.py +222 -0
- memos/api/handlers/suggestion_handler.py +117 -0
- memos/api/mcp_serve.py +614 -0
- memos/api/middleware/request_context.py +101 -0
- memos/api/product_api.py +38 -0
- memos/api/product_models.py +1206 -0
- memos/api/routers/__init__.py +1 -0
- memos/api/routers/product_router.py +477 -0
- memos/api/routers/server_router.py +394 -0
- memos/api/server_api.py +44 -0
- memos/api/start_api.py +433 -0
- memos/chunkers/__init__.py +4 -0
- memos/chunkers/base.py +24 -0
- memos/chunkers/charactertext_chunker.py +41 -0
- memos/chunkers/factory.py +24 -0
- memos/chunkers/markdown_chunker.py +62 -0
- memos/chunkers/sentence_chunker.py +54 -0
- memos/chunkers/simple_chunker.py +50 -0
- memos/cli.py +113 -0
- memos/configs/__init__.py +0 -0
- memos/configs/base.py +82 -0
- memos/configs/chunker.py +59 -0
- memos/configs/embedder.py +88 -0
- memos/configs/graph_db.py +236 -0
- memos/configs/internet_retriever.py +100 -0
- memos/configs/llm.py +151 -0
- memos/configs/mem_agent.py +54 -0
- memos/configs/mem_chat.py +81 -0
- memos/configs/mem_cube.py +105 -0
- memos/configs/mem_os.py +83 -0
- memos/configs/mem_reader.py +91 -0
- memos/configs/mem_scheduler.py +385 -0
- memos/configs/mem_user.py +70 -0
- memos/configs/memory.py +324 -0
- memos/configs/parser.py +38 -0
- memos/configs/reranker.py +18 -0
- memos/configs/utils.py +8 -0
- memos/configs/vec_db.py +80 -0
- memos/context/context.py +355 -0
- memos/dependency.py +52 -0
- memos/deprecation.py +262 -0
- memos/embedders/__init__.py +0 -0
- memos/embedders/ark.py +95 -0
- memos/embedders/base.py +106 -0
- memos/embedders/factory.py +29 -0
- memos/embedders/ollama.py +77 -0
- memos/embedders/sentence_transformer.py +49 -0
- memos/embedders/universal_api.py +51 -0
- memos/exceptions.py +30 -0
- memos/graph_dbs/__init__.py +0 -0
- memos/graph_dbs/base.py +274 -0
- memos/graph_dbs/factory.py +27 -0
- memos/graph_dbs/item.py +46 -0
- memos/graph_dbs/nebular.py +1794 -0
- memos/graph_dbs/neo4j.py +1942 -0
- memos/graph_dbs/neo4j_community.py +1058 -0
- memos/graph_dbs/polardb.py +5446 -0
- memos/hello_world.py +97 -0
- memos/llms/__init__.py +0 -0
- memos/llms/base.py +25 -0
- memos/llms/deepseek.py +13 -0
- memos/llms/factory.py +38 -0
- memos/llms/hf.py +443 -0
- memos/llms/hf_singleton.py +114 -0
- memos/llms/ollama.py +135 -0
- memos/llms/openai.py +222 -0
- memos/llms/openai_new.py +198 -0
- memos/llms/qwen.py +13 -0
- memos/llms/utils.py +14 -0
- memos/llms/vllm.py +218 -0
- memos/log.py +237 -0
- memos/mem_agent/base.py +19 -0
- memos/mem_agent/deepsearch_agent.py +391 -0
- memos/mem_agent/factory.py +36 -0
- memos/mem_chat/__init__.py +0 -0
- memos/mem_chat/base.py +30 -0
- memos/mem_chat/factory.py +21 -0
- memos/mem_chat/simple.py +200 -0
- memos/mem_cube/__init__.py +0 -0
- memos/mem_cube/base.py +30 -0
- memos/mem_cube/general.py +240 -0
- memos/mem_cube/navie.py +172 -0
- memos/mem_cube/utils.py +169 -0
- memos/mem_feedback/base.py +15 -0
- memos/mem_feedback/feedback.py +1192 -0
- memos/mem_feedback/simple_feedback.py +40 -0
- memos/mem_feedback/utils.py +230 -0
- memos/mem_os/client.py +5 -0
- memos/mem_os/core.py +1203 -0
- memos/mem_os/main.py +582 -0
- memos/mem_os/product.py +1608 -0
- memos/mem_os/product_server.py +455 -0
- memos/mem_os/utils/default_config.py +359 -0
- memos/mem_os/utils/format_utils.py +1403 -0
- memos/mem_os/utils/reference_utils.py +162 -0
- memos/mem_reader/__init__.py +0 -0
- memos/mem_reader/base.py +47 -0
- memos/mem_reader/factory.py +53 -0
- memos/mem_reader/memory.py +298 -0
- memos/mem_reader/multi_modal_struct.py +965 -0
- memos/mem_reader/read_multi_modal/__init__.py +43 -0
- memos/mem_reader/read_multi_modal/assistant_parser.py +311 -0
- memos/mem_reader/read_multi_modal/base.py +273 -0
- memos/mem_reader/read_multi_modal/file_content_parser.py +826 -0
- memos/mem_reader/read_multi_modal/image_parser.py +359 -0
- memos/mem_reader/read_multi_modal/multi_modal_parser.py +252 -0
- memos/mem_reader/read_multi_modal/string_parser.py +139 -0
- memos/mem_reader/read_multi_modal/system_parser.py +327 -0
- memos/mem_reader/read_multi_modal/text_content_parser.py +131 -0
- memos/mem_reader/read_multi_modal/tool_parser.py +210 -0
- memos/mem_reader/read_multi_modal/user_parser.py +218 -0
- memos/mem_reader/read_multi_modal/utils.py +358 -0
- memos/mem_reader/simple_struct.py +912 -0
- memos/mem_reader/strategy_struct.py +163 -0
- memos/mem_reader/utils.py +157 -0
- memos/mem_scheduler/__init__.py +0 -0
- memos/mem_scheduler/analyzer/__init__.py +0 -0
- memos/mem_scheduler/analyzer/api_analyzer.py +714 -0
- memos/mem_scheduler/analyzer/eval_analyzer.py +219 -0
- memos/mem_scheduler/analyzer/mos_for_test_scheduler.py +571 -0
- memos/mem_scheduler/analyzer/scheduler_for_eval.py +280 -0
- memos/mem_scheduler/base_scheduler.py +1319 -0
- memos/mem_scheduler/general_modules/__init__.py +0 -0
- memos/mem_scheduler/general_modules/api_misc.py +137 -0
- memos/mem_scheduler/general_modules/base.py +80 -0
- memos/mem_scheduler/general_modules/init_components_for_scheduler.py +425 -0
- memos/mem_scheduler/general_modules/misc.py +313 -0
- memos/mem_scheduler/general_modules/scheduler_logger.py +389 -0
- memos/mem_scheduler/general_modules/task_threads.py +315 -0
- memos/mem_scheduler/general_scheduler.py +1495 -0
- memos/mem_scheduler/memory_manage_modules/__init__.py +5 -0
- memos/mem_scheduler/memory_manage_modules/memory_filter.py +306 -0
- memos/mem_scheduler/memory_manage_modules/retriever.py +547 -0
- memos/mem_scheduler/monitors/__init__.py +0 -0
- memos/mem_scheduler/monitors/dispatcher_monitor.py +366 -0
- memos/mem_scheduler/monitors/general_monitor.py +394 -0
- memos/mem_scheduler/monitors/task_schedule_monitor.py +254 -0
- memos/mem_scheduler/optimized_scheduler.py +410 -0
- memos/mem_scheduler/orm_modules/__init__.py +0 -0
- memos/mem_scheduler/orm_modules/api_redis_model.py +518 -0
- memos/mem_scheduler/orm_modules/base_model.py +729 -0
- memos/mem_scheduler/orm_modules/monitor_models.py +261 -0
- memos/mem_scheduler/orm_modules/redis_model.py +699 -0
- memos/mem_scheduler/scheduler_factory.py +23 -0
- memos/mem_scheduler/schemas/__init__.py +0 -0
- memos/mem_scheduler/schemas/analyzer_schemas.py +52 -0
- memos/mem_scheduler/schemas/api_schemas.py +233 -0
- memos/mem_scheduler/schemas/general_schemas.py +55 -0
- memos/mem_scheduler/schemas/message_schemas.py +173 -0
- memos/mem_scheduler/schemas/monitor_schemas.py +406 -0
- memos/mem_scheduler/schemas/task_schemas.py +132 -0
- memos/mem_scheduler/task_schedule_modules/__init__.py +0 -0
- memos/mem_scheduler/task_schedule_modules/dispatcher.py +740 -0
- memos/mem_scheduler/task_schedule_modules/local_queue.py +247 -0
- memos/mem_scheduler/task_schedule_modules/orchestrator.py +74 -0
- memos/mem_scheduler/task_schedule_modules/redis_queue.py +1385 -0
- memos/mem_scheduler/task_schedule_modules/task_queue.py +162 -0
- memos/mem_scheduler/utils/__init__.py +0 -0
- memos/mem_scheduler/utils/api_utils.py +77 -0
- memos/mem_scheduler/utils/config_utils.py +100 -0
- memos/mem_scheduler/utils/db_utils.py +50 -0
- memos/mem_scheduler/utils/filter_utils.py +176 -0
- memos/mem_scheduler/utils/metrics.py +125 -0
- memos/mem_scheduler/utils/misc_utils.py +290 -0
- memos/mem_scheduler/utils/monitor_event_utils.py +67 -0
- memos/mem_scheduler/utils/status_tracker.py +229 -0
- memos/mem_scheduler/webservice_modules/__init__.py +0 -0
- memos/mem_scheduler/webservice_modules/rabbitmq_service.py +485 -0
- memos/mem_scheduler/webservice_modules/redis_service.py +380 -0
- memos/mem_user/factory.py +94 -0
- memos/mem_user/mysql_persistent_user_manager.py +271 -0
- memos/mem_user/mysql_user_manager.py +502 -0
- memos/mem_user/persistent_factory.py +98 -0
- memos/mem_user/persistent_user_manager.py +260 -0
- memos/mem_user/redis_persistent_user_manager.py +225 -0
- memos/mem_user/user_manager.py +488 -0
- memos/memories/__init__.py +0 -0
- memos/memories/activation/__init__.py +0 -0
- memos/memories/activation/base.py +42 -0
- memos/memories/activation/item.py +56 -0
- memos/memories/activation/kv.py +292 -0
- memos/memories/activation/vllmkv.py +219 -0
- memos/memories/base.py +19 -0
- memos/memories/factory.py +42 -0
- memos/memories/parametric/__init__.py +0 -0
- memos/memories/parametric/base.py +19 -0
- memos/memories/parametric/item.py +11 -0
- memos/memories/parametric/lora.py +41 -0
- memos/memories/textual/__init__.py +0 -0
- memos/memories/textual/base.py +92 -0
- memos/memories/textual/general.py +236 -0
- memos/memories/textual/item.py +304 -0
- memos/memories/textual/naive.py +187 -0
- memos/memories/textual/prefer_text_memory/__init__.py +0 -0
- memos/memories/textual/prefer_text_memory/adder.py +504 -0
- memos/memories/textual/prefer_text_memory/config.py +106 -0
- memos/memories/textual/prefer_text_memory/extractor.py +221 -0
- memos/memories/textual/prefer_text_memory/factory.py +85 -0
- memos/memories/textual/prefer_text_memory/retrievers.py +177 -0
- memos/memories/textual/prefer_text_memory/spliter.py +132 -0
- memos/memories/textual/prefer_text_memory/utils.py +93 -0
- memos/memories/textual/preference.py +344 -0
- memos/memories/textual/simple_preference.py +161 -0
- memos/memories/textual/simple_tree.py +69 -0
- memos/memories/textual/tree.py +459 -0
- memos/memories/textual/tree_text_memory/__init__.py +0 -0
- memos/memories/textual/tree_text_memory/organize/__init__.py +0 -0
- memos/memories/textual/tree_text_memory/organize/handler.py +184 -0
- memos/memories/textual/tree_text_memory/organize/manager.py +518 -0
- memos/memories/textual/tree_text_memory/organize/relation_reason_detector.py +238 -0
- memos/memories/textual/tree_text_memory/organize/reorganizer.py +622 -0
- memos/memories/textual/tree_text_memory/retrieve/__init__.py +0 -0
- memos/memories/textual/tree_text_memory/retrieve/advanced_searcher.py +364 -0
- memos/memories/textual/tree_text_memory/retrieve/bm25_util.py +186 -0
- memos/memories/textual/tree_text_memory/retrieve/bochasearch.py +419 -0
- memos/memories/textual/tree_text_memory/retrieve/internet_retriever.py +270 -0
- memos/memories/textual/tree_text_memory/retrieve/internet_retriever_factory.py +102 -0
- memos/memories/textual/tree_text_memory/retrieve/reasoner.py +61 -0
- memos/memories/textual/tree_text_memory/retrieve/recall.py +497 -0
- memos/memories/textual/tree_text_memory/retrieve/reranker.py +111 -0
- memos/memories/textual/tree_text_memory/retrieve/retrieval_mid_structs.py +16 -0
- memos/memories/textual/tree_text_memory/retrieve/retrieve_utils.py +472 -0
- memos/memories/textual/tree_text_memory/retrieve/searcher.py +848 -0
- memos/memories/textual/tree_text_memory/retrieve/task_goal_parser.py +135 -0
- memos/memories/textual/tree_text_memory/retrieve/utils.py +54 -0
- memos/memories/textual/tree_text_memory/retrieve/xinyusearch.py +387 -0
- memos/memos_tools/dinding_report_bot.py +453 -0
- memos/memos_tools/lockfree_dict.py +120 -0
- memos/memos_tools/notification_service.py +44 -0
- memos/memos_tools/notification_utils.py +142 -0
- memos/memos_tools/singleton.py +174 -0
- memos/memos_tools/thread_safe_dict.py +310 -0
- memos/memos_tools/thread_safe_dict_segment.py +382 -0
- memos/multi_mem_cube/__init__.py +0 -0
- memos/multi_mem_cube/composite_cube.py +86 -0
- memos/multi_mem_cube/single_cube.py +874 -0
- memos/multi_mem_cube/views.py +54 -0
- memos/parsers/__init__.py +0 -0
- memos/parsers/base.py +15 -0
- memos/parsers/factory.py +21 -0
- memos/parsers/markitdown.py +28 -0
- memos/reranker/__init__.py +4 -0
- memos/reranker/base.py +25 -0
- memos/reranker/concat.py +103 -0
- memos/reranker/cosine_local.py +102 -0
- memos/reranker/factory.py +72 -0
- memos/reranker/http_bge.py +324 -0
- memos/reranker/http_bge_strategy.py +327 -0
- memos/reranker/noop.py +19 -0
- memos/reranker/strategies/__init__.py +4 -0
- memos/reranker/strategies/base.py +61 -0
- memos/reranker/strategies/concat_background.py +94 -0
- memos/reranker/strategies/concat_docsource.py +110 -0
- memos/reranker/strategies/dialogue_common.py +109 -0
- memos/reranker/strategies/factory.py +31 -0
- memos/reranker/strategies/single_turn.py +107 -0
- memos/reranker/strategies/singleturn_outmem.py +98 -0
- memos/settings.py +10 -0
- memos/templates/__init__.py +0 -0
- memos/templates/advanced_search_prompts.py +211 -0
- memos/templates/cloud_service_prompt.py +107 -0
- memos/templates/instruction_completion.py +66 -0
- memos/templates/mem_agent_prompts.py +85 -0
- memos/templates/mem_feedback_prompts.py +822 -0
- memos/templates/mem_reader_prompts.py +1096 -0
- memos/templates/mem_reader_strategy_prompts.py +238 -0
- memos/templates/mem_scheduler_prompts.py +626 -0
- memos/templates/mem_search_prompts.py +93 -0
- memos/templates/mos_prompts.py +403 -0
- memos/templates/prefer_complete_prompt.py +735 -0
- memos/templates/tool_mem_prompts.py +139 -0
- memos/templates/tree_reorganize_prompts.py +230 -0
- memos/types/__init__.py +34 -0
- memos/types/general_types.py +151 -0
- memos/types/openai_chat_completion_types/__init__.py +15 -0
- memos/types/openai_chat_completion_types/chat_completion_assistant_message_param.py +56 -0
- memos/types/openai_chat_completion_types/chat_completion_content_part_image_param.py +27 -0
- memos/types/openai_chat_completion_types/chat_completion_content_part_input_audio_param.py +23 -0
- memos/types/openai_chat_completion_types/chat_completion_content_part_param.py +43 -0
- memos/types/openai_chat_completion_types/chat_completion_content_part_refusal_param.py +16 -0
- memos/types/openai_chat_completion_types/chat_completion_content_part_text_param.py +16 -0
- memos/types/openai_chat_completion_types/chat_completion_message_custom_tool_call_param.py +27 -0
- memos/types/openai_chat_completion_types/chat_completion_message_function_tool_call_param.py +32 -0
- memos/types/openai_chat_completion_types/chat_completion_message_param.py +18 -0
- memos/types/openai_chat_completion_types/chat_completion_message_tool_call_union_param.py +15 -0
- memos/types/openai_chat_completion_types/chat_completion_system_message_param.py +36 -0
- memos/types/openai_chat_completion_types/chat_completion_tool_message_param.py +30 -0
- memos/types/openai_chat_completion_types/chat_completion_user_message_param.py +34 -0
- memos/utils.py +123 -0
- memos/vec_dbs/__init__.py +0 -0
- memos/vec_dbs/base.py +117 -0
- memos/vec_dbs/factory.py +23 -0
- memos/vec_dbs/item.py +50 -0
- memos/vec_dbs/milvus.py +654 -0
- memos/vec_dbs/qdrant.py +355 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from typing import Any, ClassVar
|
|
2
|
+
|
|
3
|
+
from pydantic import Field, field_validator, model_validator
|
|
4
|
+
|
|
5
|
+
from memos.configs.base import BaseConfig
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BaseAdderConfig(BaseConfig):
|
|
9
|
+
"""Base configuration class for Adder."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class NaiveAdderConfig(BaseAdderConfig):
|
|
13
|
+
"""Configuration for Naive Adder."""
|
|
14
|
+
|
|
15
|
+
# No additional config needed since components are passed from parent
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AdderConfigFactory(BaseConfig):
|
|
19
|
+
"""Factory class for creating Adder configurations."""
|
|
20
|
+
|
|
21
|
+
backend: str = Field(..., description="Backend for Adder")
|
|
22
|
+
config: dict[str, Any] = Field(..., description="Configuration for the Adder backend")
|
|
23
|
+
|
|
24
|
+
backend_to_class: ClassVar[dict[str, Any]] = {
|
|
25
|
+
"naive": NaiveAdderConfig,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@field_validator("backend")
|
|
29
|
+
@classmethod
|
|
30
|
+
def validate_backend(cls, backend: str) -> str:
|
|
31
|
+
"""Validate the backend field."""
|
|
32
|
+
if backend not in cls.backend_to_class:
|
|
33
|
+
raise ValueError(f"Invalid backend: {backend}")
|
|
34
|
+
return backend
|
|
35
|
+
|
|
36
|
+
@model_validator(mode="after")
|
|
37
|
+
def create_config(self) -> "AdderConfigFactory":
|
|
38
|
+
config_class = self.backend_to_class[self.backend]
|
|
39
|
+
self.config = config_class(**self.config)
|
|
40
|
+
return self
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class BaseExtractorConfig(BaseConfig):
|
|
44
|
+
"""Base configuration class for Extractor."""
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class NaiveExtractorConfig(BaseExtractorConfig):
|
|
48
|
+
"""Configuration for Naive Extractor."""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class ExtractorConfigFactory(BaseConfig):
|
|
52
|
+
"""Factory class for creating Extractor configurations."""
|
|
53
|
+
|
|
54
|
+
backend: str = Field(..., description="Backend for Extractor")
|
|
55
|
+
config: dict[str, Any] = Field(..., description="Configuration for the Extractor backend")
|
|
56
|
+
|
|
57
|
+
backend_to_class: ClassVar[dict[str, Any]] = {
|
|
58
|
+
"naive": NaiveExtractorConfig,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@field_validator("backend")
|
|
62
|
+
@classmethod
|
|
63
|
+
def validate_backend(cls, backend: str) -> str:
|
|
64
|
+
"""Validate the backend field."""
|
|
65
|
+
if backend not in cls.backend_to_class:
|
|
66
|
+
raise ValueError(f"Invalid backend: {backend}")
|
|
67
|
+
return backend
|
|
68
|
+
|
|
69
|
+
@model_validator(mode="after")
|
|
70
|
+
def create_config(self) -> "ExtractorConfigFactory":
|
|
71
|
+
config_class = self.backend_to_class[self.backend]
|
|
72
|
+
self.config = config_class(**self.config)
|
|
73
|
+
return self
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class BaseRetrieverConfig(BaseConfig):
|
|
77
|
+
"""Base configuration class for Retrievers."""
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class NaiveRetrieverConfig(BaseRetrieverConfig):
|
|
81
|
+
"""Configuration for Naive Retriever."""
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class RetrieverConfigFactory(BaseConfig):
|
|
85
|
+
"""Factory class for creating Retriever configurations."""
|
|
86
|
+
|
|
87
|
+
backend: str = Field(..., description="Backend for Retriever")
|
|
88
|
+
config: dict[str, Any] = Field(..., description="Configuration for the Retriever backend")
|
|
89
|
+
|
|
90
|
+
backend_to_class: ClassVar[dict[str, Any]] = {
|
|
91
|
+
"naive": NaiveRetrieverConfig,
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@field_validator("backend")
|
|
95
|
+
@classmethod
|
|
96
|
+
def validate_backend(cls, backend: str) -> str:
|
|
97
|
+
"""Validate the backend field."""
|
|
98
|
+
if backend not in cls.backend_to_class:
|
|
99
|
+
raise ValueError(f"Invalid backend: {backend}")
|
|
100
|
+
return backend
|
|
101
|
+
|
|
102
|
+
@model_validator(mode="after")
|
|
103
|
+
def create_config(self) -> "RetrieverConfigFactory":
|
|
104
|
+
config_class = self.backend_to_class[self.backend]
|
|
105
|
+
self.config = config_class(**self.config)
|
|
106
|
+
return self
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import uuid
|
|
3
|
+
|
|
4
|
+
from abc import ABC, abstractmethod
|
|
5
|
+
from concurrent.futures import as_completed
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from memos.context.context import ContextThreadPoolExecutor
|
|
10
|
+
from memos.log import get_logger
|
|
11
|
+
from memos.mem_reader.read_multi_modal import detect_lang
|
|
12
|
+
from memos.memories.textual.item import (
|
|
13
|
+
PreferenceTextualMemoryMetadata,
|
|
14
|
+
TextualMemoryItem,
|
|
15
|
+
list_all_fields,
|
|
16
|
+
)
|
|
17
|
+
from memos.memories.textual.prefer_text_memory.spliter import Splitter
|
|
18
|
+
from memos.memories.textual.prefer_text_memory.utils import convert_messages_to_string
|
|
19
|
+
from memos.templates.prefer_complete_prompt import (
|
|
20
|
+
NAIVE_EXPLICIT_PREFERENCE_EXTRACT_PROMPT,
|
|
21
|
+
NAIVE_EXPLICIT_PREFERENCE_EXTRACT_PROMPT_ZH,
|
|
22
|
+
NAIVE_IMPLICIT_PREFERENCE_EXTRACT_PROMPT,
|
|
23
|
+
NAIVE_IMPLICIT_PREFERENCE_EXTRACT_PROMPT_ZH,
|
|
24
|
+
)
|
|
25
|
+
from memos.types import MessageList
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
logger = get_logger(__name__)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class BaseExtractor(ABC):
|
|
32
|
+
"""Abstract base class for extractors."""
|
|
33
|
+
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def __init__(self, llm_provider=None, embedder=None, vector_db=None):
|
|
36
|
+
"""Initialize the extractor."""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class NaiveExtractor(BaseExtractor):
|
|
40
|
+
"""Extractor."""
|
|
41
|
+
|
|
42
|
+
def __init__(self, llm_provider=None, embedder=None, vector_db=None):
|
|
43
|
+
"""Initialize the extractor."""
|
|
44
|
+
super().__init__(llm_provider, embedder, vector_db)
|
|
45
|
+
self.llm_provider = llm_provider
|
|
46
|
+
self.embedder = embedder
|
|
47
|
+
self.vector_db = vector_db
|
|
48
|
+
self.splitter = Splitter()
|
|
49
|
+
|
|
50
|
+
def extract_basic_info(self, qa_pair: MessageList) -> dict[str, Any]:
|
|
51
|
+
"""Extract basic information from a QA pair (no LLM needed)."""
|
|
52
|
+
basic_info = {
|
|
53
|
+
"dialog_id": str(uuid.uuid4()),
|
|
54
|
+
"original_text": convert_messages_to_string(qa_pair),
|
|
55
|
+
"created_at": datetime.now().isoformat(),
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return basic_info
|
|
59
|
+
|
|
60
|
+
def extract_explicit_preference(self, qa_pair: MessageList | str) -> dict[str, Any] | None:
|
|
61
|
+
"""Extract explicit preference from a QA pair."""
|
|
62
|
+
qa_pair_str = convert_messages_to_string(qa_pair) if isinstance(qa_pair, list) else qa_pair
|
|
63
|
+
lang = detect_lang(qa_pair_str)
|
|
64
|
+
_map = {
|
|
65
|
+
"zh": NAIVE_EXPLICIT_PREFERENCE_EXTRACT_PROMPT_ZH,
|
|
66
|
+
"en": NAIVE_EXPLICIT_PREFERENCE_EXTRACT_PROMPT,
|
|
67
|
+
}
|
|
68
|
+
prompt = _map[lang].replace("{qa_pair}", qa_pair_str)
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
response = self.llm_provider.generate([{"role": "user", "content": prompt}])
|
|
72
|
+
if not response:
|
|
73
|
+
logger.info(
|
|
74
|
+
f"[prefer_extractor]: (Error) LLM response content is {response} when extracting explicit preference"
|
|
75
|
+
)
|
|
76
|
+
return None
|
|
77
|
+
response = response.strip().replace("```json", "").replace("```", "").strip()
|
|
78
|
+
result = json.loads(response)
|
|
79
|
+
for d in result:
|
|
80
|
+
d["preference"] = d.pop("explicit_preference")
|
|
81
|
+
return result
|
|
82
|
+
except Exception as e:
|
|
83
|
+
logger.info(f"Error extracting explicit preference: {e}, return None")
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
def extract_implicit_preference(self, qa_pair: MessageList | str) -> dict[str, Any] | None:
|
|
87
|
+
"""Extract implicit preferences from cluster qa pairs."""
|
|
88
|
+
if not qa_pair:
|
|
89
|
+
return None
|
|
90
|
+
qa_pair_str = convert_messages_to_string(qa_pair) if isinstance(qa_pair, list) else qa_pair
|
|
91
|
+
lang = detect_lang(qa_pair_str)
|
|
92
|
+
_map = {
|
|
93
|
+
"zh": NAIVE_IMPLICIT_PREFERENCE_EXTRACT_PROMPT_ZH,
|
|
94
|
+
"en": NAIVE_IMPLICIT_PREFERENCE_EXTRACT_PROMPT,
|
|
95
|
+
}
|
|
96
|
+
prompt = _map[lang].replace("{qa_pair}", qa_pair_str)
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
response = self.llm_provider.generate([{"role": "user", "content": prompt}])
|
|
100
|
+
if not response:
|
|
101
|
+
logger.info(
|
|
102
|
+
f"[prefer_extractor]: (Error) LLM response content is {response} when extracting implicit preference"
|
|
103
|
+
)
|
|
104
|
+
return None
|
|
105
|
+
response = response.strip().replace("```json", "").replace("```", "").strip()
|
|
106
|
+
result = json.loads(response)
|
|
107
|
+
for d in result:
|
|
108
|
+
d["preference"] = d.pop("implicit_preference")
|
|
109
|
+
return result
|
|
110
|
+
except Exception as e:
|
|
111
|
+
logger.info(f"Error extracting implicit preferences: {e}, return None")
|
|
112
|
+
return None
|
|
113
|
+
|
|
114
|
+
def _process_single_chunk_explicit(
|
|
115
|
+
self, chunk: MessageList, msg_type: str, info: dict[str, Any]
|
|
116
|
+
) -> TextualMemoryItem | None:
|
|
117
|
+
"""Process a single chunk and return a TextualMemoryItem."""
|
|
118
|
+
basic_info = self.extract_basic_info(chunk)
|
|
119
|
+
if not basic_info["original_text"]:
|
|
120
|
+
return None
|
|
121
|
+
|
|
122
|
+
explicit_pref = self.extract_explicit_preference(basic_info["original_text"])
|
|
123
|
+
if not explicit_pref:
|
|
124
|
+
return None
|
|
125
|
+
|
|
126
|
+
memories = []
|
|
127
|
+
for pref in explicit_pref:
|
|
128
|
+
vector_info = {
|
|
129
|
+
"embedding": self.embedder.embed([pref["context_summary"]])[0],
|
|
130
|
+
}
|
|
131
|
+
user_info = {k: v for k, v in info.items() if k not in list_all_fields()}
|
|
132
|
+
extract_info = {**basic_info, **pref, **vector_info, **info, "info": user_info}
|
|
133
|
+
|
|
134
|
+
metadata = PreferenceTextualMemoryMetadata(
|
|
135
|
+
type=msg_type, preference_type="explicit_preference", **extract_info
|
|
136
|
+
)
|
|
137
|
+
memory = TextualMemoryItem(
|
|
138
|
+
id=str(uuid.uuid4()), memory=pref["context_summary"], metadata=metadata
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
memories.append(memory)
|
|
142
|
+
|
|
143
|
+
return memories
|
|
144
|
+
|
|
145
|
+
def _process_single_chunk_implicit(
|
|
146
|
+
self, chunk: MessageList, msg_type: str, info: dict[str, Any]
|
|
147
|
+
) -> TextualMemoryItem | None:
|
|
148
|
+
basic_info = self.extract_basic_info(chunk)
|
|
149
|
+
if not basic_info["original_text"]:
|
|
150
|
+
return None
|
|
151
|
+
implicit_pref = self.extract_implicit_preference(basic_info["original_text"])
|
|
152
|
+
if not implicit_pref:
|
|
153
|
+
return None
|
|
154
|
+
|
|
155
|
+
memories = []
|
|
156
|
+
for pref in implicit_pref:
|
|
157
|
+
vector_info = {
|
|
158
|
+
"embedding": self.embedder.embed([pref["context_summary"]])[0],
|
|
159
|
+
}
|
|
160
|
+
user_info = {k: v for k, v in info.items() if k not in list_all_fields()}
|
|
161
|
+
extract_info = {**basic_info, **pref, **vector_info, **info, "info": user_info}
|
|
162
|
+
|
|
163
|
+
metadata = PreferenceTextualMemoryMetadata(
|
|
164
|
+
type=msg_type, preference_type="implicit_preference", **extract_info
|
|
165
|
+
)
|
|
166
|
+
memory = TextualMemoryItem(
|
|
167
|
+
id=str(uuid.uuid4()), memory=pref["context_summary"], metadata=metadata
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
memories.append(memory)
|
|
171
|
+
|
|
172
|
+
return memories
|
|
173
|
+
|
|
174
|
+
def extract(
|
|
175
|
+
self,
|
|
176
|
+
messages: list[MessageList],
|
|
177
|
+
msg_type: str,
|
|
178
|
+
info: dict[str, Any],
|
|
179
|
+
max_workers: int = 10,
|
|
180
|
+
) -> list[TextualMemoryItem]:
|
|
181
|
+
"""Extract preference memories based on the messages using thread pool for acceleration."""
|
|
182
|
+
chunks: list[MessageList] = []
|
|
183
|
+
for message in messages:
|
|
184
|
+
chunk = self.splitter.split_chunks(message, split_type="overlap")
|
|
185
|
+
chunks.extend(chunk)
|
|
186
|
+
if not chunks:
|
|
187
|
+
return []
|
|
188
|
+
|
|
189
|
+
memories = []
|
|
190
|
+
with ContextThreadPoolExecutor(max_workers=min(max_workers, len(chunks))) as executor:
|
|
191
|
+
futures = {
|
|
192
|
+
executor.submit(self._process_single_chunk_explicit, chunk, msg_type, info): (
|
|
193
|
+
"explicit",
|
|
194
|
+
chunk,
|
|
195
|
+
)
|
|
196
|
+
for chunk in chunks
|
|
197
|
+
}
|
|
198
|
+
futures.update(
|
|
199
|
+
{
|
|
200
|
+
executor.submit(self._process_single_chunk_implicit, chunk, msg_type, info): (
|
|
201
|
+
"implicit",
|
|
202
|
+
chunk,
|
|
203
|
+
)
|
|
204
|
+
for chunk in chunks
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
for future in as_completed(futures):
|
|
209
|
+
try:
|
|
210
|
+
memory = future.result()
|
|
211
|
+
if memory:
|
|
212
|
+
if isinstance(memory, list):
|
|
213
|
+
memories.extend(memory)
|
|
214
|
+
else:
|
|
215
|
+
memories.append(memory)
|
|
216
|
+
except Exception as e:
|
|
217
|
+
task_type, chunk = futures[future]
|
|
218
|
+
logger.error(f"Error processing {task_type} chunk: {chunk}\n{e}")
|
|
219
|
+
continue
|
|
220
|
+
|
|
221
|
+
return memories
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
from typing import Any, ClassVar
|
|
2
|
+
|
|
3
|
+
from memos.memories.textual.prefer_text_memory.adder import BaseAdder, NaiveAdder
|
|
4
|
+
from memos.memories.textual.prefer_text_memory.config import (
|
|
5
|
+
AdderConfigFactory,
|
|
6
|
+
ExtractorConfigFactory,
|
|
7
|
+
RetrieverConfigFactory,
|
|
8
|
+
)
|
|
9
|
+
from memos.memories.textual.prefer_text_memory.extractor import BaseExtractor, NaiveExtractor
|
|
10
|
+
from memos.memories.textual.prefer_text_memory.retrievers import BaseRetriever, NaiveRetriever
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class AdderFactory(BaseAdder):
|
|
14
|
+
"""Factory class for creating Adder instances."""
|
|
15
|
+
|
|
16
|
+
backend_to_class: ClassVar[dict[str, Any]] = {
|
|
17
|
+
"naive": NaiveAdder,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@classmethod
|
|
21
|
+
def from_config(
|
|
22
|
+
cls,
|
|
23
|
+
config_factory: AdderConfigFactory,
|
|
24
|
+
llm_provider=None,
|
|
25
|
+
embedder=None,
|
|
26
|
+
vector_db=None,
|
|
27
|
+
text_mem=None,
|
|
28
|
+
) -> BaseAdder:
|
|
29
|
+
"""Create a Adder instance from a configuration factory."""
|
|
30
|
+
backend = config_factory.backend
|
|
31
|
+
if backend not in cls.backend_to_class:
|
|
32
|
+
raise ValueError(f"Invalid backend: {backend}")
|
|
33
|
+
adder_class = cls.backend_to_class[backend]
|
|
34
|
+
return adder_class(
|
|
35
|
+
llm_provider=llm_provider, embedder=embedder, vector_db=vector_db, text_mem=text_mem
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ExtractorFactory(BaseExtractor):
|
|
40
|
+
"""Factory class for creating Extractor instances."""
|
|
41
|
+
|
|
42
|
+
backend_to_class: ClassVar[dict[str, Any]] = {
|
|
43
|
+
"naive": NaiveExtractor,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def from_config(
|
|
48
|
+
cls,
|
|
49
|
+
config_factory: ExtractorConfigFactory,
|
|
50
|
+
llm_provider=None,
|
|
51
|
+
embedder=None,
|
|
52
|
+
vector_db=None,
|
|
53
|
+
) -> BaseExtractor:
|
|
54
|
+
"""Create a Extractor instance from a configuration factory."""
|
|
55
|
+
backend = config_factory.backend
|
|
56
|
+
if backend not in cls.backend_to_class:
|
|
57
|
+
raise ValueError(f"Invalid backend: {backend}")
|
|
58
|
+
extractor_class = cls.backend_to_class[backend]
|
|
59
|
+
return extractor_class(llm_provider=llm_provider, embedder=embedder, vector_db=vector_db)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class RetrieverFactory(BaseRetriever):
|
|
63
|
+
"""Factory class for creating Retriever instances."""
|
|
64
|
+
|
|
65
|
+
backend_to_class: ClassVar[dict[str, Any]] = {
|
|
66
|
+
"naive": NaiveRetriever,
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@classmethod
|
|
70
|
+
def from_config(
|
|
71
|
+
cls,
|
|
72
|
+
config_factory: RetrieverConfigFactory,
|
|
73
|
+
llm_provider=None,
|
|
74
|
+
embedder=None,
|
|
75
|
+
reranker=None,
|
|
76
|
+
vector_db=None,
|
|
77
|
+
) -> BaseRetriever:
|
|
78
|
+
"""Create a Retriever instance from a configuration factory."""
|
|
79
|
+
backend = config_factory.backend
|
|
80
|
+
if backend not in cls.backend_to_class:
|
|
81
|
+
raise ValueError(f"Invalid backend: {backend}")
|
|
82
|
+
retriever_class = cls.backend_to_class[backend]
|
|
83
|
+
return retriever_class(
|
|
84
|
+
llm_provider=llm_provider, embedder=embedder, reranker=reranker, vector_db=vector_db
|
|
85
|
+
)
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from memos.context.context import ContextThreadPoolExecutor
|
|
7
|
+
from memos.memories.textual.item import PreferenceTextualMemoryMetadata, TextualMemoryItem
|
|
8
|
+
from memos.vec_dbs.item import MilvusVecDBItem
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class BaseRetriever(ABC):
|
|
12
|
+
"""Abstract base class for retrievers."""
|
|
13
|
+
|
|
14
|
+
@abstractmethod
|
|
15
|
+
def __init__(self, llm_provider=None, embedder=None, reranker=None, vector_db=None):
|
|
16
|
+
"""Initialize the retriever."""
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def retrieve(
|
|
20
|
+
self,
|
|
21
|
+
query: str,
|
|
22
|
+
top_k: int,
|
|
23
|
+
info: dict[str, Any] | None = None,
|
|
24
|
+
search_filter: dict[str, Any] | None = None,
|
|
25
|
+
) -> list[TextualMemoryItem]:
|
|
26
|
+
"""Retrieve memories from the retriever."""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class NaiveRetriever(BaseRetriever):
|
|
30
|
+
"""Naive retriever."""
|
|
31
|
+
|
|
32
|
+
def __init__(self, llm_provider=None, embedder=None, reranker=None, vector_db=None):
|
|
33
|
+
"""Initialize the naive retriever."""
|
|
34
|
+
super().__init__(llm_provider, embedder, reranker, vector_db)
|
|
35
|
+
self.reranker = reranker
|
|
36
|
+
self.vector_db = vector_db
|
|
37
|
+
self.embedder = embedder
|
|
38
|
+
|
|
39
|
+
def _naive_reranker(
|
|
40
|
+
self, query: str, prefs_mem: list[TextualMemoryItem], top_k: int, **kwargs: Any
|
|
41
|
+
) -> list[TextualMemoryItem]:
|
|
42
|
+
if self.reranker:
|
|
43
|
+
prefs_mem_reranked = []
|
|
44
|
+
prefs_mem_tuple = self.reranker.rerank(query, prefs_mem, top_k)
|
|
45
|
+
for item, score in prefs_mem_tuple:
|
|
46
|
+
item.metadata.score = score
|
|
47
|
+
prefs_mem_reranked.append(item)
|
|
48
|
+
return prefs_mem_reranked
|
|
49
|
+
|
|
50
|
+
def _original_text_reranker(
|
|
51
|
+
self,
|
|
52
|
+
query: str,
|
|
53
|
+
prefs_mem: list[TextualMemoryItem],
|
|
54
|
+
prefs: list[MilvusVecDBItem],
|
|
55
|
+
top_k: int,
|
|
56
|
+
**kwargs: Any,
|
|
57
|
+
) -> list[TextualMemoryItem]:
|
|
58
|
+
if self.reranker:
|
|
59
|
+
from copy import deepcopy
|
|
60
|
+
|
|
61
|
+
prefs_mem_for_reranker = deepcopy(prefs_mem)
|
|
62
|
+
for pref_mem, pref in zip(prefs_mem_for_reranker, prefs, strict=False):
|
|
63
|
+
pref_mem.memory = pref_mem.memory + "\n" + pref.original_text
|
|
64
|
+
reranked_results = self.reranker.rerank(query, prefs_mem_for_reranker, top_k)
|
|
65
|
+
prefs_mem_for_reranker = [item for item, _ in reranked_results]
|
|
66
|
+
prefs_ids = [item.id for item in prefs_mem_for_reranker]
|
|
67
|
+
prefs_dict = {item.id: item for item in prefs_mem}
|
|
68
|
+
|
|
69
|
+
# Create mapping from id to score from reranked results
|
|
70
|
+
reranked_scores = {item.id: score for item, score in reranked_results}
|
|
71
|
+
|
|
72
|
+
# Assign scores to the original items
|
|
73
|
+
result_items = []
|
|
74
|
+
for item_id in prefs_ids:
|
|
75
|
+
if item_id in prefs_dict:
|
|
76
|
+
original_item = prefs_dict[item_id]
|
|
77
|
+
original_item.metadata.score = reranked_scores.get(item_id)
|
|
78
|
+
result_items.append(original_item)
|
|
79
|
+
return result_items
|
|
80
|
+
return prefs_mem
|
|
81
|
+
|
|
82
|
+
def retrieve(
|
|
83
|
+
self,
|
|
84
|
+
query: str,
|
|
85
|
+
top_k: int,
|
|
86
|
+
info: dict[str, Any] | None = None,
|
|
87
|
+
search_filter: dict[str, Any] | None = None,
|
|
88
|
+
) -> list[TextualMemoryItem]:
|
|
89
|
+
"""Retrieve memories from the naive retriever."""
|
|
90
|
+
# TODO: un-support rewrite query and session filter now
|
|
91
|
+
if info:
|
|
92
|
+
info = info.copy() # Create a copy to avoid modifying the original
|
|
93
|
+
info.pop("chat_history", None)
|
|
94
|
+
info.pop("session_id", None)
|
|
95
|
+
search_filter = {"and": [info, search_filter]}
|
|
96
|
+
query_embeddings = self.embedder.embed([query]) # Pass as list to get list of embeddings
|
|
97
|
+
query_embedding = query_embeddings[0] # Get the first (and only) embedding
|
|
98
|
+
|
|
99
|
+
# Use thread pool to parallelize the searches
|
|
100
|
+
with ContextThreadPoolExecutor(max_workers=2) as executor:
|
|
101
|
+
# Submit all search tasks
|
|
102
|
+
future_explicit = executor.submit(
|
|
103
|
+
self.vector_db.search,
|
|
104
|
+
query_embedding,
|
|
105
|
+
query,
|
|
106
|
+
"explicit_preference",
|
|
107
|
+
top_k * 2,
|
|
108
|
+
search_filter,
|
|
109
|
+
)
|
|
110
|
+
future_implicit = executor.submit(
|
|
111
|
+
self.vector_db.search,
|
|
112
|
+
query_embedding,
|
|
113
|
+
query,
|
|
114
|
+
"implicit_preference",
|
|
115
|
+
top_k * 2,
|
|
116
|
+
search_filter,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# Wait for all results
|
|
120
|
+
explicit_prefs = future_explicit.result()
|
|
121
|
+
implicit_prefs = future_implicit.result()
|
|
122
|
+
|
|
123
|
+
# sort by score
|
|
124
|
+
explicit_prefs.sort(key=lambda x: x.score, reverse=True)
|
|
125
|
+
implicit_prefs.sort(key=lambda x: x.score, reverse=True)
|
|
126
|
+
|
|
127
|
+
explicit_prefs_mem = [
|
|
128
|
+
TextualMemoryItem(
|
|
129
|
+
id=pref.id,
|
|
130
|
+
memory=pref.memory,
|
|
131
|
+
metadata=PreferenceTextualMemoryMetadata(**pref.payload),
|
|
132
|
+
)
|
|
133
|
+
for pref in explicit_prefs
|
|
134
|
+
if pref.payload.get("preference", None)
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
implicit_prefs_mem = [
|
|
138
|
+
TextualMemoryItem(
|
|
139
|
+
id=pref.id,
|
|
140
|
+
memory=pref.memory,
|
|
141
|
+
metadata=PreferenceTextualMemoryMetadata(**pref.payload),
|
|
142
|
+
)
|
|
143
|
+
for pref in implicit_prefs
|
|
144
|
+
if pref.payload.get("preference", None)
|
|
145
|
+
]
|
|
146
|
+
|
|
147
|
+
reranker_map = {
|
|
148
|
+
"naive": self._naive_reranker,
|
|
149
|
+
"original_text": self._original_text_reranker,
|
|
150
|
+
}
|
|
151
|
+
reranker_func = reranker_map["naive"]
|
|
152
|
+
prefs_mem_explicit = reranker_func(
|
|
153
|
+
query=query,
|
|
154
|
+
prefs_mem=explicit_prefs_mem,
|
|
155
|
+
prefs=explicit_prefs,
|
|
156
|
+
top_k=top_k,
|
|
157
|
+
)
|
|
158
|
+
prefs_mem_implicit = reranker_func(
|
|
159
|
+
query=query,
|
|
160
|
+
prefs_mem=implicit_prefs_mem,
|
|
161
|
+
prefs=implicit_prefs,
|
|
162
|
+
top_k=top_k,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# filter explicit mem by score bigger than threshold
|
|
166
|
+
prefs_mem_explicit = [
|
|
167
|
+
item
|
|
168
|
+
for item in prefs_mem_explicit
|
|
169
|
+
if item.metadata.score >= float(os.getenv("PREFERENCE_SEARCH_THRESHOLD", 0.0))
|
|
170
|
+
]
|
|
171
|
+
prefs_mem_implicit = [
|
|
172
|
+
item
|
|
173
|
+
for item in prefs_mem_implicit
|
|
174
|
+
if item.metadata.score >= float(os.getenv("PREFERENCE_SEARCH_THRESHOLD", 0.0))
|
|
175
|
+
]
|
|
176
|
+
|
|
177
|
+
return prefs_mem_explicit + prefs_mem_implicit
|