调整根目录结构,kb/logs/media/nltk_data 移动到专用数据目录(可配置,默认 data)。注意知识库文件要做相应移动
7
.gitignore
vendored
@ -3,9 +3,10 @@
|
|||||||
*.bak
|
*.bak
|
||||||
logs
|
logs
|
||||||
/media/
|
/media/
|
||||||
/knowledge_base/*
|
/data/*
|
||||||
!/knowledge_base/samples
|
!/data/knowledge_base/samples
|
||||||
/knowledge_base/samples/vector_store
|
/data/knowledge_base/samples/vector_store
|
||||||
|
!/data/nltk_data
|
||||||
|
|
||||||
/configs/*.py
|
/configs/*.py
|
||||||
/configs/loom.yaml
|
/configs/loom.yaml
|
||||||
|
|||||||
2
.gitmodules
vendored
@ -1,3 +1,3 @@
|
|||||||
[submodule "knowledge_base/samples/content/wiki"]
|
[submodule "knowledge_base/samples/content/wiki"]
|
||||||
path = knowledge_base/samples/content/wiki
|
path = data/knowledge_base/samples/content/wiki
|
||||||
url = https://github.com/chatchat-space/Langchain-Chatchat.wiki.git
|
url = https://github.com/chatchat-space/Langchain-Chatchat.wiki.git
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 178 KiB |
|
Before Width: | Height: | Size: 227 KiB After Width: | Height: | Size: 227 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 228 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 331 KiB After Width: | Height: | Size: 331 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 143 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 227 KiB After Width: | Height: | Size: 227 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 177 KiB After Width: | Height: | Size: 177 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 266 KiB After Width: | Height: | Size: 266 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
@ -1,94 +0,0 @@
|
|||||||
import multiprocessing as mp
|
|
||||||
from multiprocessing import Process
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
from loom_core.constants import LOOM_LOG_BACKUP_COUNT, LOOM_LOG_MAX_BYTES
|
|
||||||
from loom_core.openai_plugins.core.adapter import ProcessesInfo
|
|
||||||
from loom_core.openai_plugins.core.application import ApplicationAdapter
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from loom_core.openai_plugins.deploy.utils import get_timestamp_ms, get_config_dict, get_log_file
|
|
||||||
from omegaconf import OmegaConf
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
# 为了能使用插件中的函数,需要将当前目录加入到sys.path中
|
|
||||||
root_dir = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
sys.path.append(root_dir)
|
|
||||||
import imitater_process_dict
|
|
||||||
from imitater_config import ImitaterCfg
|
|
||||||
from imitater_wrapper import run_imitater
|
|
||||||
|
|
||||||
|
|
||||||
class ImitaterApplicationAdapter(ApplicationAdapter):
|
|
||||||
model_worker_started: mp.Event = None
|
|
||||||
|
|
||||||
def __init__(self, cfg=None, state_dict: dict = None):
|
|
||||||
self.processesInfo = None
|
|
||||||
self._cfg = ImitaterCfg(cfg=cfg)
|
|
||||||
super().__init__(state_dict=state_dict)
|
|
||||||
|
|
||||||
def class_name(self) -> str:
|
|
||||||
"""Get class name."""
|
|
||||||
return self.__name__
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_config(cls, cfg=None):
|
|
||||||
_state_dict = {
|
|
||||||
"application_name": "Imitate",
|
|
||||||
"application_version": "0.0.1",
|
|
||||||
"application_description": "Imitate application",
|
|
||||||
"application_author": "Imitate"
|
|
||||||
}
|
|
||||||
state_dict = cfg.get("state_dict", {})
|
|
||||||
if state_dict is not None and _state_dict is not None:
|
|
||||||
_state_dict = {**state_dict, **_state_dict}
|
|
||||||
else:
|
|
||||||
# 处理其中一个或两者都为 None 的情况
|
|
||||||
_state_dict = state_dict or _state_dict or {}
|
|
||||||
return cls(cfg=cfg, state_dict=_state_dict)
|
|
||||||
|
|
||||||
def init_processes(self, processesInfo: ProcessesInfo):
|
|
||||||
|
|
||||||
self.processesInfo = processesInfo
|
|
||||||
|
|
||||||
logging_conf = get_config_dict(
|
|
||||||
processesInfo.log_level,
|
|
||||||
get_log_file(log_path=self._cfg.get_cfg().get("logdir"), sub_dir=f"local_{get_timestamp_ms()}"),
|
|
||||||
LOOM_LOG_BACKUP_COUNT,
|
|
||||||
LOOM_LOG_MAX_BYTES,
|
|
||||||
)
|
|
||||||
logging.config.dictConfig(logging_conf) # type: ignore
|
|
||||||
worker_name = self._cfg.get_cfg().get("worker_name", [])
|
|
||||||
imitater_process_dict.mp_manager = mp.Manager()
|
|
||||||
|
|
||||||
# prevent re-init cuda error.
|
|
||||||
mp.set_start_method(method="spawn", force=True)
|
|
||||||
|
|
||||||
self.model_worker_started = imitater_process_dict.mp_manager.Event()
|
|
||||||
|
|
||||||
process = Process(
|
|
||||||
target=run_imitater,
|
|
||||||
name=f"model_worker - {worker_name}",
|
|
||||||
kwargs=dict(cfg=self._cfg,
|
|
||||||
worker_name=worker_name,
|
|
||||||
started_event=self.model_worker_started,
|
|
||||||
logging_conf=logging_conf),
|
|
||||||
daemon=True,
|
|
||||||
)
|
|
||||||
imitater_process_dict.processes[worker_name] = process
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
|
|
||||||
for n, p in imitater_process_dict.processes.items():
|
|
||||||
p.start()
|
|
||||||
p.name = f"{p.name} ({p.pid})"
|
|
||||||
|
|
||||||
# 等待 model_worker启动完成
|
|
||||||
# self.model_worker_started.wait()
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
imitater_process_dict.stop()
|
|
||||||
|
|
||||||
@ -1,80 +0,0 @@
|
|||||||
import time
|
|
||||||
from multiprocessing import Process
|
|
||||||
|
|
||||||
from loom_core.openai_plugins.core.control import ControlAdapter
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
# 为了能使用插件中的函数,需要将当前目录加入到sys.path中
|
|
||||||
root_dir = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
sys.path.append(root_dir)
|
|
||||||
|
|
||||||
import imitater_process_dict
|
|
||||||
|
|
||||||
from imitater_wrapper import run_imitater
|
|
||||||
from imitater_config import ImitaterCfg
|
|
||||||
|
|
||||||
|
|
||||||
class ImitaterControlAdapter(ControlAdapter):
|
|
||||||
|
|
||||||
def __init__(self, cfg=None, state_dict: dict = None):
|
|
||||||
self._cfg = ImitaterCfg(cfg=cfg)
|
|
||||||
super().__init__(state_dict=state_dict)
|
|
||||||
|
|
||||||
def class_name(self) -> str:
|
|
||||||
"""Get class name."""
|
|
||||||
return self.__name__
|
|
||||||
|
|
||||||
def start_model(self, new_model_name):
|
|
||||||
|
|
||||||
imitater_process_dict.stop()
|
|
||||||
|
|
||||||
logger.info(f"准备启动新进程:{new_model_name}")
|
|
||||||
e = imitater_process_dict.mp_manager.Event()
|
|
||||||
process = Process(
|
|
||||||
target=run_imitater,
|
|
||||||
name=f"model_worker - {new_model_name}",
|
|
||||||
kwargs=dict(cfg=self._cfg,
|
|
||||||
worker_name=new_model_name,
|
|
||||||
started_event=e),
|
|
||||||
daemon=True,
|
|
||||||
)
|
|
||||||
process.start()
|
|
||||||
process.name = f"{process.name} ({process.pid})"
|
|
||||||
imitater_process_dict.processes[new_model_name] = process
|
|
||||||
# e.wait()
|
|
||||||
logger.info(f"成功启动新进程:{new_model_name}")
|
|
||||||
|
|
||||||
def stop_model(self, model_name: str):
|
|
||||||
|
|
||||||
if model_name in imitater_process_dict.processes:
|
|
||||||
process = imitater_process_dict.processes.pop(model_name)
|
|
||||||
time.sleep(1)
|
|
||||||
process.kill()
|
|
||||||
logger.info(f"停止进程:{model_name}")
|
|
||||||
else:
|
|
||||||
logger.error(f"未找到进程:{model_name}")
|
|
||||||
raise Exception(f"未找到进程:{model_name}")
|
|
||||||
|
|
||||||
def replace_model(self, model_name: str, new_model_name: str):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_config(cls, cfg=None):
|
|
||||||
_state_dict = {
|
|
||||||
"controller_name": "Imitate",
|
|
||||||
"controller_version": "0.0.1",
|
|
||||||
"controller_description": "Imitate controller",
|
|
||||||
"controller_author": "Imitate"
|
|
||||||
}
|
|
||||||
state_dict = cfg.get("state_dict", {})
|
|
||||||
if state_dict is not None and _state_dict is not None:
|
|
||||||
_state_dict = {**state_dict, **_state_dict}
|
|
||||||
else:
|
|
||||||
# 处理其中一个或两者都为 None 的情况
|
|
||||||
_state_dict = state_dict or _state_dict or {}
|
|
||||||
|
|
||||||
return cls(cfg=cfg, state_dict=_state_dict)
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"bos_token_id": 1,
|
|
||||||
"eos_token_id": [2, 92542],
|
|
||||||
"pad_token_id": 2,
|
|
||||||
"max_new_tokens": 1024,
|
|
||||||
"do_sample": true,
|
|
||||||
"transformers_version": "4.33.2"
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"eos_token_id": [151643, 151645],
|
|
||||||
"pad_token_id": 151643,
|
|
||||||
"max_new_tokens": 1024,
|
|
||||||
"do_sample": true,
|
|
||||||
"top_k": 0,
|
|
||||||
"top_p": 0.8,
|
|
||||||
"transformers_version": "4.34.0"
|
|
||||||
}
|
|
||||||
@ -1,80 +0,0 @@
|
|||||||
# httpx 请求默认超时时间(秒)。如果加载模型或对话较慢,出现超时错误,可以适当加大该值。
|
|
||||||
from typing import List, TypedDict
|
|
||||||
|
|
||||||
HTTPX_DEFAULT_TIMEOUT = 300.0
|
|
||||||
log_verbose = True
|
|
||||||
|
|
||||||
|
|
||||||
class ImitaterModel(TypedDict):
|
|
||||||
name: str
|
|
||||||
chat_model_path: str
|
|
||||||
chat_model_device: str
|
|
||||||
chat_template_path: str
|
|
||||||
generation_config_path: str
|
|
||||||
agent_type: str
|
|
||||||
|
|
||||||
|
|
||||||
class ImitaterEmbedding(TypedDict):
|
|
||||||
name: str
|
|
||||||
embed_model_path: str
|
|
||||||
embed_model_device: str
|
|
||||||
embed_batch_size: int
|
|
||||||
|
|
||||||
|
|
||||||
class ImitaterWorker(TypedDict):
|
|
||||||
name: str
|
|
||||||
model: ImitaterModel
|
|
||||||
embedding: ImitaterEmbedding
|
|
||||||
|
|
||||||
|
|
||||||
class ImitaterCfg:
|
|
||||||
def __init__(self, cfg: dict = None):
|
|
||||||
if cfg is None:
|
|
||||||
raise RuntimeError("ImitaterCfg cfg is None.")
|
|
||||||
self._cfg = cfg
|
|
||||||
|
|
||||||
def get_cfg(self):
|
|
||||||
return self._cfg
|
|
||||||
|
|
||||||
def get_run_openai_api_cfg(self):
|
|
||||||
return self._cfg.get("run_openai_api", {})
|
|
||||||
|
|
||||||
def get_imitate_model_workers_by_name(self, name: str) -> ImitaterWorker:
|
|
||||||
|
|
||||||
imitate_model_workers_cfg = self._cfg.get("imitate_model_workers", None)
|
|
||||||
if imitate_model_workers_cfg is None:
|
|
||||||
raise RuntimeError("imitate_model_workers_cfg is None.")
|
|
||||||
|
|
||||||
get = lambda model_name: imitate_model_workers_cfg[
|
|
||||||
self.get_imitate_model_workers_index_by_name(model_name)
|
|
||||||
].get(model_name, {})
|
|
||||||
imitate = get(name)
|
|
||||||
# 初始化imitate为ImitaterWorker
|
|
||||||
worker_cfg = ImitaterWorker(name=name,
|
|
||||||
model=ImitaterModel(**imitate.get("model", {})),
|
|
||||||
embedding=ImitaterEmbedding(**imitate.get("embedding", {}))
|
|
||||||
)
|
|
||||||
return worker_cfg
|
|
||||||
|
|
||||||
def get_imitate_model_workers_names(self) -> List[str]:
|
|
||||||
|
|
||||||
imitate_model_workers_cfg = self._cfg.get("imitate_model_workers", None)
|
|
||||||
if imitate_model_workers_cfg is None:
|
|
||||||
raise RuntimeError("imitate_model_workers_cfg is None.")
|
|
||||||
worker_name_cfg = []
|
|
||||||
for cfg in imitate_model_workers_cfg:
|
|
||||||
for key, imitate_model_workers in cfg.items():
|
|
||||||
worker_name_cfg.append(key)
|
|
||||||
return worker_name_cfg
|
|
||||||
|
|
||||||
def get_imitate_model_workers_index_by_name(self, name) -> int:
|
|
||||||
|
|
||||||
imitate_model_workers_cfg = self._cfg.get("imitate_model_workers", None)
|
|
||||||
if imitate_model_workers_cfg is None:
|
|
||||||
raise RuntimeError("imitate_model_workers_cfg is None.")
|
|
||||||
|
|
||||||
for cfg in imitate_model_workers_cfg:
|
|
||||||
for key, imitate_model_workers in cfg.items():
|
|
||||||
if key == name:
|
|
||||||
return imitate_model_workers_cfg.index(cfg)
|
|
||||||
return -1
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
from multiprocessing import Process
|
|
||||||
from typing import Dict
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
mp_manager = None
|
|
||||||
processes: Dict[str, Process] = {}
|
|
||||||
|
|
||||||
|
|
||||||
def stop():
|
|
||||||
for n, process in processes.items():
|
|
||||||
logger.warning("Sending SIGKILL to %s", p)
|
|
||||||
try:
|
|
||||||
|
|
||||||
process.kill()
|
|
||||||
except Exception as e:
|
|
||||||
logger.info("Failed to kill process %s", p, exc_info=True)
|
|
||||||
|
|
||||||
for n, p in processes.items():
|
|
||||||
logger.info("Process status: %s", p)
|
|
||||||
|
|
||||||
del processes
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
import multiprocessing
|
|
||||||
from typing import List, Optional, Dict
|
|
||||||
|
|
||||||
from fastapi import FastAPI
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import multiprocessing as mp
|
|
||||||
import uvicorn
|
|
||||||
import os
|
|
||||||
import logging
|
|
||||||
import asyncio
|
|
||||||
import signal
|
|
||||||
import inspect
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
# 为了能使用fastchat_wrapper.py中的函数,需要将当前目录加入到sys.path中
|
|
||||||
root_dir = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
sys.path.append(root_dir)
|
|
||||||
|
|
||||||
from imitater_config import ImitaterCfg
|
|
||||||
|
|
||||||
"""
|
|
||||||
防止Can't pickle Function
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def _start_imitater(
|
|
||||||
started_event: mp.Event = None
|
|
||||||
):
|
|
||||||
from imitater.service.app import launch_app
|
|
||||||
# 跳过键盘中断,
|
|
||||||
signal.signal(signal.SIGINT, lambda *_: None)
|
|
||||||
launch_app()
|
|
||||||
|
|
||||||
|
|
||||||
def run_imitater(
|
|
||||||
cfg: ImitaterCfg,
|
|
||||||
worker_name: str,
|
|
||||||
started_event: mp.Event = None,
|
|
||||||
logging_conf: Optional[dict] = None):
|
|
||||||
# 跳过键盘中断,
|
|
||||||
signal.signal(signal.SIGINT, lambda *_: None)
|
|
||||||
|
|
||||||
logging.config.dictConfig(logging_conf) # type: ignore
|
|
||||||
import os
|
|
||||||
worker_cfg = cfg.get_imitate_model_workers_by_name(worker_name)
|
|
||||||
|
|
||||||
os.environ["AGENT_TYPE"] = worker_cfg.get("model").get("agent_type")
|
|
||||||
os.environ["CHAT_MODEL_PATH"] = worker_cfg.get("model").get("chat_model_path")
|
|
||||||
os.environ["CHAT_MODEL_DEVICE"] = worker_cfg.get("model").get("chat_model_device")
|
|
||||||
os.environ["CHAT_TEMPLATE_PATH"] = worker_cfg.get("model").get("chat_template_path")
|
|
||||||
os.environ["GENERATION_CONFIG_PATH"] = worker_cfg.get("model").get("generation_config_path")
|
|
||||||
|
|
||||||
os.environ["EMBED_MODEL_PATH"] = worker_cfg.get("embedding").get("embed_model_path")
|
|
||||||
os.environ["EMBED_MODEL_DEVICE"] = worker_cfg.get("embedding").get("embed_model_device")
|
|
||||||
os.environ["EMBED_BATCH_SIZE"] = str(worker_cfg.get("embedding").get("embed_batch_size"))
|
|
||||||
|
|
||||||
os.environ["SERVICE_PORT"] = str(cfg.get_run_openai_api_cfg().get("port", 30000))
|
|
||||||
|
|
||||||
_start_imitater(started_event=started_event)
|
|
||||||