From 3df387995498c643db5da84efd0aef69b3119bfd Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Thu, 30 Nov 2023 12:46:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E4=BA=BA=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cores/qqbot/core.py | 45 ++++++++++++++++++++----------- cores/qqbot/global_object.py | 2 ++ model/command/openai_official.py | 8 +++--- model/provider/openai_official.py | 29 ++++++++++++++++++-- model/provider/provider.py | 2 +- model/provider/rev_chatgpt.py | 7 ++++- util/cmd_config.py | 5 ++-- 7 files changed, 72 insertions(+), 26 deletions(-) diff --git a/cores/qqbot/core.py b/cores/qqbot/core.py index e4f39f7bb..a78367184 100644 --- a/cores/qqbot/core.py +++ b/cores/qqbot/core.py @@ -121,7 +121,7 @@ cc.init_attributes("CHATGPT_BASE_URL", "") cc.init_attributes("qqbot_appid", "") cc.init_attributes("qqbot_secret", "") cc.init_attributes("llm_env_prompt", "> hint: 末尾根据内容和心情添加 1-2 个emoji") -cc.init_attributes("default_personality_name", "") +cc.init_attributes("default_personality_str", "") # cc.init_attributes(["qq_forward_mode"], False) # QQ机器人 @@ -419,6 +419,15 @@ def initBot(cfg, prov): input("[System-Error] 没有启用/成功启用任何机器人,程序退出") exit() + default_personality_str = cc.get("default_personality_str", "") + if default_personality_str == "": + _global_object.default_personality = None + else: + _global_object.default_personality = { + "name": "default", + "prompt": default_personality_str, + } + gu.log("🎉 项目启动完成。") # thread_inst.join() @@ -430,21 +439,25 @@ async def cli(): prompt = input(">>> ") if prompt == "": continue - ngm = NakuruGuildMessage() - ngm.channel_id = 6180 - ngm.user_id = 6180 - ngm.message = [Plain(prompt)] - ngm.type = "GuildMessage" - ngm.self_id = 6180 - ngm.self_tiny_id = 6180 - ngm.guild_id = 6180 - ngm.sender = NakuruGuildMember() - ngm.sender.tiny_id = 6180 - ngm.sender.user_id = 6180 - ngm.sender.nickname = "CLI" - ngm.sender.role = 0 + ngm = await cli_pack_message(prompt) await oper_msg(ngm, True, PLATFORM_CLI) +async def cli_pack_message(prompt: str) -> NakuruGuildMessage: + ngm = NakuruGuildMessage() + ngm.channel_id = 6180 + ngm.user_id = 6180 + ngm.message = [Plain(prompt)] + ngm.type = "GuildMessage" + ngm.self_id = 6180 + ngm.self_tiny_id = 6180 + ngm.guild_id = 6180 + ngm.sender = NakuruGuildMember() + ngm.sender.tiny_id = 6180 + ngm.sender.user_id = 6180 + ngm.sender.nickname = "CLI" + ngm.sender.role = 0 + return ngm + ''' 运行QQ频道机器人 ''' @@ -729,13 +742,13 @@ async def oper_msg(message: Union[GroupMessage, FriendMessage, GuildMessage, Nak qq_msg = qq_msg[3:] web_sch_flag = True else: - qq_msg += cc.get("llm_env_prompt", "") + qq_msg += " " + cc.get("llm_env_prompt", "") if chosen_provider == REV_CHATGPT or chosen_provider == OPENAI_OFFICIAL: if _global_object.web_search or web_sch_flag: official_fc = chosen_provider == OPENAI_OFFICIAL chatgpt_res = gplugin.web_search(qq_msg, llm_instance[chosen_provider], session_id, official_fc) else: - chatgpt_res = str(llm_instance[chosen_provider].text_chat(qq_msg, session_id, image_url)) + chatgpt_res = str(llm_instance[chosen_provider].text_chat(qq_msg, session_id, image_url, default_personality = _global_object.default_personality)) elif chosen_provider == REV_EDGEGPT: res, res_code = await llm_instance[chosen_provider].text_chat(qq_msg, platform) if res_code == 0: # bing不想继续话题,重置会话后重试。 diff --git a/cores/qqbot/global_object.py b/cores/qqbot/global_object.py index cc6873450..d9871429e 100644 --- a/cores/qqbot/global_object.py +++ b/cores/qqbot/global_object.py @@ -26,6 +26,7 @@ class GlobalObject: cnt_total: int platform_qq: QQ platform_qqchan: QQChan + default_personality: dict def __init__(self): self.nick = None # gocq 的昵称 @@ -39,6 +40,7 @@ class GlobalObject: self.cnt_total = 0 self.platform_qq = None self.platform_qqchan = None + self.default_personality = None class AstrMessageEvent(): message_str: str # 纯消息字符串 diff --git a/model/command/openai_official.py b/model/command/openai_official.py index aa5247e6f..8d919a989 100644 --- a/model/command/openai_official.py +++ b/model/command/openai_official.py @@ -189,7 +189,7 @@ class CommandOpenAIOfficial(Command): def unset(self, session_id: str): if self.provider is None: return False, "未启动OpenAI ChatGPT语言模型.", "unset" - self.provider.now_personality = {} + self.provider.curr_personality = {} self.provider.forget(session_id) return True, "已清除人格并重置历史记录。", "unset" @@ -200,7 +200,7 @@ class CommandOpenAIOfficial(Command): if len(l) == 1: return True, f"【人格文本由PlexPt开源项目awesome-chatgpt-pr \ ompts-zh提供】\n设置人格: \n/set 人格名。例如/set 编剧\n人格列表: /set list\n人格详细信息: \ - /set view 人格名\n自定义人格: /set 人格文本\n重置会话(清除人格): /reset\n重置会话(保留人格): /reset p\n【当前人格】: {str(self.provider.now_personality)}", "set" + /set view 人格名\n自定义人格: /set 人格文本\n重置会话(清除人格): /reset\n重置会话(保留人格): /reset p\n【当前人格】: {str(self.provider.curr_personality)}", "set" elif l[1] == "list": msg = "人格列表:\n" for key in personalities.keys(): @@ -221,7 +221,7 @@ class CommandOpenAIOfficial(Command): else: ps = l[1].strip() if ps in personalities: - self.provider.now_personality = { + self.provider.curr_personality = { 'name': ps, 'prompt': personalities[ps] } @@ -243,7 +243,7 @@ class CommandOpenAIOfficial(Command): self.personality_str = message return True, f"人格{ps}已设置。", "set" else: - self.provider.now_personality = { + self.provider.curr_personality = { 'name': '自定义人格', 'prompt': ps } diff --git a/model/provider/openai_official.py b/model/provider/openai_official.py index 2e0b36a95..9f469501b 100644 --- a/model/provider/openai_official.py +++ b/model/provider/openai_official.py @@ -83,7 +83,7 @@ class ProviderOpenAIOfficial(Provider): threading.Thread(target=self.dump_history, daemon=True).start() # 人格 - self.now_personality = {} + self.curr_personality = {} # 转储历史记录 @@ -109,11 +109,30 @@ class ProviderOpenAIOfficial(Provider): # 每隔10分钟转储一次 time.sleep(10*self.history_dump_interval) + def personality_set(self, default_personality: dict, session_id: str): + self.curr_personality = default_personality + new_record = { + "user": { + "role": "user", + "content": default_personality['prompt'], + }, + "AI": { + "role": "assistant", + "content": "好的,接下来我会扮演这个角色。" + }, + 'type': "personality", + 'usage_tokens': 0, + 'single-tokens': 0 + } + self.session_dict[session_id].append(new_record) + + def text_chat(self, prompt, session_id = None, image_url = None, function_call=None, - extra_conf: dict = None): + extra_conf: dict = None, + default_personality: dict = None): if session_id is None: session_id = "unknown" if "unknown" in self.session_dict: @@ -136,6 +155,12 @@ class ProviderOpenAIOfficial(Provider): f.flush() f.close() + if len(self.session_dict[session_id]) == 0: + # 设置默认人格 + if default_personality is not None: + self.personality_set(default_personality, session_id) + + # 使用 tictoken 截断消息 _encoded_prompt = self.enc.encode(prompt) if self.openai_model_configs['max_tokens'] < len(_encoded_prompt): diff --git a/model/provider/provider.py b/model/provider/provider.py index 23d07f568..a3a77867c 100644 --- a/model/provider/provider.py +++ b/model/provider/provider.py @@ -5,7 +5,7 @@ class Provider: pass @abc.abstractmethod - def text_chat(self, prompt, session_id, image_url: None, function_call: None): + def text_chat(self, prompt, session_id, image_url: None, function_call: None, extra_conf: dict = None, default_personality: dict = None) -> str: pass @abc.abstractmethod diff --git a/model/provider/rev_chatgpt.py b/model/provider/rev_chatgpt.py index 24f94b22b..fd1ece956 100644 --- a/model/provider/rev_chatgpt.py +++ b/model/provider/rev_chatgpt.py @@ -101,7 +101,12 @@ class ProviderRevChatGPT(Provider): # print("[RevChatGPT] "+str(resp)) return resp - def text_chat(self, prompt, session_id = None, image_url = None, function_call=None) -> str: + def text_chat(self, prompt, + session_id = None, + image_url = None, + function_call=None, + extra_conf: dict = None, + default_personality: dict = None) -> str: # 选择一个人少的账号。 selected_revstat = None diff --git a/util/cmd_config.py b/util/cmd_config.py index 396ad721f..9a138829a 100644 --- a/util/cmd_config.py +++ b/util/cmd_config.py @@ -50,8 +50,9 @@ class CmdConfig(): _tag = False if isinstance(key, str): - d[key] = init_val - _tag = True + if key not in d: + d[key] = init_val + _tag = True elif isinstance(key, list): for k in key: if k not in d: