[dev] add g global context

This commit is contained in:
jinli.yl 2024-06-20 15:22:53 +08:00
parent b2a3c47c36
commit ea3bd2ae7e
8 changed files with 1 additions and 314 deletions

View file

@ -2,8 +2,8 @@ import datetime
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.enumeration.message_role_enum import MessageRoleEnum
from memory_scope.handler.global_context import GLOBAL_CONTEXT
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

View file

@ -1,6 +1,3 @@
from enumeration.dash_api_enum import DashApiEnum
from enumeration.env_type import EnvType
APP_ENV = "APP_ENV"
PIPELINE = "pipeline"
@ -82,37 +79,3 @@ MAX_WORKERS = "max_workers"
TIME_MATCHED = "time_matched"
QUERY_KEYWORDS = "query_keywords"
DASH_ENV_URL_DICT = {
EnvType.DAILY: "https://dashscope.aliyuncs.com",
# EnvType.PRE: "https://dashscope.aliyuncs.com",
EnvType.PRE: "http://nlb-a3gi6od2xpdx16ezde.cn-beijing.nlb.aliyuncs.com",
EnvType.PROD: "http://ep-2zei3b9a7e2e447bd259.epsrv-2zexnj17q1p8mtjwe3dx.cn-beijing.privatelink.aliyuncs.com",
}
DASH_API_URL_DICT = {
DashApiEnum.GENERATION: "/api/v1/services/aigc/text-generation/generation",
DashApiEnum.EMBEDDING: "/api/v1/services/embeddings/text-embedding/text-embedding",
DashApiEnum.RERANK: "/api/v1/services/rerank/text-rerank/text-rerank",
}
ES_ENV_URL_DICT = {
EnvType.DAILY: "http://es-cn-lr53pmrna0002pffb.public.elasticsearch.aliyuncs.com:9200",
EnvType.PRE: "http://ep-bp1i04ae830e377a26a4.epsrv-bp15vzbd1o3umr1girls.cn-hangzhou.privatelink.aliyuncs.com:9200",
EnvType.PROD: "http://ep-2zeibdbbe2904414e741.epsrv-2zet33kwqg8bphgmm36f.cn-beijing.privatelink.aliyuncs.com:9200",
}
WEEKDAYS = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
DATATIME_WORD_LIST = ["", "", "", "", "星期", "", "分钟", "小时", "", "上午", "下午", "早上", "早晨",
"晚上", "中午", "", "", "清晨", "傍晚", "凌晨", ""]
TIME_FORMAT_V1 = "{year}{month}{day}{weekday}{hour}"
DATATIME_KEY_MAP = {
"": "year",
"": "month",
"": "day",
"": "week",
"星期几": "weekday",
}

View file

