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,714 @@
|
|
|
1
|
+
"""
|
|
2
|
+
API Analyzer for Scheduler
|
|
3
|
+
|
|
4
|
+
This module provides the APIAnalyzerForScheduler class that handles API requests
|
|
5
|
+
for search and add operations with reusable instance variables.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import http.client
|
|
9
|
+
import json
|
|
10
|
+
|
|
11
|
+
from typing import Any
|
|
12
|
+
from urllib.parse import urlparse
|
|
13
|
+
|
|
14
|
+
import requests
|
|
15
|
+
|
|
16
|
+
from memos.api.product_models import APIADDRequest, APISearchRequest
|
|
17
|
+
from memos.api.routers.server_router import add_memories, search_memories
|
|
18
|
+
from memos.log import get_logger
|
|
19
|
+
from memos.types import MessageDict, SearchMode, UserContext
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
logger = get_logger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class APIAnalyzerForScheduler:
|
|
26
|
+
"""
|
|
27
|
+
API Analyzer class for scheduler operations.
|
|
28
|
+
|
|
29
|
+
This class provides methods to interact with APIs for search and add operations,
|
|
30
|
+
with reusable instance variables for better performance and configuration management.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
base_url: str = "http://127.0.0.1:8002",
|
|
36
|
+
default_headers: dict[str, str] | None = None,
|
|
37
|
+
timeout: int = 30,
|
|
38
|
+
):
|
|
39
|
+
"""
|
|
40
|
+
Initialize the APIAnalyzerForScheduler.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
base_url: Base URL for API requests
|
|
44
|
+
default_headers: Default headers to use for all requests
|
|
45
|
+
timeout: Request timeout in seconds
|
|
46
|
+
"""
|
|
47
|
+
self.base_url = base_url.rstrip("/")
|
|
48
|
+
self.timeout = timeout
|
|
49
|
+
|
|
50
|
+
# Default headers
|
|
51
|
+
self.default_headers = default_headers or {"Content-Type": "application/json"}
|
|
52
|
+
|
|
53
|
+
# Parse URL for http.client usage
|
|
54
|
+
parsed_url = urlparse(self.base_url)
|
|
55
|
+
self.host = parsed_url.hostname
|
|
56
|
+
self.port = parsed_url.port or 8002
|
|
57
|
+
self.is_https = parsed_url.scheme == "https"
|
|
58
|
+
|
|
59
|
+
# Reusable connection for http.client
|
|
60
|
+
self._connection = None
|
|
61
|
+
|
|
62
|
+
# Attributes
|
|
63
|
+
self.user_id = "test_user_id"
|
|
64
|
+
self.mem_cube_id = "test_mem_cube_id"
|
|
65
|
+
|
|
66
|
+
logger.info(f"APIAnalyzerForScheduler initialized with base_url: {self.base_url}")
|
|
67
|
+
|
|
68
|
+
def _get_connection(self) -> http.client.HTTPConnection | http.client.HTTPSConnection:
|
|
69
|
+
"""
|
|
70
|
+
Get or create a reusable HTTP connection.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
HTTP connection object
|
|
74
|
+
"""
|
|
75
|
+
if self._connection is None:
|
|
76
|
+
if self.is_https:
|
|
77
|
+
self._connection = http.client.HTTPSConnection(self.host, self.port)
|
|
78
|
+
else:
|
|
79
|
+
self._connection = http.client.HTTPConnection(self.host, self.port)
|
|
80
|
+
return self._connection
|
|
81
|
+
|
|
82
|
+
def _close_connection(self):
|
|
83
|
+
"""Close the HTTP connection if it exists."""
|
|
84
|
+
if self._connection:
|
|
85
|
+
self._connection.close()
|
|
86
|
+
self._connection = None
|
|
87
|
+
|
|
88
|
+
def search(
|
|
89
|
+
self, user_id: str, mem_cube_id: str, query: str, top_k: int = 50, use_requests: bool = True
|
|
90
|
+
) -> dict[str, Any]:
|
|
91
|
+
"""
|
|
92
|
+
Search for memories using the product/search API endpoint.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
user_id: User identifier
|
|
96
|
+
mem_cube_id: Memory cube identifier
|
|
97
|
+
query: Search query string
|
|
98
|
+
top_k: Number of top_k results to return
|
|
99
|
+
use_requests: Whether to use requests library (True) or http.client (False)
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Dictionary containing the API response
|
|
103
|
+
"""
|
|
104
|
+
payload = {"user_id": user_id, "mem_cube_id": mem_cube_id, "query": query, "top_k": top_k}
|
|
105
|
+
|
|
106
|
+
try:
|
|
107
|
+
if use_requests:
|
|
108
|
+
return self._search_with_requests(payload)
|
|
109
|
+
else:
|
|
110
|
+
return self._search_with_http_client(payload)
|
|
111
|
+
except Exception as e:
|
|
112
|
+
logger.error(f"Error in search operation: {e}")
|
|
113
|
+
return {"error": str(e), "success": False}
|
|
114
|
+
|
|
115
|
+
def _search_with_requests(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
116
|
+
"""
|
|
117
|
+
Perform search using requests library.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
payload: Request payload
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Dictionary containing the API response
|
|
124
|
+
"""
|
|
125
|
+
url = f"{self.base_url}/product/search"
|
|
126
|
+
|
|
127
|
+
response = requests.post(
|
|
128
|
+
url, headers=self.default_headers, data=json.dumps(payload), timeout=self.timeout
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
logger.info(f"Search request to {url} completed with status: {response.status_code}")
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
return {
|
|
135
|
+
"success": True,
|
|
136
|
+
"status_code": response.status_code,
|
|
137
|
+
"data": response.json() if response.content else {},
|
|
138
|
+
"text": response.text,
|
|
139
|
+
}
|
|
140
|
+
except json.JSONDecodeError:
|
|
141
|
+
return {
|
|
142
|
+
"success": True,
|
|
143
|
+
"status_code": response.status_code,
|
|
144
|
+
"data": {},
|
|
145
|
+
"text": response.text,
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
def _search_with_http_client(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
149
|
+
"""
|
|
150
|
+
Perform search using http.client.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
payload: Request payload
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
Dictionary containing the API response
|
|
157
|
+
"""
|
|
158
|
+
conn = self._get_connection()
|
|
159
|
+
|
|
160
|
+
try:
|
|
161
|
+
conn.request("POST", "/product/search", json.dumps(payload), self.default_headers)
|
|
162
|
+
|
|
163
|
+
response = conn.getresponse()
|
|
164
|
+
data = response.read()
|
|
165
|
+
response_text = data.decode("utf-8")
|
|
166
|
+
|
|
167
|
+
logger.info(f"Search request completed with status: {response.status}")
|
|
168
|
+
|
|
169
|
+
try:
|
|
170
|
+
response_data = json.loads(response_text) if response_text else {}
|
|
171
|
+
except json.JSONDecodeError:
|
|
172
|
+
response_data = {}
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
"success": True,
|
|
176
|
+
"status_code": response.status,
|
|
177
|
+
"data": response_data,
|
|
178
|
+
"text": response_text,
|
|
179
|
+
}
|
|
180
|
+
except Exception as e:
|
|
181
|
+
logger.error(f"Error in http.client search: {e}")
|
|
182
|
+
return {"error": str(e), "success": False}
|
|
183
|
+
|
|
184
|
+
def add(
|
|
185
|
+
self, messages: list, user_id: str, mem_cube_id: str, use_requests: bool = True
|
|
186
|
+
) -> dict[str, Any]:
|
|
187
|
+
"""
|
|
188
|
+
Add memories using the product/add API endpoint.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
messages: List of message objects with role and content
|
|
192
|
+
user_id: User identifier
|
|
193
|
+
mem_cube_id: Memory cube identifier
|
|
194
|
+
use_requests: Whether to use requests library (True) or http.client (False)
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
Dictionary containing the API response
|
|
198
|
+
"""
|
|
199
|
+
payload = {"messages": messages, "user_id": user_id, "mem_cube_id": mem_cube_id}
|
|
200
|
+
|
|
201
|
+
try:
|
|
202
|
+
if use_requests:
|
|
203
|
+
return self._add_with_requests(payload)
|
|
204
|
+
else:
|
|
205
|
+
return self._add_with_http_client(payload)
|
|
206
|
+
except Exception as e:
|
|
207
|
+
logger.error(f"Error in add operation: {e}")
|
|
208
|
+
return {"error": str(e), "success": False}
|
|
209
|
+
|
|
210
|
+
def _add_with_requests(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
211
|
+
"""
|
|
212
|
+
Perform add using requests library.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
payload: Request payload
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
Dictionary containing the API response
|
|
219
|
+
"""
|
|
220
|
+
url = f"{self.base_url}/product/add"
|
|
221
|
+
|
|
222
|
+
response = requests.post(
|
|
223
|
+
url, headers=self.default_headers, data=json.dumps(payload), timeout=self.timeout
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
logger.info(f"Add request to {url} completed with status: {response.status_code}")
|
|
227
|
+
|
|
228
|
+
try:
|
|
229
|
+
return {
|
|
230
|
+
"success": True,
|
|
231
|
+
"status_code": response.status_code,
|
|
232
|
+
"data": response.json() if response.content else {},
|
|
233
|
+
"text": response.text,
|
|
234
|
+
}
|
|
235
|
+
except json.JSONDecodeError:
|
|
236
|
+
return {
|
|
237
|
+
"success": True,
|
|
238
|
+
"status_code": response.status_code,
|
|
239
|
+
"data": {},
|
|
240
|
+
"text": response.text,
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
def _add_with_http_client(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
244
|
+
"""
|
|
245
|
+
Perform add using http.client.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
payload: Request payload
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
Dictionary containing the API response
|
|
252
|
+
"""
|
|
253
|
+
conn = self._get_connection()
|
|
254
|
+
|
|
255
|
+
try:
|
|
256
|
+
conn.request("POST", "/product/add", json.dumps(payload), self.default_headers)
|
|
257
|
+
|
|
258
|
+
response = conn.getresponse()
|
|
259
|
+
data = response.read()
|
|
260
|
+
response_text = data.decode("utf-8")
|
|
261
|
+
|
|
262
|
+
logger.info(f"Add request completed with status: {response.status}")
|
|
263
|
+
|
|
264
|
+
try:
|
|
265
|
+
response_data = json.loads(response_text) if response_text else {}
|
|
266
|
+
except json.JSONDecodeError:
|
|
267
|
+
response_data = {}
|
|
268
|
+
|
|
269
|
+
return {
|
|
270
|
+
"success": True,
|
|
271
|
+
"status_code": response.status,
|
|
272
|
+
"data": response_data,
|
|
273
|
+
"text": response_text,
|
|
274
|
+
}
|
|
275
|
+
except Exception as e:
|
|
276
|
+
logger.error(f"Error in http.client add: {e}")
|
|
277
|
+
return {"error": str(e), "success": False}
|
|
278
|
+
|
|
279
|
+
def update_base_url(self, new_base_url: str):
|
|
280
|
+
"""
|
|
281
|
+
Update the base URL and reinitialize connection parameters.
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
new_base_url: New base URL for API requests
|
|
285
|
+
"""
|
|
286
|
+
self._close_connection()
|
|
287
|
+
self.base_url = new_base_url.rstrip("/")
|
|
288
|
+
|
|
289
|
+
# Re-parse URL
|
|
290
|
+
parsed_url = urlparse(self.base_url)
|
|
291
|
+
self.host = parsed_url.hostname
|
|
292
|
+
self.port = parsed_url.port or (443 if parsed_url.scheme == "https" else 80)
|
|
293
|
+
self.is_https = parsed_url.scheme == "https"
|
|
294
|
+
|
|
295
|
+
logger.info(f"Base URL updated to: {self.base_url}")
|
|
296
|
+
|
|
297
|
+
def update_headers(self, headers: dict[str, str]):
|
|
298
|
+
"""
|
|
299
|
+
Update default headers.
|
|
300
|
+
|
|
301
|
+
Args:
|
|
302
|
+
headers: New headers to merge with existing ones
|
|
303
|
+
"""
|
|
304
|
+
self.default_headers.update(headers)
|
|
305
|
+
logger.info("Headers updated")
|
|
306
|
+
|
|
307
|
+
def __del__(self):
|
|
308
|
+
"""Cleanup method to close connection when object is destroyed."""
|
|
309
|
+
self._close_connection()
|
|
310
|
+
|
|
311
|
+
def analyze_service(self):
|
|
312
|
+
# Example add operation
|
|
313
|
+
messages = [
|
|
314
|
+
{"role": "user", "content": "Where should I go for New Year's Eve in Shanghai?"},
|
|
315
|
+
{
|
|
316
|
+
"role": "assistant",
|
|
317
|
+
"content": "You could head to the Bund for the countdown, attend a rooftop party, or enjoy the fireworks at Disneyland Shanghai.",
|
|
318
|
+
},
|
|
319
|
+
]
|
|
320
|
+
|
|
321
|
+
add_result = self.add(
|
|
322
|
+
messages=messages, user_id="test_user_id", mem_cube_id="test_mem_cube_id"
|
|
323
|
+
)
|
|
324
|
+
print("Add result:", add_result)
|
|
325
|
+
|
|
326
|
+
# Example search operation
|
|
327
|
+
search_result = self.search(
|
|
328
|
+
user_id="test_user_id",
|
|
329
|
+
mem_cube_id="test_mem_cube_id",
|
|
330
|
+
query="What are some good places to celebrate New Year's Eve in Shanghai?",
|
|
331
|
+
top_k=50,
|
|
332
|
+
)
|
|
333
|
+
print("Search result:", search_result)
|
|
334
|
+
|
|
335
|
+
def analyze_features(self):
|
|
336
|
+
try:
|
|
337
|
+
# Test basic search functionality
|
|
338
|
+
search_result = self.search(
|
|
339
|
+
user_id="test_user_id",
|
|
340
|
+
mem_cube_id="test_mem_cube_id",
|
|
341
|
+
query="What are some good places to celebrate New Year's Eve in Shanghai?",
|
|
342
|
+
top_k=50,
|
|
343
|
+
)
|
|
344
|
+
print("Search result:", search_result)
|
|
345
|
+
except Exception as e:
|
|
346
|
+
logger.error(f"Feature analysis failed: {e}")
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
class DirectSearchMemoriesAnalyzer:
|
|
350
|
+
"""
|
|
351
|
+
Direct analyzer for testing search_memories function
|
|
352
|
+
Used for debugging and analyzing search_memories function behavior without starting a full API server
|
|
353
|
+
"""
|
|
354
|
+
|
|
355
|
+
def __init__(self):
|
|
356
|
+
"""Initialize the analyzer"""
|
|
357
|
+
# Import necessary modules
|
|
358
|
+
self.APISearchRequest = APISearchRequest
|
|
359
|
+
self.APIADDRequest = APIADDRequest
|
|
360
|
+
self.search_memories = search_memories
|
|
361
|
+
self.add_memories = add_memories
|
|
362
|
+
self.UserContext = UserContext
|
|
363
|
+
self.MessageDict = MessageDict
|
|
364
|
+
|
|
365
|
+
# Initialize conversation history for continuous conversation support
|
|
366
|
+
self.conversation_history = []
|
|
367
|
+
self.current_session_id = None
|
|
368
|
+
self.current_user_id = None
|
|
369
|
+
self.current_mem_cube_id = None
|
|
370
|
+
|
|
371
|
+
logger.info("DirectSearchMemoriesAnalyzer initialized successfully")
|
|
372
|
+
|
|
373
|
+
def start_conversation(self, user_id="test_user", mem_cube_id="test_cube", session_id=None):
|
|
374
|
+
"""
|
|
375
|
+
Start a new conversation session for continuous dialogue.
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
user_id: User ID for the conversation
|
|
379
|
+
mem_cube_id: Memory cube ID for the conversation
|
|
380
|
+
session_id: Session ID for the conversation (auto-generated if None)
|
|
381
|
+
"""
|
|
382
|
+
self.current_user_id = user_id
|
|
383
|
+
self.current_mem_cube_id = mem_cube_id
|
|
384
|
+
self.current_session_id = (
|
|
385
|
+
session_id or f"session_{hash(user_id + mem_cube_id)}_{len(self.conversation_history)}"
|
|
386
|
+
)
|
|
387
|
+
self.conversation_history = []
|
|
388
|
+
|
|
389
|
+
logger.info(f"Started conversation session: {self.current_session_id}")
|
|
390
|
+
print(f"š Started new conversation session: {self.current_session_id}")
|
|
391
|
+
print(f" User ID: {self.current_user_id}")
|
|
392
|
+
print(f" Mem Cube ID: {self.current_mem_cube_id}")
|
|
393
|
+
|
|
394
|
+
def add_to_conversation(self, user_message, assistant_message=None):
|
|
395
|
+
"""
|
|
396
|
+
Add messages to the current conversation and store them in memory.
|
|
397
|
+
|
|
398
|
+
Args:
|
|
399
|
+
user_message: User's message content
|
|
400
|
+
assistant_message: Assistant's response (optional)
|
|
401
|
+
|
|
402
|
+
Returns:
|
|
403
|
+
Result from add_memories function
|
|
404
|
+
"""
|
|
405
|
+
if not self.current_session_id:
|
|
406
|
+
raise ValueError("No active conversation session. Call start_conversation() first.")
|
|
407
|
+
|
|
408
|
+
# Prepare messages for adding to memory
|
|
409
|
+
messages = [{"role": "user", "content": user_message}]
|
|
410
|
+
if assistant_message:
|
|
411
|
+
messages.append({"role": "assistant", "content": assistant_message})
|
|
412
|
+
|
|
413
|
+
# Add to conversation history
|
|
414
|
+
self.conversation_history.extend(messages)
|
|
415
|
+
|
|
416
|
+
# Create add request
|
|
417
|
+
add_req = self.create_test_add_request(
|
|
418
|
+
user_id=self.current_user_id,
|
|
419
|
+
mem_cube_id=self.current_mem_cube_id,
|
|
420
|
+
messages=messages,
|
|
421
|
+
session_id=self.current_session_id,
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
print(f"š¬ Adding to conversation (Session: {self.current_session_id}):")
|
|
425
|
+
print(f" User: {user_message}")
|
|
426
|
+
if assistant_message:
|
|
427
|
+
print(f" Assistant: {assistant_message}")
|
|
428
|
+
|
|
429
|
+
# Add to memory
|
|
430
|
+
result = self.add_memories(add_req)
|
|
431
|
+
print(" ā
Added to memory successfully")
|
|
432
|
+
|
|
433
|
+
return result
|
|
434
|
+
|
|
435
|
+
def search_in_conversation(self, query, mode="fast", top_k=10, include_history=True):
|
|
436
|
+
"""
|
|
437
|
+
Search memories within the current conversation context.
|
|
438
|
+
|
|
439
|
+
Args:
|
|
440
|
+
query: Search query
|
|
441
|
+
mode: Search mode ("fast", "fine", or "mixture")
|
|
442
|
+
top_k: Number of results to return
|
|
443
|
+
include_history: Whether to include conversation history in the search
|
|
444
|
+
|
|
445
|
+
Returns:
|
|
446
|
+
Search results
|
|
447
|
+
"""
|
|
448
|
+
if not self.current_session_id:
|
|
449
|
+
raise ValueError("No active conversation session. Call start_conversation() first.")
|
|
450
|
+
|
|
451
|
+
# Prepare chat history if requested
|
|
452
|
+
chat_history = self.conversation_history if include_history else None
|
|
453
|
+
|
|
454
|
+
# Create search request
|
|
455
|
+
search_req = self.create_test_search_request(
|
|
456
|
+
query=query,
|
|
457
|
+
user_id=self.current_user_id,
|
|
458
|
+
mem_cube_id=self.current_mem_cube_id,
|
|
459
|
+
mode=mode,
|
|
460
|
+
top_k=top_k,
|
|
461
|
+
chat_history=chat_history,
|
|
462
|
+
session_id=self.current_session_id,
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
print(f"š Searching in conversation (Session: {self.current_session_id}):")
|
|
466
|
+
print(f" Query: {query}")
|
|
467
|
+
print(f" Mode: {mode}")
|
|
468
|
+
print(f" Top K: {top_k}")
|
|
469
|
+
print(f" Include History: {include_history}")
|
|
470
|
+
print(f" History Length: {len(self.conversation_history) if chat_history else 0}")
|
|
471
|
+
|
|
472
|
+
# Perform search
|
|
473
|
+
result = self.search_memories(search_req)
|
|
474
|
+
|
|
475
|
+
print(" ā
Search completed")
|
|
476
|
+
if hasattr(result, "data") and result.data:
|
|
477
|
+
total_memories = sum(
|
|
478
|
+
len(mem_list) for mem_list in result.data.values() if isinstance(mem_list, list)
|
|
479
|
+
)
|
|
480
|
+
print(f" š Found {total_memories} total memories")
|
|
481
|
+
|
|
482
|
+
return result
|
|
483
|
+
|
|
484
|
+
def test_continuous_conversation(self, mode=SearchMode.MIXTURE):
|
|
485
|
+
"""Test continuous conversation functionality"""
|
|
486
|
+
print("=" * 80)
|
|
487
|
+
print("Testing Continuous Conversation Functionality")
|
|
488
|
+
print("=" * 80)
|
|
489
|
+
|
|
490
|
+
try:
|
|
491
|
+
# Start a conversation
|
|
492
|
+
self.start_conversation(user_id="conv_test_user", mem_cube_id="conv_test_cube")
|
|
493
|
+
|
|
494
|
+
# Prepare all conversation messages for batch addition
|
|
495
|
+
all_messages = [
|
|
496
|
+
{
|
|
497
|
+
"role": "user",
|
|
498
|
+
"content": "I'm planning a trip to Shanghai for New Year's Eve. What are some good places to visit?",
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
"role": "assistant",
|
|
502
|
+
"content": "Shanghai has many great places for New Year's Eve! You could visit the Bund for the countdown, go to a rooftop party, or enjoy fireworks at Disneyland Shanghai. The French Concession also has nice bars and restaurants.",
|
|
503
|
+
},
|
|
504
|
+
{"role": "user", "content": "What about food? Any restaurant recommendations?"},
|
|
505
|
+
{
|
|
506
|
+
"role": "assistant",
|
|
507
|
+
"content": "For New Year's Eve dining in Shanghai, I'd recommend trying some local specialties like xiaolongbao at Din Tai Fung, or for a fancy dinner, you could book at restaurants in the Bund area with great views.",
|
|
508
|
+
},
|
|
509
|
+
{"role": "user", "content": "I'm on a budget though. Any cheaper alternatives?"},
|
|
510
|
+
{
|
|
511
|
+
"role": "assistant",
|
|
512
|
+
"content": "For budget-friendly options, try street food in Yuyuan Garden area, local noodle shops, or food courts in shopping malls. You can also watch the fireworks from free public areas along the Huangpu River.",
|
|
513
|
+
},
|
|
514
|
+
]
|
|
515
|
+
|
|
516
|
+
# Add all conversation messages at once
|
|
517
|
+
print("\nš Adding all conversation messages at once:")
|
|
518
|
+
add_req = self.create_test_add_request(
|
|
519
|
+
user_id=self.current_user_id,
|
|
520
|
+
mem_cube_id=self.current_mem_cube_id,
|
|
521
|
+
messages=all_messages,
|
|
522
|
+
session_id=self.current_session_id,
|
|
523
|
+
)
|
|
524
|
+
|
|
525
|
+
print(
|
|
526
|
+
f"š¬ Adding {len(all_messages)} messages to conversation (Session: {self.current_session_id})"
|
|
527
|
+
)
|
|
528
|
+
self.add_memories(add_req)
|
|
529
|
+
|
|
530
|
+
# Update conversation history
|
|
531
|
+
self.conversation_history.extend(all_messages)
|
|
532
|
+
print(" ā
Added all messages to memory successfully")
|
|
533
|
+
|
|
534
|
+
# Test searching within the conversation
|
|
535
|
+
print("\nš Testing search within conversation:")
|
|
536
|
+
|
|
537
|
+
# Search for trip-related information
|
|
538
|
+
self.search_in_conversation(
|
|
539
|
+
query="New Year's Eve Shanghai recommendations", mode=mode, top_k=5
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
# Search for food-related information
|
|
543
|
+
self.search_in_conversation(query="budget food Shanghai", mode=mode, top_k=3)
|
|
544
|
+
|
|
545
|
+
# Search without conversation history
|
|
546
|
+
self.search_in_conversation(
|
|
547
|
+
query="Shanghai travel", mode=mode, top_k=3, include_history=False
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
print("\nā
Continuous conversation test completed successfully!")
|
|
551
|
+
return True
|
|
552
|
+
|
|
553
|
+
except Exception as e:
|
|
554
|
+
print(f"ā Continuous conversation test failed: {e}")
|
|
555
|
+
import traceback
|
|
556
|
+
|
|
557
|
+
traceback.print_exc()
|
|
558
|
+
return False
|
|
559
|
+
|
|
560
|
+
def create_test_search_request(
|
|
561
|
+
self,
|
|
562
|
+
query="test query",
|
|
563
|
+
user_id="test_user",
|
|
564
|
+
mem_cube_id="test_cube",
|
|
565
|
+
mode="fast",
|
|
566
|
+
top_k=10,
|
|
567
|
+
chat_history=None,
|
|
568
|
+
session_id=None,
|
|
569
|
+
):
|
|
570
|
+
"""
|
|
571
|
+
Create a test APISearchRequest object with the given parameters.
|
|
572
|
+
|
|
573
|
+
Args:
|
|
574
|
+
query: Search query string
|
|
575
|
+
user_id: User ID for the request
|
|
576
|
+
mem_cube_id: Memory cube ID for the request
|
|
577
|
+
mode: Search mode ("fast" or "fine")
|
|
578
|
+
top_k: Number of results to return
|
|
579
|
+
chat_history: Chat history for context (optional)
|
|
580
|
+
session_id: Session ID for the request (optional)
|
|
581
|
+
|
|
582
|
+
Returns:
|
|
583
|
+
APISearchRequest: A configured request object
|
|
584
|
+
"""
|
|
585
|
+
return self.APISearchRequest(
|
|
586
|
+
query=query,
|
|
587
|
+
user_id=user_id,
|
|
588
|
+
mem_cube_id=mem_cube_id,
|
|
589
|
+
mode=mode,
|
|
590
|
+
top_k=top_k,
|
|
591
|
+
chat_history=chat_history,
|
|
592
|
+
session_id=session_id,
|
|
593
|
+
)
|
|
594
|
+
|
|
595
|
+
def create_test_add_request(
|
|
596
|
+
self,
|
|
597
|
+
user_id="test_user",
|
|
598
|
+
mem_cube_id="test_cube",
|
|
599
|
+
messages=None,
|
|
600
|
+
memory_content=None,
|
|
601
|
+
session_id=None,
|
|
602
|
+
extract_mode=None,
|
|
603
|
+
async_mode="sync",
|
|
604
|
+
):
|
|
605
|
+
"""
|
|
606
|
+
Create a test APIADDRequest object with the given parameters.
|
|
607
|
+
|
|
608
|
+
Args:
|
|
609
|
+
user_id: User ID for the request
|
|
610
|
+
mem_cube_id: Memory cube ID for the request
|
|
611
|
+
messages: List of messages to add (optional)
|
|
612
|
+
memory_content: Direct memory content to add (optional)
|
|
613
|
+
session_id: Session ID for the request (optional)
|
|
614
|
+
|
|
615
|
+
Returns:
|
|
616
|
+
APIADDRequest: A configured request object
|
|
617
|
+
"""
|
|
618
|
+
if messages is None and memory_content is None:
|
|
619
|
+
# Default test messages
|
|
620
|
+
messages = [
|
|
621
|
+
{"role": "user", "content": "What's the weather like today?"},
|
|
622
|
+
{
|
|
623
|
+
"role": "assistant",
|
|
624
|
+
"content": "I don't have access to real-time weather data, but you can check a weather app or website for current conditions.",
|
|
625
|
+
},
|
|
626
|
+
]
|
|
627
|
+
|
|
628
|
+
# Ensure we have a valid session_id
|
|
629
|
+
if session_id is None:
|
|
630
|
+
session_id = "test_session_" + str(hash(user_id + mem_cube_id))[:8]
|
|
631
|
+
|
|
632
|
+
return self.APIADDRequest(
|
|
633
|
+
user_id=user_id,
|
|
634
|
+
mem_cube_id=mem_cube_id,
|
|
635
|
+
messages=messages,
|
|
636
|
+
memory_content=memory_content,
|
|
637
|
+
session_id=session_id,
|
|
638
|
+
doc_path=None,
|
|
639
|
+
source="api_analyzer_test",
|
|
640
|
+
chat_history=None,
|
|
641
|
+
operation=None,
|
|
642
|
+
mode=extract_mode,
|
|
643
|
+
async_mode=async_mode,
|
|
644
|
+
)
|
|
645
|
+
|
|
646
|
+
def run_all_tests(self, mode=SearchMode.MIXTURE):
|
|
647
|
+
"""Run all available tests"""
|
|
648
|
+
print("š Starting comprehensive test suite")
|
|
649
|
+
print("=" * 80)
|
|
650
|
+
|
|
651
|
+
# Test continuous conversation functionality
|
|
652
|
+
print("\nš¬ Testing CONTINUOUS CONVERSATION functions:")
|
|
653
|
+
try:
|
|
654
|
+
self.test_continuous_conversation(mode=mode)
|
|
655
|
+
print("ā
Continuous conversation test completed successfully")
|
|
656
|
+
except Exception as e:
|
|
657
|
+
print(f"ā Continuous conversation test failed: {e}")
|
|
658
|
+
|
|
659
|
+
print("\n" + "=" * 80)
|
|
660
|
+
print("ā
All tests completed!")
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
# Example usage
|
|
664
|
+
if __name__ == "__main__":
|
|
665
|
+
import argparse
|
|
666
|
+
|
|
667
|
+
parser = argparse.ArgumentParser(description="API Analyzer for Memory Scheduler")
|
|
668
|
+
parser.add_argument(
|
|
669
|
+
"--mode",
|
|
670
|
+
choices=["direct", "api"],
|
|
671
|
+
default="direct",
|
|
672
|
+
help="Test mode: 'direct' for direct function testing, 'api' for API testing (default: direct)",
|
|
673
|
+
)
|
|
674
|
+
|
|
675
|
+
args = parser.parse_args()
|
|
676
|
+
|
|
677
|
+
if args.mode == "direct":
|
|
678
|
+
# Direct test mode for search_memories and add_memories functions
|
|
679
|
+
print("Using direct test mode")
|
|
680
|
+
try:
|
|
681
|
+
direct_analyzer = DirectSearchMemoriesAnalyzer()
|
|
682
|
+
direct_analyzer.run_all_tests(mode=SearchMode.FINE)
|
|
683
|
+
except Exception as e:
|
|
684
|
+
print(f"Direct test mode failed: {e}")
|
|
685
|
+
import traceback
|
|
686
|
+
|
|
687
|
+
traceback.print_exc()
|
|
688
|
+
else:
|
|
689
|
+
# Original API test mode
|
|
690
|
+
print("Using API test mode")
|
|
691
|
+
analyzer = APIAnalyzerForScheduler()
|
|
692
|
+
|
|
693
|
+
# Test add operation
|
|
694
|
+
messages = [
|
|
695
|
+
{"role": "user", "content": "Where should I go for New Year's Eve in Shanghai?"},
|
|
696
|
+
{
|
|
697
|
+
"role": "assistant",
|
|
698
|
+
"content": "You could head to the Bund for the countdown, attend a rooftop party, or enjoy the fireworks at Disneyland Shanghai.",
|
|
699
|
+
},
|
|
700
|
+
]
|
|
701
|
+
|
|
702
|
+
add_result = analyzer.add(
|
|
703
|
+
messages=messages, user_id="test_user_id", mem_cube_id="test_mem_cube_id"
|
|
704
|
+
)
|
|
705
|
+
print("Add result:", add_result)
|
|
706
|
+
|
|
707
|
+
# Test search operation
|
|
708
|
+
search_result = analyzer.search(
|
|
709
|
+
user_id="test_user_id",
|
|
710
|
+
mem_cube_id="test_mem_cube_id",
|
|
711
|
+
query="What are some good places to celebrate New Year's Eve in Shanghai?",
|
|
712
|
+
top_k=10,
|
|
713
|
+
)
|
|
714
|
+
print("Search result:", search_result)
|