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,571 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
from memos.configs.mem_os import MOSConfig
|
|
4
|
+
from memos.log import get_logger
|
|
5
|
+
from memos.mem_os.main import MOS
|
|
6
|
+
from memos.mem_scheduler.schemas.general_schemas import (
|
|
7
|
+
MONITOR_WORKING_MEMORY_TYPE,
|
|
8
|
+
)
|
|
9
|
+
from memos.mem_scheduler.schemas.message_schemas import ScheduleMessageItem
|
|
10
|
+
from memos.mem_scheduler.schemas.task_schemas import (
|
|
11
|
+
ANSWER_TASK_LABEL,
|
|
12
|
+
QUERY_TASK_LABEL,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
logger = get_logger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class MOSForTestScheduler(MOS):
|
|
20
|
+
"""This class is only to test abilities of mem scheduler with enhanced monitoring"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, config: MOSConfig):
|
|
23
|
+
super().__init__(config)
|
|
24
|
+
self.memory_helpfulness_analysis = []
|
|
25
|
+
|
|
26
|
+
def _str_memories(self, memories: list[str]) -> str:
|
|
27
|
+
"""Format memories for display."""
|
|
28
|
+
if not memories:
|
|
29
|
+
return "No memories."
|
|
30
|
+
return "\n".join(f"{i + 1}. {memory}" for i, memory in enumerate(memories))
|
|
31
|
+
|
|
32
|
+
def _analyze_memory_helpfulness(
|
|
33
|
+
self,
|
|
34
|
+
query: str,
|
|
35
|
+
working_memories_before: list,
|
|
36
|
+
working_memories_after: list,
|
|
37
|
+
scheduler_memories: list,
|
|
38
|
+
):
|
|
39
|
+
"""Analyze how helpful each memory is for answering the current query."""
|
|
40
|
+
print("\n" + "=" * 80)
|
|
41
|
+
print("š§ MEMORY HELPFULNESS ANALYSIS FOR QUERY")
|
|
42
|
+
print("=" * 80)
|
|
43
|
+
|
|
44
|
+
print(f"š Query: {query}")
|
|
45
|
+
print(f"š Working Memories Before Scheduler: {len(working_memories_before)}")
|
|
46
|
+
print(f"š Working Memories After Scheduler: {len(working_memories_after)}")
|
|
47
|
+
print(f"š Working Memories from Monitor: {len(scheduler_memories)}")
|
|
48
|
+
|
|
49
|
+
# Display working memories before scheduler (first 5 only)
|
|
50
|
+
if working_memories_before:
|
|
51
|
+
print("\nš WORKING MEMORIES BEFORE SCHEDULER (first 5):")
|
|
52
|
+
for i, mem in enumerate(working_memories_before[:5]):
|
|
53
|
+
print(f" {i + 1}. {mem}")
|
|
54
|
+
|
|
55
|
+
# Display working memories after scheduler (first 5 only)
|
|
56
|
+
if working_memories_after:
|
|
57
|
+
print("\nš WORKING MEMORIES AFTER SCHEDULER (first 5):")
|
|
58
|
+
for i, mem in enumerate(working_memories_after[:5]):
|
|
59
|
+
print(f" {i + 1}. {mem}")
|
|
60
|
+
|
|
61
|
+
# Display scheduler memories from monitor (first 5 only)
|
|
62
|
+
if scheduler_memories:
|
|
63
|
+
print("\nš WORKING MEMORIES FROM MONITOR (first 5):")
|
|
64
|
+
for i, mem in enumerate(scheduler_memories[:5]):
|
|
65
|
+
print(f" {i + 1}. {mem}")
|
|
66
|
+
|
|
67
|
+
# Batch assess working memory helpfulness before scheduler
|
|
68
|
+
if working_memories_before:
|
|
69
|
+
print(
|
|
70
|
+
f"\nš WORKING MEMORY HELPFULNESS BEFORE SCHEDULER ({len(working_memories_before)}):"
|
|
71
|
+
)
|
|
72
|
+
before_assessment = self._batch_assess_memories(
|
|
73
|
+
query, working_memories_before[:5], "before scheduler"
|
|
74
|
+
)
|
|
75
|
+
for i, (_mem, score, reason) in enumerate(before_assessment):
|
|
76
|
+
print(f" {i + 1}. Helpfulness: {score}/10 - {reason}")
|
|
77
|
+
|
|
78
|
+
# Batch assess working memory helpfulness after scheduler
|
|
79
|
+
if working_memories_after:
|
|
80
|
+
print(
|
|
81
|
+
f"\nš WORKING MEMORY HELPFULNESS AFTER SCHEDULER ({len(working_memories_after)}):"
|
|
82
|
+
)
|
|
83
|
+
after_assessment = self._batch_assess_memories(
|
|
84
|
+
query, working_memories_after[:5], "after scheduler"
|
|
85
|
+
)
|
|
86
|
+
for i, (_mem, score, reason) in enumerate(after_assessment):
|
|
87
|
+
print(f" {i + 1}. Helpfulness: {score}/10 - {reason}")
|
|
88
|
+
|
|
89
|
+
# Batch assess scheduler memories from monitor
|
|
90
|
+
if scheduler_memories:
|
|
91
|
+
print(f"\nš WORKINGMEMORIES FROM MONITOR HELPFULNESS ({len(scheduler_memories)}):")
|
|
92
|
+
scheduler_assessment = self._batch_assess_memories(
|
|
93
|
+
query, scheduler_memories[:5], "from monitor"
|
|
94
|
+
)
|
|
95
|
+
for i, (_mem, score, reason) in enumerate(scheduler_assessment):
|
|
96
|
+
print(f" {i + 1}. Helpfulness: {score}/10 - {reason}")
|
|
97
|
+
|
|
98
|
+
# Overall assessment - compare before vs after vs scheduler
|
|
99
|
+
print("\nš” OVERALL ASSESSMENT:")
|
|
100
|
+
if working_memories_before and working_memories_after:
|
|
101
|
+
before_scores = (
|
|
102
|
+
[score for _, score, _ in before_assessment]
|
|
103
|
+
if "before_assessment" in locals()
|
|
104
|
+
else []
|
|
105
|
+
)
|
|
106
|
+
after_scores = (
|
|
107
|
+
[score for _, score, _ in after_assessment]
|
|
108
|
+
if "after_assessment" in locals()
|
|
109
|
+
else []
|
|
110
|
+
)
|
|
111
|
+
scheduler_scores = (
|
|
112
|
+
[score for _, score, _ in scheduler_assessment]
|
|
113
|
+
if "scheduler_assessment" in locals()
|
|
114
|
+
else []
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
avg_before_helpfulness = sum(before_scores) / len(before_scores)
|
|
118
|
+
avg_after_helpfulness = sum(after_scores) / len(after_scores)
|
|
119
|
+
|
|
120
|
+
print(f" Average Helpfulness Before Scheduler: {avg_before_helpfulness:.1f}/10")
|
|
121
|
+
print(f" Average Helpfulness After Scheduler: {avg_after_helpfulness:.1f}/10")
|
|
122
|
+
print(f" Improvement: {avg_after_helpfulness - avg_before_helpfulness:+.1f}")
|
|
123
|
+
|
|
124
|
+
if avg_after_helpfulness > avg_before_helpfulness:
|
|
125
|
+
print(" ā
Scheduler improved working memory quality")
|
|
126
|
+
elif avg_after_helpfulness < avg_before_helpfulness:
|
|
127
|
+
print(" ā Scheduler decreased working memory quality")
|
|
128
|
+
else:
|
|
129
|
+
print(" āļø Scheduler maintained working memory quality")
|
|
130
|
+
|
|
131
|
+
# Compare scheduler memories vs working memories
|
|
132
|
+
|
|
133
|
+
avg_scheduler_helpfulness = sum(scheduler_scores) / len(scheduler_scores)
|
|
134
|
+
print(
|
|
135
|
+
f" Average Helpfulness of Memories from Monitors: {avg_scheduler_helpfulness:.1f}/10"
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
if avg_scheduler_helpfulness > avg_after_helpfulness:
|
|
139
|
+
print(" šÆ Memories from Monitors are more helpful than working memories")
|
|
140
|
+
elif avg_scheduler_helpfulness < avg_after_helpfulness:
|
|
141
|
+
print(" ā ļø Working memories are more helpful than Memories from Monitors")
|
|
142
|
+
else:
|
|
143
|
+
print(
|
|
144
|
+
" āļø WORKING Memories from Monitors and working memories have similar helpfulness"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
# Record analysis results
|
|
148
|
+
self.memory_helpfulness_analysis.append(
|
|
149
|
+
{
|
|
150
|
+
"query": query,
|
|
151
|
+
"working_memories_before_count": len(working_memories_before),
|
|
152
|
+
"working_memories_after_count": len(working_memories_after),
|
|
153
|
+
"scheduler_memories_count": len(scheduler_memories),
|
|
154
|
+
"working_helpfulness_before": [score for _, score, _ in before_assessment]
|
|
155
|
+
if "before_assessment" in locals()
|
|
156
|
+
else [],
|
|
157
|
+
"working_helpfulness_after": [score for _, score, _ in after_assessment]
|
|
158
|
+
if "after_assessment" in locals()
|
|
159
|
+
else [],
|
|
160
|
+
"scheduler_helpfulness": [score for _, score, _ in scheduler_assessment]
|
|
161
|
+
if "scheduler_assessment" in locals()
|
|
162
|
+
else [],
|
|
163
|
+
}
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
print("=" * 80 + "\n")
|
|
167
|
+
|
|
168
|
+
def _batch_assess_memories(self, query: str, memories: list, context: str) -> list:
|
|
169
|
+
"""Use LLM to assess multiple memories at once and compare their quality."""
|
|
170
|
+
try:
|
|
171
|
+
# Create prompt for batch assessment
|
|
172
|
+
memories_text = "\n".join([f"{i + 1}. {mem}" for i, mem in enumerate(memories)])
|
|
173
|
+
|
|
174
|
+
assessment_prompt = f"""
|
|
175
|
+
Task: Assess and compare the helpfulness of multiple memories for answering a query.
|
|
176
|
+
|
|
177
|
+
Query: "{query}"
|
|
178
|
+
|
|
179
|
+
Context: These are working memories {context}.
|
|
180
|
+
|
|
181
|
+
Memories to assess:
|
|
182
|
+
{memories_text}
|
|
183
|
+
|
|
184
|
+
Please provide:
|
|
185
|
+
1. A helpfulness score from 1-10 for each memory (where 10 = extremely helpful, 1 = not helpful at all)
|
|
186
|
+
2. A brief reason for each score
|
|
187
|
+
3. Rank the memories from most helpful to least helpful
|
|
188
|
+
|
|
189
|
+
Format your response as:
|
|
190
|
+
Memory 1: Score [number] - [reason]
|
|
191
|
+
Memory 2: Score [number] - [reason]
|
|
192
|
+
Memory 3: Score [number] - [reason]
|
|
193
|
+
Memory 4: Score [number] - [reason]
|
|
194
|
+
Memory 5: Score [number] - [reason]
|
|
195
|
+
|
|
196
|
+
Ranking: [memory numbers in order from most to least helpful]
|
|
197
|
+
|
|
198
|
+
Consider:
|
|
199
|
+
- Direct relevance to the query
|
|
200
|
+
- Information completeness
|
|
201
|
+
- How directly it answers the question
|
|
202
|
+
- Whether it provides useful context or background
|
|
203
|
+
- Compare memories against each other for relative quality
|
|
204
|
+
"""
|
|
205
|
+
|
|
206
|
+
# Use the chat LLM to get batch assessment
|
|
207
|
+
messages = [{"role": "user", "content": assessment_prompt}]
|
|
208
|
+
response = self.chat_llm.generate(messages)
|
|
209
|
+
|
|
210
|
+
# Parse the response to extract scores and reasons
|
|
211
|
+
assessment_results = []
|
|
212
|
+
lines = response.strip().split("\n")
|
|
213
|
+
|
|
214
|
+
for i, mem in enumerate(memories):
|
|
215
|
+
score = 5 # Default score
|
|
216
|
+
reason = "LLM assessment failed, using default score"
|
|
217
|
+
|
|
218
|
+
# Look for the corresponding memory line
|
|
219
|
+
for line in lines:
|
|
220
|
+
if line.startswith(f"Memory {i + 1}:"):
|
|
221
|
+
try:
|
|
222
|
+
# Extract score and reason from line like "Memory 1: Score 8 - Highly relevant"
|
|
223
|
+
parts = line.split("Score ")[1].split(" - ", 1)
|
|
224
|
+
score = int(parts[0])
|
|
225
|
+
score = max(1, min(10, score)) # Ensure score is 1-10
|
|
226
|
+
reason = parts[1] if len(parts) > 1 else "No reason provided"
|
|
227
|
+
except Exception:
|
|
228
|
+
pass
|
|
229
|
+
break
|
|
230
|
+
|
|
231
|
+
assessment_results.append((mem, score, reason))
|
|
232
|
+
|
|
233
|
+
return assessment_results
|
|
234
|
+
|
|
235
|
+
except Exception as e:
|
|
236
|
+
logger.warning(f"LLM batch assessment failed: {e}, using fallback scoring")
|
|
237
|
+
# Fallback to individual assessment if batch fails
|
|
238
|
+
return [
|
|
239
|
+
(
|
|
240
|
+
mem,
|
|
241
|
+
self._assess_memory_helpfulness(query, mem)["score"],
|
|
242
|
+
self._assess_memory_helpfulness(query, mem)["reason"],
|
|
243
|
+
)
|
|
244
|
+
for mem in memories
|
|
245
|
+
]
|
|
246
|
+
|
|
247
|
+
def _assess_memory_helpfulness(self, query: str, memory: str) -> dict:
|
|
248
|
+
"""Use LLM to assess how helpful a memory is for answering the current query (1-10 scale)"""
|
|
249
|
+
try:
|
|
250
|
+
# Create prompt for LLM assessment
|
|
251
|
+
assessment_prompt = f"""
|
|
252
|
+
Task: Rate how helpful this memory is for answering the given query on a scale of 1-10.
|
|
253
|
+
|
|
254
|
+
Query: "{query}"
|
|
255
|
+
|
|
256
|
+
Memory: "{memory}"
|
|
257
|
+
|
|
258
|
+
Please provide:
|
|
259
|
+
1. A score from 1-10 (where 10 = extremely helpful, 1 = not helpful at all)
|
|
260
|
+
2. A brief reason for your score
|
|
261
|
+
|
|
262
|
+
Format your response as:
|
|
263
|
+
Score: [number]
|
|
264
|
+
Reason: [your explanation]
|
|
265
|
+
|
|
266
|
+
Consider:
|
|
267
|
+
- Direct relevance to the query
|
|
268
|
+
- Information completeness
|
|
269
|
+
- How directly it answers the question
|
|
270
|
+
- Whether it provides useful context or background
|
|
271
|
+
"""
|
|
272
|
+
|
|
273
|
+
# Use the chat LLM to get assessment
|
|
274
|
+
messages = [{"role": "user", "content": assessment_prompt}]
|
|
275
|
+
response = self.chat_llm.generate(messages)
|
|
276
|
+
|
|
277
|
+
# Parse the response to extract score and reason
|
|
278
|
+
lines = response.strip().split("\n")
|
|
279
|
+
score = 5 # Default score
|
|
280
|
+
reason = "LLM assessment failed, using default score"
|
|
281
|
+
|
|
282
|
+
for line in lines:
|
|
283
|
+
if line.startswith("Score:"):
|
|
284
|
+
try:
|
|
285
|
+
score_text = line.split(":")[1].strip()
|
|
286
|
+
score = int(score_text)
|
|
287
|
+
score = max(1, min(10, score)) # Ensure score is 1-10
|
|
288
|
+
except Exception:
|
|
289
|
+
pass
|
|
290
|
+
elif line.startswith("Reason:"):
|
|
291
|
+
reason = line.split(":", 1)[1].strip()
|
|
292
|
+
|
|
293
|
+
return {"score": score, "reason": reason}
|
|
294
|
+
|
|
295
|
+
except Exception as e:
|
|
296
|
+
logger.warning(f"LLM assessment failed: {e}, using fallback scoring")
|
|
297
|
+
# Fallback to simple keyword matching if LLM fails
|
|
298
|
+
return self._fallback_memory_assessment(query, memory)
|
|
299
|
+
|
|
300
|
+
def _fallback_memory_assessment(self, query: str, memory: str) -> dict:
|
|
301
|
+
"""Fallback assessment method using keyword matching if LLM fails"""
|
|
302
|
+
query_lower = query.lower()
|
|
303
|
+
memory_lower = memory.lower()
|
|
304
|
+
|
|
305
|
+
# Keyword matching
|
|
306
|
+
query_words = set(query_lower.split())
|
|
307
|
+
memory_words = set(memory_lower.split())
|
|
308
|
+
common_words = query_words.intersection(memory_words)
|
|
309
|
+
|
|
310
|
+
# Semantic relevance scoring
|
|
311
|
+
score = 0
|
|
312
|
+
|
|
313
|
+
# Exact keyword matches (highest weight)
|
|
314
|
+
if len(common_words) > 0:
|
|
315
|
+
score += min(len(common_words) * 2, 6)
|
|
316
|
+
|
|
317
|
+
# Partial matches (medium weight)
|
|
318
|
+
partial_matches = sum(
|
|
319
|
+
1 for qw in query_words for mw in memory_words if qw in mw or mw in qw
|
|
320
|
+
)
|
|
321
|
+
if partial_matches > 0:
|
|
322
|
+
score += min(partial_matches, 3)
|
|
323
|
+
|
|
324
|
+
# Topic relevance (through common topic words)
|
|
325
|
+
topic_words = [
|
|
326
|
+
"problem",
|
|
327
|
+
"solution",
|
|
328
|
+
"answer",
|
|
329
|
+
"method",
|
|
330
|
+
"reason",
|
|
331
|
+
"result",
|
|
332
|
+
"analysis",
|
|
333
|
+
"compare",
|
|
334
|
+
"explain",
|
|
335
|
+
]
|
|
336
|
+
topic_matches = sum(1 for topic in topic_words if topic in memory_lower)
|
|
337
|
+
score += topic_matches
|
|
338
|
+
|
|
339
|
+
# Ensure score is 1-10
|
|
340
|
+
score = max(1, min(10, score))
|
|
341
|
+
|
|
342
|
+
# Determine helpfulness level
|
|
343
|
+
if score >= 8:
|
|
344
|
+
reason = "Highly relevant, directly answers the query"
|
|
345
|
+
elif score >= 6:
|
|
346
|
+
reason = "Relevant, provides useful information"
|
|
347
|
+
elif score >= 4:
|
|
348
|
+
reason = "Partially relevant, somewhat helpful"
|
|
349
|
+
elif score >= 2:
|
|
350
|
+
reason = "Low relevance, limited help"
|
|
351
|
+
else:
|
|
352
|
+
reason = "Very low relevance, minimal help"
|
|
353
|
+
|
|
354
|
+
return {"score": score, "reason": reason}
|
|
355
|
+
|
|
356
|
+
def _assess_ranking_quality(self, rank: int, helpfulness: int) -> str:
|
|
357
|
+
"""Use LLM to assess whether the memory ranking is reasonable"""
|
|
358
|
+
try:
|
|
359
|
+
# Create prompt for LLM ranking assessment
|
|
360
|
+
ranking_prompt = f"""
|
|
361
|
+
Task: Assess whether this memory ranking is reasonable.
|
|
362
|
+
|
|
363
|
+
Context: A memory with helpfulness score {helpfulness}/10 is ranked at position {rank}.
|
|
364
|
+
|
|
365
|
+
Please evaluate if this ranking makes sense and provide a brief assessment.
|
|
366
|
+
|
|
367
|
+
Consider:
|
|
368
|
+
- Higher helpfulness scores should generally rank higher
|
|
369
|
+
- Rank 1 should typically have the highest helpfulness
|
|
370
|
+
- The relationship between rank and helpfulness
|
|
371
|
+
|
|
372
|
+
Provide a brief assessment in one sentence.
|
|
373
|
+
"""
|
|
374
|
+
|
|
375
|
+
# Use the chat LLM to get assessment
|
|
376
|
+
messages = [{"role": "user", "content": ranking_prompt}]
|
|
377
|
+
response = self.chat_llm.generate(messages)
|
|
378
|
+
|
|
379
|
+
return response.strip()
|
|
380
|
+
|
|
381
|
+
except Exception as e:
|
|
382
|
+
logger.warning(f"LLM ranking assessment failed: {e}, using fallback assessment")
|
|
383
|
+
# Fallback assessment
|
|
384
|
+
if rank == 1 and helpfulness >= 8:
|
|
385
|
+
return "ā
Ranking is reasonable - most helpful memory ranked first"
|
|
386
|
+
elif rank == 1 and helpfulness <= 4:
|
|
387
|
+
return "ā Ranking is unreasonable - first ranked memory has low helpfulness"
|
|
388
|
+
elif rank <= 3 and helpfulness >= 6:
|
|
389
|
+
return "ā
Ranking is reasonable - high helpfulness memory ranked high"
|
|
390
|
+
elif rank <= 3 and helpfulness <= 3:
|
|
391
|
+
return "ā ļø Ranking may be unreasonable - low helpfulness memory ranked high"
|
|
392
|
+
elif rank > 3 and helpfulness >= 7:
|
|
393
|
+
return "ā ļø Ranking may be unreasonable - high helpfulness memory ranked low"
|
|
394
|
+
else:
|
|
395
|
+
return "š” Ranking is acceptable - helpfulness and rank generally match"
|
|
396
|
+
|
|
397
|
+
def chat(self, query: str, user_id: str | None = None) -> str:
|
|
398
|
+
"""
|
|
399
|
+
Chat with the MOS with memory helpfulness analysis.
|
|
400
|
+
|
|
401
|
+
Args:
|
|
402
|
+
query (str): The user's query.
|
|
403
|
+
user_id (str | None): The user ID.
|
|
404
|
+
|
|
405
|
+
Returns:
|
|
406
|
+
str: The response from the MOS.
|
|
407
|
+
"""
|
|
408
|
+
target_user_id = user_id if user_id is not None else self.user_id
|
|
409
|
+
accessible_cubes = self.user_manager.get_user_cubes(target_user_id)
|
|
410
|
+
user_cube_ids = [cube.cube_id for cube in accessible_cubes]
|
|
411
|
+
|
|
412
|
+
if target_user_id not in self.chat_history_manager:
|
|
413
|
+
self._register_chat_history(target_user_id)
|
|
414
|
+
|
|
415
|
+
chat_history = self.chat_history_manager[target_user_id]
|
|
416
|
+
topk_for_scheduler = 2
|
|
417
|
+
|
|
418
|
+
if self.config.enable_textual_memory and self.mem_cubes:
|
|
419
|
+
memories_all = []
|
|
420
|
+
for mem_cube_id, mem_cube in self.mem_cubes.items():
|
|
421
|
+
if mem_cube_id not in user_cube_ids:
|
|
422
|
+
continue
|
|
423
|
+
if not mem_cube.text_mem:
|
|
424
|
+
continue
|
|
425
|
+
|
|
426
|
+
# Get working memories BEFORE scheduler
|
|
427
|
+
working_memories_before = [m.memory for m in mem_cube.text_mem.get_working_memory()]
|
|
428
|
+
|
|
429
|
+
message_item = ScheduleMessageItem(
|
|
430
|
+
user_id=target_user_id,
|
|
431
|
+
mem_cube_id=mem_cube_id,
|
|
432
|
+
label=QUERY_TASK_LABEL,
|
|
433
|
+
content=query,
|
|
434
|
+
timestamp=datetime.now(),
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
print(f"\nš Starting Scheduler for {mem_cube_id}...")
|
|
438
|
+
|
|
439
|
+
# Force scheduler to run immediately
|
|
440
|
+
self.mem_scheduler.monitor.query_trigger_interval = 0
|
|
441
|
+
self.mem_scheduler._query_message_consumer(messages=[message_item])
|
|
442
|
+
|
|
443
|
+
# Get scheduler memories
|
|
444
|
+
scheduler_memories = self.mem_scheduler.monitor.get_monitor_memories(
|
|
445
|
+
user_id=target_user_id,
|
|
446
|
+
mem_cube_id=mem_cube_id,
|
|
447
|
+
memory_type=MONITOR_WORKING_MEMORY_TYPE,
|
|
448
|
+
top_k=20,
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
# Get working memories AFTER scheduler
|
|
452
|
+
working_memories_after = [m.memory for m in mem_cube.text_mem.get_working_memory()]
|
|
453
|
+
|
|
454
|
+
# Get mem_cube memories for response generation
|
|
455
|
+
memories = mem_cube.text_mem.search(
|
|
456
|
+
query,
|
|
457
|
+
top_k=self.config.top_k - topk_for_scheduler,
|
|
458
|
+
info={
|
|
459
|
+
"user_id": target_user_id,
|
|
460
|
+
"session_id": self.session_id,
|
|
461
|
+
"chat_history": chat_history.chat_history,
|
|
462
|
+
},
|
|
463
|
+
)
|
|
464
|
+
text_memories = [m.memory for m in memories]
|
|
465
|
+
|
|
466
|
+
# Analyze memory helpfulness - compare before vs after vs scheduler
|
|
467
|
+
self._analyze_memory_helpfulness(
|
|
468
|
+
query, working_memories_before, working_memories_after, scheduler_memories
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
# Combine all memories for response generation
|
|
472
|
+
memories_all.extend(scheduler_memories[:topk_for_scheduler])
|
|
473
|
+
memories_all.extend(text_memories)
|
|
474
|
+
memories_all = list(set(memories_all))
|
|
475
|
+
|
|
476
|
+
logger.info(f"š§ [Memory] Searched memories:\n{self._str_memories(memories_all)}\n")
|
|
477
|
+
system_prompt = self._build_system_prompt(memories_all)
|
|
478
|
+
else:
|
|
479
|
+
system_prompt = self._build_system_prompt()
|
|
480
|
+
|
|
481
|
+
current_messages = [
|
|
482
|
+
{"role": "system", "content": system_prompt},
|
|
483
|
+
*chat_history.chat_history,
|
|
484
|
+
{"role": "user", "content": query},
|
|
485
|
+
]
|
|
486
|
+
past_key_values = None
|
|
487
|
+
|
|
488
|
+
if self.config.enable_activation_memory:
|
|
489
|
+
if self.config.chat_model.backend != "huggingface":
|
|
490
|
+
logger.error(
|
|
491
|
+
"Activation memory only used for huggingface backend. Skipping activation memory."
|
|
492
|
+
)
|
|
493
|
+
else:
|
|
494
|
+
# TODO this only one cubes
|
|
495
|
+
for mem_cube_id, mem_cube in self.mem_cubes.items():
|
|
496
|
+
if mem_cube_id not in user_cube_ids:
|
|
497
|
+
continue
|
|
498
|
+
if mem_cube.act_mem:
|
|
499
|
+
kv_cache = next(iter(mem_cube.act_mem.get_all()), None)
|
|
500
|
+
past_key_values = (
|
|
501
|
+
kv_cache.memory if (kv_cache and hasattr(kv_cache, "memory")) else None
|
|
502
|
+
)
|
|
503
|
+
break
|
|
504
|
+
# Generate response
|
|
505
|
+
response = self.chat_llm.generate(current_messages, past_key_values=past_key_values)
|
|
506
|
+
else:
|
|
507
|
+
response = self.chat_llm.generate(current_messages)
|
|
508
|
+
|
|
509
|
+
logger.info(f"š¤ [Assistant] {response}\n")
|
|
510
|
+
chat_history.chat_history.append({"role": "user", "content": query})
|
|
511
|
+
chat_history.chat_history.append({"role": "assistant", "content": response})
|
|
512
|
+
self.chat_history_manager[user_id] = chat_history
|
|
513
|
+
|
|
514
|
+
# Submit message to scheduler for answer processing
|
|
515
|
+
for accessible_mem_cube in accessible_cubes:
|
|
516
|
+
mem_cube_id = accessible_mem_cube.cube_id
|
|
517
|
+
mem_cube = self.mem_cubes[mem_cube_id]
|
|
518
|
+
if self.enable_mem_scheduler and self.mem_scheduler is not None:
|
|
519
|
+
message_item = ScheduleMessageItem(
|
|
520
|
+
user_id=target_user_id,
|
|
521
|
+
mem_cube_id=mem_cube_id,
|
|
522
|
+
label=ANSWER_TASK_LABEL,
|
|
523
|
+
content=response,
|
|
524
|
+
timestamp=datetime.now(),
|
|
525
|
+
)
|
|
526
|
+
self.mem_scheduler.submit_messages(messages=[message_item])
|
|
527
|
+
|
|
528
|
+
return response
|
|
529
|
+
|
|
530
|
+
def get_memory_helpfulness_summary(self) -> dict:
|
|
531
|
+
"""Get summary of memory helpfulness analysis."""
|
|
532
|
+
if not self.memory_helpfulness_analysis:
|
|
533
|
+
return {"message": "No memory helpfulness analysis data available"}
|
|
534
|
+
|
|
535
|
+
total_queries = len(self.memory_helpfulness_analysis)
|
|
536
|
+
|
|
537
|
+
# Calculate average helpfulness for working memories before scheduler
|
|
538
|
+
before_scores = []
|
|
539
|
+
for analysis in self.memory_helpfulness_analysis:
|
|
540
|
+
before_scores.extend(analysis["working_helpfulness_before"])
|
|
541
|
+
|
|
542
|
+
# Calculate average helpfulness for working memories after scheduler
|
|
543
|
+
after_scores = []
|
|
544
|
+
for analysis in self.memory_helpfulness_analysis:
|
|
545
|
+
after_scores.extend(analysis["working_helpfulness_after"])
|
|
546
|
+
|
|
547
|
+
# Calculate average helpfulness for scheduler memories from monitor
|
|
548
|
+
scheduler_scores = []
|
|
549
|
+
for analysis in self.memory_helpfulness_analysis:
|
|
550
|
+
scheduler_scores.extend(analysis["scheduler_helpfulness"])
|
|
551
|
+
|
|
552
|
+
avg_before_helpfulness = sum(before_scores) / len(before_scores) if before_scores else 0
|
|
553
|
+
avg_after_helpfulness = sum(after_scores) / len(after_scores) if after_scores else 0
|
|
554
|
+
avg_scheduler_helpfulness = (
|
|
555
|
+
sum(scheduler_scores) / len(scheduler_scores) if scheduler_scores else 0
|
|
556
|
+
)
|
|
557
|
+
|
|
558
|
+
return {
|
|
559
|
+
"total_queries": total_queries,
|
|
560
|
+
"working_memories_before_analyzed": len(before_scores),
|
|
561
|
+
"working_memories_after_analyzed": len(after_scores),
|
|
562
|
+
"scheduler_memories_analyzed": len(scheduler_scores),
|
|
563
|
+
"average_helpfulness_before_scheduler": f"{avg_before_helpfulness:.1f}/10",
|
|
564
|
+
"average_helpfulness_after_scheduler": f"{avg_after_helpfulness:.1f}/10",
|
|
565
|
+
"average_helpfulness_scheduler_memories": f"{avg_scheduler_helpfulness:.1f}/10",
|
|
566
|
+
"overall_improvement": f"{avg_after_helpfulness - avg_before_helpfulness:+.1f}",
|
|
567
|
+
"improvement_percentage": f"{((avg_after_helpfulness - avg_before_helpfulness) / avg_before_helpfulness * 100):+.1f}%"
|
|
568
|
+
if avg_before_helpfulness > 0
|
|
569
|
+
else "N/A",
|
|
570
|
+
"scheduler_vs_working_comparison": f"{avg_scheduler_helpfulness - avg_after_helpfulness:+.1f}",
|
|
571
|
+
}
|