@ -1,90 +0,0 @@
import json
import os
from concurrent.futures import ThreadPoolExecutor
from typing import Dict, Any
from memory_scope.db.base_db_client import BaseDBClient
from memory_scope.models.base_model import BaseModel
from memory_scope.monitor.base_monitor import BaseMonitor
from memory_scope.utils.tool_functions import init_instance_by_config_v2
from memory_scope.worker.base_worker import BaseWorker
class InitHandler(object):
def __init__(self, path: str):
self.path: str = path
self.config_name: str = os.path.basename(path)
self.config_base_dir: str = os.path.dirname(path)
self.config: dict = {}
self.global_configs: Dict[str, Any] = {}
self.worker_dict: Dict[str, BaseWorker] = {}
self.model_dict: Dict[str, BaseModel] = {}
self.db_client: BaseDBClient | None = None
self.monitor: BaseMonitor | None = None
self.thread_pool: ThreadPoolExecutor | None = None
self.worker_base_dir: str = ""
self.model_base_dir: str = ""
self.db_base_dir: str = ""
self.minitor_base_dir: str = ""
self.retrieve_pipeline: str = ""
self.summary_short_pipeline: str = ""
self.summary_long_pipeline: str = ""
def init(self):
with open(self.path) as f:
self.config = json.load(f)
self.retrieve_pipeline = self.config["pipelines"]["retrieve"]
self.summary_short_pipeline = self.config["pipelines"]["summary_short"]
self.summary_long_pipeline = self.config["pipelines"]["summary_long"]
self.global_configs = self.config["global"]
self.set_global_config()
self.init_workers(self.config["workers"])
self.init_db(self.config["db"])
self.init_chat_model(self.config["chat_model"])
self.init_monitor(self.config["monitor"])
def set_global_config(self):
"""set global_configs & set apikey into env
"""
self.worker_base_dir = self.global_configs["worker_base_dir"]
self.model_base_dir = self.global_configs["model_base_dir"]
self.db_base_dir = self.global_configs["db_base_dir"]
self.minitor_base_dir = self.global_configs["minitor_base_dir"]
self.thread_pool = ThreadPoolExecutor(max_workers=int(self.global_configs["max_workers"]))
# TODO @ sen
def init_workers(self, worker_config_name: str):
""" load worker config & init workers
"""
with open(os.path.join(self.config_base_dir, worker_config_name)) as f:
worker_config_dict = json.load(f)
for worker_name, worker_config in worker_config_dict.items():
if worker_name in self.worker_dict:
raise RuntimeError(f"worker_name={worker_name} is repeated!")
self.worker_dict[worker_name] = init_instance_by_config_v2(worker_config,
default_clazz_path=self.worker_base_dir,
suffix_name="worker",
**self.global_configs)
self.init_model(worker_config.get("embedding_model"))
self.init_model(worker_config.get("generation_model"))
self.init_model(worker_config.get("rank_model"))
def init_db(self, db_config: dict):
self.db_client = init_instance_by_config_v2(db_config, default_clazz_path=self.db_base_dir)
def init_chat_model(self, chat_model_config: dict):
chat_model_name = chat_model_config["name"]
self.init_model(chat_model_name)
def init_monitor(self, monitor_config: dict):
self.monitor = init_instance_by_config_v2(monitor_config, default_clazz_path=self.db_base_dir)

View file

@ -1,18 +0,0 @@
from typing import List, Dict
from pydantic import Field, BaseModel
from node.message import Message
from node.user_attribute import UserAttribute
class MemoryServiceRequestModel(BaseModel):
user: UserConfig = None
messages: List[Message] = Field(...,
description="summary: 多轮对话的list,默认按照时间正序,最后一条是最新的; retrieve: 最后一条是query")
user_profile: List[UserAttribute] = Field([], description="user_profile")
ext_info: Dict[str, str] = Field({}, description="extra information")
extra_user_attrs: List = []

View file

@ -1,151 +0,0 @@
import json
import re
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from importlib import import_module
from itertools import zip_longest
from typing import Dict, Any
from worker.base_worker import BaseWorker
from utils.context_handler import ContextHandler
from utils.logger import Logger
from utils.timer import timer, Timer
from common.tool_functions import under_line_to_hump
from constants import common_constants
from constants.common_constants import RESPONSE_EXT_INFO, MAX_WORKERS, PIPELINE
from enumeration.memory_method_enum import MemoryMethodEnum
from pipeline.memory import MemoryServiceRequestModel
from cli.cli_config import C
from utils.tool_functions import init_instance_by_config
class MemoryService(object):
def __init__(self, method: MemoryMethodEnum):
self.method = method
self.context_handler = ContextHandler()
# 线程池
self.thread_pool = ThreadPoolExecutor(max_workers=C.thread_pool_max_count)
# 全部初始化的worker
self.worker_dict: Dict[str, BaseWorker] = {}
# 日志
self.logger: Logger = Logger.get_memory_logger()
# 初始化pipeline
self.pipeline_list = self.get_pipeline()
self.print_and_init_worker(self.pipeline_list)
def get_worker(self, worker_name: str, is_multi_thread: bool = False) -> BaseWorker:
return init_instance_by_config(
config = C.worker.get(worker_name),
try_kwargs={
"is_multi_thread": is_multi_thread,
"thread_pool": self.thread_pool
}
)
def worker_run(self, worker_list: list[str]) -> bool:
for worker_name in worker_list:
worker = self.worker_dict[worker_name]
# 执行子类实现的_run函数
worker.run()
# 保存worker的运行信息
self.run_infos.append(worker.run_info_dict)
# 结束pipeline
if not worker.continue_run:
return False
return True
@timer
def print_and_init_worker(self, pipeline_list: list[list]):
self.logger.info("----- Pipeline Begin -----")
i: int = 0
for pipeline_part in pipeline_list:
if len(pipeline_part) == 1:
for w in pipeline_part[0]:
self.logger.info(f"stage{i}: {w}")
self.worker_dict[w] = self.get_worker(w)
i += 1
else:
for w_zip in zip_longest(*pipeline_part, fillvalue="-"):
self.logger.info(f"stage{i}: {' | '.join(w_zip)}")
i += 1
for w in w_zip:
if w == "-":
continue
self.worker_dict[w] = self.get_worker(w, is_multi_thread=True)
self.logger.info("----- Pipeline End -----")
def get_context(self, key: str, default=None) -> Any:
return self.context_handler.get_context(key, default)
def flush(self, request: MemoryServiceRequestModel):
# 全局上下文worker之间交换参数和变量
self.context_handler.flush()
# 运行信息
self.run_infos = []
self.context_handler.set_context(common_constants.REQUEST, request)
for pipeline_part in self.pipeline_list:
pipeline_part.flush(self.context_handler)
@timer
def get_pipeline(self) -> list[list]:
pipeline_str = C.pipeline.get(self.method)
self.logger.info(f"pipeline={pipeline_str}")
# re-match e.g., [a|b],c,[d,e,f|g,h],j
pattern = r'(\[[^\]]*\]|[^,]+)'
pipeline_split = re.findall(pattern, pipeline_str)
pipeline_list = []
for pipeline_part in pipeline_split:
# e.g., [d,e,f|g,h]
pipeline_part = pipeline_part.strip()
if '[' in pipeline_part or ']' in pipeline_part:
pipeline_part = pipeline_part.replace('[', '').replace(']', '')
# e.g., ["d,e,f", "g,h"]
line_split = [x.strip() for x in pipeline_part.split("|") if x]
if len(line_split) <= 0:
continue
# e.g., ["d","e","f"]
pipeline_list.append([x.split(",") for x in line_split])
return pipeline_list
def run(self):
# run workers in multi threads
with self.thread_pool, Timer("ALL_PIPELINE"):
for pipeline_part in self.pipeline_list:
if len(pipeline_part) == 1:
if not self.worker_run(pipeline_part[0]):
break
elif self.max_workers == 1:
for worker_list in pipeline_part:
self.worker_run(worker_list)
else:
t_list = []
for worker_list in pipeline_part:
time.sleep(0.001)
t_list.append(self.thread_pool.submit(self.worker_run, worker_list))
flag = True
for future in as_completed(t_list):
if not future.result():
flag = False
break
if not flag:
break
# 获取ext_info
ext_info = self.get_context(RESPONSE_EXT_INFO)
if ext_info is None:
ext_info = {}
self.context_handler.set_context(RESPONSE_EXT_INFO, ext_info)
# 保存 run_info_list
ext_info["run_infos"] = json.dumps(self.run_infos, ensure_ascii=False)

View file

@ -1,17 +0,0 @@
# -*- coding: utf-8 -*-
"""A common base class for Pipeline"""
from abc import ABC
from abc import abstractmethod
class Operator(ABC):
"""
Abstract base class `Operator` defines a protocol for classes that
implement callable behavior.
The class is designed to be subclassed with an overridden `__call__`
method that specifies the execution logic for the operator.
"""
@abstractmethod
def __call__(self) -> None:
"""Calling function"""