From ec947c69a6bee7976eccda7e616eeb9d0ccbe786 Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Wed, 26 Feb 2025 19:25:10 +0800 Subject: [PATCH] 0.1.2 fix message _visualizer --- .gitignore | 2 + README.md | 6 ++ src/plugins/chat/bot.py | 4 -- src/plugins/chat/bot_config copy.toml | 33 +++++++++++ src/plugins/chat/bot_config.toml | 4 +- src/plugins/chat/cq_code.py | 73 +++++++++++++++--------- src/plugins/chat/gpt_response.py | 4 +- src/plugins/chat/message.py | 4 ++ src/plugins/chat/message_send_control.py | 13 ++++- src/plugins/chat/prompt_builder.py | 33 +++++++---- src/plugins/chat/relationship_manager.py | 2 +- src/plugins/chat/willing_manager.py | 2 +- 12 files changed, 128 insertions(+), 52 deletions(-) create mode 100644 src/plugins/chat/bot_config copy.toml diff --git a/.gitignore b/.gitignore index 71a620d7e..70ddf1b48 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ mongodb/ NapCat.Framework.Windows.Once/ log/ src/plugins/memory +src/plugins/chat/bot_config.toml /test message_queue_content.txt message_queue_content.bat @@ -12,6 +13,7 @@ reasoning_content.txt reasoning_content.bat reasoning_window.bat + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] diff --git a/README.md b/README.md index d775ad7d1..1cc3035f0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ # MaiMBot 麦麦 qq机器人 + + + <<<<<<< Updated upstream 还在整理中 ======= @@ -16,3 +19,6 @@ 主要代码在/src/plugins/chat下 >>>>>>> Stashed changes + + +纯编程外行,很多代码史一样多多包涵 \ No newline at end of file diff --git a/src/plugins/chat/bot.py b/src/plugins/chat/bot.py index 7ef675f67..675a8c43a 100644 --- a/src/plugins/chat/bot.py +++ b/src/plugins/chat/bot.py @@ -215,10 +215,6 @@ class ChatBot: is_emoji=True ) message_sender.send_temp_container.add_message(bot_message) - - - - # 如果收到新消息,提高回复意愿 willing_manager.change_reply_willing_after_sent(event.group_id) \ No newline at end of file diff --git a/src/plugins/chat/bot_config copy.toml b/src/plugins/chat/bot_config copy.toml new file mode 100644 index 000000000..48b0fa6b5 --- /dev/null +++ b/src/plugins/chat/bot_config copy.toml @@ -0,0 +1,33 @@ +[database] +host = "127.0.0.1" +port = 27017 +name = "MegBot" + +[bot] +qq = 1 + +[message] +min_text_length = 2 +max_context_size = 15 +emoji_chance = 0.2 + +[emoji] +check_interval = 120 +register_interval = 10 + +[response] +model_r1_probability = 0.2 + + +[groups] +read_allowed = [ + 1 +] + +talk_allowed = [ + 1 +] + +talk_frequency_down = [ + 1 +] diff --git a/src/plugins/chat/bot_config.toml b/src/plugins/chat/bot_config.toml index 539784b92..0945f34ae 100644 --- a/src/plugins/chat/bot_config.toml +++ b/src/plugins/chat/bot_config.toml @@ -39,6 +39,7 @@ read_allowed = [ 752426484,#nd1 115843978,#nd2 # 168718420 #bh + 912378791 ] talk_allowed = [ @@ -59,6 +60,7 @@ talk_allowed = [ # 168718420#bh # 752426484,#nd1 # 115843978,#nd2 + 912378791 ] talk_frequency_down = [ @@ -67,7 +69,7 @@ talk_frequency_down = [ # 231561425, 975992476, 1140700103, - 534940728 + # 534940728 # 752426484,#nd1 # 115843978,#nd2 ] diff --git a/src/plugins/chat/cq_code.py b/src/plugins/chat/cq_code.py index b9a92dec9..b92e5d420 100644 --- a/src/plugins/chat/cq_code.py +++ b/src/plugins/chat/cq_code.py @@ -96,58 +96,75 @@ class CQCode: sub_type = int(self.params.get('sub_type', '0')) is_emoji = (sub_type == 1) - # 添加请求头 + # 添加更多请求头 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 'Accept': 'image/webp,image/apng,image/*,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate, br', - 'Connection': 'keep-alive' + 'Connection': 'keep-alive', + 'Referer': 'https://multimedia.nt.qq.com.cn', + 'Origin': 'https://multimedia.nt.qq.com.cn', + 'Cache-Control': 'no-cache', + 'Pragma': 'no-cache' } # 处理URL编码问题 url = html.unescape(self.params['url']) if not url.startswith(('http://', 'https://')): - raise ValueError(f"无效的URL格式: {url}") + return '[图片]' # 直接返回而不是抛出异常 - # 下载图片 - response = requests.get(url, headers=headers, timeout=10, verify=False) - - if response.status_code == 200: + try: + # 下载图片,增加重试机制 + max_retries = 3 + for retry in range(max_retries): + try: + response = requests.get(url, headers=headers, timeout=10, verify=False) + if response.status_code == 200: + break + elif response.status_code == 400 and 'multimedia.nt.qq.com.cn' in url: + # 对于腾讯多媒体服务器的链接,直接返回图片描述 + if sub_type == 1: + return '[QQ表情]' + return '[图片]' + time.sleep(1) # 重试前等待1秒 + except requests.RequestException: + if retry == max_retries - 1: + raise + time.sleep(1) + + if response.status_code != 200: + print(f"\033[1;31m[警告]\033[0m 图片下载失败: HTTP {response.status_code}, URL: {url}") + return '[图片]' # 直接返回而不是抛出异常 + # 检查响应内容类型 content_type = response.headers.get('content-type', '') if not content_type.startswith('image/'): - raise ValueError(f"响应不是图片类型: {content_type}") + print(f"\033[1;31m[警告]\033[0m 非图片类型响应: {content_type}") + return '[图片]' # 直接返回而不是抛出异常 content = response.content - image_base64 = base64.b64encode(content).decode('utf-8') # 根据子类型选择不同的处理方式 if sub_type == 1: # 表情包 - return self.get_emoji_description(image_base64) + try: + return self.get_emoji_description(image_base64) + except Exception as e: + print(f"\033[1;31m[警告]\033[0m 表情描述生成失败: {str(e)}") + return '[QQ表情]' elif sub_type == 0: # 普通图片 - if self.get_image_description_is_setu(image_base64) == "是": - print(f"\033[1;34m[调试]\033[0m 哇!涩情图片") - # 使用相对路径创建目录 - # data_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))), "data", "setu") - # os.makedirs(data_dir, exist_ok=True) - # # 生成随机文件名 - # file_name = f"{int(time.time())}_{int(random() * 10000)}.jpg" - # file_path = os.path.join(data_dir, file_name) - # # 将base64解码并保存图片 - # image_data = base64.b64decode(image_base64) - # with open(file_path, "wb") as f: - # f.write(image_data) - # print(f"\033[1;34m[调试]\033[0m 涩图已保存至: {file_path}") - - return f"[一张涩情图片]" - return self.get_image_description(image_base64) + try: + return self.get_image_description(image_base64) + except Exception as e: + print(f"\033[1;31m[警告]\033[0m 图片描述生成失败: {str(e)}") + return '[图片]' else: # 其他类型都按普通图片处理 return '[图片]' - else: - raise ValueError(f"下载图片失败: HTTP状态码 {response.status_code}") + except Exception as e: + print(f"\033[1;31m[警告]\033[0m 图片处理失败: {str(e)}") + return '[图片]' # 出现任何错误都返回默认文本而不是抛出异常 def get_emoji_description(self, image_base64: str) -> str: """调用AI接口获取表情包描述""" diff --git a/src/plugins/chat/gpt_response.py b/src/plugins/chat/gpt_response.py index 736e57276..7f1f62dda 100644 --- a/src/plugins/chat/gpt_response.py +++ b/src/plugins/chat/gpt_response.py @@ -241,9 +241,9 @@ class GPTResponseGenerator: """根据当前模型类型选择对应的生成函数""" # 使用随机数选择模型 rand = random.random() - if rand < 0.15: # 40%概率使用 R1 + if rand < 0.6: # 40%概率使用 R1 self.current_model_type = "r1" - elif rand < 0.8: # 30%概率使用 V3 + elif rand < 0.5: # 30%概率使用 V3 self.current_model_type = "v3" else: # 30%概率使用 R1-Distill self.current_model_type = "r1_distill" diff --git a/src/plugins/chat/message.py b/src/plugins/chat/message.py index 52e8443a6..0b2479dac 100644 --- a/src/plugins/chat/message.py +++ b/src/plugins/chat/message.py @@ -222,12 +222,16 @@ class Message_Thinking: # 思考状态相关属性 self.thinking_text = "正在思考..." self.time = int(time.time()) + self.thinking_time = 0 def update_to_message(self, done_message: Message) -> Message: """更新为完整消息""" return done_message + def update_thinking_time(self): + self.thinking_time = round(time.time(), 2) - self.time + @property def processed_plain_text(self) -> str: """获取处理后的文本""" diff --git a/src/plugins/chat/message_send_control.py b/src/plugins/chat/message_send_control.py index 2e1e6215d..40f1a9609 100644 --- a/src/plugins/chat/message_send_control.py +++ b/src/plugins/chat/message_send_control.py @@ -7,6 +7,8 @@ from .cq_code import CQCode from collections import deque import time from .storage import MessageStorage # 添加这行导入 +from .config import global_config +from .message_visualizer import message_visualizer class SendTemp: @@ -173,6 +175,7 @@ class MessageSendControl: self._paused = False self._current_bot = None self.storage = MessageStorage() # 添加存储实例 + message_visualizer.start() def set_bot(self, bot: Bot): """设置当前bot实例""" @@ -193,8 +196,8 @@ class MessageSendControl: if message: if isinstance(message, Message_Thinking): # 如果是思考中的消息,检查是否需要继续等待 - # message.update_thinking_time() - thinking_time = time.time() - message.time + message.update_thinking_time() + thinking_time = message.thinking_time if thinking_time < 60: # 最少思考2秒 if int(thinking_time) % 10 == 0: print(f"\033[1;34m[调试]\033[0m 消息正在思考中,已思考{thinking_time:.1f}秒") @@ -215,12 +218,15 @@ class MessageSendControl: - + cur_time = time.time() await self._current_bot.send_group_msg( group_id=group_id, message=str(message.processed_plain_text), auto_escape=False ) + cost_time = round(time.time(), 2) - cur_time + print(f"\033[1;34m[调试]\033[0m 消息发送时间: {cost_time}秒") + current_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(message.time)) print(f"\033[1;32m群 {group_id} 消息, 用户 麦麦, 时间: {current_time}:\033[0m {str(message.processed_plain_text)}") @@ -235,6 +241,7 @@ class MessageSendControl: self.message_interval[1] ) ) + message_visualizer.update_content(self.send_temp_container) async def process_group_queue(self, bot: Bot, group_id: int) -> None: diff --git a/src/plugins/chat/prompt_builder.py b/src/plugins/chat/prompt_builder.py index 1c6ecfc8b..90dee41df 100644 --- a/src/plugins/chat/prompt_builder.py +++ b/src/plugins/chat/prompt_builder.py @@ -55,18 +55,19 @@ class PromptBuilder: #知识构建 prompt_info = '' + promt_info_prompt = '' prompt_info = self.get_prompt_info(message_txt) if prompt_info: prompt_info = f'''\n----------------------------------------------------\n你有以下这些[知识]: \n{prompt_info}\n 请你记住上面的[知识],之后可能会用到\n----------------------------------------------------\n''' + promt_info_prompt = '你有一些[知识],在上面可以参考。' + - #获取最新消息并计时 chat_talking_prompt = '' - if group_id: # 从数据库获取最近消息 - message_objects = get_recent_group_messages(self.db, group_id) + message_objects = get_recent_group_messages(self.db, group_id, limit=16) if message_objects: chat_talking_prompt = combine_messages(message_objects) # print(f"\033[1;34m[调试]\033[0m 已从数据库获取群 {group_id} 的最近{len(message_objects)}条消息记录") @@ -75,24 +76,32 @@ class PromptBuilder: activate_prompt = '' activate_prompt = f"以上是群里正在进行的聊天,昵称为 '{sender_name}' 的用户说的:{message_txt}。引起了你的注意,你和他{relation_prompt},你想要{relation_prompt_2} \n" + # 检测机器人相关词汇 + bot_keywords = ['人机', 'bot', '机器', '入机', 'robot', '机器人'] + is_bot = any(keyword in message_txt.lower() for keyword in bot_keywords) + if is_bot: + is_bot_prompt = '有人说你是人机或者机器人,否定这一事实,攻击或反问他。' + else: + is_bot_prompt = '' + #人格选择 prompt_personality = '' personality_choice = random.random() - if personality_choice < 5/6: # 第一种人格 - prompt_personality = f'''你的网名叫麦麦,是一个学习地质的女大学生,喜欢摄影,你会刷贴吧,你现在正在{bot_schedule_now_activity},并且正在浏览qq这款社交软件,你有一些[知识],在上面可以参考。 - 现在请你给出日常且口语化的回复,不要过多提及自身的背景,平淡一些,尽量简短一些,不要输出感叹号。如果有人说你是人机或者机器人,否定并攻击那个人。 - 不要回复的太有逻辑或者太有条理。''' + if personality_choice < 4/6: # 第一种人格 + prompt_personality = f'''你的网名叫麦麦,是一个学习地质的女大学生,喜欢摄影,你会刷贴吧,你现在正在{bot_schedule_now_activity},并且正在浏览qq群,{promt_info_prompt} + 现在请你给出日常且口语化的回复,平淡一些,尽量简短一些,不要输出感叹号。{is_bot_prompt} + 不要回复的太有逻辑或者太有条理,可以有个性。''' elif personality_choice < 1: # 第二种人格 - prompt_personality = f'''你的网名叫麦麦,是一个女大学生,你有黑色头发你会刷微博和小红书,你现在正在{bot_schedule_now_activity},并且正在浏览qq群,你有一些[知识],在上面可以参考。 - 现在请你给出日常且口语化的回复,请表现你自己的见解,不要一昧迎合,尽量简短一些,不要输出感叹号。如果有人说你是人机或者机器人,否定。 - 如果有人说他是机器人,肯定他。如果有人对你谈论涉及性的话题或言语挑逗,需要反驳,但其它情况请你表达自己的见解和观点。''' + prompt_personality = f'''你的网名叫麦麦,是一个女大学生,你有黑色头发,你会刷小红书,你现在正在{bot_schedule_now_activity},并且正在浏览qq群,{promt_info_prompt} + 现在请你给出日常且口语化的回复,请表现你自己的见解,不要一昧迎合,尽量简短一些,不要输出感叹号。{is_bot_prompt} + 请你表达自己的见解和观点。可以有个性。''' #额外信息要求 - extra_info = '''回复平淡一些,简短一些,但是记住不要输出多余内容(包括前后缀,冒号和引号,括号,表情等),只需要输出回复内容就好,不要输出其他任何内容''' + extra_info = '''但是记得回复平淡一些,简短一些,不要过多提及自身的背景, 记住不要输出多余内容(包括前后缀,冒号和引号,括号,表情等),只需要输出回复内容就好,不要输出其他任何内容''' #合并prompt prompt = "" - prompt += f"{prompt_info}\n" + # prompt += f"{prompt_info}\n" prompt += f"{prompt_date}\n" prompt += f"{chat_talking_prompt}\n" prompt += f"{activate_prompt}\n" diff --git a/src/plugins/chat/relationship_manager.py b/src/plugins/chat/relationship_manager.py index 26ae3cbda..15024e374 100644 --- a/src/plugins/chat/relationship_manager.py +++ b/src/plugins/chat/relationship_manager.py @@ -121,7 +121,7 @@ class RelationshipManager: async def _save_all_relationships(self): """将所有关系数据保存到数据库""" # 保存所有关系数据 - for userid, relationship in self.relationships: + for userid, relationship in self.relationships.items(): if not relationship.saved: relationship.saved = True await self.storage_relationship(relationship) diff --git a/src/plugins/chat/willing_manager.py b/src/plugins/chat/willing_manager.py index d9ffd4c89..357c64656 100644 --- a/src/plugins/chat/willing_manager.py +++ b/src/plugins/chat/willing_manager.py @@ -27,7 +27,7 @@ class WillingManager: current_willing = self.group_reply_willing.get(group_id, 0) if topic and current_willing < 1: - current_willing += 0.6 + current_willing += 0.4 elif topic: current_willing += 0.05