From 263e8d196ad5ecda2312dba284f301da4616e134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=99=B4=E7=8C=AB?= Date: Thu, 1 May 2025 06:55:05 +0900 Subject: [PATCH] fix: Update type hints to use newer Python syntax MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace Dict, List, Optional with dict, list, < /dev/null | None syntax - Fix abstract method implementation in message.py - Improve type annotations and function return types - Remove unreachable code in get_current_task_tool.py - Refactor HTML elements to use style attributes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- README.md | 16 ++-- scripts/import_openie.py | 7 +- src/api/config_api.py | 28 +++---- src/common/logger.py | 6 +- src/common/message_repository.py | 8 +- src/config/config.py | 4 +- src/do_tool/not_used/change_mood.py | 6 +- src/do_tool/not_used/change_relationship.py | 2 +- src/do_tool/not_used/get_current_task.py | 9 ++- src/do_tool/not_used/mid_chat_mem.py | 6 +- src/do_tool/not_used/send_emoji.py | 2 +- src/do_tool/tool_can_use/README.md | 2 +- src/do_tool/tool_can_use/base_tool.py | 12 +-- .../tool_can_use/compare_numbers_tool.py | 7 +- src/do_tool/tool_can_use/get_knowledge.py | 7 +- src/do_tool/tool_can_use/get_memory.py | 1 - src/do_tool/tool_can_use/get_time_date.py | 1 - .../tool_can_use/lpmm_get_knowledge.py | 1 - src/do_tool/tool_use.py | 1 - src/individuality/scene.py | 12 +-- src/plugins/PFC/chat_observer.py | 1 + src/plugins/PFC/pfc_manager.py | 1 + src/plugins/PFC/pfc_utils.py | 1 + src/plugins/PFC/reply_checker.py | 2 + src/plugins/chat/message.py | 80 ++++++++----------- src/plugins/chat/message_sender.py | 16 ++-- src/plugins/chat/utils.py | 22 +++-- src/plugins/memory_system/Hippocampus.py | 4 +- src/plugins/schedule/schedule_generator.py | 3 +- 29 files changed, 125 insertions(+), 143 deletions(-) diff --git a/README.md b/README.md index 58cb82c7d..f349e0ca7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 麦麦!MaiCore-MaiMBot (编辑中)
-
+
![Python Version](https://img.shields.io/badge/Python-3.10+-blue) ![License](https://img.shields.io/github/license/SengokuCola/MaiMBot?label=协议) @@ -12,7 +12,7 @@
-

+

Logo @@ -21,8 +21,8 @@ 画师:略nd -

MaiBot(麦麦)

-

+

MaiBot(麦麦)

+

一款专注于 群组聊天 的赛博网友
探索本项目的文档 » @@ -50,7 +50,7 @@ - 🧠 **持久记忆系统**:基于MongoDB的长期记忆存储 - 🔄 **动态人格系统**:自适应的性格特征 -

+
麦麦演示视频
@@ -97,9 +97,9 @@ - [四群](https://qm.qq.com/q/wlH5eT8OmQ) 729957033【已满】 -
-

📚 文档

-
+ +## 📚 文档 + ### (部分内容可能过时,请注意版本对应) diff --git a/scripts/import_openie.py b/scripts/import_openie.py index 26cbd8ce1..595f22ec2 100644 --- a/scripts/import_openie.py +++ b/scripts/import_openie.py @@ -8,7 +8,6 @@ import sys import os sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) -from typing import Dict, List from src.plugins.knowledge.src.lpmmconfig import PG_NAMESPACE, global_config from src.plugins.knowledge.src.embedding_store import EmbeddingManager @@ -26,8 +25,8 @@ logger = get_module_logger("LPMM知识库-OpenIE导入") def hash_deduplicate( - raw_paragraphs: Dict[str, str], - triple_list_data: Dict[str, List[List[str]]], + raw_paragraphs: dict[str, str], + triple_list_data: dict[str, list[list[str]]], stored_pg_hashes: set, stored_paragraph_hashes: set, ): @@ -126,7 +125,7 @@ def main(): ) # 初始化Embedding库 - embed_manager = embed_manager = EmbeddingManager(llm_client_list[global_config["embedding"]["provider"]]) + embed_manager = EmbeddingManager(llm_client_list[global_config["embedding"]["provider"]]) logger.info("正在从文件加载Embedding库") try: embed_manager.load_from_file() diff --git a/src/api/config_api.py b/src/api/config_api.py index 025888d82..6ecd4e6db 100644 --- a/src/api/config_api.py +++ b/src/api/config_api.py @@ -1,4 +1,4 @@ -from typing import Dict, List, Optional +from typing import List, Optional import strawberry # from packaging.version import Version, InvalidVersion @@ -128,22 +128,22 @@ class BotConfig: enable_pfc_chatting: bool # 是否启用PFC聊天 # 模型配置 - llm_reasoning: Dict[str, str] # LLM推理 - # llm_reasoning_minor: Dict[str, str] - llm_normal: Dict[str, str] # LLM普通 - llm_topic_judge: Dict[str, str] # LLM话题判断 - llm_summary: Dict[str, str] # LLM话题总结 - llm_emotion_judge: Dict[str, str] # LLM情感判断 - embedding: Dict[str, str] # 嵌入 - vlm: Dict[str, str] # VLM - moderation: Dict[str, str] # 审核 + llm_reasoning: dict[str, str] # LLM推理 + # llm_reasoning_minor: dict[str, str] + llm_normal: dict[str, str] # LLM普通 + llm_topic_judge: dict[str, str] # LLM话题判断 + llm_summary: dict[str, str] # LLM话题总结 + llm_emotion_judge: dict[str, str] # LLM情感判断 + embedding: dict[str, str] # 嵌入 + vlm: dict[str, str] # VLM + moderation: dict[str, str] # 审核 # 实验性 - llm_observation: Dict[str, str] # LLM观察 - llm_sub_heartflow: Dict[str, str] # LLM子心流 - llm_heartflow: Dict[str, str] # LLM心流 + llm_observation: dict[str, str] # LLM观察 + llm_sub_heartflow: dict[str, str] # LLM子心流 + llm_heartflow: dict[str, str] # LLM心流 - api_urls: Dict[str, str] # API URLs + api_urls: dict[str, str] # API URLs @strawberry.type diff --git a/src/common/logger.py b/src/common/logger.py index a0d621d9b..a82c6d883 100644 --- a/src/common/logger.py +++ b/src/common/logger.py @@ -1,5 +1,5 @@ from loguru import logger -from typing import Dict, Optional, Union, List, Tuple +from typing import Optional, Union, List, Tuple import sys import os from types import ModuleType @@ -75,8 +75,8 @@ if default_handler_id is not None: LoguruLogger = logger.__class__ # 全局注册表:记录模块与处理器ID的映射 -_handler_registry: Dict[str, List[int]] = {} -_custom_style_handlers: Dict[Tuple[str, str], List[int]] = {} # 记录自定义样式处理器ID +_handler_registry: dict[str, List[int]] = {} +_custom_style_handlers: dict[Tuple[str, str], List[int]] = {} # 记录自定义样式处理器ID # 获取日志存储根地址 current_file_path = Path(__file__).resolve() diff --git a/src/common/message_repository.py b/src/common/message_repository.py index 72643f913..11bd6095e 100644 --- a/src/common/message_repository.py +++ b/src/common/message_repository.py @@ -7,11 +7,11 @@ logger = get_module_logger(__name__) def find_messages( - message_filter: Dict[str, Any], + message_filter: dict[str, Any], sort: Optional[List[tuple[str, int]]] = None, limit: int = 0, limit_mode: str = "latest", -) -> List[Dict[str, Any]]: +) -> List[dict[str, Any]]: """ 根据提供的过滤器、排序和限制条件查找消息。 @@ -26,7 +26,7 @@ def find_messages( """ try: query = db.messages.find(message_filter) - results: List[Dict[str, Any]] = [] + results: List[dict[str, Any]] = [] if limit > 0: if limit_mode == "earliest": @@ -56,7 +56,7 @@ def find_messages( return [] -def count_messages(message_filter: Dict[str, Any]) -> int: +def count_messages(message_filter: dict[str, Any]) -> int: """ 根据提供的过滤器计算消息数量。 diff --git a/src/config/config.py b/src/config/config.py index fbf558a37..033d57f56 100644 --- a/src/config/config.py +++ b/src/config/config.py @@ -271,8 +271,8 @@ class BotConfig: enable_pfc_chatting: bool = False # 是否启用PFC聊天 # 模型配置 - llm_reasoning: Dict[str, str] = field(default_factory=lambda: {}) - # llm_reasoning_minor: Dict[str, str] = field(default_factory=lambda: {}) + llm_reasoning: dict[str, str] = field(default_factory=lambda: {}) + # llm_reasoning_minor: dict[str, str] = field(default_factory=lambda: {}) llm_normal: Dict[str, str] = field(default_factory=lambda: {}) llm_topic_judge: Dict[str, str] = field(default_factory=lambda: {}) llm_summary: Dict[str, str] = field(default_factory=lambda: {}) diff --git a/src/do_tool/not_used/change_mood.py b/src/do_tool/not_used/change_mood.py index 430561a26..5dee6ac98 100644 --- a/src/do_tool/not_used/change_mood.py +++ b/src/do_tool/not_used/change_mood.py @@ -3,7 +3,7 @@ from src.config.config import global_config from src.common.logger_manager import get_logger from src.plugins.moods.moods import MoodManager -from typing import Dict, Any +from typing import Any logger = get_logger("change_mood_tool") @@ -22,7 +22,7 @@ class ChangeMoodTool(BaseTool): "required": ["text", "response_set"], } - async def execute(self, function_args: Dict[str, Any], message_txt: str = "") -> Dict[str, Any]: + async def execute(self, function_args: dict[str, Any], message_txt: str = "") -> dict[str, Any]: """执行心情改变 Args: @@ -30,7 +30,7 @@ class ChangeMoodTool(BaseTool): message_txt: 原始消息文本 Returns: - Dict: 工具执行结果 + dict: 工具执行结果 """ try: response_set = function_args.get("response_set") diff --git a/src/do_tool/not_used/change_relationship.py b/src/do_tool/not_used/change_relationship.py index 4af32fb8c..ab91489fc 100644 --- a/src/do_tool/not_used/change_relationship.py +++ b/src/do_tool/not_used/change_relationship.py @@ -19,7 +19,7 @@ class RelationshipTool(BaseTool): "required": ["text", "changed_value", "reason"], } - async def execute(self, function_args: Dict[str, Any], message_txt: str = "") -> dict: + async def execute(self, function_args: dict[str, Any], message_txt: str = "") -> dict: """执行工具功能 Args: diff --git a/src/do_tool/not_used/get_current_task.py b/src/do_tool/not_used/get_current_task.py index d5660f6ab..30184d672 100644 --- a/src/do_tool/not_used/get_current_task.py +++ b/src/do_tool/not_used/get_current_task.py @@ -1,7 +1,7 @@ from src.do_tool.tool_can_use.base_tool import BaseTool from src.plugins.schedule.schedule_generator import bot_schedule from src.common.logger import get_module_logger -from typing import Dict, Any +from typing import Any from datetime import datetime logger = get_module_logger("get_current_task_tool") @@ -21,7 +21,7 @@ class GetCurrentTaskTool(BaseTool): "required": ["start_time", "end_time"], } - async def execute(self, function_args: Dict[str, Any], message_txt: str = "") -> Dict[str, Any]: + async def execute(self, function_args: dict[str, Any], message_txt: str = "") -> dict[str, Any]: """执行获取当前任务或指定时间段的日程信息 Args: @@ -29,7 +29,7 @@ class GetCurrentTaskTool(BaseTool): message_txt: 原始消息文本,此工具不使用 Returns: - Dict: 工具执行结果 + dict: 工具执行结果 """ start_time = function_args.get("start_time") end_time = function_args.get("end_time") @@ -55,5 +55,6 @@ class GetCurrentTaskTool(BaseTool): task_info = "\n".join(task_list) else: task_info = f"在 {start_time} 到 {end_time} 之间没有找到日程信息" - + else: + task_info = "请提供有效的开始时间和结束时间" return {"name": "get_current_task", "content": f"日程信息: {task_info}"} diff --git a/src/do_tool/not_used/mid_chat_mem.py b/src/do_tool/not_used/mid_chat_mem.py index 71726a57f..0340df139 100644 --- a/src/do_tool/not_used/mid_chat_mem.py +++ b/src/do_tool/not_used/mid_chat_mem.py @@ -1,6 +1,6 @@ from src.do_tool.tool_can_use.base_tool import BaseTool from src.common.logger import get_module_logger -from typing import Dict, Any +from typing import Any logger = get_module_logger("get_mid_memory_tool") @@ -18,7 +18,7 @@ class GetMidMemoryTool(BaseTool): "required": ["id"], } - async def execute(self, function_args: Dict[str, Any], message_txt: str = "") -> Dict[str, Any]: + async def execute(self, function_args: dict[str, Any], message_txt: str = "") -> dict[str, Any]: """执行记忆获取 Args: @@ -26,7 +26,7 @@ class GetMidMemoryTool(BaseTool): message_txt: 原始消息文本 Returns: - Dict: 工具执行结果 + dict: 工具执行结果 """ try: id = function_args.get("id") diff --git a/src/do_tool/not_used/send_emoji.py b/src/do_tool/not_used/send_emoji.py index 3c6c8a3f1..9bf2dd482 100644 --- a/src/do_tool/not_used/send_emoji.py +++ b/src/do_tool/not_used/send_emoji.py @@ -17,7 +17,7 @@ class SendEmojiTool(BaseTool): "required": ["text"], } - async def execute(self, function_args: Dict[str, Any], message_txt: str = "") -> Dict[str, Any]: + async def execute(self, function_args: dict[str, Any], message_txt: str = "") -> dict[str, Any]: text = function_args.get("text", message_txt) return { "name": "send_emoji", diff --git a/src/do_tool/tool_can_use/README.md b/src/do_tool/tool_can_use/README.md index 15c771887..0b746b4ec 100644 --- a/src/do_tool/tool_can_use/README.md +++ b/src/do_tool/tool_can_use/README.md @@ -42,7 +42,7 @@ class MyNewTool(BaseTool): message_txt: 原始消息文本 Returns: - Dict: 包含执行结果的字典,必须包含name和content字段 + dict: 包含执行结果的字典,必须包含name和content字段 """ # 实现工具逻辑 result = f"工具执行结果: {function_args.get('param1')}" diff --git a/src/do_tool/tool_can_use/base_tool.py b/src/do_tool/tool_can_use/base_tool.py index 1dd15bafc..b01e543e5 100644 --- a/src/do_tool/tool_can_use/base_tool.py +++ b/src/do_tool/tool_can_use/base_tool.py @@ -22,11 +22,11 @@ class BaseTool: parameters = None @classmethod - def get_tool_definition(cls) -> Dict[str, Any]: + def get_tool_definition(cls) -> dict[str, Any]: """获取工具定义,用于LLM工具调用 Returns: - Dict: 工具定义字典 + dict: 工具定义字典 """ if not cls.name or not cls.description or not cls.parameters: raise NotImplementedError(f"工具类 {cls.__name__} 必须定义 name, description 和 parameters 属性") @@ -36,14 +36,14 @@ class BaseTool: "function": {"name": cls.name, "description": cls.description, "parameters": cls.parameters}, } - async def execute(self, function_args: Dict[str, Any]) -> Dict[str, Any]: + async def execute(self, function_args: dict[str, Any]) -> dict[str, Any]: """执行工具函数 Args: function_args: 工具调用参数 Returns: - Dict: 工具执行结果 + dict: 工具执行结果 """ raise NotImplementedError("子类必须实现execute方法") @@ -88,11 +88,11 @@ def discover_tools(): logger.info(f"工具发现完成,共注册 {len(TOOL_REGISTRY)} 个工具") -def get_all_tool_definitions() -> List[Dict[str, Any]]: +def get_all_tool_definitions() -> List[dict[str, Any]]: """获取所有已注册工具的定义 Returns: - List[Dict]: 工具定义列表 + List[dict]: 工具定义列表 """ return [tool_class().get_tool_definition() for tool_class in TOOL_REGISTRY.values()] diff --git a/src/do_tool/tool_can_use/compare_numbers_tool.py b/src/do_tool/tool_can_use/compare_numbers_tool.py index 1fbd812a0..ef037de9e 100644 --- a/src/do_tool/tool_can_use/compare_numbers_tool.py +++ b/src/do_tool/tool_can_use/compare_numbers_tool.py @@ -1,6 +1,6 @@ from src.do_tool.tool_can_use.base_tool import BaseTool from src.common.logger import get_module_logger -from typing import Dict, Any +from typing import Any logger = get_module_logger("compare_numbers_tool") @@ -19,15 +19,14 @@ class CompareNumbersTool(BaseTool): "required": ["num1", "num2"], } - async def execute(self, function_args: Dict[str, Any]) -> Dict[str, Any]: + async def execute(self, function_args: dict[str, Any]) -> dict[str, Any]: """执行比较两个数的大小 Args: function_args: 工具参数 - message_txt: 原始消息文本 Returns: - Dict: 工具执行结果 + dict: 工具执行结果 """ try: num1 = function_args.get("num1") diff --git a/src/do_tool/tool_can_use/get_knowledge.py b/src/do_tool/tool_can_use/get_knowledge.py index bd4ce86b4..20a922646 100644 --- a/src/do_tool/tool_can_use/get_knowledge.py +++ b/src/do_tool/tool_can_use/get_knowledge.py @@ -2,7 +2,7 @@ from src.do_tool.tool_can_use.base_tool import BaseTool from src.plugins.chat.utils import get_embedding from src.common.database import db from src.common.logger_manager import get_logger -from typing import Dict, Any, Union +from typing import Any, Union logger = get_logger("get_knowledge_tool") @@ -21,15 +21,14 @@ class SearchKnowledgeTool(BaseTool): "required": ["query"], } - async def execute(self, function_args: Dict[str, Any]) -> Dict[str, Any]: + async def execute(self, function_args: dict[str, Any]) -> dict[str, Any]: """执行知识库搜索 Args: function_args: 工具参数 - message_txt: 原始消息文本 Returns: - Dict: 工具执行结果 + dict: 工具执行结果 """ try: query = function_args.get("query") diff --git a/src/do_tool/tool_can_use/get_memory.py b/src/do_tool/tool_can_use/get_memory.py index b38423ed0..c1bcc9277 100644 --- a/src/do_tool/tool_can_use/get_memory.py +++ b/src/do_tool/tool_can_use/get_memory.py @@ -25,7 +25,6 @@ class GetMemoryTool(BaseTool): Args: function_args: 工具参数 - message_txt: 原始消息文本 Returns: Dict: 工具执行结果 diff --git a/src/do_tool/tool_can_use/get_time_date.py b/src/do_tool/tool_can_use/get_time_date.py index 6104026ef..bd3b1a9c1 100644 --- a/src/do_tool/tool_can_use/get_time_date.py +++ b/src/do_tool/tool_can_use/get_time_date.py @@ -22,7 +22,6 @@ class GetCurrentDateTimeTool(BaseTool): Args: function_args: 工具参数(此工具不使用) - message_txt: 原始消息文本(此工具不使用) Returns: Dict: 工具执行结果 diff --git a/src/do_tool/tool_can_use/lpmm_get_knowledge.py b/src/do_tool/tool_can_use/lpmm_get_knowledge.py index 4dba1bc71..8754e603b 100644 --- a/src/do_tool/tool_can_use/lpmm_get_knowledge.py +++ b/src/do_tool/tool_can_use/lpmm_get_knowledge.py @@ -29,7 +29,6 @@ class SearchKnowledgeFromLPMMTool(BaseTool): Args: function_args: 工具参数 - message_txt: 原始消息文本 Returns: Dict: 工具执行结果 diff --git a/src/do_tool/tool_use.py b/src/do_tool/tool_use.py index 88289fe01..b2f59cc8b 100644 --- a/src/do_tool/tool_use.py +++ b/src/do_tool/tool_use.py @@ -106,7 +106,6 @@ class ToolUser: Args: message_txt: 用户消息文本 - sender_name: 发送者名称 chat_stream: 聊天流对象 observation: 观察对象(可选) diff --git a/src/individuality/scene.py b/src/individuality/scene.py index 76304dbbd..4edd5dc21 100644 --- a/src/individuality/scene.py +++ b/src/individuality/scene.py @@ -1,9 +1,9 @@ import json -from typing import Dict import os +from typing import Any -def load_scenes() -> Dict: +def load_scenes() -> dict[str, Any]: """ 从JSON文件加载场景数据 @@ -20,7 +20,7 @@ def load_scenes() -> Dict: PERSONALITY_SCENES = load_scenes() -def get_scene_by_factor(factor: str) -> Dict: +def get_scene_by_factor(factor: str) -> dict | None: """ 根据人格因子获取对应的情景测试 @@ -28,12 +28,12 @@ def get_scene_by_factor(factor: str) -> Dict: factor (str): 人格因子名称 Returns: - Dict: 包含情景描述的字典 + dict: 包含情景描述的字典 """ - return PERSONALITY_SCENES.get(factor, None) + return PERSONALITY_SCENES.get(factor,None) -def get_all_scenes() -> Dict: +def get_all_scenes() -> dict: """ 获取所有情景测试 diff --git a/src/plugins/PFC/chat_observer.py b/src/plugins/PFC/chat_observer.py index 2822e1111..e99ed8005 100644 --- a/src/plugins/PFC/chat_observer.py +++ b/src/plugins/PFC/chat_observer.py @@ -23,6 +23,7 @@ class ChatObserver: Args: stream_id: 聊天流ID + private_name: 私聊名称 Returns: ChatObserver: 观察器实例 diff --git a/src/plugins/PFC/pfc_manager.py b/src/plugins/PFC/pfc_manager.py index 621686a90..7837606ca 100644 --- a/src/plugins/PFC/pfc_manager.py +++ b/src/plugins/PFC/pfc_manager.py @@ -33,6 +33,7 @@ class PFCManager: Args: stream_id: 聊天流ID + private_name: 私聊名称 Returns: Optional[Conversation]: 对话实例,创建失败则返回None diff --git a/src/plugins/PFC/pfc_utils.py b/src/plugins/PFC/pfc_utils.py index 5e35d47be..2f7bd5e06 100644 --- a/src/plugins/PFC/pfc_utils.py +++ b/src/plugins/PFC/pfc_utils.py @@ -18,6 +18,7 @@ def get_items_from_json( Args: content: 包含JSON的文本 + private_name: 私聊名称 *items: 要提取的字段名 default_values: 字段的默认值,格式为 {字段名: 默认值} required_types: 字段的必需类型,格式为 {字段名: 类型} diff --git a/src/plugins/PFC/reply_checker.py b/src/plugins/PFC/reply_checker.py index 180888956..35e9af500 100644 --- a/src/plugins/PFC/reply_checker.py +++ b/src/plugins/PFC/reply_checker.py @@ -29,6 +29,8 @@ class ReplyChecker: Args: reply: 生成的回复 goal: 对话目标 + chat_history: 对话历史记录 + chat_history_text: 对话历史记录文本 retry_count: 当前重试次数 Returns: diff --git a/src/plugins/chat/message.py b/src/plugins/chat/message.py index 525d30c9b..2de88561b 100644 --- a/src/plugins/chat/message.py +++ b/src/plugins/chat/message.py @@ -1,6 +1,7 @@ import time +from abc import abstractmethod from dataclasses import dataclass -from typing import Dict, List, Optional, Union +from typing import Optional, Any import urllib3 @@ -58,12 +59,37 @@ class Message(MessageBase): # 回复消息 self.reply = reply + async def _process_message_segments(self, segment: Seg) -> str: + """递归处理消息段,转换为文字描述 + + Args: + segment: 要处理的消息段 + + Returns: + str: 处理后的文本 + """ + if segment.type == "seglist": + # 处理消息段列表 + segments_text = [] + for seg in segment.data: + processed = await self._process_message_segments(seg) + if processed: + segments_text.append(processed) + return " ".join(segments_text) + else: + # 处理单个消息段 + return await self._process_single_segment(segment) + + @abstractmethod + async def _process_single_segment(self, segment): + pass + @dataclass class MessageRecv(Message): """接收消息类,用于处理从MessageCQ序列化的消息""" - def __init__(self, message_dict: Dict): + def __init__(self, message_dict: dict[str, Any]): """从MessageCQ的字典初始化 Args: @@ -90,26 +116,7 @@ class MessageRecv(Message): self.processed_plain_text = await self._process_message_segments(self.message_segment) self.detailed_plain_text = self._generate_detailed_text() - async def _process_message_segments(self, segment: Seg) -> str: - """递归处理消息段,转换为文字描述 - Args: - segment: 要处理的消息段 - - Returns: - str: 处理后的文本 - """ - if segment.type == "seglist": - # 处理消息段列表 - segments_text = [] - for seg in segment.data: - processed = await self._process_message_segments(seg) - if processed: - segments_text.append(processed) - return " ".join(segments_text) - else: - # 处理单个消息段 - return await self._process_single_segment(segment) async def _process_single_segment(self, seg: Seg) -> str: """处理单个消息段 @@ -179,28 +186,7 @@ class MessageProcessBase(Message): self.thinking_time = round(time.time() - self.thinking_start_time, 2) return self.thinking_time - async def _process_message_segments(self, segment: Seg) -> str: - """递归处理消息段,转换为文字描述 - - Args: - segment: 要处理的消息段 - - Returns: - str: 处理后的文本 - """ - if segment.type == "seglist": - # 处理消息段列表 - segments_text = [] - for seg in segment.data: - processed = await self._process_message_segments(seg) - if processed: - segments_text.append(processed) - return " ".join(segments_text) - else: - # 处理单个消息段 - return await self._process_single_segment(segment) - - async def _process_single_segment(self, seg: Seg) -> Union[str, None]: + async def _process_single_segment(self, seg: Seg) -> str | None: """处理单个消息段 Args: @@ -278,7 +264,7 @@ class MessageSending(MessageProcessBase): message_id: str, chat_stream: ChatStream, bot_user_info: UserInfo, - sender_info: UserInfo, # 用来记录发送者信息,用于私聊回复 + sender_info: UserInfo | None, # 用来记录发送者信息,用于私聊回复 message_segment: Seg, reply: Optional["MessageRecv"] = None, is_head: bool = False, @@ -303,7 +289,7 @@ class MessageSending(MessageProcessBase): self.is_emoji = is_emoji self.apply_set_reply_logic = apply_set_reply_logic - def set_reply(self, reply: Optional["MessageRecv"] = None) -> None: + def set_reply(self, reply: Optional["MessageRecv"] = None): """设置回复消息""" if self.message_info.format_info is not None and "reply" in self.message_info.format_info.accept_format: if reply: @@ -317,7 +303,6 @@ class MessageSending(MessageProcessBase): self.message_segment, ], ) - return self async def process(self) -> None: """处理消息内容,生成纯文本和详细文本""" @@ -342,6 +327,7 @@ class MessageSending(MessageProcessBase): reply=thinking.reply, is_head=is_head, is_emoji=is_emoji, + sender_info=None, ) def to_dict(self): @@ -361,7 +347,7 @@ class MessageSet: def __init__(self, chat_stream: ChatStream, message_id: str): self.chat_stream = chat_stream self.message_id = message_id - self.messages: List[MessageSending] = [] + self.messages: list[MessageSending] = [] self.time = round(time.time(), 3) # 保留3位小数 def add_message(self, message: MessageSending) -> None: diff --git a/src/plugins/chat/message_sender.py b/src/plugins/chat/message_sender.py index 30d943d97..ee4865d92 100644 --- a/src/plugins/chat/message_sender.py +++ b/src/plugins/chat/message_sender.py @@ -1,7 +1,7 @@ # src/plugins/chat/message_sender.py import asyncio import time -from typing import Dict, List, Optional, Union +from typing import Union # from ...common.database import db # 数据库依赖似乎不需要了,注释掉 from ..message.api import global_api @@ -70,7 +70,7 @@ class MessageContainer: def __init__(self, chat_id: str, max_size: int = 100): self.chat_id = chat_id self.max_size = max_size - self.messages: List[Union[MessageThinking, MessageSending]] = [] # 明确类型 + self.messages: list[MessageThinking | MessageSending] = [] # 明确类型 self.last_send_time = 0 self.thinking_wait_timeout = 20 # 思考等待超时时间(秒) - 从旧 sender 合并 @@ -78,7 +78,7 @@ class MessageContainer: """计算当前容器中思考消息的数量""" return sum(1 for msg in self.messages if isinstance(msg, MessageThinking)) - def get_timeout_sending_messages(self) -> List[MessageSending]: + def get_timeout_sending_messages(self) -> list[MessageSending]: """获取所有超时的MessageSending对象(思考时间超过20秒),按thinking_start_time排序 - 从旧 sender 合并""" current_time = time.time() timeout_messages = [] @@ -94,7 +94,7 @@ class MessageContainer: timeout_messages.sort(key=lambda x: x.thinking_start_time) return timeout_messages - def get_earliest_message(self) -> Optional[Union[MessageThinking, MessageSending]]: + def get_earliest_message(self): """获取thinking_start_time最早的消息对象""" if not self.messages: return None @@ -108,7 +108,7 @@ class MessageContainer: earliest_message = msg return earliest_message - def add_message(self, message: Union[MessageThinking, MessageSending, MessageSet]) -> None: + def add_message(self, message: Union[MessageThinking, MessageSending, MessageSet]): """添加消息到队列""" if isinstance(message, MessageSet): for single_message in message.messages: @@ -116,7 +116,7 @@ class MessageContainer: else: self.messages.append(message) - def remove_message(self, message_to_remove: Union[MessageThinking, MessageSending]) -> bool: + def remove_message(self, message_to_remove: Union[MessageThinking, MessageSending]): """移除指定的消息对象,如果消息存在则返回True,否则返回False""" try: _initial_len = len(self.messages) @@ -138,7 +138,7 @@ class MessageContainer: """检查是否有待发送的消息""" return bool(self.messages) - def get_all_messages(self) -> List[Union[MessageSending, MessageThinking]]: + def get_all_messages(self) -> list[MessageThinking | MessageSending]: """获取所有消息""" return list(self.messages) # 返回副本 @@ -148,7 +148,7 @@ class MessageManager: def __init__(self): self._processor_task = None - self.containers: Dict[str, MessageContainer] = {} + self.containers: dict[str, MessageContainer] = {} self.storage = MessageStorage() # 添加 storage 实例 self._running = True # 处理器运行状态 self._container_lock = asyncio.Lock() # 保护 containers 字典的锁 diff --git a/src/plugins/chat/utils.py b/src/plugins/chat/utils.py index 16581f3aa..40b4ab7c4 100644 --- a/src/plugins/chat/utils.py +++ b/src/plugins/chat/utils.py @@ -2,7 +2,6 @@ import random import time import re from collections import Counter -from typing import Dict, List, Optional import jieba import numpy as np @@ -26,7 +25,7 @@ def is_english_letter(char: str) -> bool: return "a" <= char.lower() <= "z" -def db_message_to_str(message_dict: Dict) -> str: +def db_message_to_str(message_dict: dict) -> str: logger.debug(f"message_dict: {message_dict}") time_str = time.strftime("%m-%d %H:%M:%S", time.localtime(message_dict["time"])) try: @@ -35,7 +34,7 @@ def db_message_to_str(message_dict: Dict) -> str: message_dict.get("user_nickname", ""), message_dict.get("user_cardname", ""), ) - except Exception: + except Exception as e: name = message_dict.get("user_nickname", "") or f"用户{message_dict['user_id']}" content = message_dict.get("processed_plain_text", "") result = f"[{time_str}] {name}: {content}\n" @@ -77,13 +76,13 @@ def is_mentioned_bot_in_message(message: MessageRecv) -> tuple[bool, float]: if not is_mentioned: # 判断是否被回复 if re.match( - f"\[回复 [\s\S]*?\({str(global_config.BOT_QQ)}\):[\s\S]*?\],说:", message.processed_plain_text + f"\[回复 [\s\S]*?\({str(global_config.BOT_QQ)}\):[\s\S]*?],说:" , message.processed_plain_text ): is_mentioned = True else: # 判断内容中是否被提及 message_content = re.sub(r"@[\s\S]*?((\d+))", "", message.processed_plain_text) - message_content = re.sub(r"\[回复 [\s\S]*?\(((\d+)|未知id)\):[\s\S]*?\],说:", "", message_content) + message_content = re.sub(r"\[回复 [\s\S]*?\(((\d+)|未知id)\):[\s\S]*?],说:", "", message_content) for keyword in keywords: if keyword in message_content: is_mentioned = True @@ -223,7 +222,7 @@ def get_recent_group_speaker(chat_stream_id: int, sender, limit: int = 12) -> li return who_chat_in_group -def split_into_sentences_w_remove_punctuation(text: str) -> List[str]: +def split_into_sentences_w_remove_punctuation(text: str) -> list[str]: """将文本分割成句子,并根据概率合并 1. 识别分割点(, , 。 ; 空格),但如果分割点左右都是英文字母则不分割。 2. 将文本分割成 (内容, 分隔符) 的元组。 @@ -370,7 +369,7 @@ def random_remove_punctuation(text: str) -> str: return result -def process_llm_response(text: str) -> List[str]: +def process_llm_response(text: str) -> list[str]: # 先保护颜文字 if global_config.enable_kaomoji_protection: protected_text, kaomoji_mapping = protect_kaomoji(text) @@ -379,7 +378,7 @@ def process_llm_response(text: str) -> List[str]: protected_text = text kaomoji_mapping = {} # 提取被 () 或 [] 包裹且包含中文的内容 - pattern = re.compile(r"[\(\[\(](?=.*[\u4e00-\u9fff]).*?[\)\]\)]") + pattern = re.compile(r"[(\[(](?=.*[一-鿿]).*?[)\])]") # _extracted_contents = pattern.findall(text) _extracted_contents = pattern.findall(protected_text) # 在保护后的文本上查找 # 去除 () 和 [] 及其包裹的内容 @@ -554,7 +553,7 @@ def protect_kaomoji(sentence): r"[^()\[\]()【】]*?" # 非括号字符(惰性匹配) r"[^一-龥a-zA-Z0-9\s]" # 非中文、非英文、非数字、非空格字符(必须包含至少一个) r"[^()\[\]()【】]*?" # 非括号字符(惰性匹配) - r"[\)\])】" # 右括号 + r"[)\])】" # 右括号 r"]" r")" r"|" @@ -704,7 +703,7 @@ def count_messages_between(start_time: float, end_time: float, stream_id: str) - return 0, 0 -def translate_timestamp_to_human_readable(timestamp: float, mode: str = "normal") -> Optional[str]: +def translate_timestamp_to_human_readable(timestamp: float, mode: str = "normal") -> str: """将时间戳转换为人类可读的时间格式 Args: @@ -732,10 +731,9 @@ def translate_timestamp_to_human_readable(timestamp: float, mode: str = "normal" return f"{int(diff / 86400)}天前:\n" else: return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(timestamp)) + ":\n" - elif mode == "lite": + else: # mode = "lite" or unknown # 只返回时分秒格式,喵~ return time.strftime("%H:%M:%S", time.localtime(timestamp)) - return None def parse_text_timestamps(text: str, mode: str = "normal") -> str: diff --git a/src/plugins/memory_system/Hippocampus.py b/src/plugins/memory_system/Hippocampus.py index 7a5fc1a82..ff34541e0 100644 --- a/src/plugins/memory_system/Hippocampus.py +++ b/src/plugins/memory_system/Hippocampus.py @@ -511,7 +511,7 @@ class Hippocampus: """从文本中提取关键词并获取相关记忆。 Args: - topic (str): 记忆主题 + keywords (list): 输入文本 max_memory_num (int, optional): 返回的记忆条目数量上限。默认为3,表示最多返回3条与输入文本相关度最高的记忆。 max_memory_length (int, optional): 每个主题最多返回的记忆条目数量。默认为2,表示每个主题最多返回2条相似度最高的记忆。 max_depth (int, optional): 记忆检索深度。默认为3。值越大,检索范围越广,可以获取更多间接相关的记忆,但速度会变慢。 @@ -829,7 +829,7 @@ class EntorhinalCortex: return chat_samples @staticmethod - def random_get_msg_snippet(target_timestamp: float, chat_size: int, max_memorized_time_per_msg: int) -> list: + def random_get_msg_snippet(target_timestamp: float, chat_size: int, max_memorized_time_per_msg: int) -> list | None: """从数据库中随机获取指定时间戳附近的消息片段 (使用 chat_message_builder)""" try_count = 0 time_window_seconds = random.randint(300, 1800) # 随机时间窗口,5到30分钟 diff --git a/src/plugins/schedule/schedule_generator.py b/src/plugins/schedule/schedule_generator.py index ee7bdee15..6bd2e587a 100644 --- a/src/plugins/schedule/schedule_generator.py +++ b/src/plugins/schedule/schedule_generator.py @@ -1,7 +1,6 @@ import datetime import os import sys -from typing import Dict import asyncio from dateutil import tz @@ -162,7 +161,7 @@ class ScheduleGenerator: async def generate_daily_schedule( self, target_date: datetime.datetime = None, - ) -> Dict[str, str]: + ) -> dict[str, str]: daytime_prompt = self.construct_daytime_prompt(target_date) daytime_response, _ = await self.llm_scheduler_all.generate_response_async(daytime_prompt) return daytime_response