From bccfb4c1223308a7fc6d01e6030b367180e3a43f Mon Sep 17 00:00:00 2001 From: "jinli.yl" Date: Thu, 20 Jun 2024 22:18:57 +0800 Subject: [PATCH] [dev] move worker dirs --- config/config.json | 18 +- memory_scope/__init__.py | 3 + memory_scope/chat/base_memory_chat.py | 6 +- memory_scope/chat/global_context.py | 11 +- memory_scope/chat/memory_chat.py | 31 +- memory_scope/chat/memory_service.py | 67 +- memory_scope/cli.py | 66 +- memory_scope/constants/common_constants.py | 76 --- memory_scope/{db => definition}/__init__.py | 0 memory_scope/definition/memory_node.py | 20 + memory_scope/definition/memory_wrap_node.py | 15 + memory_scope/{node => definition}/message.py | 0 memory_scope/enumeration/dash_api_enum.py | 9 - memory_scope/enumeration/language_enum.py | 7 + ...y_recall_type.py => memory_recall_enum.py} | 0 memory_scope/enumeration/memory_scene_enum.py | 11 - ...y_node_status.py => memory_status_enum.py} | 0 .../{model_type.py => model_enum.py} | 2 +- memory_scope/models/__init__.py | 2 - memory_scope/prompts/bailian_prompt_config.py | 627 ------------------ .../info_filter_prompt.py} | 0 memory_scope/prompts/memory_chat_prompt.py | 15 + memory_scope/prompts/prompt_cn.py | 7 - memory_scope/{monitor => storage}/__init__.py | 0 .../{monitor => storage}/base_monitor.py | 2 +- .../base_vector_store.py} | 2 +- memory_scope/utils/logger.py | 1 - .../pipeline_handler.py => utils/pipeline.py} | 75 ++- .../response_text_parser.py | 2 +- memory_scope/utils/timer.py | 6 +- memory_scope/utils/tool_functions.py | 154 +---- memory_scope/utils/version.py | 4 - memory_scope/worker/base_worker.py | 14 +- memory_scope/worker/memory_base_worker.py | 35 +- memory_scope/worker/summary_short/__init__.py | 0 {memory_scope/node => old}/__init__.py | 0 {memory_scope/models => old}/dash_client.py | 0 .../models => old}/dash_embedding_client.py | 0 .../models => old}/dash_generate_client.py | 0 .../models => old}/dash_rerank_client.py | 0 .../db => old}/elastic_search_client.py | 0 {memory_scope/parsers => old/es}/__init__.py | 0 .../worker => old}/es/es_insight_worker.py | 0 .../worker => old}/es/es_keyword_worker.py | 0 .../worker => old}/es/es_new_obs_worker.py | 0 .../es/es_not_reflected_worker.py | 0 .../es/es_retrieve_all_worker.py | 0 .../worker => old}/es/es_similar_worker.py | 0 .../worker => old}/es/es_today_obs_worker.py | 0 .../worker => old}/es/load_profile_worker.py | 0 {memory_scope/node => old}/memory_node.py | 0 .../node => old}/memory_wrap_node.py | 0 .../worker/es => old/retrieve}/__init__.py | 0 .../retrieve/extract_time_worker.py | 0 .../retrieve/fuse_rerank_worker.py | 0 .../retrieve/memory_store_worker.py | 0 .../retrieve/parse_params_worker.py | 0 .../retrieve/semantic_rank_worker.py | 0 .../retrieve => old/summary_long}/__init__.py | 0 .../summary_long/get_insight_worker.py | 0 .../summary_long/get_reflection_worker.py | 0 .../summary_long/long_contra_repeat_worker.py | 0 .../summary_long/summary_collect_worker.py | 0 .../summary_long/update_insight_worker.py | 0 .../summary_long/update_profile_worker.py | 0 .../summary_short}/__init__.py | 0 .../summary_short/contra_repeat_worker.py | 0 .../get_observation_with_time_worker.py | 0 .../summary_short/get_observation_worker.py | 0 .../summary_short/info_filter_worker.py | 0 old/tool_functions.py | 198 ++++++ {memory_scope/node => old}/user_attribute.py | 0 .../utils => old}/user_profile_handler.py | 0 tests/es_test2.py | 89 --- tests/test_dash_api.py | 321 --------- tests/test_memory.py | 252 ------- 76 files changed, 467 insertions(+), 1681 deletions(-) rename memory_scope/{db => definition}/__init__.py (100%) create mode 100644 memory_scope/definition/memory_node.py create mode 100644 memory_scope/definition/memory_wrap_node.py rename memory_scope/{node => definition}/message.py (100%) delete mode 100644 memory_scope/enumeration/dash_api_enum.py create mode 100644 memory_scope/enumeration/language_enum.py rename memory_scope/enumeration/{memory_recall_type.py => memory_recall_enum.py} (100%) delete mode 100644 memory_scope/enumeration/memory_scene_enum.py rename memory_scope/enumeration/{memory_node_status.py => memory_status_enum.py} (100%) rename memory_scope/enumeration/{model_type.py => model_enum.py} (83%) delete mode 100644 memory_scope/prompts/bailian_prompt_config.py rename memory_scope/{handler/__init__.py => prompts/info_filter_prompt.py} (100%) create mode 100644 memory_scope/prompts/memory_chat_prompt.py delete mode 100644 memory_scope/prompts/prompt_cn.py rename memory_scope/{monitor => storage}/__init__.py (100%) rename memory_scope/{monitor => storage}/base_monitor.py (93%) rename memory_scope/{db/base_db_client.py => storage/base_vector_store.py} (96%) rename memory_scope/{handler/pipeline_handler.py => utils/pipeline.py} (74%) rename memory_scope/{parsers => utils}/response_text_parser.py (95%) delete mode 100644 memory_scope/utils/version.py delete mode 100644 memory_scope/worker/summary_short/__init__.py rename {memory_scope/node => old}/__init__.py (100%) rename {memory_scope/models => old}/dash_client.py (100%) rename {memory_scope/models => old}/dash_embedding_client.py (100%) rename {memory_scope/models => old}/dash_generate_client.py (100%) rename {memory_scope/models => old}/dash_rerank_client.py (100%) rename {memory_scope/db => old}/elastic_search_client.py (100%) rename {memory_scope/parsers => old/es}/__init__.py (100%) rename {memory_scope/worker => old}/es/es_insight_worker.py (100%) rename {memory_scope/worker => old}/es/es_keyword_worker.py (100%) rename {memory_scope/worker => old}/es/es_new_obs_worker.py (100%) rename {memory_scope/worker => old}/es/es_not_reflected_worker.py (100%) rename {memory_scope/worker => old}/es/es_retrieve_all_worker.py (100%) rename {memory_scope/worker => old}/es/es_similar_worker.py (100%) rename {memory_scope/worker => old}/es/es_today_obs_worker.py (100%) rename {memory_scope/worker => old}/es/load_profile_worker.py (100%) rename {memory_scope/node => old}/memory_node.py (100%) rename {memory_scope/node => old}/memory_wrap_node.py (100%) rename {memory_scope/worker/es => old/retrieve}/__init__.py (100%) rename {memory_scope/worker => old}/retrieve/extract_time_worker.py (100%) rename {memory_scope/worker => old}/retrieve/fuse_rerank_worker.py (100%) rename {memory_scope/worker => old}/retrieve/memory_store_worker.py (100%) rename {memory_scope/worker => old}/retrieve/parse_params_worker.py (100%) rename {memory_scope/worker => old}/retrieve/semantic_rank_worker.py (100%) rename {memory_scope/worker/retrieve => old/summary_long}/__init__.py (100%) rename {memory_scope/worker => old}/summary_long/get_insight_worker.py (100%) rename {memory_scope/worker => old}/summary_long/get_reflection_worker.py (100%) rename {memory_scope/worker => old}/summary_long/long_contra_repeat_worker.py (100%) rename {memory_scope/worker => old}/summary_long/summary_collect_worker.py (100%) rename {memory_scope/worker => old}/summary_long/update_insight_worker.py (100%) rename {memory_scope/worker => old}/summary_long/update_profile_worker.py (100%) rename {memory_scope/worker/summary_long => old/summary_short}/__init__.py (100%) rename {memory_scope/worker => old}/summary_short/contra_repeat_worker.py (100%) rename {memory_scope/worker => old}/summary_short/get_observation_with_time_worker.py (100%) rename {memory_scope/worker => old}/summary_short/get_observation_worker.py (100%) rename {memory_scope/worker => old}/summary_short/info_filter_worker.py (100%) create mode 100644 old/tool_functions.py rename {memory_scope/node => old}/user_attribute.py (100%) rename {memory_scope/utils => old}/user_profile_handler.py (100%) delete mode 100644 tests/es_test2.py delete mode 100644 tests/test_dash_api.py delete mode 100644 tests/test_memory.py diff --git a/config/config.json b/config/config.json index 92b5e716..43d53b94 100644 --- a/config/config.json +++ b/config/config.json @@ -3,24 +3,26 @@ "thread_pool_max_count": 5, "dash_scope_apikey": "", "open_ai_apikey": "", + "language": "en", "chat_list": [ "memory_chat" ] }, "memory_chat": { + "memory_user_name": "用户", "clazz": "chat.memory_chat", - "retrieve": "parse_params,load_profile,[extract_time|es_similar|es_keyword],semantic_rank,fuse_rerank", - "generation_model": "dashscope_generation" + "retrieve": "parse_params,load_profile,extract_time,es_similar,es_keyword,semantic_rank,fuse_rerank", + "generation_model": "dashscope_generation", + "history_msg_count": 3 }, - "db": { - "clazz": "db.base_db_client", + "vector_store": { + "clazz": "storage.base_vector_store", "index_name": "memory_test", - "user_name": "" + "password": "" }, "monitor": { - "clazz": "minitor.base_monitor", - "index_name": "memory_test", - "user_name": "" + "clazz": "storage.base_monitor", + "index_name": "memory_test" }, "workers": "workers" } \ No newline at end of file diff --git a/memory_scope/__init__.py b/memory_scope/__init__.py index e69de29b..d8b7815a 100644 --- a/memory_scope/__init__.py +++ b/memory_scope/__init__.py @@ -0,0 +1,3 @@ +""" Version of MemoryScope.""" + +__version__ = "0.1.0-alpha.1" diff --git a/memory_scope/chat/base_memory_chat.py b/memory_scope/chat/base_memory_chat.py index c336df6d..c20c61bb 100644 --- a/memory_scope/chat/base_memory_chat.py +++ b/memory_scope/chat/base_memory_chat.py @@ -5,8 +5,10 @@ from memory_scope.chat.memory_service import MemoryService class BaseMemoryChat(metaclass=ABCMeta): - def __init__(self, **kwargs): - self.memory_service = MemoryService(**kwargs) + def __init__(self, chat_name: str, memory_user_name: str, **kwargs): + self.memory_service = MemoryService(chat_name=chat_name, + memory_user_name=memory_user_name, + **kwargs) @abstractmethod def chat_with_memory(self, query: str): diff --git a/memory_scope/chat/global_context.py b/memory_scope/chat/global_context.py index 594d386c..ceb071e9 100644 --- a/memory_scope/chat/global_context.py +++ b/memory_scope/chat/global_context.py @@ -2,9 +2,10 @@ from concurrent.futures import ThreadPoolExecutor from typing import Dict, Any from memory_scope.chat.base_memory_chat import BaseMemoryChat -from memory_scope.db.base_db_client import BaseDBClient +from memory_scope.enumeration.language_enum import LanguageEnum from memory_scope.models.base_model import BaseModel -from memory_scope.monitor.base_monitor import BaseMonitor +from memory_scope.storage.base_monitor import BaseMonitor +from memory_scope.storage.base_vector_store import BaseVectorStore from memory_scope.worker.base_worker import BaseWorker @@ -12,17 +13,19 @@ class GlobalContext(object): def __init__(self): self.global_configs: Dict[str, Any] = {} - self.worker_dict: Dict[str, BaseWorker] = {} + self.worker_dict: Dict[str, Dict[str, BaseWorker]] = {} self.model_dict: Dict[str, BaseModel] = {} self.memory_chat_dict: Dict[str, BaseMemoryChat] = {} - self.db_client: BaseDBClient | None = None + self.vector_store: BaseVectorStore | None = None self.monitor: BaseMonitor | None = None self.thread_pool: ThreadPoolExecutor | None = None + self.language: LanguageEnum = LanguageEnum.EN + GLOBAL_CONTEXT = GlobalContext() diff --git a/memory_scope/chat/memory_chat.py b/memory_scope/chat/memory_chat.py index 69311966..d408f7b9 100644 --- a/memory_scope/chat/memory_chat.py +++ b/memory_scope/chat/memory_chat.py @@ -3,41 +3,44 @@ from typing import List from memory_scope.chat.base_memory_chat import BaseMemoryChat from memory_scope.chat.global_context import GLOBAL_CONTEXT +from memory_scope.definition.message import Message from memory_scope.enumeration.message_role_enum import MessageRoleEnum from memory_scope.models.base_model import BaseModel -from memory_scope.node.message import Message -from memory_scope.prompts.prompt_cn import SYSTEM_PROMPT, MEMORY_PROMPT +from memory_scope.prompts.memory_chat_prompt import SYSTEM_PROMPT, MEMORY_PROMPT class MemoryChat(BaseMemoryChat): - """ - TODO add agent - """ def __init__(self, generation_model: str, history_msg_count: int, **kwargs): super().__init__(**kwargs) - self.model: BaseModel = GLOBAL_CONTEXT.model_dict[generation_model] + self.generation_model_name: str = generation_model self.history_msg_count: int = history_msg_count - self.memory_service.start_summary_short_backend() - self.memory_service.start_summary_long_backend() - + self._generation_model: BaseModel | None = None self.history_message_list: List[Message] = [] + @property + def generation_model(self): + if self._generation_model is None: + self._generation_model = GLOBAL_CONTEXT.model_dict[self.generation_model_name] + return self._generation_model + @staticmethod def get_system_prompt(related_memories: List[str], time_created: int) -> Message: - system_prompt = SYSTEM_PROMPT + system_prompt = SYSTEM_PROMPT[GLOBAL_CONTEXT.language] if related_memories: - system_prompt = "\n".join([SYSTEM_PROMPT, MEMORY_PROMPT] + related_memories) + memory_prompt = MEMORY_PROMPT[GLOBAL_CONTEXT.language] + system_prompt = "\n".join([system_prompt, memory_prompt] + related_memories) return Message(role=MessageRoleEnum.SYSTEM, content=system_prompt.strip(), time_created=time_created) def chat_with_memory(self, query: str): query = query.strip() if not query: return + time_created = int(datetime.datetime.now().timestamp()) new_message: Message = Message(role=MessageRoleEnum.USER, content=query, time_created=time_created) related_memories: List[str] = self.memory_service.retrieve(message=new_message) @@ -45,7 +48,5 @@ class MemoryChat(BaseMemoryChat): self.history_message_list.append(new_message) self.history_message_list = self.history_message_list[-self.history_msg_count:] all_messages = [system_message] + self.history_message_list - return self.model.call(messages=all_messages) - - def chat_with_memory_stream(self): - raise NotImplementedError + # TODO at xian zhe + return self.generation_model.call(messages=all_messages, stream=True) diff --git a/memory_scope/chat/memory_service.py b/memory_scope/chat/memory_service.py index 011fe435..8fc340e9 100644 --- a/memory_scope/chat/memory_service.py +++ b/memory_scope/chat/memory_service.py @@ -1,13 +1,14 @@ from memory_scope.constants.common_constants import RELATED_MEMORIES +from memory_scope.definition.message import Message from memory_scope.enumeration.memory_method_enum import MemoryMethodEnum -from memory_scope.handler.pipeline_handler import PipelineHandler -from memory_scope.node.message import Message +from memory_scope.utils.pipeline import Pipeline class MemoryService(object): def __init__(self, - user_name: str, + chat_name: str, + memory_user_name: str, retrieve_pipeline: str, retrieve_all_pipeline: str, summary_short_pipeline: str, @@ -17,39 +18,49 @@ class MemoryService(object): summary_long_interval_time: int = 60 * 5, summary_long_minimum_count: int = 5 * 5, **kwargs): - self.retrieve_pipeline_handler = PipelineHandler(user_name=user_name, - memory_method_type=MemoryMethodEnum.RETRIEVE, - pipeline_str=retrieve_pipeline) + self.retrieve_pipeline = Pipeline(chat_name=chat_name, + user_name=memory_user_name, + memory_method_type=MemoryMethodEnum.RETRIEVE, + pipeline_str=retrieve_pipeline) - self.retrieve_all_pipeline_handler = PipelineHandler(user_name=user_name, - memory_method_type=MemoryMethodEnum.RETRIEVE_ALL, - pipeline_str=retrieve_all_pipeline) + self.retrieve_all_pipeline = Pipeline(chat_name=chat_name, + user_name=memory_user_name, + memory_method_type=MemoryMethodEnum.RETRIEVE_ALL, + pipeline_str=retrieve_all_pipeline) - self.summary_short_pipeline_handler = PipelineHandler(user_name=user_name, - memory_method_type=MemoryMethodEnum.SUMMARY_SHORT, - pipeline_str=summary_short_pipeline, - loop_interval_time=summary_short_interval_time, - loop_minimum_count=summary_short_minimum_count) + self.summary_short_pipeline = Pipeline(chat_name=chat_name, + user_name=memory_user_name, + memory_method_type=MemoryMethodEnum.SUMMARY_SHORT, + pipeline_str=summary_short_pipeline, + loop_interval_time=summary_short_interval_time, + loop_minimum_count=summary_short_minimum_count) - self.summary_long_pipeline_handler = PipelineHandler(user_name=user_name, - memory_method_type=MemoryMethodEnum.SUMMARY_LONG, - pipeline_str=summary_long_pipeline, - loop_interval_time=summary_long_interval_time, - loop_minimum_count=summary_long_minimum_count) + self.summary_long_pipeline = Pipeline(chat_name=chat_name, + user_name=memory_user_name, + memory_method_type=MemoryMethodEnum.SUMMARY_LONG, + pipeline_str=summary_long_pipeline, + loop_interval_time=summary_long_interval_time, + loop_minimum_count=summary_long_minimum_count) self.kwargs = kwargs def retrieve(self, message: Message): - self.retrieve_pipeline_handler.submit_message(message, with_lock=False) - self.summary_short_pipeline_handler.submit_message(message) - self.summary_long_pipeline_handler.submit_message(message) - return self.retrieve_pipeline_handler.run(RELATED_MEMORIES) + self.retrieve_pipeline.submit_message(message, with_lock=False) + self.summary_short_pipeline.submit_message(message) + self.summary_long_pipeline.submit_message(message) + return self.retrieve_pipeline.run(RELATED_MEMORIES) def retrieve_all(self): - return self.retrieve_all_pipeline_handler.run(RELATED_MEMORIES) + return self.retrieve_all_pipeline.run(RELATED_MEMORIES) - def start_summary_short_backend(self): - self.summary_short_pipeline_handler.start_loop_run() + def start_memory_backend(self): + self.summary_short_pipeline.start_loop_run() + self.summary_long_pipeline.start_loop_run() - def start_summary_long_backend(self): - self.summary_long_pipeline_handler.start_loop_run() + def get_worker_list(self) -> list: + worker_set = set() + worker_set.update(self.retrieve_pipeline.worker_set) + worker_set.update(self.retrieve_all_pipeline.worker_set) + worker_set.update(self.summary_short_pipeline.worker_set) + worker_set.update(self.summary_long_pipeline.worker_set) + return sorted(worker_set) diff --git a/memory_scope/cli.py b/memory_scope/cli.py index ae795cf7..d353fa2d 100644 --- a/memory_scope/cli.py +++ b/memory_scope/cli.py @@ -1,15 +1,17 @@ import json import os from concurrent.futures import ThreadPoolExecutor -from typing import Dict, Any +from typing import Dict, Any, List import fire -from handler.global_context import GLOBAL_CONTEXT -from memory_scope.enumeration.model_type import ModelType +from memory_scope.chat.base_memory_chat import BaseMemoryChat +from memory_scope.chat.global_context import GLOBAL_CONTEXT +from memory_scope.enumeration.language_enum import LanguageEnum +from memory_scope.enumeration.model_enum import ModelEnum from memory_scope.utils.logger import Logger from memory_scope.utils.timer import Timer -from memory_scope.utils.tool_functions import complete_config_name, init_instance_by_config_v2 +from memory_scope.utils.tool_functions import complete_config_name, init_instance_by_config class CliJob(object): @@ -17,18 +19,23 @@ class CliJob(object): def __init__(self, config_path: str): self.config_path: str = config_path self.config_base_dir: str = os.path.dirname(config_path) - self.config: Dict[str, Any] = {} + self.worker_chat_dict: Dict[str, List[str]] = {} self.logger: Logger = Logger.get_logger("memory_chat") def init_memory_chat(self): - for chat in self.config["chat_list"]: - memory_chat_config = self.config[chat] - memory_chat = init_instance_by_config_v2(memory_chat_config) - GLOBAL_CONTEXT.memory_chat_dict[chat] = memory_chat + for chat_name in self.config["chat_list"]: + memory_chat_config = self.config[chat_name] + memory_chat: BaseMemoryChat = init_instance_by_config(memory_chat_config, chat_name=chat_name) + GLOBAL_CONTEXT.memory_chat_dict[chat_name] = memory_chat - generation_model = memory_chat_config[ModelType.GENERATION_MODEL.value] + for worker_name in memory_chat.memory_service.get_worker_list(): + if worker_name not in self.worker_chat_dict: + self.worker_chat_dict[worker_name] = [] + self.worker_chat_dict[worker_name].append(chat_name) + + generation_model = memory_chat_config[ModelEnum.GENERATION_MODEL.value] self.init_model(generation_model) def init_model(self, model_name: str): @@ -37,7 +44,7 @@ class CliJob(object): with open(os.path.join(self.config_base_dir, "model", complete_config_name(model_name))) as f: model_config = json.load(f) - GLOBAL_CONTEXT.model_dict[model_name] = init_instance_by_config_v2(model_config) + GLOBAL_CONTEXT.model_dict[model_name] = init_instance_by_config(model_config) def init_workers(self): """ load worker config & init workers @@ -47,17 +54,28 @@ class CliJob(object): worker_config_dict = json.load(f) for worker_name, worker_config in worker_config_dict.items(): - GLOBAL_CONTEXT.worker_dict[worker_name] = init_instance_by_config_v2(worker_config, - suffix_name="worker", - **GLOBAL_CONTEXT.global_configs) + if worker_name not in self.worker_chat_dict: + continue - self.init_model(worker_config.get(ModelType.EMBEDDING_MODEL.value)) - self.init_model(worker_config.get(ModelType.GENERATION_MODEL.value)) - self.init_model(worker_config.get(ModelType.RANK_MODEL.value)) + chat_name_list = self.worker_chat_dict[worker_name] + for chat_name in chat_name_list: + if chat_name not in GLOBAL_CONTEXT.worker_dict: + GLOBAL_CONTEXT.worker_dict[chat_name] = {} + GLOBAL_CONTEXT.worker_dict[chat_name][worker_name] = init_instance_by_config( + worker_config, + suffix_name="worker", + **GLOBAL_CONTEXT.global_configs) - def set_global_config(self): - """set global_configs & set apikey into env + self.init_model(worker_config.get(ModelEnum.EMBEDDING_MODEL.value)) + self.init_model(worker_config.get(ModelEnum.GENERATION_MODEL.value)) + self.init_model(worker_config.get(ModelEnum.RANK_MODEL.value)) + + @staticmethod + def set_global_config(): + """ TODO set global_configs & set apikey into env """ + GLOBAL_CONTEXT.language = LanguageEnum(GLOBAL_CONTEXT.global_configs["language"]) + GLOBAL_CONTEXT.thread_pool = ThreadPoolExecutor(max_workers=int(GLOBAL_CONTEXT.global_configs["max_workers"])) def init_global_content_by_config(self): with open(complete_config_name(self.config_path)) as f: @@ -65,17 +83,17 @@ class CliJob(object): GLOBAL_CONTEXT.global_configs = self.config["global_configs"] self.set_global_config() - GLOBAL_CONTEXT.thread_pool = ThreadPoolExecutor(max_workers=int(GLOBAL_CONTEXT.global_configs["max_workers"])) - - self.init_workers() - GLOBAL_CONTEXT.db_client = init_instance_by_config_v2(self.config["db"]) - GLOBAL_CONTEXT.monitor = init_instance_by_config_v2(self.config["monitor"]) self.init_memory_chat() + self.init_workers() + GLOBAL_CONTEXT.vector_store = init_instance_by_config(self.config["vector_store"]) + GLOBAL_CONTEXT.monitor = init_instance_by_config(self.config["monitor"]) + def run(self): with GLOBAL_CONTEXT.thread_pool, Timer("job", log_time=False) as t: memory_chat = list(GLOBAL_CONTEXT.memory_chat_dict.values())[0] + memory_chat.memory_service.start_memory_backend() while True: query = input("wait for input:") if query in ["stop", "停止"]: diff --git a/memory_scope/constants/common_constants.py b/memory_scope/constants/common_constants.py index 3706e39e..e41a92ab 100644 --- a/memory_scope/constants/common_constants.py +++ b/memory_scope/constants/common_constants.py @@ -1,81 +1,5 @@ -APP_ENV = "APP_ENV" - -PIPELINE = "pipeline" - -WORKER = "worker" - -MEMORY = "memory" - USER_NAME = "user_name" -DEFAULT_SYSTEM_PROMPT = "default_system_prompt" - RELATED_MEMORIES = "related_memories" -MODIFIED_MEMORIES = "modified_memories" - -RESPONSE_EXT_INFO = "response_ext_info" - -REQUEST = "request" - -CONFIG = "config" - -PROMPT_CONFIG = "prompt_config" - MESSAGES = "messages" - -EXTRACT_TIME_DICT = "extract_time_dict" - -NEW_OBS_NODES = "new_obs_nodes" - -NEW_OBS_WITH_TIME_NODES = "new_obs_with_time_nodes" - -INSIGHT_NODES = "insight_nodes" - -MERGE_OBS_NODES = "merge_obs_nodes" - -NEW_INSIGHT_NODES = "new_insight_nodes" - -TODAY_OBS_NODES = "today_obs_nodes" - -ALL_NODES = "all_nodes" - -ALL_MEMORIES = "all_memories" - -SIMILAR_OBS_NODES = "similar_obs_nodes" - -KEYWORD_OBS_NODES = "keyword_obs_nodes" - -NOT_REFLECTED_OBS_NODES = "not_reflected_obs_nodes" - -NOT_REFLECTED_MERGE_NODES = "not_reflected_merge_nodes" - -NEW_INSIGHT_KEYS = "new_insight_keys" - -INSIGHT_KEY = "insight_key" - -INSIGHT_VALUE = "insight_value" - -DT = "dt" - -MSG_TIME = "msg_time" - -NEW = "new" - -TIME_INFER = "time_infer" - -KEY_WORD = "key_word" - -REFLECTED = "reflected" - -NEW_USER_PROFILE = "new_user_profile" - -RECALL_TYPE = "recall_type" - -ALL_ONLINE_NODES = "all_online_nodes" - -MAX_WORKERS = "max_workers" - -TIME_MATCHED = "time_matched" - -QUERY_KEYWORDS = "query_keywords" diff --git a/memory_scope/db/__init__.py b/memory_scope/definition/__init__.py similarity index 100% rename from memory_scope/db/__init__.py rename to memory_scope/definition/__init__.py diff --git a/memory_scope/definition/memory_node.py b/memory_scope/definition/memory_node.py new file mode 100644 index 00000000..5e0061a4 --- /dev/null +++ b/memory_scope/definition/memory_node.py @@ -0,0 +1,20 @@ +from typing import Dict, List + +from pydantic import Field, BaseModel + + +class MemoryNode(BaseModel): + id: str = Field("", description="uuid64") + + content: str = Field("", description="memory content") + + memoryId: str = Field("", description="unique memory id") + + memoryType: str = Field("", description="conversation/observation/insight...") + + metaData: Dict[str, str] = Field({}, description="other data infos") + + status: str = Field("active", description="active or expired") + + vector: List[float] = Field([], description="content embedding result, return empty") + diff --git a/memory_scope/definition/memory_wrap_node.py b/memory_scope/definition/memory_wrap_node.py new file mode 100644 index 00000000..8533e31f --- /dev/null +++ b/memory_scope/definition/memory_wrap_node.py @@ -0,0 +1,15 @@ +from pydantic import Field, BaseModel + +from memory_scope.definition.memory_node import MemoryNode + + +class MemoryWrapNode(BaseModel): + id: str = Field("", description="uuid64") + + score_similar: float = Field(0, description="相似度打分") + + score_rank: float = Field(0, description="排序打分") + + score_rerank: float = Field(0, description="重排打分") + + memory_node: MemoryNode = Field(None, description="memory node 核心,返回给上游的结构") diff --git a/memory_scope/node/message.py b/memory_scope/definition/message.py similarity index 100% rename from memory_scope/node/message.py rename to memory_scope/definition/message.py diff --git a/memory_scope/enumeration/dash_api_enum.py b/memory_scope/enumeration/dash_api_enum.py deleted file mode 100644 index 8a58a2af..00000000 --- a/memory_scope/enumeration/dash_api_enum.py +++ /dev/null @@ -1,9 +0,0 @@ -from enum import Enum - - -class DashApiEnum(str, Enum): - GENERATION = "generation" - - EMBEDDING = "embedding" - - RERANK = "rerank" diff --git a/memory_scope/enumeration/language_enum.py b/memory_scope/enumeration/language_enum.py new file mode 100644 index 00000000..9c0423f1 --- /dev/null +++ b/memory_scope/enumeration/language_enum.py @@ -0,0 +1,7 @@ +from enum import Enum + + +class LanguageEnum(str, Enum): + CN = "cn" + + EN = "en" diff --git a/memory_scope/enumeration/memory_recall_type.py b/memory_scope/enumeration/memory_recall_enum.py similarity index 100% rename from memory_scope/enumeration/memory_recall_type.py rename to memory_scope/enumeration/memory_recall_enum.py diff --git a/memory_scope/enumeration/memory_scene_enum.py b/memory_scope/enumeration/memory_scene_enum.py deleted file mode 100644 index ed9a5fc8..00000000 --- a/memory_scope/enumeration/memory_scene_enum.py +++ /dev/null @@ -1,11 +0,0 @@ -from enum import Enum - - -class MemorySceneEnum(str, Enum): - BAILIAN = "BAILIAN" - - TONGYI_MAIN_CHAT = "TONGYI_MAIN_CHAT" - - TONGYI_CHAR_CHAT = "TONGYI_CHAR_CHAT" - - ASSISTANT_API = "ASSISTANT_API" diff --git a/memory_scope/enumeration/memory_node_status.py b/memory_scope/enumeration/memory_status_enum.py similarity index 100% rename from memory_scope/enumeration/memory_node_status.py rename to memory_scope/enumeration/memory_status_enum.py diff --git a/memory_scope/enumeration/model_type.py b/memory_scope/enumeration/model_enum.py similarity index 83% rename from memory_scope/enumeration/model_type.py rename to memory_scope/enumeration/model_enum.py index 25af770a..d1d9aecc 100644 --- a/memory_scope/enumeration/model_type.py +++ b/memory_scope/enumeration/model_enum.py @@ -1,7 +1,7 @@ from enum import Enum -class ModelType(str, Enum): +class ModelEnum(str, Enum): GENERATION_MODEL = "generation_model" EMBEDDING_MODEL = "embedding_model" diff --git a/memory_scope/models/__init__.py b/memory_scope/models/__init__.py index 35395203..5a9d5579 100644 --- a/memory_scope/models/__init__.py +++ b/memory_scope/models/__init__.py @@ -1,5 +1,3 @@ -from llama_index.embeddings.dashscope import DashScopeEmbedding - from memory_scope.utils.registry import Registry MODEL_REGISTRY = Registry("models") diff --git a/memory_scope/prompts/bailian_prompt_config.py b/memory_scope/prompts/bailian_prompt_config.py deleted file mode 100644 index 3aa3b782..00000000 --- a/memory_scope/prompts/bailian_prompt_config.py +++ /dev/null @@ -1,627 +0,0 @@ -from pydantic import BaseModel -from textwrap import dedent - - -class BailianPromptConfig(BaseModel): - """ - NOTE 不需要strip() 拼装会统一strip - """ - - info_filter_system: str = dedent(""" - 任务指令:对所给{batch_size}个句子中所含有的关于用户的信息打分,分数为0,1,2或3。 - 注意:其中0表示不包含用户信息,1表示句子中包含用户假设的信息或者用户虚构的内容,2表示可以对用户信息做一些不准确的猜测,3表示明确含有关于用户的有效信息或者可以推断出用户准确的信息或者用户要求记录。 - 按如下格式输出, 每一行输出一个打分,一定加<>,一共输出{batch_size}个分数: - 结果: - <分数:0或1或2或3> - """) - - - info_filter_few_shot: str = dedent(""" - 示例1 - 句子: - 1 用户:帮我写一段给同事张三女儿三岁生日的祝福语。 - 2 用户:公元1400年至1550年中国历史大事表。 - 3 用户:你吃午饭了吗? - 4 用户:我今天心情不好,可以安慰我一下吗? - 5 用户:能给我整理一张如何使用大模型的技巧列表吗,要求内容尽量精简。 - 6 用户:明天下午3点提醒我去拿一下文件。 - 结果: - <3> - <0> - <0> - <2> - <2> - <3> - - 示例2 - 句子: - 1 用户:我刚刚入职了阿里巴巴。 - 2 用户:露天睡觉蚊子多,咋搞。 - 3 用户:创造力和外倾性有关? - 4 用户:一个区县的所有的事业人员的档案审核、修改和规范,应该是县委组织部下属的干部档案中心负责还是县人社局负责? - 5 用户:假如我要和一个女人准备要孩子,我作为男人,怎么保护女人和孩子以及怎么备孕确保精子质量高对后代好 - 6 用户:我和你一起出去玩,你会感觉开心吗? - 结果: - <3> - <2> - <0> - <0> - <1> - <1> - - 示例3 - 句子: - 1 用户:你的妈妈患有焦虑症,怎么安慰和开导她? - 2 用户:肾脏严重亏空 - 3 用户:我很喜欢打篮球,所以我身体很好 - 4 用户:篮球明星有哪些? - 结果: - <1> - <1> - <3> - <0> - """) - info_filter_user_query: str = """ -句子: -{user_query} -结果: - """ - - """ - 思考:思考的依据和过程,不超过20字。 - """ - get_observation_system: str = """ -任务:从下面的{num_obs}句用户句子中依次提取出关于用户的重要信息,与相应的关键词。最多提取{num_obs}条信息。对每一句句子,只提取非常明确的信息,不要进行任何推测。 -不要提取重复的信息,如果句子中的所有信息与已经提取出的信息重复了则回答“重复“,如果没有重要信息则回答“无”。 -请一定要按如下格式依次输出,最后的结果一定要加<>: -信息:<句子序号> <> <明确的重要信息或“重复”或”无“> <关键词> - """ - - """ -思考:从第1句可以得知用户现在没有工作,负债几万,这是关于用户工作与经济状况的重要信息。 -思考:第2句是用户对他人观点的讨论和疑问,没有明确提及用户个人信息。 -思考:第3句含有的信息与第1句重复了。 -思考:从第4句可以得知用户是一个刚毕业的学生,这是关于用户身份背景状况的重要信息。其余信息重要性不足。 -思考:从第1句可以得知张三是用户的同事,这是关于用户的人际关系的重要信息。其余信息重要性不足。 -思考:第2句是用户提出的要求,没有明确提及用户个人信息。 -思考:从第3句可以得知用户前天打羽毛球时把球拍打断了线,但这不是重要的信息。还可以得知用户对猫毛过敏,这是关于用户的健康的重要信息。 -思考:从第4句是用户提出的要求,没有明确提及用户个人信息。 -思考:从第5句可以得知用户在阿里巴巴徐汇滨江园区工作,这是关于用户的工作地点的重要信息。 -思考:从第1句可以得知用户寻求购买新能源汽车的建议或推荐,这是这是关于用户的大宗消费的重要的信息。 -思考:从第2句可以得知用户当前所在城市为上海,这是关于用户的生活地区的重要信息。其余信息与第1句重复了。 -思考:第3句是用户对某个观点的讨论和疑问,没有明确提及用户个人信息。 -思考:第4句是用户提出的要求,没有明确提及用户个人信息。 -思考:从第5句可以得知用户购买了海天味业股票,购买数量为100股,购买金额为5000元,这是关于用户的投资决策的重要信息。 - """ - get_observation_few_shot: str = """ -示例1: -用户句子: -1 用户:我现在处境很糟,没有工作,负债几万,怎么办 -2 用户:有人说兴趣是最好的老师,也建议兴趣和职业联系起来,但我发现喜欢打篮球的人很多,但靠打篮球成职业的稀少,赚钱的更少,此外,怎么分辨兴趣和喜欢 -3 用户:我现在处境很糟,没有工作,负债几万,怎么办 -4 用户:我是一个刚毕业的学生,对社会,行业不了解,给我介绍一下社会系统和行业格局 -思考:从第1句可以得知用户现在没有工作,负债几万,这是关于用户工作与经济状况的重要信息。 -信息:<1> <> <用户当前无工作且负债几万> <无工作, 负债几万> -思考:第2句是用户对他人观点的讨论和疑问,没有明确提及用户个人信息。 -信息:<2> <> <无> <> -思考:第3句含有的信息与第1句重复了。 -信息:<3> <> <重复> <> -思考:从第4句可以得知用户是一个刚毕业的学生,这是关于用户身份背景状况的重要信息。其余信息重要性不足。 -信息:<4> <> <用户是一名刚毕业的学生。> <刚毕业, 学生> - -示例2: -用户句子: -1 用户:帮我写一段给同事张三女儿三岁生日的祝福语。 -2 用户:能给我整理一张如何使用大模型的技巧列表吗,要求内容尽量精简。 -3 用户:两个坏消息,我打羽毛球把拍子打断线了。。。然后我去我朋友家撸猫,结果我猫毛过敏,今天疯狂打喷嚏。。。 -4 用户:公元1400年至1550年中国历史大事表。 -5 用户:谢啦。我中午在公司附近吃,帮我推荐一家阿里巴巴徐汇滨江园区附近的餐厅吧。 -思考:从第1句可以得知张三是用户的同事,这是关于用户的人际关系的重要信息。其余信息重要性不足。 -信息:<1> <> <张三是用户的同事。> <张三, 同事> -思考:第2句是用户提出的要求,没有明确提及用户个人信息。 -信息:<2> <> <无> <> -思考:从第3句可以得知用户前天打羽毛球时把球拍打断了线,但这不是重要的信息。还可以得知用户对猫毛过敏,这是关于用户的健康的重要信息。 -信息:<3> <> <用户对猫毛过敏。> <猫毛, 过敏> -思考:从第4句是用户提出的要求,没有明确提及用户个人信息。 -信息:<4> <> <无> <> -思考:从第5句可以得知用户在阿里巴巴徐汇滨江园区工作,这是关于用户的工作地点的重要信息。 -信息:<5> <> <用户在阿里巴巴徐汇滨江园区工作。> <阿里巴巴, 徐汇滨江园区, 工作> - -示例3: -用户句子: -1 用户:我想买辆新能源汽车,有什么推荐吗? -2 用户:我在上海,想买辆新能源汽车,有什么推荐吗? -3 用户:案外人异议审查期间,人民法院不得对执行标的进行处分,不就是中止执行的意思吗? -4 用户:请写两句藏头诗分别以“胜”和“利”开头。 -5 用户:我花5000元买了100股海天味业。 -思考:从第1句可以得知用户寻求购买新能源汽车的建议或推荐,这是这是关于用户的大宗消费的重要的信息。 -信息:<1> <> <用户寻求购买新能源汽车的建议或推荐。> <购买, 新能源汽车> -思考:从第2句可以得知用户当前所在城市为上海,这是关于用户的生活地区的重要信息。其余信息与第1句重复了。 -信息:<2> <> <用户所在的城市是上海。> <上海> -思考:第3句是用户对某个观点的讨论和疑问,没有明确提及用户个人信息。 -信息:<3> <> <无> <> -思考:第4句是用户提出的要求,没有明确提及用户个人信息。 -信息:<4> <> <无> <> -思考:从第5句可以得知用户购买了海天味业股票,购买数量为100股,购买金额为5000元,这是关于用户的投资决策的重要信息。 -信息:<5> <> <用户购买了海天味业股票,购买数量为100股,购买金额为5000元。> <海天味业, 股票> - """ - - get_observation_user_query: str = """ -用户句子: -{user_query} - """ - - get_observation_with_time_system: str = """ -任务:从下面的{num_obs}句用户句子中依次提取出关于用户的重要信息,相应的关键词与时间信息。 -每一句用户句子的格式是:<序号> <对话时间> 用户:<句子> -对每一句句子,只提取非常明确的重要信息,不要进行任何推测。不要提取重复的信息,如果句子中的所有信息与已经提取出的信息重复了则回答“重复“,如果没有重要信息则回答“无”。 -如果用户信息涉及时间,则结合对话时间推断用户信息的时间信息,没有则不输出。 -请一步步思考,并一定要按如下格式依次输出,最后的结果一定要加<>: -信息:<句子序号> <时间信息或“无”> <明确的重要信息或“重复”或”无“> <关键词> - """ - - get_observation_with_time_few_shot: str = """ -示例1: -句子: -1 2022年5月1日周二3点 用户:帮我写一段给同事张三女儿三岁生日的祝福语。 -2 2022年5月2日周二17点 用户:公元1400年至1550年中国历史大事表。 -3 2022年5月3日周二18点 用户:能给我整理一张如何使用大模型的技巧列表吗,要求内容尽量精简。 -4 2022年7月3日周四12点 用户:上上个月我办了游泳卡。 - -思考:从第1句可以得知张三是用户的同事,这是关于用户的人际关系的重要信息。其余信息重要性不足。用户信息不涉及时间。 -信息:<1> <> <张三是用户的同事。> <张三, 同事> -思考:第2句是用户提出的要求,没有明确提及用户个人信息。 -信息:<2> <> <无> <> -思考:第3句是用户提出的要求,没有明确提及用户个人信息。 -信息:<3> <> <无> <> -思考:从第4句可以得出用户上上个月办了游泳卡。用户信息涉及时间,结合对话时间为2022年7月,推断用户在2022年5月用户办了游泳卡。 -信息:<4> <2022年5月> <用户在2022年5月办了游泳卡。> <游泳卡> - - -示例2: -句子: -1 2020年1月4日周日10点 用户:我花5000元买了100股海天味业。 -2 2023年4月27日周五8点 用户:明天是我和妻子的结婚纪念日,帮我推荐一家餐厅。 -3 2020年1月4日周日10点 用户:我花5000元买了100股海天味业。 -4 2021年6月2日周四23点 用户:谢啦。我中午在公司附近吃,帮我推荐一家阿里巴巴徐汇滨江园区附近的餐厅吧。 -5 2021年7月9日周六11点 用户:两个坏消息,我打羽毛球把拍子打断线了。。。然后我去我朋友家撸猫,结果我猫毛过敏,今天疯狂打喷嚏。。。 - -思考:从第1句可以得知用户购买了海天味业股票,购买数量为100股,购买金额为5000元,这是关于用户的投资决策的重要信息。用户信息不涉及时间。 -信息:<1> <> <用户购买了海天味业股票,购买数量为100股,购买金额为5000元。> <海天味业, 股票> -思考:从第2句可以得知用户与妻子的结婚纪念日是明天,这是关于用户重要纪念日的信息。其余信息重要性不足。用户信息涉及时间,结合对话时间为2023年4月27日, -以及结婚纪念日为周期性日期,推断用户与妻子的结婚纪念日是每年4月28日。 -信息:<2> <每年4月28日> <用户与妻子的结婚纪念日是每年4月28日。> <妻子, 结婚纪念日> -思考:第3句含有的信息与第1句重复了。 -信息:<3> <> <重复> <> -思考:从第4句以得知用户在阿里巴巴徐汇滨江园区工作,这是关于用户的工作的重要信息。其余信息重要性不足。用户信息不涉及时间。 -信息:<4> <> <用户在阿里巴巴徐汇滨江园区工作。> <阿里巴巴, 徐汇滨江园区, 工作> -思考:从第5句可以得知用户前天打羽毛球时把球拍打断了线,但这不是重要的信息。还可以得知用户对猫毛过敏,这是关于用户的健康的重要信息。用户信息不涉及时间。 -信息:<5> <> <用户对猫毛过敏。> <猫毛, 过敏> - - -示例3: -句子: -1 2023年6月30日周五15点 用户:上个月我和家人一起去杭州旅游,景色很不错。 -2 2023年7月2日周二10点 用户:昨天是我生日,一个人过的。 -3 2020年7月3日周四11点 用户:提醒我下周一去体检。 -4 2023年5月21日周六14点 用户:有人说兴趣是最好的老师,也建议兴趣和职业联系起来,但我发现喜欢打篮球的人很多,但靠打篮球成职业的稀少,赚钱的更少,此外,怎么分辨兴趣和喜欢 - -思考:从第1句可以得知用户和家人上个月去杭州旅游了,这是关于用户的经历的重要信息。其余信息重要性不足。用户信息涉及时间,结合对话时间为2023年6月推断用户和家人2023年5月去杭州旅游了。 -信息:<1> <2023年5月> <用户和家人2023年5月去杭州旅游了。> <家人, 杭州, 旅游> -思考:从第2句可以得知用户的生日是昨天,这是关于用户重要纪念日的信息。其余信息重要性不足。用户信息涉及时间,结合对话时间为2023年7月2日, -以及生日为周期性日期,推断用户的生日是每年7月2日。 -信息:<2> <每年7月2日> <用户的生日是每年7月2日。> <生日> -思考:从第3句可以得出用户下周一去体检,这是用户要求记忆的重要信息。用户信息涉及时间,结合对话时间为2020年7月3日周四,推断用户2020年7月6日周一去体检。 -信息:<3> <2020年7月6日周一> <用户2020年7月6日周一去体检。> <体检> -思考:第4句是用户对他人观点的讨论和疑问,没有明确提及用户个人信息。 -信息:<4> <> <无> <> - """ - - get_observation_with_time_user_query: str = """ -用户句子: -{user_query} - """ - - contra_repeat_system: str = """ -对下面的{num_obs}句句子,逐一判断是否与“前面序号”的任意句子存在信息的矛盾,或者句子的主要信息被“前面序号”的任意句子中的信息包含。只判断与“前面序号”的句子的关系。 -请一步步思考,并按如下格式输出: -思考:思考的依据和过程,30字以内。 -判断:<句子序号> <矛盾,被包含,无>,一定加<> -""" - - contra_repeat_few_shot: str = """ -示例1 -句子: -1 用户经常失眠,对安眠药的效果感兴趣,暗示可能考虑使用。 -2 用户经常失眠,寻求缓解方法。 -3 陈伟业是用户的领导 -4 陈伟业是用户的领导 -5 陈伟业是用户的领导,是银行分行行长 - -思考:第1句不会存在与前面序号句子的矛盾或者完全重复。 -判断:<1> <无> -思考:第2句中所有信息都被前面序号中第1句的信息完全包含。 -判断:<2> <被包含> -思考:第3句信息没有在前面序号句子中出现 -判断:<3> <无> -思考:第4句与前面序号中第3句的信息完全重复,即被完全包含。 -判断:<4> <被包含> -思考:第5句中陈伟业是用户的领导的信息被前面序号中第3句的信息包含,但新增了陈伟业是银行分行行长的信息,故不是被完全包含。 -判断:<5> <无> - -示例2 -句子: -1 用户的孩子成绩不太好。 -2 用户的孩子在学校经常逃课。 -3 用户的父亲生日在2024年6月2日,用户打算准备礼物。 -4 用户的父亲生日在2024年5月1日。 -5 用户很喜欢和同班同学打篮球。 -6 用户喜欢打篮球。 - -思考:第1句不会存在与前面序号句子的矛盾或者完全重复。 -判断:<1> <无> -思考:第2句与前面序号句子既不矛盾也不重复。 -判断:<2> <无> -思考:第3句与前面序号句子既不矛盾也不重复。 -判断:<3> <无> -思考:第4句关于用户父亲生日的日期信息与前面序号句子第3句矛盾了。 -判断:<4> <矛盾> -思考:第5句与前面序号句子既不矛盾也不重复。 -判断:<5> <无> -思考:第6句中所有信息都被前面序号中第5句的信息完全包含。 -判断:<2> <被包含> - """ - - contra_repeat_user_query: str = """ -句子: -{user_query} - """ - - long_contra_repeat_system: str = """ - 对下面的{num_obs}句句子,逐一判断是否与“前面序号”的任意句子存在信息的矛盾,或者句子的主要信息被“前面序号”的任意句子中的信息包含。只判断与“前面序号”的句子的关系。 - 请一步步思考,并按如下格式输出: - 思考:思考的依据和过程,30字以内。 - 判断:<句子序号> <矛盾,被包含,无>,一定加<> - """ - - long_contra_repeat_few_shot: str = """ - 示例1 - 句子: - 1 用户经常失眠,对安眠药的效果感兴趣,暗示可能考虑使用。 - 2 用户经常失眠,寻求缓解方法。 - 3 陈伟业是用户的领导 - 4 陈伟业是用户的领导 - 5 陈伟业是用户的领导,是银行分行行长 - - 思考:第1句不会存在与前面序号句子的矛盾或者完全重复。 - 判断:<1> <无> - 思考:第2句中所有信息都被前面序号中第1句的信息完全包含。 - 判断:<2> <被包含> - 思考:第3句信息没有在前面序号句子中出现 - 判断:<3> <无> - 思考:第4句与前面序号中第3句的信息完全重复,即被完全包含。 - 判断:<4> <被包含> - 思考:第5句中陈伟业是用户的领导的信息被前面序号中第3句的信息包含,但新增了陈伟业是银行分行行长的信息,故不是被完全包含。 - 判断:<5> <无> - - 示例2 - 句子: - 1 用户的孩子成绩不太好。 - 2 用户的孩子在学校经常逃课。 - 3 用户的父亲生日在2024年6月2日,用户打算准备礼物。 - 4 用户的父亲生日在2024年5月1日。 - 5 用户很喜欢和同班同学打篮球。 - 6 用户喜欢打篮球。 - - 思考:第1句不会存在与前面序号句子的矛盾或者完全重复。 - 判断:<1> <无> - 思考:第2句与前面序号句子既不矛盾也不重复。 - 判断:<2> <无> - 思考:第3句与前面序号句子既不矛盾也不重复。 - 判断:<3> <无> - 思考:第4句关于用户父亲生日的日期信息与前面序号句子第3句矛盾了。 - 判断:<4> <矛盾> - 思考:第5句与前面序号句子既不矛盾也不重复。 - 判断:<5> <无> - 思考:第6句中所有信息都被前面序号中第5句的信息完全包含。 - 判断:<2> <被包含> - """ - - long_contra_repeat_user_query: str = """ - 句子: - {user_query} - """ - - get_reflect_system: str = """ -任务:从下面的信息中提取出最重要的{num_questions}条用户属性,要求不与已有的用户属性语义重复。 -要求1:用户属性可以是一般的用户偏好,也可以是运动偏好,旅游偏好,饮食偏好等等,也可以是重要事件性质,比如最近重要的事情,也可以是一些高度概括的人生理想,价值观,人生观,性格, 也可以是和朋友的人际关系等等。 -要求2:根据用户属性,我们可以生成“用户的<用户属性>是什么?”的问题,以此可以从下面的信息中提取用户属性对应的值。 -输出格式:每一行输出一个用户属性,每个用户属性推荐4个字,如果没有信息请回答无,最多输出{num_questions}条。 - """ - - get_reflect_few_shot: str = """ -示例1 -信息: -用户想知道明天上海的天气情况。 -用户可能在上海工作,并关心是否需要带伞上班。 -用户在阿里巴巴徐汇滨江园区附近工作。 -用户计划中午在公司附近用餐。 -用户对咖啡因过敏。 -用户喝了咖啡后晚上会出现失眠的情况。 -用户偏好口味较为清淡、不辣的中餐馆。 -用户刚开始了他们的第一份工作。 -用户的工作岗位是阿里巴巴的算法工程师。 -用户希望得到与该岗位相关的职场建议。 -用户面临的问题是在项目进展初期如何有效与上司沟通。 -用户的目标是及时同步项目状态给上司。 -用户希望了解image generation(图像生成)技术的发展概览和最新进展。 -用户对variational auto-encoder、GAN、Diffusion Model等技术及其相互关系感兴趣。 -已有用户属性:性别,工作地点,工作单位,睡眠状况,美食偏好 -新增用户属性: -过敏源 -技术方向 -工作岗位 - - -示例2 -信息: -用户想要了解如何使用torchvision库来可视化深度学习任务的进度信息。 -用户希望了解如何将基于numpy和pytorch的并行计算方案迁移到CUDA支持的GPU上运行。 -用户询问是否需要依赖特定的包来完成这一任务。 -用户希望了解如何在Python中自定义进程和线程以实现并行计算。 -用户在编程中遇到了与并行计算相关的问题。 -用户希望学习如何使用Python(numpy,pytorch)在GPU上实现简单的并行计算。 -用户希望了解并行计算的基本概念,包括threads。 -用户询问有关世界各地著名菜系的信息。 -用户对全球各地的美食非常感兴趣。 -用户关心其体重与运动消耗的额外热量及心率之间的关系。 -用户在询问为了实现这一目标,每天需要额外消耗多少大卡热量。 -用户希望每月减重1kg。 -用户希望得到类似战略类手机游戏的推荐。 -用户喜欢玩三国志系列、文明系列、全面战争、骑马与砍杀等战略类游戏。 -用户希望根据他们的喜好获得新的游戏推荐。 -用户列举了他们喜欢的具体游戏类型,包括:三国志系列、文明系列、全面战争、骑马与砍杀等。 -用户喜欢玩战略类游戏。 -已有用户属性:工作地点,性别,美食偏好 -新增用户属性: -游戏偏好 -运动计划 -技术方向 - -示例3 -信息: -用户寻求推荐一个相关课程或网址以进行学习。 -用户计划去青岛旅游。 -用户正为张三的女儿选购生日礼物。 -用户请求为一位名叫张三的人的女儿撰写一段温馨的祝福语。 -用户的同事名叫张三。 -用户与张三约定讨论阿里云百炼项目。 -用户与同事张三讨论了该项目的PRD(产品需求文档)。 -同事张三计划下周对PRD进行最终确定。 -张三还安排了在再下一周进行POC(Proof of Concept,概念验证)的讨论。 -用户希望获知该项目工程开发工作的负责团队信息,以了解项目执行的组织架构与分工情况。 -已有用户属性: -新增用户属性: -朋友关系 - -示例4 -信息: -用户在寻求有关推拿按摩手法的教程或相关网站推荐。 -用户希望系统地学习正规的推拿按摩手法。 -用户对按摩感兴趣,并且经常去推拿按摩店。 -用户想了解自己在静息状态下一小时大概会消耗多少大卡热量。 -用户年龄为28岁。 -用户体重为70kg。 -用户是男性。 -已有用户属性:性别,年龄,体重,当前学习进展 -新增用户属性: -无 - """ - - get_reflect_user_query: str = """ -信息: -{user_query} -已有用户属性:{exist_keys} -新增用户属性: - """ - - get_insight_system: str = """ -任务:从下面的信息中提取出关于用户属性信息。语言简洁,每条不超过50字。请在一句话内表达,语言简洁,每条不超过50字。 - """ - - get_insight_few_shot: str = """ -示例1 -信息: -用户考虑是否应该给猫咪Sally购买一些猫玩具。 -用户家中有一只名为Sally的宠物,需要在室内自由活动以保障其身心健康。 -用户想要为名为Sally的宠物购买猫粮。 -用户养有一只名叫Sally的猫,并很喜欢它。 -孙二为这只猫取名为“Sally”。 -用户希望得到关于购买何种猫粮的建议。 -用户希望了解不同品种猫咪的基本信息。 -用户对猫毛过敏。 -用户关心领养猫与在宠物店购买猫之间的区别。 -用户正在寻求治疗猫毛过敏的方法。 -问题:用户的过敏源是什么? -用户对猫毛过敏,正寻求有效的解决方案,以便更好地照顾其宠物猫Sally并减轻过敏症状。 - -示例2 -信息: -用户的工作岗位是阿里巴巴的算法工程师。 -用户希望详细了解和学习图像生成技术。 -用户面临的问题是在项目进展初期如何有效与上司沟通。 -用户希望了解image generation(图像生成)技术的发展概览和最新进展。 -用户希望得到与该岗位相关的职场建议。 -用户刚开始了他们的第一份工作。 -用户的身份可能是初学者或专业人士。 -用户希望学习如何使用Python(numpy,pytorch)在GPU上实现简单的并行计算。 -用户想要了解如何使用torchvision库来可视化深度学习任务的进度信息。 -用户对variational auto-encoder、GAN、Diffusion Model等技术及其相互关系感兴趣。 -问题:用户的技术方向是什么? -用户是初入职场的阿里巴巴算法工程师,正积极探索图像生成技术和并行计算的知识,并寻求技术学习方面的指导,以提升自己的专业技能。 - """ - - get_insight_user_query: str = """ -信息: -{user_query} -问题:用户的{insight_key}是什么? - """ - - update_plural_profile_system: str = """ -从下面的句子中提取出给定类别的用户资料信息,并判断和已有信息是否重复。只输出无重复的新信息。若无法提取该类别的用户资料的新信息则回答无。 -请一步步思考,并按如下格式输出: -思考: 思考的依据和过程,150字以内。 -用户资料: <信息>或<无>, 一定加<> - """ - - update_plural_profile_few_shot: str = """ -示例1: -句子:用户上周去了西溪游泳馆游泳,那个游泳馆人非常多。 -句子:用户计划每周六和朋友张三去朝阳体育馆打羽毛球。 -类别:运动(用户喜欢的运动) -已有信息:运动(用户喜欢的运动):游泳 -思考:从第一句句子可以得出游泳是用户喜欢的运动之一,但与已有信息重复。从第二句句子可以得出羽毛球是用户喜欢的运动之一,是新的信息。 -用户资料: <羽毛球> - -示例2: -句子:用户对咖啡因过敏。 -句子:用户不喜欢吃香菇。 -类别:过敏(用户的已知过敏反应) -已有信息:过敏(用户的已知过敏反应): 咖啡因 -思考:从第一句句子可以得出咖啡因是用户的已知过敏反应之一,但与已有信息重复。从第二句句子只能得出用户不喜欢香菇而非对香菇过敏,无法得出新的用户已知过敏信息。 -用户资料: <无> - -示例3: -句子:用户热衷于动作类类游戏如只狼、艾尔登法环。 -句子:用户在休闲时间经常长时间玩策略类游戏如文明6。 -句子:用户是音乐发烧友,关注各个品牌的耳机的音质和性价比。 -类别:爱好(用户的业余爱好) -已有信息:爱好(用户的业余爱好): -思考:从第一句句子可以得出动作类游戏是用户的爱好之一,是新的信息。从第二句句子可以得出策略类游戏是用户的爱好之一,是新的信息。从第三句句子可以得出音乐是用户的爱好之一,是新的信息。 -用户资料: <动作类游戏, 策略类游戏, 音乐> - -示例4: -句子:关于职场沟通你有什么具体的建议吗?最好结合一个实例。我一直听人说要加强沟通,经常和上司沟通,同步项目的进展,但是我总是感觉还有许多事情要做。 -句子:项目并没有达到一个充分的可以汇报的状态,然后准备汇报材料又很费时间,导致有时候我没有及时和上司同步项目状态。针对这个情况你有什么建议? -类别:职业(用户的职业) -已有信息:职业(用户的职业):工程师 -思考:句子中虽然提及了职场沟通等工作相关内容,但是并不能推断出用户的职位是什么,只能推知与宽泛的项目实施与管理相关。 -用户资料: <无> - """ - - update_plural_profile_user_query: str = """ -{user_query} -类别:{update_profile} -已有信息:{update_profile_value} - """ - - update_unique_profile_system: str = """ -从下面的句子中提取出给定类别的用户资料信息,并判断与已有信息是否矛盾。若矛盾则输出更新的信息,若不矛盾则保留已有信息,整合已有信息和新信息并输出。 -请一步步思考,并按如下格式输出: -思考: 思考的依据和过程,150字以内。 -用户资料: <信息>, 一定加<> - """ - - update_unique_profile_few_shot: str = """ -示例1: -句子:因为昨天成都下大雨,用户全身都被淋湿了。 -句子:用户关心明天成都的天气预报。 -类别:地区(用户所在地区) -已有信息:地区(用户所在地区): 杭州 -思考:从第一句句子可以得出用户在成都。第二句句子没有直接透露用户所在地信息,但与第一句句子用户在成都的信息吻合。这与已有信息(用户在杭州)矛盾,输出更新的信息。 -用户资料:<成都> - -示例2: -句子:用户女朋友下个月过生日。 -句子:用户生日在7月15日。 -类别:生日(用户的生日)。 -已有信息:生日(用户的生日):1987年7月15日。 -思考:第一句句子中提及生日,但并不是用户的生日,无法得出用户生日信息。从第二句句子可以得出用户生日在7月15日,与已有信息不矛盾,整合可以得出用户生日是1987年7月15日。 -用户资料: <1987年7月15日> - -示例3: -句子:用户在招商银行工作。 -句子:用户刚刚毕业,第一份工作是银行前台。 -句子:用户的理想工作是职业游戏选手。 -类别:职业(用户的职业) -已有信息:职业(用户的职业): -思考:整合第一和第二句句子的信息可以得出用户的现在的职业是招商银行前台。第三句句子说明了用户的理想工作但并不是现在的职业。 -用户资料:<招商银行前台> - -示例4: -句子:用户大学期间接触过优化算法的研究。 -类别:学习专业 (用户大学学习的专业) -已有信息:学习专业 (用户大学学习的专业):与人工智能相关 -思考:从句子可以得出用户大学学习的专业与优化算法相关,这与已有信息(用户大学学习的专业与人工智能相关)不矛盾,整合可以得出用户大学学习的专业与人工智能和优化算法相关。 -用户资料:<与人工智能和优化算法相关> - -示例5: -句子:今天和同学去打球了。 -句子:明天和女朋友一起去杭州旅游。 -类别:学习专业 (用户大学学习的专业) -已有信息:学习专业 (用户大学学习的专业): -思考:两个句子和学习专业都没有关联,没有新提取的信息。 -用户资料:<无> - """ - - update_unique_profile_user_query: str = """ -{user_query} -类别:{update_profile} -已有信息:{update_profile_value} - """ - - update_insight_system: str = """ -从下面的句子中提取出给定类别的用户资料信息,并判断与已有信息是否矛盾,若矛盾以新信息为准。整合已有信息和新信息并输出。 -请一步步思考,并按如下格式输出: -思考: 思考的依据和过程,150字以内。 -用户资料: <信息>, 一定加<> - """ - - update_insight_few_shot: str = """ -示例1: -句子:因为昨天成都下大雨,用户全身都被淋湿了。 -句子:用户关心明天成都的天气预报。 -类别:用户所在地区 -已有信息:用户所在地区: 杭州 -思考:从第一句句子可以得出用户在成都。第二句句子没有直接透露用户所在地信息,但与第一句句子用户在成都的信息吻合。这与已有信息(用户在杭州)矛盾,输出更新的信息。 -用户资料:<成都> - -示例2: -句子:用户最近养好了肠胃。 -句子:用户关注中医养生。 -类别:用户健康状况 -已有信息:用户健康状况: 肠胃不好,高血压 -思考:从第一句句子可以得出用户最近养好了肠胃,与已有信息矛盾,以新信息为准。第二句句子与用户健康状况无关。整合已有信息和新信息得到用户健康状况是肠胃健康,高血压。 -用户资料:<肠胃健康,高血压> - -示例3: -句子:用户刚刚毕业,第一份工作是银行前台。 -句子:用户的理想工作是职业游戏选手。 -类别:用户职业 -已有信息:用户职业:在招商银行工作 -思考:整合已有信息和第一句句子的信息可以得出用户的现在的职业是招商银行前台。第二句句子说明了用户的理想工作但并不是现在的职业。 -用户资料:<招商银行前台> - -示例4: -句子:用户大学期间接触过优化算法的研究。 -类别:用户学习专业 -已有信息:用户学习专业:与人工智能相关 -思考:从句子可以得出用户大学学习的专业与优化算法相关,这与已有信息(用户学习专业与人工智能相关)不矛盾,整合可以得出用户大学学习的专业与人工智能和优化算法相关。 -用户资料:<与人工智能和优化算法相关> - -示例5: -句子:用户单身。 -句子:用户受到一名18岁男生的追求,但不想接受又不想伤害他。 -句子:用户喜欢成熟且情绪稳定的男生。 -类别:用户情感状况 -已有信息:用户情感状况:有男朋友 -思考:从第一句句子可以得出用户现在单身,与已有信息矛盾,以新信息为准。从第二句句子得出用户受到一名18岁男生的追求但并不喜欢他。第三句话表达了用户理想的伴侣类型但与用户 -情感状况无关。整合得出用户情感状况为单身,受到一名18岁男生的追求但并不喜欢他。 -用户资料:<单身,受到一名18岁男生的追求但并不喜欢他。> - """ - - update_insight_user_query: str = """ -{user_query} -类别:{insight_key} -已有信息:{insight_key_value} - """ diff --git a/memory_scope/handler/__init__.py b/memory_scope/prompts/info_filter_prompt.py similarity index 100% rename from memory_scope/handler/__init__.py rename to memory_scope/prompts/info_filter_prompt.py diff --git a/memory_scope/prompts/memory_chat_prompt.py b/memory_scope/prompts/memory_chat_prompt.py new file mode 100644 index 00000000..7e44f823 --- /dev/null +++ b/memory_scope/prompts/memory_chat_prompt.py @@ -0,0 +1,15 @@ +from memory_scope.enumeration.language_enum import LanguageEnum + +SYSTEM_PROMPT = { + LanguageEnum.CN: """ +""", + LanguageEnum.EN: """ +""" +} + +MEMORY_PROMPT = { + LanguageEnum.CN: """ +""", + LanguageEnum.EN: """ +""" +} diff --git a/memory_scope/prompts/prompt_cn.py b/memory_scope/prompts/prompt_cn.py deleted file mode 100644 index f64e5cd8..00000000 --- a/memory_scope/prompts/prompt_cn.py +++ /dev/null @@ -1,7 +0,0 @@ -SYSTEM_PROMPT = """ - -""" - -MEMORY_PROMPT = """ - -""" \ No newline at end of file diff --git a/memory_scope/monitor/__init__.py b/memory_scope/storage/__init__.py similarity index 100% rename from memory_scope/monitor/__init__.py rename to memory_scope/storage/__init__.py diff --git a/memory_scope/monitor/base_monitor.py b/memory_scope/storage/base_monitor.py similarity index 93% rename from memory_scope/monitor/base_monitor.py rename to memory_scope/storage/base_monitor.py index fd30f437..1d84621e 100644 --- a/memory_scope/monitor/base_monitor.py +++ b/memory_scope/storage/base_monitor.py @@ -14,7 +14,7 @@ class BaseMonitor(metaclass=ABCMeta): @abstractmethod def add_token(self): - """ TODO @xianzhe + """ :return: """ diff --git a/memory_scope/db/base_db_client.py b/memory_scope/storage/base_vector_store.py similarity index 96% rename from memory_scope/db/base_db_client.py rename to memory_scope/storage/base_vector_store.py index d8f53713..f5954053 100644 --- a/memory_scope/db/base_db_client.py +++ b/memory_scope/storage/base_vector_store.py @@ -4,7 +4,7 @@ from typing import Dict, List from memory_scope.models.base_model import BaseModel -class BaseDBClient(metaclass=ABCMeta): +class BaseVectorStore(metaclass=ABCMeta): def __init__(self, index_name: str, embedding_model: BaseModel, content_key: str = "text", **kwargs): self.index_name: str = index_name diff --git a/memory_scope/utils/logger.py b/memory_scope/utils/logger.py index 671c521b..c71d153d 100644 --- a/memory_scope/utils/logger.py +++ b/memory_scope/utils/logger.py @@ -2,7 +2,6 @@ import logging from logging.handlers import RotatingFileHandler from pathlib import Path -# remove %(thread)s .%(funcName)s LOG_FORMAT = "%(asctime)s %(levelname)s %(trace_id)s %(module)s:%(lineno)d] %(message)s" DATE_FORMAT = "%Y-%m-%d %H:%M:%S" diff --git a/memory_scope/handler/pipeline_handler.py b/memory_scope/utils/pipeline.py similarity index 74% rename from memory_scope/handler/pipeline_handler.py rename to memory_scope/utils/pipeline.py index e6161d50..a4badd61 100644 --- a/memory_scope/handler/pipeline_handler.py +++ b/memory_scope/utils/pipeline.py @@ -5,16 +5,18 @@ from concurrent.futures import as_completed from itertools import zip_longest from typing import Dict, Any, List +from memory_scope.chat.global_context import GLOBAL_CONTEXT from memory_scope.constants.common_constants import MESSAGES, USER_NAME +from memory_scope.definition.message import Message from memory_scope.enumeration.memory_method_enum import MemoryMethodEnum -from memory_scope.handler.global_context import GLOBAL_CONTEXT -from memory_scope.node.message import Message from memory_scope.utils.logger import Logger from memory_scope.utils.timer import Timer +from memory_scope.worker.base_worker import BaseWorker -class PipelineHandler(object): +class Pipeline(object): def __init__(self, + chat_name: str, user_name: str, memory_method_type: MemoryMethodEnum, pipeline_str: str, @@ -22,6 +24,7 @@ class PipelineHandler(object): loop_interval_time: int = 300, loop_minimum_count: int = 20): + self.chat_name: str = chat_name self.user_name: str = user_name self.memory_method_type: MemoryMethodEnum = memory_method_type self.pipeline_str: str = pipeline_str @@ -29,27 +32,31 @@ class PipelineHandler(object): self.loop_interval_time: int = loop_interval_time self.loop_minimum_count: int = loop_minimum_count - # 日志 - self.logger: Logger = Logger.get_logger() - # pipeline上下文和锁 self.context: Dict[str, Any] = {} self.context_lock = threading.Lock() # pipeline run config self.loop_switch: bool = False - - # 解析和打印 pipeline self.pipeline_list: list[list] = [] - self._parse_pipeline() - self._print_pipeline() + self.worker_set: set[str] = set() + self.worker_dict: Dict[str, BaseWorker] = {} + self.injected: bool = False # message list self.history_message_list: List[Message] = [] self.current_message_list: List[Message] = [] self.message_lock = threading.Lock() + # 日志 + self.logger: Logger = Logger.get_logger() + + self._parse_pipeline() + def _parse_pipeline(self): + if not self.pipeline_str: + return + # re-match e.g., [a|b],c,[d,e,f|g,h],j pattern = r'(\[[^\]]*\]|[^,]+)' pipeline_split = re.findall(pattern, self.pipeline_str) @@ -67,17 +74,31 @@ class PipelineHandler(object): continue # e.g., ["d","e","f"] - self.pipeline_list.append([x.split(",") for x in line_split]) + line_split_split = [] + for sub_line_split in line_split: + sub_split = [x.strip() for x in sub_line_split.split(",")] + line_split_split.append(sub_split) + # add to workers + self.worker_set.update(sub_split) + self.pipeline_list.append(line_split_split) - def _print_pipeline(self): - self.logger.info(f"----- {self.user_name} {self.memory_method_type.value} Pipeline Begin -----") + def _visit_and_inject_workers(self): + if self.injected: + return + + self.worker_dict = GLOBAL_CONTEXT.worker_dict[self.chat_name] + + self.logger.info(f"----- {self.chat_name} {self.memory_method_type.value} Pipeline Begin -----") i: int = 0 for pipeline_part in self.pipeline_list: if len(pipeline_part) == 1: for w in pipeline_part[0]: self.logger.info(f"stage{i}: {w}") i += 1 - GLOBAL_CONTEXT.worker_dict[w].context = self.context + if w not in self.worker_dict: + raise RuntimeError(f"worker={w} is not inited.") + # 注入context + self.worker_dict[w].set_context_dict(self.context) else: for w_zip in zip_longest(*pipeline_part, fillvalue="-"): self.logger.info(f"stage{i}: {' | '.join(w_zip)}") @@ -85,21 +106,26 @@ class PipelineHandler(object): for w in w_zip: if w == "-": continue - GLOBAL_CONTEXT.worker_dict[w].is_multi_thread = True - GLOBAL_CONTEXT.worker_dict[w].context_lock = self.context_lock - GLOBAL_CONTEXT.worker_dict[w].context = self.context - self.logger.info(f"----- {self.user_name} {self.memory_method_type.value} Pipeline End -----") + if w not in self.worker_dict: + raise RuntimeError(f"worker={w} is not inited.") - @staticmethod - def _worker_run(worker_list: list[str]) -> bool: + # 注入context & lock + self.worker_dict[w].set_context_dict(self.context, self.context_lock) + + self.logger.info(f"----- {self.chat_name} {self.memory_method_type.value} Pipeline End -----") + self.injected = True + + def _worker_run(self, worker_list: list[str]) -> bool: for worker_name in worker_list: - worker = GLOBAL_CONTEXT.worker_dict[worker_name] + worker = self.worker_dict[worker_name] worker.run() if not worker.continue_run: return False return True - def _run(self, result_key: str = None): + def _run(self): + self._visit_and_inject_workers() + with Timer(f"pipeline_{self.user_name}_{self.memory_method_type.value}"): self.context[MESSAGES] = self.history_message_list + self.current_message_list self.context[USER_NAME] = self.user_name @@ -120,11 +146,6 @@ class PipelineHandler(object): break if not flag: break - if result_key: - return self.context.get(result_key) - self.context.clear() - - return None def _thread_loop(self): while self.loop_switch: diff --git a/memory_scope/parsers/response_text_parser.py b/memory_scope/utils/response_text_parser.py similarity index 95% rename from memory_scope/parsers/response_text_parser.py rename to memory_scope/utils/response_text_parser.py index 48dbbd9c..61ff538e 100644 --- a/memory_scope/parsers/response_text_parser.py +++ b/memory_scope/utils/response_text_parser.py @@ -1,6 +1,6 @@ import re -from utils.logger import Logger +from memory_scope.utils.logger import Logger class ResponseTextParser(object): diff --git a/memory_scope/utils/timer.py b/memory_scope/utils/timer.py index 9e1e3e80..e3ab0d4d 100644 --- a/memory_scope/utils/timer.py +++ b/memory_scope/utils/timer.py @@ -1,8 +1,4 @@ -""" -file: timer.py -author: yuli -date: 20221106 -""" + import time diff --git a/memory_scope/utils/tool_functions.py b/memory_scope/utils/tool_functions.py index 91d8b6a9..653e58e1 100644 --- a/memory_scope/utils/tool_functions.py +++ b/memory_scope/utils/tool_functions.py @@ -1,10 +1,5 @@ -import re -from datetime import datetime from importlib import import_module -from typing import Dict, List - -from constants.common_constants import WEEKDAYS - +import re from memory_scope.enumeration.message_role_enum import MessageRoleEnum @@ -13,152 +8,7 @@ def under_line_to_hump(underline_str): return sub[0:1].upper() + sub[1:] -def parse_response_text_v1(response_text: str) -> dict: - """ - parse text like: - <1> - <2> ddd - <4> dddd<555> - - result = {1: "AAA", 2: "BBB", 4: "CCC"} - """ - result_dict: Dict[int, str] = {} - - # 确保第一个数字,后面是string - matches = re.findall(r'<(\d+)>\s*<([^>]+)>', response_text.strip()) - - # matches 为空返回 - for key, value in matches: - result_dict[int(key)] = value - - return result_dict - - -def parse_response_text_v2(response_text: str) -> Dict[int, List[str]]: - """ - parse text like: - XXX - <1> <222> - <2> - <4,5> - - result = {1: ["AAA", "222"], 2: "BBB", 4: "CCC"} - """ - result_dict: Dict[int, List[str]] = {} - for line in response_text.strip().split("\n"): - if "> <" not in line: - continue - ll = [x.removeprefix("<").removesuffix(">") for x in line.strip().split("> <")] - idx: str = ll[0] - values: List[str] = ll[1:] - if idx.isdigit(): - idx_int = int(idx) - else: - idx_split = idx.split(",") - if len(idx_split) == 0: - continue - idx = idx_split[0] - if idx.isdigit(): - idx_int = int(idx) - else: - continue - if values: - result_dict[idx_int] = values - - return result_dict - - -def parse_response_text_v3(response_text: str) -> List[List[str]]: - """ - parse text like: - XXX - <1> - <2c> - <41> - - result = [["1", "AAA"], ["2c", "BBB"], ["41", "CCC", "BBB"]] - """ - result_list: List[List[str]] = [] - for line in response_text.strip().split("\n"): - if "> <" not in line: - continue - ll = [x.removeprefix("<").removesuffix(">") for x in line.strip().split("> <")] - result_list.append(ll) - return result_list - - -def get_datetime_info_dict(parse_dt: datetime): - return { - "year": parse_dt.year, - "month": parse_dt.month, - "day": parse_dt.day, - "hour": parse_dt.hour, - "minute": parse_dt.minute, - "second": parse_dt.second, - "week": parse_dt.isocalendar().week, - "weekday": WEEKDAYS[parse_dt.isocalendar().weekday - 1], - } - - -def extract_date_parts(input_string: str): - # Extending our pattern to handle "每" (every) as a possible value. - patterns = { - 'year': r'(\d+|每)年', - 'month': r'(\d+|每)月', - 'day': r'(\d+|每)日', - 'weekday': r'周([一二三四五六日])?', - 'hour': r'(\d+)点' - } - weekday_dict = {"一": 1, "二": 2, "三": 3, "四": 4, "五": 5, "六": 6, "日": 7} - extracted_data = {} - - # Search for patterns in the input string and populate the dictionary - for key, pattern in patterns.items(): - match = re.search(pattern, input_string) - if match: # If there is a match, include it in the output dictionary - if match.group(1) == "每": - extracted_data[key] = -1 - elif match.group(1) in weekday_dict.keys(): - extracted_data[key] = weekday_dict[match.group(1)] - else: - extracted_data[key] = int(match.group(1)) - return extracted_data - - -def time_to_formatted_str(time: datetime | str | int | float = None, - date_format: str = "%Y%m%d", # e.g. %Y%m%d -> "20240528", add %H:%M:%S - string_format: str = "") -> str: - if isinstance(time, str | int | float): - if isinstance(time, str): - time = float(time) - current_dt = datetime.fromtimestamp(time) - elif isinstance(time, datetime): - current_dt = time - else: - current_dt = datetime.now() - - return_str = "" - if date_format: - return_str = current_dt.strftime(date_format) - elif string_format: - return_str = string_format.format(**get_datetime_info_dict(current_dt)) - - return return_str - - -def init_instance_by_config(config: dict|object, default_module_path: str = None, try_kwargs: dict = {}, accept_types: type = None): - if isinstance(config, accept_types): - return config - - import_module(config.pop("path", default_module_path)) - clazz = getattr(module, config.pop("name")) - try: - return clazz(**config, **try_kwargs) - except: - return clazz(**config) - - -def init_instance_by_config_v2(config: dict, default_clazz_path: str = "", suffix_name: str = "", **kwargs): +def init_instance_by_config(config: dict, default_clazz_path: str = "", suffix_name: str = "", **kwargs): clazz_path = config.pop("clazz") if not clazz_path: raise RuntimeError("empty clazz_path!") diff --git a/memory_scope/utils/version.py b/memory_scope/utils/version.py deleted file mode 100644 index 76bcdefd..00000000 --- a/memory_scope/utils/version.py +++ /dev/null @@ -1,4 +0,0 @@ -# -*- coding: utf-8 -*- -""" Version of MemoryScope.""" - -__version__ = "0.1.0-alpha.1" diff --git a/memory_scope/worker/base_worker.py b/memory_scope/worker/base_worker.py index 42feb437..fd2972b7 100644 --- a/memory_scope/worker/base_worker.py +++ b/memory_scope/worker/base_worker.py @@ -21,7 +21,7 @@ class BaseWorker(object): self.is_multi_thread: bool = False # pipeline 上下文 - self.context: Dict[str, Any] | None = None + self.context_dict: Dict[str, Any] | None = None self.context_lock = None # 日志 @@ -46,16 +46,22 @@ class BaseWorker(object): self.logger.info(f"----- End {self.name_simple} cost={t.cost_str}-----") + def set_context_dict(self, context_dict: dict, context_lock=None): + self.context_dict = context_dict + if context_lock is not None: + self.context_lock = context_lock + self.is_multi_thread = True + def get_context(self, key: str, default=None): - return self.context.get(key, default) + return self.context_dict.get(key, default) def set_context(self, key: str, value: Any): if self.is_multi_thread: # add lock to multi thread with self.context_lock: - self.context[key] = value + self.context_dict[key] = value else: - self.context[key] = value + self.context_dict[key] = value @property def name_simple(self) -> str: diff --git a/memory_scope/worker/memory_base_worker.py b/memory_scope/worker/memory_base_worker.py index b17f4e7d..d964e3b0 100644 --- a/memory_scope/worker/memory_base_worker.py +++ b/memory_scope/worker/memory_base_worker.py @@ -1,9 +1,11 @@ from typing import List +from memory_scope.chat.global_context import GLOBAL_CONTEXT from memory_scope.constants.common_constants import MESSAGES, USER_NAME -from memory_scope.handler.global_context import GLOBAL_CONTEXT +from memory_scope.definition.message import Message from memory_scope.models.base_model import BaseModel -from memory_scope.node.message import Message +from memory_scope.storage.base_monitor import BaseMonitor +from memory_scope.storage.base_vector_store import BaseVectorStore from memory_scope.worker.base_worker import BaseWorker @@ -22,32 +24,47 @@ class MemoryBaseWorker(BaseWorker): self._generation_model: BaseModel | None = None self._rank_model: BaseModel | None = None + self._vector_store: BaseVectorStore | None = None + self._monitor: BaseMonitor | None = None + @property def messages(self) -> List[Message]: - return self.context[MESSAGES] + return self.get_context(MESSAGES) @messages.setter def messages(self, value): - self.context[MESSAGES] = value + self.set_context(MESSAGES, value) + + @property + def user_name(self): + return self.get_context(USER_NAME) @property def embedding_model(self): if self._embedding_model is None: - GLOBAL_CONTEXT.model_dict.get(self.embedding_model_name) + self._embedding_model = GLOBAL_CONTEXT.model_dict.get(self.embedding_model_name) return self._embedding_model @property def generation_model(self): if self._generation_model is None: - GLOBAL_CONTEXT.model_dict.get(self.generation_model_name) + self._generation_model = GLOBAL_CONTEXT.model_dict.get(self.generation_model_name) return self._generation_model @property def rank_model(self): if self._rank_model is None: - GLOBAL_CONTEXT.model_dict.get(self.rank_model_name) + self._rank_model = GLOBAL_CONTEXT.model_dict.get(self.rank_model_name) return self._rank_model @property - def user_name(self): - return self.context[USER_NAME] + def vector_store(self): + if self._vector_store is None: + self._vector_store = GLOBAL_CONTEXT.vector_store + return self._vector_store + + @property + def monitor(self): + if self._monitor is None: + self._monitor = GLOBAL_CONTEXT.monitor + return self._monitor diff --git a/memory_scope/worker/summary_short/__init__.py b/memory_scope/worker/summary_short/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/memory_scope/node/__init__.py b/old/__init__.py similarity index 100% rename from memory_scope/node/__init__.py rename to old/__init__.py diff --git a/memory_scope/models/dash_client.py b/old/dash_client.py similarity index 100% rename from memory_scope/models/dash_client.py rename to old/dash_client.py diff --git a/memory_scope/models/dash_embedding_client.py b/old/dash_embedding_client.py similarity index 100% rename from memory_scope/models/dash_embedding_client.py rename to old/dash_embedding_client.py diff --git a/memory_scope/models/dash_generate_client.py b/old/dash_generate_client.py similarity index 100% rename from memory_scope/models/dash_generate_client.py rename to old/dash_generate_client.py diff --git a/memory_scope/models/dash_rerank_client.py b/old/dash_rerank_client.py similarity index 100% rename from memory_scope/models/dash_rerank_client.py rename to old/dash_rerank_client.py diff --git a/memory_scope/db/elastic_search_client.py b/old/elastic_search_client.py similarity index 100% rename from memory_scope/db/elastic_search_client.py rename to old/elastic_search_client.py diff --git a/memory_scope/parsers/__init__.py b/old/es/__init__.py similarity index 100% rename from memory_scope/parsers/__init__.py rename to old/es/__init__.py diff --git a/memory_scope/worker/es/es_insight_worker.py b/old/es/es_insight_worker.py similarity index 100% rename from memory_scope/worker/es/es_insight_worker.py rename to old/es/es_insight_worker.py diff --git a/memory_scope/worker/es/es_keyword_worker.py b/old/es/es_keyword_worker.py similarity index 100% rename from memory_scope/worker/es/es_keyword_worker.py rename to old/es/es_keyword_worker.py diff --git a/memory_scope/worker/es/es_new_obs_worker.py b/old/es/es_new_obs_worker.py similarity index 100% rename from memory_scope/worker/es/es_new_obs_worker.py rename to old/es/es_new_obs_worker.py diff --git a/memory_scope/worker/es/es_not_reflected_worker.py b/old/es/es_not_reflected_worker.py similarity index 100% rename from memory_scope/worker/es/es_not_reflected_worker.py rename to old/es/es_not_reflected_worker.py diff --git a/memory_scope/worker/es/es_retrieve_all_worker.py b/old/es/es_retrieve_all_worker.py similarity index 100% rename from memory_scope/worker/es/es_retrieve_all_worker.py rename to old/es/es_retrieve_all_worker.py diff --git a/memory_scope/worker/es/es_similar_worker.py b/old/es/es_similar_worker.py similarity index 100% rename from memory_scope/worker/es/es_similar_worker.py rename to old/es/es_similar_worker.py diff --git a/memory_scope/worker/es/es_today_obs_worker.py b/old/es/es_today_obs_worker.py similarity index 100% rename from memory_scope/worker/es/es_today_obs_worker.py rename to old/es/es_today_obs_worker.py diff --git a/memory_scope/worker/es/load_profile_worker.py b/old/es/load_profile_worker.py similarity index 100% rename from memory_scope/worker/es/load_profile_worker.py rename to old/es/load_profile_worker.py diff --git a/memory_scope/node/memory_node.py b/old/memory_node.py similarity index 100% rename from memory_scope/node/memory_node.py rename to old/memory_node.py diff --git a/memory_scope/node/memory_wrap_node.py b/old/memory_wrap_node.py similarity index 100% rename from memory_scope/node/memory_wrap_node.py rename to old/memory_wrap_node.py diff --git a/memory_scope/worker/es/__init__.py b/old/retrieve/__init__.py similarity index 100% rename from memory_scope/worker/es/__init__.py rename to old/retrieve/__init__.py diff --git a/memory_scope/worker/retrieve/extract_time_worker.py b/old/retrieve/extract_time_worker.py similarity index 100% rename from memory_scope/worker/retrieve/extract_time_worker.py rename to old/retrieve/extract_time_worker.py diff --git a/memory_scope/worker/retrieve/fuse_rerank_worker.py b/old/retrieve/fuse_rerank_worker.py similarity index 100% rename from memory_scope/worker/retrieve/fuse_rerank_worker.py rename to old/retrieve/fuse_rerank_worker.py diff --git a/memory_scope/worker/retrieve/memory_store_worker.py b/old/retrieve/memory_store_worker.py similarity index 100% rename from memory_scope/worker/retrieve/memory_store_worker.py rename to old/retrieve/memory_store_worker.py diff --git a/memory_scope/worker/retrieve/parse_params_worker.py b/old/retrieve/parse_params_worker.py similarity index 100% rename from memory_scope/worker/retrieve/parse_params_worker.py rename to old/retrieve/parse_params_worker.py diff --git a/memory_scope/worker/retrieve/semantic_rank_worker.py b/old/retrieve/semantic_rank_worker.py similarity index 100% rename from memory_scope/worker/retrieve/semantic_rank_worker.py rename to old/retrieve/semantic_rank_worker.py diff --git a/memory_scope/worker/retrieve/__init__.py b/old/summary_long/__init__.py similarity index 100% rename from memory_scope/worker/retrieve/__init__.py rename to old/summary_long/__init__.py diff --git a/memory_scope/worker/summary_long/get_insight_worker.py b/old/summary_long/get_insight_worker.py similarity index 100% rename from memory_scope/worker/summary_long/get_insight_worker.py rename to old/summary_long/get_insight_worker.py diff --git a/memory_scope/worker/summary_long/get_reflection_worker.py b/old/summary_long/get_reflection_worker.py similarity index 100% rename from memory_scope/worker/summary_long/get_reflection_worker.py rename to old/summary_long/get_reflection_worker.py diff --git a/memory_scope/worker/summary_long/long_contra_repeat_worker.py b/old/summary_long/long_contra_repeat_worker.py similarity index 100% rename from memory_scope/worker/summary_long/long_contra_repeat_worker.py rename to old/summary_long/long_contra_repeat_worker.py diff --git a/memory_scope/worker/summary_long/summary_collect_worker.py b/old/summary_long/summary_collect_worker.py similarity index 100% rename from memory_scope/worker/summary_long/summary_collect_worker.py rename to old/summary_long/summary_collect_worker.py diff --git a/memory_scope/worker/summary_long/update_insight_worker.py b/old/summary_long/update_insight_worker.py similarity index 100% rename from memory_scope/worker/summary_long/update_insight_worker.py rename to old/summary_long/update_insight_worker.py diff --git a/memory_scope/worker/summary_long/update_profile_worker.py b/old/summary_long/update_profile_worker.py similarity index 100% rename from memory_scope/worker/summary_long/update_profile_worker.py rename to old/summary_long/update_profile_worker.py diff --git a/memory_scope/worker/summary_long/__init__.py b/old/summary_short/__init__.py similarity index 100% rename from memory_scope/worker/summary_long/__init__.py rename to old/summary_short/__init__.py diff --git a/memory_scope/worker/summary_short/contra_repeat_worker.py b/old/summary_short/contra_repeat_worker.py similarity index 100% rename from memory_scope/worker/summary_short/contra_repeat_worker.py rename to old/summary_short/contra_repeat_worker.py diff --git a/memory_scope/worker/summary_short/get_observation_with_time_worker.py b/old/summary_short/get_observation_with_time_worker.py similarity index 100% rename from memory_scope/worker/summary_short/get_observation_with_time_worker.py rename to old/summary_short/get_observation_with_time_worker.py diff --git a/memory_scope/worker/summary_short/get_observation_worker.py b/old/summary_short/get_observation_worker.py similarity index 100% rename from memory_scope/worker/summary_short/get_observation_worker.py rename to old/summary_short/get_observation_worker.py diff --git a/memory_scope/worker/summary_short/info_filter_worker.py b/old/summary_short/info_filter_worker.py similarity index 100% rename from memory_scope/worker/summary_short/info_filter_worker.py rename to old/summary_short/info_filter_worker.py diff --git a/old/tool_functions.py b/old/tool_functions.py new file mode 100644 index 00000000..91d8b6a9 --- /dev/null +++ b/old/tool_functions.py @@ -0,0 +1,198 @@ +import re +from datetime import datetime +from importlib import import_module +from typing import Dict, List + +from constants.common_constants import WEEKDAYS + +from memory_scope.enumeration.message_role_enum import MessageRoleEnum + + +def under_line_to_hump(underline_str): + sub = re.sub(r'(_\w)', lambda x: x.group(1)[1].upper(), underline_str) + return sub[0:1].upper() + sub[1:] + + +def parse_response_text_v1(response_text: str) -> dict: + """ + parse text like: + <1> + <2> ddd + <4> dddd<555> + + result = {1: "AAA", 2: "BBB", 4: "CCC"} + """ + result_dict: Dict[int, str] = {} + + # 确保第一个数字,后面是string + matches = re.findall(r'<(\d+)>\s*<([^>]+)>', response_text.strip()) + + # matches 为空返回 + for key, value in matches: + result_dict[int(key)] = value + + return result_dict + + +def parse_response_text_v2(response_text: str) -> Dict[int, List[str]]: + """ + parse text like: + XXX + <1> <222> + <2> + <4,5> + + result = {1: ["AAA", "222"], 2: "BBB", 4: "CCC"} + """ + result_dict: Dict[int, List[str]] = {} + for line in response_text.strip().split("\n"): + if "> <" not in line: + continue + ll = [x.removeprefix("<").removesuffix(">") for x in line.strip().split("> <")] + idx: str = ll[0] + values: List[str] = ll[1:] + if idx.isdigit(): + idx_int = int(idx) + else: + idx_split = idx.split(",") + if len(idx_split) == 0: + continue + idx = idx_split[0] + if idx.isdigit(): + idx_int = int(idx) + else: + continue + if values: + result_dict[idx_int] = values + + return result_dict + + +def parse_response_text_v3(response_text: str) -> List[List[str]]: + """ + parse text like: + XXX + <1> + <2c> + <41> + + result = [["1", "AAA"], ["2c", "BBB"], ["41", "CCC", "BBB"]] + """ + result_list: List[List[str]] = [] + for line in response_text.strip().split("\n"): + if "> <" not in line: + continue + ll = [x.removeprefix("<").removesuffix(">") for x in line.strip().split("> <")] + result_list.append(ll) + return result_list + + +def get_datetime_info_dict(parse_dt: datetime): + return { + "year": parse_dt.year, + "month": parse_dt.month, + "day": parse_dt.day, + "hour": parse_dt.hour, + "minute": parse_dt.minute, + "second": parse_dt.second, + "week": parse_dt.isocalendar().week, + "weekday": WEEKDAYS[parse_dt.isocalendar().weekday - 1], + } + + +def extract_date_parts(input_string: str): + # Extending our pattern to handle "每" (every) as a possible value. + patterns = { + 'year': r'(\d+|每)年', + 'month': r'(\d+|每)月', + 'day': r'(\d+|每)日', + 'weekday': r'周([一二三四五六日])?', + 'hour': r'(\d+)点' + } + weekday_dict = {"一": 1, "二": 2, "三": 3, "四": 4, "五": 5, "六": 6, "日": 7} + extracted_data = {} + + # Search for patterns in the input string and populate the dictionary + for key, pattern in patterns.items(): + match = re.search(pattern, input_string) + if match: # If there is a match, include it in the output dictionary + if match.group(1) == "每": + extracted_data[key] = -1 + elif match.group(1) in weekday_dict.keys(): + extracted_data[key] = weekday_dict[match.group(1)] + else: + extracted_data[key] = int(match.group(1)) + return extracted_data + + +def time_to_formatted_str(time: datetime | str | int | float = None, + date_format: str = "%Y%m%d", # e.g. %Y%m%d -> "20240528", add %H:%M:%S + string_format: str = "") -> str: + if isinstance(time, str | int | float): + if isinstance(time, str): + time = float(time) + current_dt = datetime.fromtimestamp(time) + elif isinstance(time, datetime): + current_dt = time + else: + current_dt = datetime.now() + + return_str = "" + if date_format: + return_str = current_dt.strftime(date_format) + elif string_format: + return_str = string_format.format(**get_datetime_info_dict(current_dt)) + + return return_str + + +def init_instance_by_config(config: dict|object, default_module_path: str = None, try_kwargs: dict = {}, accept_types: type = None): + if isinstance(config, accept_types): + return config + + import_module(config.pop("path", default_module_path)) + clazz = getattr(module, config.pop("name")) + try: + return clazz(**config, **try_kwargs) + except: + return clazz(**config) + + +def init_instance_by_config_v2(config: dict, default_clazz_path: str = "", suffix_name: str = "", **kwargs): + clazz_path = config.pop("clazz") + if not clazz_path: + raise RuntimeError("empty clazz_path!") + clazz_name_split = clazz_path.split(".") + clazz_name: str = clazz_name_split[-1] + if suffix_name and not clazz_name.endswith(suffix_name): + clazz_name = f"{clazz_name}_{suffix_name}" + + # 构造path + clazz_paths = [] + if default_clazz_path: + clazz_paths.append(default_clazz_path) + clazz_paths.extend(clazz_name_split[:-1]) + clazz_paths.append(clazz_name) + module = import_module(".".join(clazz_paths)) + + cls_name = under_line_to_hump(clazz_name) + return getattr(module, cls_name)(**config, **kwargs) + + +def complete_config_name(config_name: str, suffix: str = ".json"): + if not config_name.endswith(suffix): + config_name += suffix + return config_name + + +def prompt_to_msg(system_prompt: str, few_shot: str, user_query: str): + return [ + { + "role": MessageRoleEnum.SYSTEM.value, + "content": system_prompt.strip(), + }, + { + "role": MessageRoleEnum.USER.value, + "content": "\n".join([x.strip() for x in [few_shot, system_prompt, user_query]]) + }, + ] diff --git a/memory_scope/node/user_attribute.py b/old/user_attribute.py similarity index 100% rename from memory_scope/node/user_attribute.py rename to old/user_attribute.py diff --git a/memory_scope/utils/user_profile_handler.py b/old/user_profile_handler.py similarity index 100% rename from memory_scope/utils/user_profile_handler.py rename to old/user_profile_handler.py diff --git a/tests/es_test2.py b/tests/es_test2.py deleted file mode 100644 index 25694c0d..00000000 --- a/tests/es_test2.py +++ /dev/null @@ -1,89 +0,0 @@ -import sys - -sys.path.append("./") - -from common.elastic_search_client import ElasticSearchClient -from common.dash_embedding_client import DashEmbeddingClient -from enumeration.memory_type_enum import MemoryTypeEnum - -from config.bailian_memory_config import BailianMemoryConfig - -api_key: str = "sk-fc77951df1d94418bb5a6cd84da76b17" - -if __name__ == "__main__": - es_index_name: str = "memory_index" - es_user_name: str = "elastic" - es_password: str = "Beilianmemory_" - es_search_top_k = 50 - config = BailianMemoryConfig() - emb_client = DashEmbeddingClient( - request_id="123", - dash_scope_uid="123", - authorization=api_key, - workspace="") - - client = ElasticSearchClient(es_user_name=es_user_name, - es_password=es_password, - es_index_name=es_index_name, - embedding_client=emb_client) - - # result = client.exact_search(100, exact_filters={"status": [MemoryNodeStatus.ACTIVE.value, MemoryNodeStatus.EXPIRED.value]}) - # for k in result[:1]: - # print(k) - # # print(type(k)) - # # print(k["_index"]) - # # print(k["_id"]) - # # print(k["_score"]) - # # print(k["_source"]) - - # result = client.similar_search("可以帮忙准备一些菜吗?", size=100, exact_filters={ - # # "code": "jinli_0530_v2_TONGYI_MAIN_CHAT_profile_音乐偏好", - # # "memoryId": "jinli_0530_v2", - # # "status": MemoryNodeStatus.ACTIVE.value, - # # # "metaData.year": "2024", - # "scene": "TONGYI_MAIN_CHAT".lower(), - # # "memoryType": "profile", - # # "content_modified": True, - # }) - - # query = "我今天出差来深圳君悦酒店了,给张三发个邮件说一下事情" - # result = client.similar_search(text=query, - # size=100, - # exact_filters={ - # "memoryId": "jinli_0607_v11", - # "status": "active", - # "scene": "TONGYI_MAIN_CHAT".lower(), - # "memoryType": [MemoryTypeEnum.OBSERVATION.value, - # MemoryTypeEnum.INSIGHT.value, - # MemoryTypeEnum.OBS_CUSTOMIZED.value], - # - # }, - # wildcard_filters={ - # f"metaData.key_word": ["天气", "工作"], - # }) - - result = client.exact_search_v2(size=100, - term_filters={ - "memoryId": "jinli_0607_v11", - "status": "active", - "scene": "TONGYI_MAIN_CHAT".lower(), - "memoryType": [MemoryTypeEnum.OBSERVATION.value, - MemoryTypeEnum.INSIGHT.value, - MemoryTypeEnum.OBS_CUSTOMIZED.value], - - }, - match_filters={ - f"metaData.key_word": ["天气", "工作"], - } - ) - - for k in result: - # print(json.dumps(k, ensure_ascii=False)) - key_word = k["_source"]["metaData"].get("key_word", "") - content = k["_source"]["content"] - print(content, "||||", key_word) - # print(type(k)) - # print(k["_index"]) - # print(k["_id"]) - # print(k["_score"]) - # print(k["_source"]) diff --git a/tests/test_dash_api.py b/tests/test_dash_api.py deleted file mode 100644 index 263044d4..00000000 --- a/tests/test_dash_api.py +++ /dev/null @@ -1,321 +0,0 @@ -import sys - - -sys.path.append(".") -from common.dash_embedding_client import DashEmbeddingClient -from common.dash_generate_client import DashGenerateClient -from common.dash_rerank_client import DashReRankClient -from enumeration.env_type import EnvType - -KEY = "sk-fc77951df1d94418bb5a6cd84da76b17" - - -def test_emb(): - client = DashEmbeddingClient(authorization=KEY, request_id="", dash_scope_uid="", workspace="") - result = client.call(text="今天你吃饭了吗?") - print(len(result)) - print(result[:10]) - - -def test_gen(): - client = DashGenerateClient(authorization=KEY, request_id="", dash_scope_uid="", workspace="") - # result = client.call("今天你吃饭了吗?") - messages = [{'role': 'system', 'content': 'You are a helpful assistant.'}, - {'role': 'user', 'content': '今天你吃饭了吗?'}] - result = client.call(messages=messages) - print(result) - - -def test_rerank(): - query = "什么是文本排序模型" - documents = [ - "文本排序模型广泛用于搜索引擎和推荐系统中,它们根据文本相关性对候选文本进行排序", - "量子计算是计算科学的一个前沿领域", - "预训练语言模型的发展给文本排序模型带来了新的进展" - ] - client = DashReRankClient(authorization=KEY, request_id="", dash_scope_uid="", workspace="") - result = client.call(query=query, documents=documents) - print(result) - - -def test_rerank2(): - query = "工作地址" - documents = [ - "我在阿里工作", - ] - client = DashReRankClient(authorization=KEY, request_id="", dash_scope_uid="", workspace="") - result = client.call(query=query, documents=documents) - print(result) - result2 = client.call(query=documents[0], documents=[query]) - print(result2) - - -def test_gen2(): - client = DashGenerateClient(authorization=KEY, request_id="", dash_scope_uid="", workspace="") - # result = client.call("今天你吃饭了吗?") - messages = [{'role': 'system', 'content': 'You are a helpful assistant.'}, - {'role': 'user', 'content': '今天你吃饭了吗?'}] - # print(client.call(messages=messages)) - print(client.call(messages=messages, model_name="deepseek-7b-chat")) - print(client.call(messages=messages, model_name="qwen1.5-7b-chat")) - print(client.call(messages=messages, model_name="qwen1.5-4b-chat")) - print(client.call(messages=messages, model_name="baichuan2-7b-chat-v1")) - print(client.call(messages=messages, model_name="qwen-max")) - print(client.call(messages=messages, model_name="qwen-plus")) - - -def test_gen3(): - messages = [{'role': 'system', - 'content': '任务:从下面每一行的信息中提取出关于用户的可以挖掘的最多1个最重要的用户画像属性,每个<用户画像属性>最多4个字。\n注意:<用户画像属性>可能是一般的用户偏好,也可能是运动偏好,旅游偏好,饮食偏好等等,也可以是重要事件性质,比如最近重要的事情,也可以是一些高度概括的人生理想,价值观,人生观,性格等等。\n要求:根据<用户画像属性>,是可以从下面的信息中提取对应的信息的。\n一定要按如下格式输出,最后的结果一定要加<>:\n<序号> <用户画像属性>'}, - {'role': 'user', - 'content': '\n任务:从下面每一行的信息中提取出关于用户的可以挖掘的最多1个最重要的用户画像属性,每个<用户画像属性>最多4个字。\n注意:<用户画像属性>可能是一般的用户偏好,也可能是运动偏好,旅游偏好,饮食偏好等等,也可以是重要事件性质,比如最近重要的事情,也可以是一些高度概括的人生理想,价值观,人生观,性格等等。\n要求:根据<用户画像属性>,是可以从下面的信息中提取对应的信息的。\n一定要按如下格式输出,最后的结果一定要加<>:\n<序号> <用户画像属性>\n\n示例1\n信息:\n用户想知道明天上海的天气情况。\n用户可能在上海工作,并关心是否需要带伞上班。\n用户在阿里巴巴徐汇滨江园区附近工作。\n用户计划中午在公司附近用餐。\n用户对咖啡因过敏。\n用户喝了咖啡后晚上会出现失眠的情况。\n用户偏好口味较为清淡、不辣的中餐馆。\n用户刚开始了他们的第一份工作。\n用户的工作岗位是阿里巴巴的算法工程师。\n用户希望得到与该岗位相关的职场建议。\n用户面临的问题是在项目进展初期如何有效与上司沟通。\n用户的目标是及时同步项目状态给上司。\n用户希望了解image generation(图像生成)技术的发展概览和最新进展。\n用户对variational auto-encoder、GAN、Diffusion Model等技术及其相互关系感兴趣。\n问题:\n<1> <饮食偏好>\n<2> <技术方向>\n\n示例2\n信息:\n用户想要了解如何使用torchvision库来可视化深度学习任务的进度信息。\n用户希望了解如何将基于numpy和pytorch的并行计算方案迁移到CUDA支持的GPU上运行。\n用户询问是否需要依赖特定的包来完成这一任务。\n用户希望了解如何在Python中自定义进程和线程以实现并行计算。\n用户在编程中遇到了与并行计算相关的问题。\n用户希望学习如何使用Python(numpy,pytorch)在GPU上实现简单的并行计算。\n用户希望了解并行计算的基本概念,包括threads。\n用户询问有关世界各地著名菜系的信息。\n用户对全球各地的美食非常感兴趣。\n用户在寻求有关推拿按摩手法的教程或相关网站推荐。\n用户希望系统地学习正规的推拿按摩手法。\n用户对按摩感兴趣,并且经常去推拿按摩店。\n用户想了解自己在静息状态下一小时大概会消耗多少大卡热量。\n用户年龄为28岁。\n用户体重为70kg。\n用户是男性。\n用户关心其体重与运动消耗的额外热量及心率之间的关系。\n用户在询问为了实现这一目标,每天需要额外消耗多少大卡热量。\n用户希望每月减重1kg。\n用户希望得到类似战略类手机游戏的推荐。\n用户喜欢玩三国志系列、文明系列、全面战争、骑马与砍杀等战略类游戏。\n用户希望根据他们的喜好获得新的游戏推荐。\n用户列举了他们喜欢的具体游戏类型,包括:三国志系列、文明系列、全面战争、骑马与砍杀等。\n用户喜欢玩战略类游戏。\n问题:\n<1> <游戏偏好>\n<2> <运动计划>\n<3> <技术方向>\n\n示例3\n信息:\n用户寻求推荐一个相关课程或网址以进行学习。\n用户计划去青岛旅游。\n用户正为张三的女儿选购生日礼物。\n用户请求为一位名叫张三的人的女儿撰写一段温馨的祝福语。\n用户的同事名叫张三。\n用户与张三约定讨论阿里云百炼项目。\n用户与同事张三讨论了该项目的PRD(产品需求文档)。\n同事张三计划下周对PRD进行最终确定。\n张三还安排了在再下一周进行POC(Proof of Concept,概念验证)的讨论。\n用户希望获知该项目工程开发工作的负责团队信息,以了解项目执行的组织架构与分工情况。\n问题:\n<1> <张三关系>\n\n信息:\n用户对策略游戏感兴趣,希望寻找新的挑战。\n用户近期感到工作压力大,寻求放松方法。\n用户在上海有几位常聚的朋友。\n用户考虑更换工作,关注上海哪些区的工作机会较多。\n用户热衷于尝试新美食,求推荐美食应用。\n用户喜欢自己烹饪,需要海鲜菜谱推荐。\n用户想了解维持广泛社交关系的方法。\n问题:\n'}] - prompt = """ -任务:从下面每一行的信息中提取出关于用户的可以挖掘的最多1个最重要的用户画像属性,每个<用户画像属性>最多4个字。 -注意:<用户画像属性>可能是一般的用户偏好,也可能是运动偏好,旅游偏好,饮食偏好等等,也可以是重要事件性质,比如最近重要的事情,也可以是一些高度概括的人生理想,价值观,人生观,性格等等。 -要求:根据<用户画像属性>,是可以从下面的信息中提取对应的信息的。 -一定要按如下格式输出,最后的结果一定要加<>: -<序号> <用户画像属性> - -示例1 -信息: -用户想知道明天上海的天气情况。 -用户可能在上海工作,并关心是否需要带伞上班。 -用户在阿里巴巴徐汇滨江园区附近工作。 -用户计划中午在公司附近用餐。 -用户对咖啡因过敏。 -用户喝了咖啡后晚上会出现失眠的情况。 -用户偏好口味较为清淡、不辣的中餐馆。 -用户刚开始了他们的第一份工作。 -用户的工作岗位是阿里巴巴的算法工程师。 -用户希望得到与该岗位相关的职场建议。 -用户面临的问题是在项目进展初期如何有效与上司沟通。 -用户的目标是及时同步项目状态给上司。 -用户希望了解image generation(图像生成)技术的发展概览和最新进展。 -用户对variational auto-encoder、GAN、Diffusion Model等技术及其相互关系感兴趣。 -问题: -<1> <饮食偏好> -<2> <技术方向> -示例2 -信息: -用户想要了解如何使用torchvision库来可视化深度学习任务的进度信息。 -用户希望了解如何将基于numpy和pytorch的并行计算方案迁移到CUDA支持的GPU上运行。 -用户询问是否需要依赖特定的包来完成这一任务。 -用户希望了解如何在Python中自定义进程和线程以实现并行计算。 -用户在编程中遇到了与并行计算相关的问题。 -用户希望学习如何使用Python(numpy,pytorch)在GPU上实现简单的并行计算。 -用户希望了解并行计算的基本概念,包括threads。 -用户询问有关世界各地著名菜系的信息。 -用户对全球各地的美食非常感兴趣。 -用户在寻求有关推拿按摩手法的教程或相关网站推荐。 -用户希望系统地学习正规的推拿按摩手法。 -用户对按摩感兴趣,并且经常去推拿按摩店。 -用户想了解自己在静息状态下一小时大概会消耗多少大卡热量。 -用户年龄为28岁。 -用户体重为70kg。 -用户是男性。 -用户关心其体重与运动消耗的额外热量及心率之间的关系。 -用户在询问为了实现这一目标,每天需要额外消耗多少大卡热量。 -用户希望每月减重1kg。 -用户希望得到类似战略类手机游戏的推荐。 -用户喜欢玩三国志系列、文明系列、全面战争、骑马与砍杀等战略类游戏。 -用户希望根据他们的喜好获得新的游戏推荐。 -用户列举了他们喜欢的具体游戏类型,包括:三国志系列、文明系列、全面战争、骑马与砍杀等。 -用户喜欢玩战略类游戏。 -问题: -<1> <游戏偏好> -<2> <运动计划> -<3> <技术方向> -示例3 -信息: -用户寻求推荐一个相关课程或网址以进行学习。 -用户计划去青岛旅游。 -用户正为张三的女儿选购生日礼物。 -用户请求为一位名叫张三的人的女儿撰写一段温馨的祝福语。 -用户的同事名叫张三。 -用户与张三约定讨论阿里云百炼项目。 -用户与同事张三讨论了该项目的PRD(产品需求文档)。 -同事张三计划下周对PRD进行最终确定。 -张三还安排了在再下一周进行POC(Proof of Concept,概念验证)的讨论。 -用户希望获知该项目工程开发工作的负责团队信息,以了解项目执行的组织架构与分工情况。 -问题: -<1> <张三关系> -信息: -用户对策略游戏感兴趣,希望寻找新的挑战。 -用户近期感到工作压力大,寻求放松方法。 -用户在上海有几位常聚的朋友。 -用户考虑更换工作,关注上海哪些区的工作机会较多。 -用户热衷于尝试新美食,求推荐美食应用。 -用户喜欢自己烹饪,需要海鲜菜谱推荐。 -用户想了解维持广泛社交关系的方法。 -问题: - """ - client = DashGenerateClient(authorization=KEY, request_id="", dash_scope_uid="", workspace="") - result = client.call(prompt=prompt.strip(), model_name="qwen-max", seed=0, top_k=1, - repetition_penalty=10) # seed=10, repetition_penalty=0.001 - # print(client.call(prompt=content, model_name="qwen-plus")) - print(result) - - -def test_rerank3(): - """ -用户喜欢在家做饭,需海鲜菜谱推荐。 score=0.33822810090097916 -2024-05-31 16:49:19 INFO jinli_05 semantic_rerank_worker:67] content=用户喜欢在家做饭,求推荐海鲜菜谱。 score=0.3285956750439506 -2024-05-31 16:49:19 INFO jinli_05 semantic_rerank_worker:67] content=用户喜欢烹饪,特别是寻找海鲜菜谱。 score=0.2792495470520024 -2024-05-31 16:49:19 INFO jinli_05 semantic_rerank_worker:67] content=用户热爱烹饪新鲜海鲜,积极寻找美食应用和菜谱。 score=0.19372969292115966 -2024-05-31 16:49:19 INFO jinli_05 semantic_rerank_worker:67] content=用户喜爱探索新美食与在家烹饪海鲜。 score=0.1566147836382108 -2024-05-31 16:49:19 INFO jinli_05 semantic_rerank_worker:67] content=用户拥有几位要好朋友,常共同外出就餐。 score=0.14541493132600777 -2024-05-31 16:49:19 INFO jinli_05 semantic_rerank_worker:67] content=用户有几位常聚餐的好友。 score=0.11955426943198397 -2024-05-31 16:49:19 INFO jinli_05 semantic_rerank_worker:67] content=用户关注上海生活信息,包括寻找新鲜海鲜地点及询问工作机会多的区域。 score=0.08339651657739067 -2024-05-31 16:49:19 INFO jinli_05 semantic_rerank_worker:67] content=用户饮食偏好 (喜欢吃什么菜): 海鲜) score=0.08032847382954839 - - - """ - query = "用户喜欢吃什么菜" - # query = "运动" - documents = [ - "用户喜欢在家做饭,求推荐海鲜菜谱。", - "用户饮食偏好 (喜欢吃什么菜): 海鲜)。", - "用户好奇打篮球是否能促进身高增长。", - "用户感到在上海的工作压力大,寻求放松方法。", - ] - client = DashReRankClient(authorization=KEY, request_id="", dash_scope_uid="", workspace="") - result = client.call(query=query, documents=documents) - print(result) - # result1 = client.call(query=documents[0], documents=[query]) - # result2 = client.call(query=documents[1], documents=[query]) - # result3 = client.call(query=documents[2], documents=[query]) - # result4 = client.call(query=documents[3], documents=[query]) - # print(result1) - # print(result2) - # print(result3) - # print(result4) - - -def test_gen4(): - messages = [{'role': 'system', - 'content': """ -任务:从下面的信息中提取出关于用户的可以挖掘的最多3个重要的用户属性,每个用户属性最多4个字。 -注意:用户属性可能是一般的用户偏好,也可能是运动偏好,旅游偏好,饮食偏好等等,也可以是重要事件性质,比如最近重要的事情,也可以是一些高度概括的人生理想,价值观,人生观,性格等等。 -要求:根据用户属性,我们可以生成“用户的<用户属性>是什么?”的问题,以此从下面的信息中提取用户属性对应的值。 -每一行输出一个<用户属性>: -<用户属性> - """.strip() - }, - {'role': 'user', - 'content': """ -示例1 -信息: -用户想知道明天上海的天气情况。 -用户可能在上海工作,并关心是否需要带伞上班。 -用户在阿里巴巴徐汇滨江园区附近工作。 -用户计划中午在公司附近用餐。 -用户对咖啡因过敏。 -用户喝了咖啡后晚上会出现失眠的情况。 -用户偏好口味较为清淡、不辣的中餐馆。 -用户刚开始了他们的第一份工作。 -用户的工作岗位是阿里巴巴的算法工程师。 -用户希望得到与该岗位相关的职场建议。 -用户面临的问题是在项目进展初期如何有效与上司沟通。 -用户的目标是及时同步项目状态给上司。 -用户希望了解image generation(图像生成)技术的发展概览和最新进展。 -用户对variational auto-encoder、GAN、Diffusion Model等技术及其相互关系感兴趣。 -问题: -饮食偏好 -技术方向 - -示例2 -信息: -用户想要了解如何使用torchvision库来可视化深度学习任务的进度信息。 -用户希望了解如何将基于numpy和pytorch的并行计算方案迁移到CUDA支持的GPU上运行。 -用户询问是否需要依赖特定的包来完成这一任务。 -用户希望了解如何在Python中自定义进程和线程以实现并行计算。 -用户在编程中遇到了与并行计算相关的问题。 -用户希望学习如何使用Python(numpy,pytorch)在GPU上实现简单的并行计算。 -用户希望了解并行计算的基本概念,包括threads。 -用户询问有关世界各地著名菜系的信息。 -用户对全球各地的美食非常感兴趣。 -用户在寻求有关推拿按摩手法的教程或相关网站推荐。 -用户希望系统地学习正规的推拿按摩手法。 -用户对按摩感兴趣,并且经常去推拿按摩店。 -用户想了解自己在静息状态下一小时大概会消耗多少大卡热量。 -用户年龄为28岁。 -用户体重为70kg。 -用户是男性。 -用户关心其体重与运动消耗的额外热量及心率之间的关系。 -用户在询问为了实现这一目标,每天需要额外消耗多少大卡热量。 -用户希望每月减重1kg。 -用户希望得到类似战略类手机游戏的推荐。 -用户喜欢玩三国志系列、文明系列、全面战争、骑马与砍杀等战略类游戏。 -用户希望根据他们的喜好获得新的游戏推荐。 -用户列举了他们喜欢的具体游戏类型,包括:三国志系列、文明系列、全面战争、骑马与砍杀等。 -用户喜欢玩战略类游戏。 -问题: -游戏偏好 -运动计划 -技术方向 - -示例3 -信息: -用户寻求推荐一个相关课程或网址以进行学习。 -用户计划去青岛旅游。 -用户正为张三的女儿选购生日礼物。 -用户请求为一位名叫张三的人的女儿撰写一段温馨的祝福语。 -用户的同事名叫张三。 -用户与张三约定讨论阿里云百炼项目。 -用户与同事张三讨论了该项目的PRD(产品需求文档)。 -同事张三计划下周对PRD进行最终确定。 -张三还安排了在再下一周进行POC(Proof of Concept,概念验证)的讨论。 -用户希望获知该项目工程开发工作的负责团队信息,以了解项目执行的组织架构与分工情况。 -问题: -朋友关系 - -任务:从下面的信息中提取出关于用户的可以挖掘的最多3个重要的用户属性,每个用户属性最多4个字。 -注意:用户属性可能是一般的用户偏好,也可能是运动偏好,旅游偏好,饮食偏好等等,也可以是重要事件性质,比如最近重要的事情,也可以是一些高度概括的人生理想,价值观,人生观,性格等等。 -要求:根据用户属性,我们可以生成“用户的<用户属性>是什么?”的问题,以此从下面的信息中提取用户属性对应的值。 -每一行输出一个<用户属性>: -<用户属性> - -信息: -用户想知道上海哪里的海鲜最新鲜,表明用户在上海生活或访问,并对食物品质有要求。 -用户寻找策略游戏推荐,显示出对策略类游戏的兴趣和寻求新挑战的愿望。 -用户提到在上海的工作压力大,寻求放松建议,反映了其当前的生活压力状态和对减压方法的需求。 -用户拥有常一起吃饭的好友,强调了其社交活动和对友谊的重视。 -用户考虑更换工作,关注上海哪些区工作机会多,表明职业规划上的变动意向。 -用户喜欢尝试新美食并询问美食应用推荐,再次强调对美食的兴趣和探索欲。 -用户提到了自己烹饪的兴趣,特别是对海鲜菜谱的需求,细化了其个人爱好。 -用户询问维持广泛社交关系的方法,显示其对社交网络维护的关注。 -问题: - """.strip() - }] - client = DashGenerateClient(authorization=KEY, request_id="", dash_scope_uid="", workspace="") - # result = client.call(messages=messages, model_name="qwen-long", seed=0, top_k=1) - result = client.call(messages=messages, model_name="qwen-max", seed=0, top_k=1) - # result = client.call(messages=messages, model_name="qwen-max", seed=0) - - # seed=10, repetition_penalty=0.001 - print(result) - - -def test_gen_time(): - prompt = "任务指令:从语句与语句发生的时间,推断并提取语句内容中指向的时间段。回答尽可能完整的时间段。\n语句:好像是前天有人来找过你。\n时间:2074年12月7日,2074年第49周,周三,16时30分0秒。\n回答:" - # 1656375133437235, 197291 - client = DashGenerateClient(authorization="sk-AdrklI1sWM", request_id="", - dash_scope_uid="", workspace="", env_type=EnvType.DAILY) - # result = client.call(messages=messages, model_name="qwen-long", seed=0, top_k=1) - result = client.call(prompt=prompt, model_name="qwen_1_8_parse_time_service", seed=0, top_k=1) - # result = client.call(messages=messages, model_name="qwen-max", seed=0) - - # seed=10, repetition_penalty=0.001 - print(result) - - -if __name__ == "__main__": - # test_emb() - # test_gen() - # test_rerank() - # test_rerank2() - # test_gen2() - # test_gen3() - # test_gen4() - # test_rerank3() - test_gen_time() diff --git a/tests/test_memory.py b/tests/test_memory.py deleted file mode 100644 index 29a4cf53..00000000 --- a/tests/test_memory.py +++ /dev/null @@ -1,252 +0,0 @@ -import datetime -import os -import time -from typing import List, Dict - -from memory_scope.utils.logger import Logger -from memory_scope.constants.common_constants import NEW_USER_PROFILE, MODIFIED_MEMORIES, RELATED_MEMORIES -from memory_scope.enumeration.memory_method_enum import MemoryMethodEnum -from memory_scope.node.memory_node import MemoryNode -from memory_scope.node.user_attribute import UserAttribute -from memory_scope.pipeline.memory import MemoryServiceRequestModel -from memory_scope.pipeline.memory_service import MemoryService - -""" -任务:随机生成一个用户的画像,随机种子0,并根据用户的画像虚拟一段用户和AI的对话。 -步骤: -1. 帮忙生成一个用户的画像:包括用户的姓名,性别,工作地点,朋友关系,饮食偏好,游戏偏好,运动偏好等等属性。 -2. 根据用户的画像虚拟一段用户和AI(比如通义千问)的对话,可以是用户的生活轨迹,生活事件,工作事件,也可以是用户的一些看法等等。要求对话中需要包含用户画像信息,并可以通过对话反推出部分用户画像。 -用户画像格式,最少10个用户画像: -<用户画像,例如性别>: <属性值,例如男性> -用户对话格式,最少20轮对话: -<轮次> <用户>:<用户问题> -<轮次> :<回答> - """ - -os.environ["APP_ENV"] = "daily" -os.environ["memory_retrieve_pipeline"] = """ -parse_params,es.load_profile,[retrieve.extract_time|es.es_similar|es.es_keyword],retrieve.semantic_rank,retrieve.fuse_rerank -""".strip() -os.environ["memory_summary_short_pipeline"] = """ -parse_params,summary_short.info_filter,[es.es_today_obs|summary_short.get_observation|summary_short.get_observation_with_time],summary_short.contra_repeat,memory_store -""".strip() -os.environ["memory_summary_long_pipeline"] = """ -parse_params,[es.load_profile|es.es_new_obs|es.es_insight],[summary_long.update_insight|summary_long.get_reflection,summary_long.get_insight|summary_long.update_profile],summary_long.summary_collect,memory_store -""".strip() - -os.environ["memory_summary_long_reflect_obs_cnt_threshold"] = "5" -os.environ["memory_summary_long_max_workers"] = "5" - -# attrs = { -# "性别": ["男性或者女性", 1], -# "工作地点": ["工作所在城市", 1], -# "朋友关系": ["和谁是什么朋友", 0], -# "饮食偏好": ["喜欢吃什么菜", 0], -# "游戏偏好": ["喜欢玩什么游戏", 0], -# "运动偏好": ["喜欢什么运动", 0], -# "音乐偏好": ["喜欢听什么音乐", 0], -# "电影类型偏好": ["喜欢看什么类型的电影", 0], -# "阅读偏好": ["喜欢看什么书", 0], -# "购物习惯": ["喜欢买什么东西", 0], -# } -# -# os.environ["memory_summary_extra_user_attrs_TONGYI_MAIN_CHAT"] = ",".join( -# [f"{k}:{v[0]}:{v[1]}" for k, v in attrs.items()]) - -memory_id: str = "jinli_0607_v26" -workspace_id: str = "" -api_key: str = "sk-AdrklI1sWM" -scene: str = "TONGYI_MAIN_CHAT" -algo_version: str = "" -output_max_count: int = 3 -""" -'工作地点:工作所在城市:1', -'所在地:当前所在地点:1', -'饮食偏好:喜欢吃什么菜:0', -'游戏偏好:喜欢玩什么游戏:0', -'运动偏好:喜欢什么运动:0', -""" -user_profile: List[UserAttribute] = [ - UserAttribute(memory_key="运动偏好", value=["足球"], description="喜欢什么运动", is_unique=0), - UserAttribute(memory_key="工作地点", description="工作所在城市", is_unique=1), - UserAttribute(memory_key="所在地", description="当前所在地点", is_unique=1), - UserAttribute(memory_key="饮食偏好", description="喜欢吃什么菜", is_unique=0), - UserAttribute(memory_key="游戏偏好", description="喜欢玩什么游戏", is_unique=0), - UserAttribute(memory_key="运动偏好", description="喜欢什么运动", is_unique=0), -] -ext_info: Dict[str, str] = {} -trace_id: str = "jinli_0530_req_id" -request_id: str = "jinli_0530_req_id" -account_id: str = "jinli" -app_id: str = "jinli_id" -uid: str = "1656375133437235" - -messages1 = [ - {"role": "user", "content": "你知道北京哪里的海鲜最新鲜吗?", "time_created": "1717037394"}, - {"role": "user", "content": "有没有推荐的策略游戏?最近想找新的挑战。", "time_created": "1717037404"}, - {"role": "user", "content": "听说篮球运动对身体很好,是真的吗?", "time_created": "1717037414"}, - {"role": "user", "content": "最近在北京的工作压力太大,有什么放松的建议吗?", "time_created": "1717037424"}, - {"role": "user", "content": "说到朋友,我确实有几位很要好的朋友,我们经常一起出去吃饭。", - "time_created": "1717037434"}, - {"role": "user", "content": "对了,最近想换工作,你觉得北京的哪个区工作机会更多?", "time_created": "1717037444"}, - {"role": "user", "content": "听你这么说,我感觉挺有信心的,谢了!", "time_created": "1717037454"}, - {"role": "user", "content": "我很喜欢尝试新的美食,有没有推荐的美食应用?", "time_created": "1717037464"}, - {"role": "user", "content": "我有时也喜欢自己在家做饭,你有没有好的海鲜菜谱推荐?", "time_created": "1717037474"}, - {"role": "user", "content": "听说打篮球可以长高,这是真的吗?", "time_created": "1717037484"}, - {"role": "user", "content": "昨天是我的生日!", "time_created": "1717037494"}, - {"role": "user", "content": "昨天和同学一起在我家开了party,庆祝了我的生日!", "time_created": "1717037494"}, - {"role": "user", "content": "我在北京阿里云园区工作", "time_created": "1717037504"}, - {"role": "user", "content": "我是阿里云百炼的工程师", "time_created": "1717037504"}, - {"role": "user", "content": "最后一个问题,你知道怎么才能维持广泛的社交关系吗?", "time_created": "1717037504"}, - -] -dt_n = datetime.datetime(year=2024, month=6, day=1, hour=12) -ts = int(dt_n.timestamp()) -for i, msg in enumerate(messages1): - msg["time_created"] = str(ts + i * 10) - -messages2 = [ - # {"role": "user", "content": "今天我和客户团队的工程师张三讨论了技术方案,聊得很愉快", - # "time_created": "1717037394"}, - # {"role": "user", "content": "帮我记一下,我和他沟通约定3天后到杭州上门提供技术解决方案", - # "time_created": "1717037394"}, - {"role": "user", "content": "帮我记一下,我和客户团队的工程师张三沟通约定3天后到杭州上门提供技术解决方案", - "time_created": "1717037394"}, -] -dt_n = datetime.datetime(year=2024, month=6, day=3, hour=12) -ts = int(dt_n.timestamp()) -for i, msg in enumerate(messages2): - msg["time_created"] = str(ts + i * 10) - -messages3 = [ - {"role": "user", "content": "我今天出差来深圳君悦酒店了,给张三发个邮件说一下事情", "time_created": "1717037394"}, - {"role": "user", "content": "我最近肠胃不好,吃不了辣", "time_created": "1717037394"}, - {"role": "user", "content": "最近肠胃养好了,换一些川菜吧", "time_created": "1717037394"}, -] -dt_n = datetime.datetime(year=2024, month=6, day=6, hour=12) -ts = int(dt_n.timestamp()) -for i, msg in enumerate(messages3): - msg["time_created"] = str(ts + i * 10) - -messages4 = [ - {"role": "user", "content": "附近有什么好吃的", "time_created": "1717037394"}, - {"role": "user", "content": "今天天气怎么样?", "time_created": "1717037394"}, -] -dt_n = datetime.datetime(year=2024, month=6, day=6, hour=13) -ts = int(dt_n.timestamp()) -for i, msg in enumerate(messages3): - msg["time_created"] = str(ts + i * 10) - - -def summary_short(messages): - request: MemoryServiceRequestModel = MemoryServiceRequestModel( - messages=messages, - memory_id=memory_id, - workspace_id=workspace_id, - api_key=api_key, - scene=scene, - algo_version=algo_version, - output_max_count=output_max_count, - user_profile=user_profile, - ext_info=ext_info, - trace_id=trace_id, - tenant_id=trace_id, - request_id=request_id, - account_id=account_id, - app_id=app_id, - uid=uid, - ) - - logger = Logger.get_memory_logger() - logger.set_trace_id(request.trace_id) - memory_service = MemoryServiceBailian(request, method=MemoryMethodEnum.SUMMARY_SHORT) - memory_service.run() - - modified_memories: List[MemoryNode] = memory_service.get_context(MODIFIED_MEMORIES) - return modified_memories - - -def summary_long(): - request: MemoryServiceRequestModel = MemoryServiceRequestModel( - messages=[], - memory_id=memory_id, - workspace_id=workspace_id, - api_key=api_key, - scene=scene, - algo_version=algo_version, - output_max_count=output_max_count, - user_profile=user_profile, - ext_info=ext_info, - trace_id=trace_id, - tenant_id=trace_id, - request_id=request_id, - account_id=account_id, - app_id=app_id, - uid=uid, - ) - logger = Logger.get_memory_logger() - logger.set_trace_id(request.trace_id) - memory_service = MemoryServiceBailian(request, method=MemoryMethodEnum.SUMMARY_LONG) - memory_service.run() - - user_profiles: List[UserAttribute] = memory_service.get_context(NEW_USER_PROFILE) - modified_memories: List[MemoryNode] = memory_service.get_context(MODIFIED_MEMORIES) - # ext_infos = memory_service.get_context(RESPONSE_EXT_INFO) - # logger.info(f"user_profile=\n{json.dumps([x.model_dump() for x in user_profiles], ensure_ascii=False)}") - # logger.info(f"modified_memories=\n{json.dumps([x.model_dump() for x in modified_memories], ensure_ascii=False)}") - # logger.info(f"ext_info=\n{json.dumps(ext_infos, ensure_ascii=False)}") - return user_profiles, modified_memories - - -def retrieve(messages): - request: MemoryServiceRequestModel = MemoryServiceRequestModel( - messages=messages, - memory_id=memory_id, - workspace_id=workspace_id, - api_key=api_key, - scene=scene, - algo_version=algo_version, - output_max_count=output_max_count, - user_profile=user_profile, - ext_info=ext_info, - trace_id=trace_id, - tenant_id=trace_id, - request_id=request_id, - account_id=account_id, - app_id=app_id, - uid=uid, - ) - - logger = Logger.get_memory_logger() - logger.set_trace_id(request.trace_id) - memory_service = MemoryServiceBailian(request, method=MemoryMethodEnum.RETRIEVE) - memory_service.run() - - modified_memories: List[str] = memory_service.get_context(RELATED_MEMORIES) - return modified_memories - - -if __name__ == "__main__": - logger = Logger.get_memory_logger() - - summary1 = summary_short(messages1) - logger.info(f"summary1={summary1}") - - summary2 = summary_short(messages2) - logger.info(f"summary2={summary2}") - - for i, msg in enumerate(messages3): - time.sleep(6) - retrieve_res = retrieve([msg]) - logger.info(f"index={i} retrieve_res={retrieve_res}") - - summary_res = summary_short([msg]) - logger.info(f"index={i} summary_res={summary_res}") - - summary3 = summary_long() - logger.info(f"summary3={summary3}") - - time.sleep(6) - for i, msg in enumerate(messages4): - retrieve_res = retrieve([msg]) - logger.info(f"index={i} retrieve_res={retrieve_res}")