From 71bd75745d2b0c752711e98c00887f631b514183 Mon Sep 17 00:00:00 2001 From: tcmofashi Date: Tue, 4 Mar 2025 22:48:22 +0800 Subject: [PATCH 1/8] =?UTF-8?q?fix:=20logger=E4=B8=89=E5=90=88=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/chat/bot.py | 7 ++++--- src/plugins/chat/config.py | 10 ++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/plugins/chat/bot.py b/src/plugins/chat/bot.py index 85dbf2223..fc9ce3215 100644 --- a/src/plugins/chat/bot.py +++ b/src/plugins/chat/bot.py @@ -16,6 +16,7 @@ from .relationship_manager import relationship_manager from .willing_manager import willing_manager # 导入意愿管理器 from .utils import is_mentioned_bot_in_txt, calculate_typing_time from ..memory_system.memory import memory_graph +from loguru import logger class ChatBot: def __init__(self): @@ -98,8 +99,8 @@ class ChatBot: # 过滤词 for word in global_config.ban_words: if word in message.detailed_plain_text: - print(f"\033[1;32m[{message.group_name}]{message.user_nickname}:\033[0m {message.processed_plain_text}") - print(f"\033[1;32m[过滤词识别]\033[0m 消息中含有{word},filtered") + logger.info(f"\033[1;32m[{message.group_name}]{message.user_nickname}:\033[0m {message.processed_plain_text}") + logger.info(f"\033[1;32m[过滤词识别]\033[0m 消息中含有{word},filtered") return current_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(message.time)) @@ -113,7 +114,7 @@ class ChatBot: # topic1 = topic_identifier.identify_topic_jieba(message.processed_plain_text) # topic2 = await topic_identifier.identify_topic_llm(message.processed_plain_text) # topic3 = topic_identifier.identify_topic_snownlp(message.processed_plain_text) - print(f"\033[1;32m[主题识别]\033[0m 使用{global_config.topic_extract}主题: {topic}") + logger.info(f"\033[1;32m[主题识别]\033[0m 使用{global_config.topic_extract}主题: {topic}") all_num = 0 interested_num = 0 diff --git a/src/plugins/chat/config.py b/src/plugins/chat/config.py index a74a668a1..96c83dfe0 100644 --- a/src/plugins/chat/config.py +++ b/src/plugins/chat/config.py @@ -1,8 +1,6 @@ from dataclasses import dataclass, field from typing import Dict, Any, Optional, Set import os -from nonebot.log import logger, default_format -import logging import configparser import tomli import sys @@ -85,9 +83,9 @@ class BotConfig: personality_config=toml_dict['personality'] personality=personality_config.get('prompt_personality') if len(personality) >= 2: - print(f"载入自定义人格:{personality}") + logger.info(f"载入自定义人格:{personality}") config.PROMPT_PERSONALITY=personality_config.get('prompt_personality',config.PROMPT_PERSONALITY) - print(f"载入自定义日程prompt:{personality_config.get('prompt_schedule',config.PROMPT_SCHEDULE_GEN)}") + logger.info(f"载入自定义日程prompt:{personality_config.get('prompt_schedule',config.PROMPT_SCHEDULE_GEN)}") config.PROMPT_SCHEDULE_GEN=personality_config.get('prompt_schedule',config.PROMPT_SCHEDULE_GEN) if "emoji" in toml_dict: @@ -141,10 +139,10 @@ class BotConfig: topic_config=toml_dict['topic'] if 'topic_extract' in topic_config: config.topic_extract=topic_config.get('topic_extract',config.topic_extract) - print(f"载入自定义主题提取为{config.topic_extract}") + logger.info(f"载入自定义主题提取为{config.topic_extract}") if config.topic_extract=='llm' and 'llm_topic' in topic_config: config.llm_topic_extract=topic_config['llm_topic'] - print(f"载入自定义主题提取模型为{config.llm_topic_extract['name']}") + logger.info(f"载入自定义主题提取模型为{config.llm_topic_extract['name']}") # 消息配置 if "message" in toml_dict: From f6e5a15ed259ab2ca68a4bb1f0fabdfe69a79541 Mon Sep 17 00:00:00 2001 From: tcmofashi Date: Wed, 5 Mar 2025 09:04:10 +0800 Subject: [PATCH 2/8] =?UTF-8?q?fix:=20emoji=E5=8E=8B=E7=BC=A9=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E6=AD=A3=E5=B8=B8=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/chat/emoji_manager.py | 96 +++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 17 deletions(-) diff --git a/src/plugins/chat/emoji_manager.py b/src/plugins/chat/emoji_manager.py index cf0adff2e..239bb6d7a 100644 --- a/src/plugins/chat/emoji_manager.py +++ b/src/plugins/chat/emoji_manager.py @@ -12,6 +12,8 @@ import base64 import shutil import asyncio import time +from PIL import Image +import io from nonebot import get_driver from ..chat.config import global_config @@ -240,41 +242,102 @@ class EmojiManager: print(f"\033[1;32m[调试信息]\033[0m 使用默认标签: neutral") return "skip" # 默认标签 + async def _compress_image(self, image_path: str, target_size: int = 4 * 1024 * 1024) -> Optional[str]: + """压缩图片并返回base64编码 + Args: + image_path: 图片文件路径 + target_size: 目标文件大小(字节),默认4MB + Returns: + Optional[str]: 成功返回base64编码的图片数据,失败返回None + """ + try: + file_size = os.path.getsize(image_path) + if file_size <= target_size: + # 如果文件已经小于目标大小,直接读取并返回base64 + with open(image_path, 'rb') as f: + return base64.b64encode(f.read()).decode('utf-8') + + # 打开图片 + with Image.open(image_path) as img: + # 获取原始尺寸 + original_width, original_height = img.size + + # 计算缩放比例 + scale = min(1.0, (target_size / file_size) ** 0.5) + + # 计算新的尺寸 + new_width = int(original_width * scale) + new_height = int(original_height * scale) + + # 创建内存缓冲区 + output_buffer = io.BytesIO() + + # 如果是GIF,处理所有帧 + if getattr(img, "is_animated", False): + frames = [] + for frame_idx in range(img.n_frames): + img.seek(frame_idx) + new_frame = img.copy() + new_frame = new_frame.resize((new_width, new_height), Image.Resampling.LANCZOS) + frames.append(new_frame) + + # 保存到缓冲区 + frames[0].save( + output_buffer, + format='GIF', + save_all=True, + append_images=frames[1:], + optimize=True, + duration=img.info.get('duration', 100), + loop=img.info.get('loop', 0) + ) + else: + # 处理静态图片 + resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) + + # 保存到缓冲区,保持原始格式 + if img.format == 'PNG' and img.mode in ('RGBA', 'LA'): + resized_img.save(output_buffer, format='PNG', optimize=True) + else: + resized_img.save(output_buffer, format='JPEG', quality=95, optimize=True) + + # 获取压缩后的数据并转换为base64 + compressed_data = output_buffer.getvalue() + print(f"\033[1;32m[成功]\033[0m 压缩图片: {os.path.basename(image_path)} ({original_width}x{original_height} -> {new_width}x{new_height})") + + return base64.b64encode(compressed_data).decode('utf-8') + + except Exception as e: + print(f"\033[1;31m[错误]\033[0m 压缩图片失败: {os.path.basename(image_path)}, 错误: {str(e)}") + return None + async def scan_new_emojis(self): """扫描新的表情包""" try: emoji_dir = "data/emoji" os.makedirs(emoji_dir, exist_ok=True) - # 获取所有jpg文件 - files_to_process = [f for f in os.listdir(emoji_dir) if f.endswith('.jpg')] + # 获取所有支持的图片文件 + files_to_process = [f for f in os.listdir(emoji_dir) if f.lower().endswith(('.jpg', '.jpeg', '.png', '.gif'))] for filename in files_to_process: image_path = os.path.join(emoji_dir, filename) - # 检查文件大小 - file_size = os.path.getsize(image_path) - if file_size > 5 * 1024 * 1024: # 5MB - print(f"\033[1;33m[警告]\033[0m 表情包文件过大 ({file_size/1024/1024:.2f}MB),删除: {filename}") - os.remove(image_path) - continue - # 检查是否已经注册过 existing_emoji = self.db.db['emoji'].find_one({'filename': filename}) if existing_emoji: continue - - # 读取图片数据 - with open(image_path, 'rb') as f: - image_data = f.read() - # 将图片转换为base64 - image_base64 = base64.b64encode(image_data).decode('utf-8') + # 压缩图片并获取base64编码 + image_base64 = await self._compress_image(image_path) + if image_base64 is None: + os.remove(image_path) + continue # 获取表情包的情感标签 tag = await self._get_emoji_tag(image_base64) if not tag == "skip": - # 准备数据库记录 + # 准备数据库记录 emoji_record = { 'filename': filename, 'path': image_path, @@ -288,7 +351,6 @@ class EmojiManager: print(f"标签: {tag}") else: print(f"\033[1;33m[警告]\033[0m 跳过表情包: {filename}") - except Exception as e: print(f"\033[1;31m[错误]\033[0m 扫描表情包失败: {str(e)}") From dfdf25c8e4f00dcda934d7c621523ccfa9cca4a5 Mon Sep 17 00:00:00 2001 From: tcmofashi Date: Wed, 5 Mar 2025 09:10:22 +0800 Subject: [PATCH 3/8] =?UTF-8?q?fix:=20=E6=8F=90=E9=AB=98=E5=8E=8B=E7=BC=A9?= =?UTF-8?q?=E7=8E=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/chat/emoji_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/chat/emoji_manager.py b/src/plugins/chat/emoji_manager.py index 239bb6d7a..982f80c59 100644 --- a/src/plugins/chat/emoji_manager.py +++ b/src/plugins/chat/emoji_manager.py @@ -242,7 +242,7 @@ class EmojiManager: print(f"\033[1;32m[调试信息]\033[0m 使用默认标签: neutral") return "skip" # 默认标签 - async def _compress_image(self, image_path: str, target_size: int = 4 * 1024 * 1024) -> Optional[str]: + async def _compress_image(self, image_path: str, target_size: int = 0.8 * 1024 * 1024) -> Optional[str]: """压缩图片并返回base64编码 Args: image_path: 图片文件路径 From d1ac1b0573c8d9ff305beea57c21b7dcb265b7a7 Mon Sep 17 00:00:00 2001 From: tcmofashi Date: Wed, 5 Mar 2025 09:20:34 +0800 Subject: [PATCH 4/8] fix: 0.8MB --- src/plugins/chat/emoji_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/chat/emoji_manager.py b/src/plugins/chat/emoji_manager.py index 982f80c59..2311b2459 100644 --- a/src/plugins/chat/emoji_manager.py +++ b/src/plugins/chat/emoji_manager.py @@ -246,7 +246,7 @@ class EmojiManager: """压缩图片并返回base64编码 Args: image_path: 图片文件路径 - target_size: 目标文件大小(字节),默认4MB + target_size: 目标文件大小(字节),默认0.8MB Returns: Optional[str]: 成功返回base64编码的图片数据,失败返回None """ From f29a7b646c2809e376e4b6dbb3295c69b2388cb7 Mon Sep 17 00:00:00 2001 From: tcmofashi Date: Wed, 5 Mar 2025 19:19:34 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8E=8B=E7=BC=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/chat/utils_image.py | 71 ++++++++++++++++++++++++++++++- src/plugins/models/utils_model.py | 2 +- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/plugins/chat/utils_image.py b/src/plugins/chat/utils_image.py index efe2f1c92..cd6b98199 100644 --- a/src/plugins/chat/utils_image.py +++ b/src/plugins/chat/utils_image.py @@ -255,4 +255,73 @@ def compress_base64_image_by_scale(base64_data: str, scale: float = 0.5) -> str: print(f"\033[1;31m[错误]\033[0m 压缩图片失败: {str(e)}") import traceback print(traceback.format_exc()) - return base64_data \ No newline at end of file + return base64_data + +async def compress_image( image_path: str, target_size: int = 0.8 * 1024 * 1024): + """压缩图片并返回base64编码 + Args: + image_path: 图片文件路径 + target_size: 目标文件大小(字节),默认0.8MB + Returns: + Optional[str]: 成功返回base64编码的图片数据,失败返回None + """ + try: + file_size = os.path.getsize(image_path) + if file_size <= target_size: + # 如果文件已经小于目标大小,直接读取并返回base64 + with open(image_path, 'rb') as f: + return base64.b64encode(f.read()).decode('utf-8') + + # 打开图片 + with Image.open(image_path) as img: + # 获取原始尺寸 + original_width, original_height = img.size + + # 计算缩放比例 + scale = min(1.0, (target_size / file_size) ** 0.5) + + # 计算新的尺寸 + new_width = int(original_width * scale) + new_height = int(original_height * scale) + + # 创建内存缓冲区 + output_buffer = io.BytesIO() + + # 如果是GIF,处理所有帧 + if getattr(img, "is_animated", False): + frames = [] + for frame_idx in range(img.n_frames): + img.seek(frame_idx) + new_frame = img.copy() + new_frame = new_frame.resize((new_width, new_height), Image.Resampling.LANCZOS) + frames.append(new_frame) + + # 保存到缓冲区 + frames[0].save( + output_buffer, + format='GIF', + save_all=True, + append_images=frames[1:], + optimize=True, + duration=img.info.get('duration', 100), + loop=img.info.get('loop', 0) + ) + else: + # 处理静态图片 + resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) + + # 保存到缓冲区,保持原始格式 + if img.format == 'PNG' and img.mode in ('RGBA', 'LA'): + resized_img.save(output_buffer, format='PNG', optimize=True) + else: + resized_img.save(output_buffer, format='JPEG', quality=95, optimize=True) + + # 获取压缩后的数据并转换为base64 + compressed_data = output_buffer.getvalue() + print(f"\033[1;32m[成功]\033[0m 压缩图片: {os.path.basename(image_path)} ({original_width}x{original_height} -> {new_width}x{new_height})") + + return base64.b64encode(compressed_data).decode('utf-8') + + except Exception as e: + print(f"\033[1;31m[错误]\033[0m 压缩图片失败: {os.path.basename(image_path)}, 错误: {str(e)}") + return None \ No newline at end of file diff --git a/src/plugins/models/utils_model.py b/src/plugins/models/utils_model.py index 3ba873d74..261fe88dd 100644 --- a/src/plugins/models/utils_model.py +++ b/src/plugins/models/utils_model.py @@ -7,7 +7,7 @@ from typing import Tuple, Union from nonebot import get_driver from loguru import logger from ..chat.config import global_config -from ..chat.utils_image import compress_base64_image_by_scale +from ..chat.utils_image import compress_base64_image_by_scale,compress_image driver = get_driver() config = driver.config From ab259c20aa6a9e190078c0f7de85b0c3485ee050 Mon Sep 17 00:00:00 2001 From: tcmofashi Date: Wed, 5 Mar 2025 22:04:36 +0800 Subject: [PATCH 6/8] =?UTF-8?q?fix:=20=E5=A2=9E=E5=BC=BA=E6=83=85=E6=84=9F?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E7=94=9F=E6=88=90=E7=9A=84=E9=B2=81=E6=A3=92?= =?UTF-8?q?=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/chat/llm_generator.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/plugins/chat/llm_generator.py b/src/plugins/chat/llm_generator.py index 034ff7348..f380d62f4 100644 --- a/src/plugins/chat/llm_generator.py +++ b/src/plugins/chat/llm_generator.py @@ -138,9 +138,12 @@ class ResponseGenerator: 内容:{content} 输出: ''' - content, _ = await self.model_v3.generate_response(prompt) - return [content.strip()] if content else ["neutral"] + content=content.strip() + if content in ['happy','angry','sad','surprised','disgusted','fearful','neutral']: + return [content] + else: + return ["neutral"] except Exception as e: print(f"获取情感标签时出错: {e}") From 1484dfa4066f0468c2508ba079f2979540286e90 Mon Sep 17 00:00:00 2001 From: tcmofashi Date: Wed, 5 Mar 2025 22:04:36 +0800 Subject: [PATCH 7/8] =?UTF-8?q?fix:=20=E5=A2=9E=E5=BC=BA=E6=83=85=E6=84=9F?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E7=94=9F=E6=88=90=E7=9A=84=E9=B2=81=E6=A3=92?= =?UTF-8?q?=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/chat/llm_generator.py | 7 +++- src/plugins/chat/utils_image.py | 70 +------------------------------ 2 files changed, 6 insertions(+), 71 deletions(-) diff --git a/src/plugins/chat/llm_generator.py b/src/plugins/chat/llm_generator.py index 034ff7348..f380d62f4 100644 --- a/src/plugins/chat/llm_generator.py +++ b/src/plugins/chat/llm_generator.py @@ -138,9 +138,12 @@ class ResponseGenerator: 内容:{content} 输出: ''' - content, _ = await self.model_v3.generate_response(prompt) - return [content.strip()] if content else ["neutral"] + content=content.strip() + if content in ['happy','angry','sad','surprised','disgusted','fearful','neutral']: + return [content] + else: + return ["neutral"] except Exception as e: print(f"获取情感标签时出错: {e}") diff --git a/src/plugins/chat/utils_image.py b/src/plugins/chat/utils_image.py index cd6b98199..bfcdab89e 100644 --- a/src/plugins/chat/utils_image.py +++ b/src/plugins/chat/utils_image.py @@ -256,72 +256,4 @@ def compress_base64_image_by_scale(base64_data: str, scale: float = 0.5) -> str: import traceback print(traceback.format_exc()) return base64_data - -async def compress_image( image_path: str, target_size: int = 0.8 * 1024 * 1024): - """压缩图片并返回base64编码 - Args: - image_path: 图片文件路径 - target_size: 目标文件大小(字节),默认0.8MB - Returns: - Optional[str]: 成功返回base64编码的图片数据,失败返回None - """ - try: - file_size = os.path.getsize(image_path) - if file_size <= target_size: - # 如果文件已经小于目标大小,直接读取并返回base64 - with open(image_path, 'rb') as f: - return base64.b64encode(f.read()).decode('utf-8') - - # 打开图片 - with Image.open(image_path) as img: - # 获取原始尺寸 - original_width, original_height = img.size - - # 计算缩放比例 - scale = min(1.0, (target_size / file_size) ** 0.5) - - # 计算新的尺寸 - new_width = int(original_width * scale) - new_height = int(original_height * scale) - - # 创建内存缓冲区 - output_buffer = io.BytesIO() - - # 如果是GIF,处理所有帧 - if getattr(img, "is_animated", False): - frames = [] - for frame_idx in range(img.n_frames): - img.seek(frame_idx) - new_frame = img.copy() - new_frame = new_frame.resize((new_width, new_height), Image.Resampling.LANCZOS) - frames.append(new_frame) - - # 保存到缓冲区 - frames[0].save( - output_buffer, - format='GIF', - save_all=True, - append_images=frames[1:], - optimize=True, - duration=img.info.get('duration', 100), - loop=img.info.get('loop', 0) - ) - else: - # 处理静态图片 - resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) - - # 保存到缓冲区,保持原始格式 - if img.format == 'PNG' and img.mode in ('RGBA', 'LA'): - resized_img.save(output_buffer, format='PNG', optimize=True) - else: - resized_img.save(output_buffer, format='JPEG', quality=95, optimize=True) - - # 获取压缩后的数据并转换为base64 - compressed_data = output_buffer.getvalue() - print(f"\033[1;32m[成功]\033[0m 压缩图片: {os.path.basename(image_path)} ({original_width}x{original_height} -> {new_width}x{new_height})") - - return base64.b64encode(compressed_data).decode('utf-8') - - except Exception as e: - print(f"\033[1;31m[错误]\033[0m 压缩图片失败: {os.path.basename(image_path)}, 错误: {str(e)}") - return None \ No newline at end of file + \ No newline at end of file From 71a0176182a55a5b6dbc1cece7fbc9af8246efd1 Mon Sep 17 00:00:00 2001 From: tcmofashi Date: Wed, 5 Mar 2025 22:08:23 +0800 Subject: [PATCH 8/8] =?UTF-8?q?fix:=20=E5=B0=8F=E4=BF=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/chat/utils_image.py | 3 +-- src/plugins/models/utils_model.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/plugins/chat/utils_image.py b/src/plugins/chat/utils_image.py index bfcdab89e..efe2f1c92 100644 --- a/src/plugins/chat/utils_image.py +++ b/src/plugins/chat/utils_image.py @@ -255,5 +255,4 @@ def compress_base64_image_by_scale(base64_data: str, scale: float = 0.5) -> str: print(f"\033[1;31m[错误]\033[0m 压缩图片失败: {str(e)}") import traceback print(traceback.format_exc()) - return base64_data - \ No newline at end of file + return base64_data \ No newline at end of file diff --git a/src/plugins/models/utils_model.py b/src/plugins/models/utils_model.py index 261fe88dd..3ba873d74 100644 --- a/src/plugins/models/utils_model.py +++ b/src/plugins/models/utils_model.py @@ -7,7 +7,7 @@ from typing import Tuple, Union from nonebot import get_driver from loguru import logger from ..chat.config import global_config -from ..chat.utils_image import compress_base64_image_by_scale,compress_image +from ..chat.utils_image import compress_base64_image_by_scale driver = get_driver() config = driver.config