From 4cc5c8ef2c263981917c7b891779af7a9ee45077 Mon Sep 17 00:00:00 2001 From: Pliosauroidea Date: Tue, 11 Mar 2025 18:37:40 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E4=BF=AE=E6=AD=A3.env.prod=E5=92=8C.env.de?= =?UTF-8?q?v=E7=9A=84=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bot.py b/bot.py index 471a98ea..9a5d4729 100644 --- a/bot.py +++ b/bot.py @@ -51,15 +51,15 @@ def init_env(): with open(".env", "w") as f: f.write("ENVIRONMENT=prod") - # 检测.env.prod文件是否存在 - if not os.path.exists(".env.prod"): - logger.error("检测到.env.prod文件不存在") - shutil.copy("template.env", "./.env.prod") + # 检测.env.prod文件是否存在 + if not os.path.exists(".env.prod"): + logger.error("检测到.env.prod文件不存在") + shutil.copy("template.env", "./.env.prod") # 检测.env.dev文件是否存在,不存在的话直接复制生产环境配置 if not os.path.exists(".env.dev"): logger.error("检测到.env.dev文件不存在") - shutil.copy(".env.prod", "./.env.dev") + shutil.copy("template.env", "./.env.dev") # 首先加载基础环境变量.env if os.path.exists(".env"): From 60a93766c7b99b71e518a5da649ae8327f386183 Mon Sep 17 00:00:00 2001 From: Pliosauroidea Date: Tue, 11 Mar 2025 18:42:35 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E6=B7=BB=E5=8A=A0logger=E7=9A=84debug?= =?UTF-8?q?=E8=BE=93=E5=87=BA=E5=BC=80=E5=85=B3,=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E4=B8=BA=E4=B8=8D=E5=BC=80=E5=90=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/chat/config.py | 9 ++++++++- template/bot_config_template.toml | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/plugins/chat/config.py b/src/plugins/chat/config.py index 7aed9eee..596d120f 100644 --- a/src/plugins/chat/config.py +++ b/src/plugins/chat/config.py @@ -1,4 +1,5 @@ import os +import sys from dataclasses import dataclass, field from typing import Dict, List, Optional @@ -67,6 +68,7 @@ class BotConfig: enable_advance_output: bool = False # 是否启用高级输出 enable_kuuki_read: bool = True # 是否启用读空气功能 + enable_debug_output: bool = False # 是否启用调试输出 mood_update_interval: float = 1.0 # 情绪更新间隔 单位秒 mood_decay_rate: float = 0.95 # 情绪衰减率 @@ -325,6 +327,7 @@ class BotConfig: others_config = parent["others"] config.enable_advance_output = others_config.get("enable_advance_output", config.enable_advance_output) config.enable_kuuki_read = others_config.get("enable_kuuki_read", config.enable_kuuki_read) + config.enable_debug_output = others_config.get("enable_debug_output", config.enable_debug_output) # 版本表达式:>=1.0.0,<2.0.0 # 允许字段:func: method, support: str, notice: str, necessary: bool @@ -419,4 +422,8 @@ global_config = BotConfig.load_config(config_path=bot_config_path) if not global_config.enable_advance_output: logger.remove() - pass + +# 调试输出功能 +if global_config.enable_debug_output: + logger.remove() + logger.add(sys.stdout, level="DEBUG") diff --git a/template/bot_config_template.toml b/template/bot_config_template.toml index 126fc501..bea6ab7b 100644 --- a/template/bot_config_template.toml +++ b/template/bot_config_template.toml @@ -100,6 +100,7 @@ word_replace_rate=0.006 # 整词替换概率 [others] enable_advance_output = true # 是否启用高级输出 enable_kuuki_read = true # 是否启用读空气功能 +enable_debug_output = false # 是否启用调试输出 [groups] talk_allowed = [ From c24bb70291b276d5e471ec554188708c86e7c14c Mon Sep 17 00:00:00 2001 From: pine Date: Tue, 11 Mar 2025 18:51:28 +0800 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20=E6=B5=81=E5=BC=8F=E8=BE=93=E5=87=BA?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E5=A2=9E=E5=8A=A0=E7=BB=93=E6=9D=9F=E5=88=A4?= =?UTF-8?q?=E6=96=AD=E4=B8=8Etoken=E7=94=A8=E9=87=8F=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/models/utils_model.py | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/plugins/models/utils_model.py b/src/plugins/models/utils_model.py index e9d11f33..461f542d 100644 --- a/src/plugins/models/utils_model.py +++ b/src/plugins/models/utils_model.py @@ -216,6 +216,7 @@ class LLM_request: # 将流式输出转化为非流式输出 if stream_mode: + flag_delta_content_finished = False accumulated_content = "" async for line_bytes in response.content: line = line_bytes.decode("utf-8").strip() @@ -227,13 +228,25 @@ class LLM_request: break try: chunk = json.loads(data_str) - delta = chunk["choices"][0]["delta"] - delta_content = delta.get("content") - if delta_content is None: - delta_content = "" - accumulated_content += delta_content + if flag_delta_content_finished: + usage = chunk.get("usage", None) # 获取tokn用量 + else: + delta = chunk["choices"][0]["delta"] + delta_content = delta.get("content") + if delta_content is None: + delta_content = "" + accumulated_content += delta_content + # 检测流式输出文本是否结束 + finish_reason = chunk["choices"][0]["finish_reason"] + if finish_reason == "stop": + usage = chunk.get("usage", None) + if usage: + break + # 部分平台在文本输出结束前不会返回token用量,此时需要再获取一次chunk + flag_delta_content_finished = True + except Exception: - logger.exception("解析流式输出错") + logger.exception("解析流式输出错误") content = accumulated_content reasoning_content = "" think_match = re.search(r'(.*?)', content, re.DOTALL) @@ -242,7 +255,7 @@ class LLM_request: content = re.sub(r'.*?', '', content, flags=re.DOTALL).strip() # 构造一个伪result以便调用自定义响应处理器或默认处理器 result = { - "choices": [{"message": {"content": content, "reasoning_content": reasoning_content}}]} + "choices": [{"message": {"content": content, "reasoning_content": reasoning_content}}], "usage": usage} return response_handler(result) if response_handler else self._default_response_handler( result, user_id, request_type, endpoint) else: From 7d017be9f7a8f9ea3a54bacceb34474818b37ab4 Mon Sep 17 00:00:00 2001 From: HYY1116 Date: Tue, 11 Mar 2025 19:23:48 +0800 Subject: [PATCH 4/6] =?UTF-8?q?fix:=E6=A8=A1=E5=9E=8B=E9=99=8D=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/models/utils_model.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/plugins/models/utils_model.py b/src/plugins/models/utils_model.py index e9d11f33..6ed0a0b2 100644 --- a/src/plugins/models/utils_model.py +++ b/src/plugins/models/utils_model.py @@ -192,13 +192,11 @@ class LLM_request: logger.warning(f"检测到403错误,模型从 {old_model_name} 降级为 {self.model_name}") # 对全局配置进行更新 - if hasattr(global_config, 'llm_normal') and global_config.llm_normal.get( - 'name') == old_model_name: + if global_config.llm_normal.get('name') == old_model_name: global_config.llm_normal['name'] = self.model_name logger.warning(f"将全局配置中的 llm_normal 模型临时降级至{self.model_name}") - if hasattr(global_config, 'llm_reasoning') and global_config.llm_reasoning.get( - 'name') == old_model_name: + if global_config.llm_reasoning.get('name') == old_model_name: global_config.llm_reasoning['name'] = self.model_name logger.warning(f"将全局配置中的 llm_reasoning 模型临时降级至{self.model_name}") From ef8691cd9e91696780d816cc144a91c1241d18f4 Mon Sep 17 00:00:00 2001 From: tcmofashi Date: Tue, 11 Mar 2025 19:30:20 +0800 Subject: [PATCH 5/6] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9message=E7=BB=A7?= =?UTF-8?q?=E6=89=BF=E9=80=BB=E8=BE=91=EF=BC=8C=E4=BF=AE=E5=A4=8D=E5=9B=9E?= =?UTF-8?q?=E5=A4=8D=E6=B6=88=E6=81=AF=E6=97=A0=E6=B3=95=E8=AF=86=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/chat/bot.py | 4 +- src/plugins/chat/cq_code.py | 10 ++-- src/plugins/chat/message.py | 103 +++++++++++++++++------------------- 3 files changed, 58 insertions(+), 59 deletions(-) diff --git a/src/plugins/chat/bot.py b/src/plugins/chat/bot.py index 81361d81..4af3a6b0 100644 --- a/src/plugins/chat/bot.py +++ b/src/plugins/chat/bot.py @@ -50,6 +50,7 @@ class ChatBot: # sender_info = await bot.get_group_member_info(group_id=event.group_id, user_id=event.user_id, no_cache=True) # 白名单设定由nontbot侧完成 + # 消息过滤,涉及到config有待更新 if event.group_id: if event.group_id not in global_config.talk_allowed_groups: return @@ -68,7 +69,6 @@ class ChatBot: group_name=None, platform='qq' ) - message_cq=MessageRecvCQ( message_id=event.message_id, user_info=user_info, @@ -86,7 +86,7 @@ class ChatBot: userinfo=message.message_info.user_info messageinfo=message.message_info - # 消息过滤,涉及到config有待更新 + chat = await chat_manager.get_or_create_stream(platform=messageinfo.platform, user_info=userinfo, group_info=groupinfo) message.update_chat_stream(chat) diff --git a/src/plugins/chat/cq_code.py b/src/plugins/chat/cq_code.py index 185e98ed..0a8a71df 100644 --- a/src/plugins/chat/cq_code.py +++ b/src/plugins/chat/cq_code.py @@ -231,7 +231,8 @@ class CQCode: group_info=group_info, ) content_seg = Seg( - type="seglist", data=message_obj.message_segment ) + type="seglist", data=[message_obj.message_segment] + ) else: content_seg = Seg(type="text", data="[空消息]") else: @@ -256,7 +257,7 @@ class CQCode: group_info=group_info, ) content_seg = Seg( - type="seglist", data=message_obj.message_segment + type="seglist", data=[message_obj.message_segment] ) else: content_seg = Seg(type="text", data="[空消息]") @@ -281,11 +282,12 @@ class CQCode: if self.reply_message.sender.user_id: message_obj = MessageRecvCQ( - user_info=UserInfo(user_id=self.reply_message.sender.user_id,user_nickname=self.reply_message.sender.get("nickname",None)), + user_info=UserInfo(user_id=self.reply_message.sender.user_id,user_nickname=self.reply_message.sender.nickname), message_id=self.reply_message.message_id, raw_message=str(self.reply_message.message), group_info=GroupInfo(group_id=self.reply_message.group_id), ) + segments = [] if message_obj.message_info.user_info.user_id == global_config.BOT_QQ: @@ -302,7 +304,7 @@ class CQCode: ) ) - segments.append(Seg(type="seglist", data=message_obj.message_segment)) + segments.append(Seg(type="seglist", data=[message_obj.message_segment])) segments.append(Seg(type="text", data="]")) return segments else: diff --git a/src/plugins/chat/message.py b/src/plugins/chat/message.py index 5eb93d70..d9f54dd4 100644 --- a/src/plugins/chat/message.py +++ b/src/plugins/chat/message.py @@ -14,9 +14,52 @@ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) #这个类是消息数据类,用于存储和管理消息数据。 #它定义了消息的属性,包括群组ID、用户ID、消息ID、原始消息内容、纯文本内容和时间戳。 #它还定义了两个辅助属性:keywords用于提取消息的关键词,is_plain_text用于判断消息是否为纯文本。 - + @dataclass -class MessageRecv(MessageBase): +class Message(MessageBase): + chat_stream: ChatStream=None + reply: Optional['Message'] = None + detailed_plain_text: str = "" + processed_plain_text: str = "" + + def __init__( + self, + message_id: str, + time: int, + chat_stream: ChatStream, + user_info: UserInfo, + message_segment: Optional[Seg] = None, + reply: Optional['MessageRecv'] = None, + detailed_plain_text: str = "", + processed_plain_text: str = "", + ): + # 构造基础消息信息 + message_info = BaseMessageInfo( + platform=chat_stream.platform, + message_id=message_id, + time=time, + group_info=chat_stream.group_info, + user_info=user_info + ) + + # 调用父类初始化 + super().__init__( + message_info=message_info, + message_segment=message_segment, + raw_message=None + ) + + self.chat_stream = chat_stream + # 文本处理相关属性 + self.processed_plain_text = detailed_plain_text + self.detailed_plain_text = processed_plain_text + + # 回复消息 + self.reply = reply + + +@dataclass +class MessageRecv(Message): """接收消息类,用于处理从MessageCQ序列化的消息""" def __init__(self, message_dict: Dict): @@ -25,20 +68,16 @@ class MessageRecv(MessageBase): Args: message_dict: MessageCQ序列化后的字典 """ - message_info = BaseMessageInfo.from_dict(message_dict.get('message_info', {})) - message_segment = Seg.from_dict(message_dict.get('message_segment', {})) - raw_message = message_dict.get('raw_message') - - super().__init__( - message_info=message_info, - message_segment=message_segment, - raw_message=raw_message - ) + self.message_info = BaseMessageInfo.from_dict(message_dict.get('message_info', {})) + self.message_segment = Seg.from_dict(message_dict.get('message_segment', {})) + self.raw_message = message_dict.get('raw_message') # 处理消息内容 self.processed_plain_text = "" # 初始化为空字符串 self.detailed_plain_text = "" # 初始化为空字符串 self.is_emoji=False + + def update_chat_stream(self,chat_stream:ChatStream): self.chat_stream=chat_stream @@ -110,48 +149,6 @@ class MessageRecv(MessageBase): ) return f"[{time_str}] {name}: {self.processed_plain_text}\n" -@dataclass -class Message(MessageBase): - chat_stream: ChatStream=None - reply: Optional['Message'] = None - detailed_plain_text: str = "" - processed_plain_text: str = "" - - def __init__( - self, - message_id: str, - time: int, - chat_stream: ChatStream, - user_info: UserInfo, - message_segment: Optional[Seg] = None, - reply: Optional['MessageRecv'] = None, - detailed_plain_text: str = "", - processed_plain_text: str = "", - ): - # 构造基础消息信息 - message_info = BaseMessageInfo( - platform=chat_stream.platform, - message_id=message_id, - time=time, - group_info=chat_stream.group_info, - user_info=user_info - ) - - # 调用父类初始化 - super().__init__( - message_info=message_info, - message_segment=message_segment, - raw_message=None - ) - - self.chat_stream = chat_stream - # 文本处理相关属性 - self.processed_plain_text = detailed_plain_text - self.detailed_plain_text = processed_plain_text - - # 回复消息 - self.reply = reply - @dataclass class MessageProcessBase(Message): From aa41f0d1d81d300709f475c8e6b2398a6f67df4e Mon Sep 17 00:00:00 2001 From: tcmofashi Date: Tue, 11 Mar 2025 19:47:09 +0800 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20=E6=94=BE=E5=8F=8D=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/chat/message.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/chat/message.py b/src/plugins/chat/message.py index d9f54dd4..c777e727 100644 --- a/src/plugins/chat/message.py +++ b/src/plugins/chat/message.py @@ -51,8 +51,8 @@ class Message(MessageBase): self.chat_stream = chat_stream # 文本处理相关属性 - self.processed_plain_text = detailed_plain_text - self.detailed_plain_text = processed_plain_text + self.processed_plain_text = processed_plain_text + self.detailed_plain_text = detailed_plain_text # 回复消息 self.reply = reply