From 08ae2e83e36cee13106eb78e03658190aa327f98 Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Tue, 8 Jul 2025 00:27:33 +0800 Subject: [PATCH 1/9] =?UTF-8?q?fix=EF=BC=9Anormal=E5=87=BA=E7=8E=B0?= =?UTF-8?q?=E6=9C=AA=E6=AD=A3=E5=B8=B8=E8=BF=9B=E8=A1=8C=E7=9A=84=E4=B8=80?= =?UTF-8?q?=E6=AD=A5=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/normal_chat/normal_chat.py | 72 +++++++++---------- src/plugins/built_in/core_actions/no_reply.py | 5 +- 2 files changed, 34 insertions(+), 43 deletions(-) diff --git a/src/chat/normal_chat/normal_chat.py b/src/chat/normal_chat/normal_chat.py index 46366e800..5bf4abb17 100644 --- a/src/chat/normal_chat/normal_chat.py +++ b/src/chat/normal_chat/normal_chat.py @@ -302,50 +302,42 @@ class NormalChat: logger.info(f"[{self.stream_name}] 在处理上下文中检测到停止信号,退出") break - # 并行处理兴趣消息 - async def process_single_message(msg_id, message, interest_value, is_mentioned): - """处理单个兴趣消息""" - try: - # 在处理每个消息前检查停止状态 - if self._disabled: - logger.debug(f"[{self.stream_name}] 处理消息时检测到停用,跳过消息 {msg_id}") - return + semaphore = asyncio.Semaphore(5) - # 处理消息 - self.adjust_reply_frequency() + async def process_and_acquire(msg_id, message, interest_value, is_mentioned): + """处理单个兴趣消息并管理信号量""" + async with semaphore: + try: + # 在处理每个消息前检查停止状态 + if self._disabled: + logger.debug(f"[{self.stream_name}] 处理消息时检测到停用,跳过消息 {msg_id}") + return - await self.normal_response( - message=message, - is_mentioned=is_mentioned, - interested_rate=interest_value * self.willing_amplifier, - ) - except asyncio.CancelledError: - logger.debug(f"[{self.stream_name}] 处理消息 {msg_id} 时被取消") - raise # 重新抛出取消异常 - except Exception as e: - logger.error(f"[{self.stream_name}] 处理兴趣消息{msg_id}时出错: {e}") - # 不打印完整traceback,避免日志污染 - finally: - # 无论如何都要清理消息 - self.interest_dict.pop(msg_id, None) + # 处理消息 + self.adjust_reply_frequency() - # 创建并行任务列表 - coroutines = [] - for msg_id, (message, interest_value, is_mentioned) in items_to_process: - coroutine = process_single_message(msg_id, message, interest_value, is_mentioned) - coroutines.append(coroutine) + await self.normal_response( + message=message, + is_mentioned=is_mentioned, + interested_rate=interest_value * self.willing_amplifier, + ) + except asyncio.CancelledError: + logger.debug(f"[{self.stream_name}] 处理消息 {msg_id} 时被取消") + raise # 重新抛出取消异常 + except Exception as e: + logger.error(f"[{self.stream_name}] 处理兴趣消息{msg_id}时出错: {e}") + # 不打印完整traceback,避免日志污染 + finally: + # 无论如何都要清理消息 + self.interest_dict.pop(msg_id, None) + + tasks = [ + process_and_acquire(msg_id, message, interest_value, is_mentioned) + for msg_id, (message, interest_value, is_mentioned) in items_to_process + ] - # 并行执行所有任务,限制并发数量避免资源过度消耗 - if coroutines: - # 使用信号量控制并发数,最多同时处理5个消息 - semaphore = asyncio.Semaphore(5) - - async def limited_process(coroutine, sem): - async with sem: - await coroutine - - limited_tasks = [limited_process(coroutine, semaphore) for coroutine in coroutines] - await asyncio.gather(*limited_tasks, return_exceptions=True) + if tasks: + await asyncio.gather(*tasks, return_exceptions=True) except asyncio.CancelledError: logger.info(f"[{self.stream_name}] 处理上下文时任务被取消") diff --git a/src/plugins/built_in/core_actions/no_reply.py b/src/plugins/built_in/core_actions/no_reply.py index 160fbb626..c3cf0201c 100644 --- a/src/plugins/built_in/core_actions/no_reply.py +++ b/src/plugins/built_in/core_actions/no_reply.py @@ -355,14 +355,13 @@ class NoReplyAction(BaseAction): last_judge_time = time.time() # 异常时也更新时间,避免频繁重试 # 每10秒输出一次等待状态 - logger.info(f"{self.log_prefix} 开始等待新消息...") if elapsed_time < 60: if int(elapsed_time) % 10 == 0 and int(elapsed_time) > 0: logger.debug(f"{self.log_prefix} 已等待{elapsed_time:.0f}秒,等待新消息...") await asyncio.sleep(1) else: - if int(elapsed_time) % 60 == 0 and int(elapsed_time) > 0: - logger.debug(f"{self.log_prefix} 已等待{elapsed_time / 60:.0f}分钟,等待新消息...") + if int(elapsed_time) % 180 == 0 and int(elapsed_time) > 0: + logger.info(f"{self.log_prefix} 已等待{elapsed_time / 60:.0f}分钟,等待新消息...") await asyncio.sleep(1) # 短暂等待后继续检查 From 723870bcdeffe9066561d68a81635721f1998829 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 7 Jul 2025 16:27:55 +0000 Subject: [PATCH 2/9] =?UTF-8?q?=F0=9F=A4=96=20=E8=87=AA=E5=8A=A8=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96=E4=BB=A3=E7=A0=81=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/normal_chat/normal_chat.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/chat/normal_chat/normal_chat.py b/src/chat/normal_chat/normal_chat.py index 5bf4abb17..48e8f4191 100644 --- a/src/chat/normal_chat/normal_chat.py +++ b/src/chat/normal_chat/normal_chat.py @@ -310,7 +310,9 @@ class NormalChat: try: # 在处理每个消息前检查停止状态 if self._disabled: - logger.debug(f"[{self.stream_name}] 处理消息时检测到停用,跳过消息 {msg_id}") + logger.debug( + f"[{self.stream_name}] 处理消息时检测到停用,跳过消息 {msg_id}" + ) return # 处理消息 @@ -330,7 +332,7 @@ class NormalChat: finally: # 无论如何都要清理消息 self.interest_dict.pop(msg_id, None) - + tasks = [ process_and_acquire(msg_id, message, interest_value, is_mentioned) for msg_id, (message, interest_value, is_mentioned) in items_to_process From f17f5cf46c0831bb8dc4652bc06d4c77b42eb7f9 Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Tue, 8 Jul 2025 02:04:31 +0800 Subject: [PATCH 3/9] =?UTF-8?q?feat=EF=BC=9A=E4=BF=AE=E6=94=B9log,?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=85=B3=E7=B3=BB=E6=9E=84=E5=BB=BA=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E8=8A=82=E7=9C=81token=EF=BC=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/emoji_system/emoji_manager.py | 4 +- .../heart_flow/heartflow_message_processor.py | 16 +- src/chat/message_receive/storage.py | 2 +- src/chat/normal_chat/normal_chat.py | 17 +- src/chat/utils/chat_message_builder.py | 3 + src/common/database/database_model.py | 3 +- src/common/logger.py | 17 +- src/person_info/person_info.py | 1 + src/person_info/relationship_manager.py | 370 ++++++++---------- src/plugins/built_in/core_actions/no_reply.py | 192 +++++---- 10 files changed, 303 insertions(+), 322 deletions(-) diff --git a/src/chat/emoji_system/emoji_manager.py b/src/chat/emoji_system/emoji_manager.py index b10d8b0bf..3511d938b 100644 --- a/src/chat/emoji_system/emoji_manager.py +++ b/src/chat/emoji_system/emoji_manager.py @@ -324,8 +324,6 @@ async def clear_temp_emoji() -> None: os.remove(file_path) logger.debug(f"[清理] 删除: {filename}") - logger.info("[清理] 完成") - async def clean_unused_emojis(emoji_dir: str, emoji_objects: List["MaiEmoji"], removed_count: int) -> int: """清理指定目录中未被 emoji_objects 追踪的表情包文件""" @@ -590,7 +588,7 @@ class EmojiManager: """定期检查表情包完整性和数量""" await self.get_all_emoji_from_db() while True: - logger.info("[扫描] 开始检查表情包完整性...") + # logger.info("[扫描] 开始检查表情包完整性...") await self.check_emoji_file_integrity() await clear_temp_emoji() logger.info("[扫描] 开始扫描新表情包...") diff --git a/src/chat/heart_flow/heartflow_message_processor.py b/src/chat/heart_flow/heartflow_message_processor.py index 66ddf362e..5de0d7015 100644 --- a/src/chat/heart_flow/heartflow_message_processor.py +++ b/src/chat/heart_flow/heartflow_message_processor.py @@ -119,15 +119,15 @@ class HeartFCMessageReceiver: # current_time = time.strftime("%H:%M:%S", time.localtime(message.message_info.time)) current_talk_frequency = global_config.chat.get_current_talk_frequency(chat.stream_id) - # 如果消息中包含图片标识,则日志展示为图片 + # 如果消息中包含图片标识,则将 [picid:...] 替换为 [图片] + picid_pattern = r"\[picid:([^\]]+)\]" + processed_plain_text = re.sub(picid_pattern, "[图片]", message.processed_plain_text) - picid_match = re.search(r"\[picid:([^\]]+)\]", message.processed_plain_text) - if picid_match: - logger.info(f"[{mes_name}]{userinfo.user_nickname}: [图片] [当前回复频率: {current_talk_frequency}]") - else: - logger.info( - f"[{mes_name}]{userinfo.user_nickname}:{message.processed_plain_text}[当前回复频率: {current_talk_frequency}]" - ) + logger.info( + f"[{mes_name}]{userinfo.user_nickname}:{processed_plain_text}" + ) + + logger.debug(f"[{mes_name}][当前时段回复频率: {current_talk_frequency}]") # 8. 关系处理 if global_config.relationship.enable_relationship: diff --git a/src/chat/message_receive/storage.py b/src/chat/message_receive/storage.py index 146a4372a..c40c4eb75 100644 --- a/src/chat/message_receive/storage.py +++ b/src/chat/message_receive/storage.py @@ -131,7 +131,7 @@ class MessageStorage: if matched_message: # 更新找到的消息记录 Messages.update(message_id=qq_message_id).where(Messages.id == matched_message.id).execute() - logger.info(f"更新消息ID成功: {matched_message.message_id} -> {qq_message_id}") + logger.debug(f"更新消息ID成功: {matched_message.message_id} -> {qq_message_id}") else: logger.debug("未找到匹配的消息") diff --git a/src/chat/normal_chat/normal_chat.py b/src/chat/normal_chat/normal_chat.py index 48e8f4191..43ab5803e 100644 --- a/src/chat/normal_chat/normal_chat.py +++ b/src/chat/normal_chat/normal_chat.py @@ -585,10 +585,19 @@ class NormalChat: ) response_set, plan_result = results except asyncio.TimeoutError: - logger.warning( - f"[{self.stream_name}] 并行执行回复生成和动作规划超时 ({gather_timeout}秒),正在取消相关任务..." - ) - print(f"111{self.timeout_count}") + gen_timed_out = not gen_task.done() + plan_timed_out = not plan_task.done() + + timeout_details = [] + if gen_timed_out: + timeout_details.append("回复生成(gen)") + if plan_timed_out: + timeout_details.append("动作规划(plan)") + + timeout_source = " 和 ".join(timeout_details) + + logger.warning(f"[{self.stream_name}] {timeout_source} 任务超时 ({global_config.chat.thinking_timeout}秒),正在取消相关任务...") + # print(f"111{self.timeout_count}") self.timeout_count += 1 if self.timeout_count > 5: logger.warning( diff --git a/src/chat/utils/chat_message_builder.py b/src/chat/utils/chat_message_builder.py index 2359abf30..ab97f395b 100644 --- a/src/chat/utils/chat_message_builder.py +++ b/src/chat/utils/chat_message_builder.py @@ -551,6 +551,9 @@ def build_readable_messages( show_actions: 是否显示动作记录 """ # 创建messages的深拷贝,避免修改原始列表 + if not messages: + return "" + copy_messages = [msg.copy() for msg in messages] if show_actions and copy_messages: diff --git a/src/common/database/database_model.py b/src/common/database/database_model.py index 500852d00..8c2bf423b 100644 --- a/src/common/database/database_model.py +++ b/src/common/database/database_model.py @@ -252,8 +252,7 @@ class PersonInfo(BaseModel): know_times = FloatField(null=True) # 认识时间 (时间戳) know_since = FloatField(null=True) # 首次印象总结时间 last_know = FloatField(null=True) # 最后一次印象总结时间 - familiarity_value = IntegerField(null=True, default=0) # 熟悉度,0-100,从完全陌生到非常熟悉 - liking_value = IntegerField(null=True, default=50) # 好感度,0-100,从非常厌恶到十分喜欢 + attitude = IntegerField(null=True, default=50) # 态度,0-100,从非常厌恶到十分喜欢 class Meta: # database = db # 继承自 BaseModel diff --git a/src/common/logger.py b/src/common/logger.py index 7202b993f..40fd15070 100644 --- a/src/common/logger.py +++ b/src/common/logger.py @@ -321,14 +321,13 @@ MODULE_COLORS = { # 核心模块 "main": "\033[1;97m", # 亮白色+粗体 (主程序) "api": "\033[92m", # 亮绿色 - "emoji": "\033[92m", # 亮绿色 + "emoji": "\033[33m", # 亮绿色 "chat": "\033[92m", # 亮蓝色 "config": "\033[93m", # 亮黄色 "common": "\033[95m", # 亮紫色 "tools": "\033[96m", # 亮青色 "lpmm": "\033[96m", "plugin_system": "\033[91m", # 亮红色 - "experimental": "\033[97m", # 亮白色 "person_info": "\033[32m", # 绿色 "individuality": "\033[34m", # 蓝色 "manager": "\033[35m", # 紫色 @@ -339,8 +338,7 @@ MODULE_COLORS = { "planner": "\033[36m", "memory": "\033[34m", "hfc": "\033[96m", - "base_action": "\033[96m", - "action_manager": "\033[32m", + "action_manager": "\033[38;5;166m", # 关系系统 "relation": "\033[38;5;201m", # 深粉色 # 聊天相关模块 @@ -356,11 +354,9 @@ MODULE_COLORS = { "message_storage": "\033[38;5;33m", # 深蓝色 # 专注聊天模块 "replyer": "\033[38;5;166m", # 橙色 - "expressor": "\033[38;5;172m", # 黄橙色 - "processor": "\033[38;5;184m", # 黄绿色 "base_processor": "\033[38;5;190m", # 绿黄色 "working_memory": "\033[38;5;22m", # 深绿色 - "memory_activator": "\033[38;5;28m", # 绿色 + "memory_activator": "\033[34m", # 绿色 # 插件系统 "plugin_manager": "\033[38;5;208m", # 红色 "base_plugin": "\033[38;5;202m", # 橙红色 @@ -386,11 +382,9 @@ MODULE_COLORS = { "tool_executor": "\033[38;5;64m", # 深绿色 "base_tool": "\033[38;5;70m", # 绿色 # 工具和实用模块 - "prompt": "\033[38;5;99m", # 紫色 "prompt_build": "\033[38;5;105m", # 紫色 "chat_utils": "\033[38;5;111m", # 蓝色 "chat_image": "\033[38;5;117m", # 浅蓝色 - "typo_gen": "\033[38;5;123m", # 青绿色 "maibot_statistic": "\033[38;5;129m", # 紫色 # 特殊功能插件 "mute_plugin": "\033[38;5;240m", # 灰色 @@ -402,16 +396,13 @@ MODULE_COLORS = { # 数据库和消息 "database_model": "\033[38;5;94m", # 橙褐色 "maim_message": "\033[38;5;100m", # 绿褐色 - # 实验性模块 - "pfc": "\033[38;5;252m", # 浅灰色 # 日志系统 "logger": "\033[38;5;8m", # 深灰色 - "demo": "\033[38;5;15m", # 白色 "confirm": "\033[1;93m", # 黄色+粗体 # 模型相关 "model_utils": "\033[38;5;164m", # 紫红色 "relationship_fetcher": "\033[38;5;170m", # 浅紫色 - "relationship_builder": "\033[38;5;117m", # 浅蓝色 + "relationship_builder": "\033[38;5;93m", # 浅蓝色 } RESET_COLOR = "\033[0m" diff --git a/src/person_info/person_info.py b/src/person_info/person_info.py index 86e3b6fcd..7f22fc2d4 100644 --- a/src/person_info/person_info.py +++ b/src/person_info/person_info.py @@ -48,6 +48,7 @@ person_info_default = { "points": None, "forgotten_points": None, "relation_value": None, + "attitude": 50, } diff --git a/src/person_info/relationship_manager.py b/src/person_info/relationship_manager.py index 2d37bcda8..813036c69 100644 --- a/src/person_info/relationship_manager.py +++ b/src/person_info/relationship_manager.py @@ -21,66 +21,11 @@ logger = get_logger("relation") class RelationshipManager: def __init__(self): - self.positive_feedback_value = 0 # 正反馈系统 - self.gain_coefficient = [1.0, 1.0, 1.1, 1.2, 1.4, 1.7, 1.9, 2.0] - self._mood_manager = None - self.relationship_llm = LLMRequest( model=global_config.model.relation, request_type="relationship", # 用于动作规划 ) - @property - def mood_manager(self): - if self._mood_manager is None: - self._mood_manager = mood_manager - return self._mood_manager - - def positive_feedback_sys(self, label: str, stance: str): - """正反馈系统,通过正反馈系数增益情绪变化,根据情绪再影响关系变更""" - - positive_list = [ - "开心", - "惊讶", - "害羞", - ] - - negative_list = [ - "愤怒", - "悲伤", - "恐惧", - "厌恶", - ] - - if label in positive_list: - if 7 > self.positive_feedback_value >= 0: - self.positive_feedback_value += 1 - elif self.positive_feedback_value < 0: - self.positive_feedback_value = 0 - elif label in negative_list: - if -7 < self.positive_feedback_value <= 0: - self.positive_feedback_value -= 1 - elif self.positive_feedback_value > 0: - self.positive_feedback_value = 0 - - if abs(self.positive_feedback_value) > 1: - logger.debug(f"触发mood变更增益,当前增益系数:{self.gain_coefficient[abs(self.positive_feedback_value)]}") - - def mood_feedback(self, value): - """情绪反馈""" - mood_manager = self.mood_manager - mood_gain = mood_manager.current_mood.valence**2 * math.copysign(1, value * mood_manager.current_mood.valence) - value += value * mood_gain - logger.debug(f"当前relationship增益系数:{mood_gain:.3f}") - return value - - def feedback_to_mood(self, mood_value): - """对情绪的反馈""" - coefficient = self.gain_coefficient[abs(self.positive_feedback_value)] - if mood_value > 0 and self.positive_feedback_value > 0 or mood_value < 0 and self.positive_feedback_value < 0: - return mood_value * coefficient - else: - return mood_value / coefficient @staticmethod async def is_known_some_one(platform, user_id): @@ -168,18 +113,6 @@ class RelationshipManager: return relation_prompt - async def _update_list_field(self, person_id: str, field_name: str, new_items: list) -> None: - """更新列表类型的字段,将新项目添加到现有列表中 - - Args: - person_id: 用户ID - field_name: 字段名称 - new_items: 新的项目列表 - """ - person_info_manager = get_person_info_manager() - old_items = await person_info_manager.get_value(person_id, field_name) or [] - updated_items = list(set(old_items + [item for item in new_items if isinstance(item, str) and item])) - await person_info_manager.update_one_field(person_id, field_name, updated_items) async def update_person_impression(self, person_id, timestamp, bot_engaged_messages=None): """更新用户印象 @@ -194,6 +127,7 @@ class RelationshipManager: person_info_manager = get_person_info_manager() person_name = await person_info_manager.get_value(person_id, "person_name") nickname = await person_info_manager.get_value(person_id, "nickname") + know_times = await person_info_manager.get_value(person_id, "know_times") or 0 alias_str = ", ".join(global_config.bot.alias_names) # personality_block =get_individuality().get_personality_prompt(x_person=2, level=2) @@ -239,8 +173,10 @@ class RelationshipManager: user_count += 1 name_mapping[replace_person_name] = f"用户{current_user}{user_count if user_count > 1 else ''}" current_user = chr(ord(current_user) + 1) - - readable_messages = self.build_focus_readable_messages(messages=user_messages, target_person_id=person_id) + + readable_messages = build_readable_messages( + messages=user_messages, replace_bot_name=True, timestamp_mode="normal_no_YMD", truncate=True + ) if not readable_messages: return @@ -385,73 +321,121 @@ class RelationshipManager: # 如果points超过10条,按权重随机选择多余的条目移动到forgotten_points if len(current_points) > 10: - # 获取现有forgotten_points - forgotten_points = await person_info_manager.get_value(person_id, "forgotten_points") or [] - if isinstance(forgotten_points, str): - try: - forgotten_points = json.loads(forgotten_points) - except json.JSONDecodeError: - logger.error(f"解析forgotten_points JSON失败: {forgotten_points}") - forgotten_points = [] - elif not isinstance(forgotten_points, list): + current_points = await self._update_impression(person_id, current_points, timestamp) + + # 更新数据库 + await person_info_manager.update_one_field( + person_id, "points", json.dumps(current_points, ensure_ascii=False, indent=None) + ) + + await person_info_manager.update_one_field(person_id, "know_times", know_times + 1) + know_since = await person_info_manager.get_value(person_id, "know_since") or 0 + if know_since == 0: + await person_info_manager.update_one_field(person_id, "know_since", timestamp) + await person_info_manager.update_one_field(person_id, "last_know", timestamp) + + logger.debug(f"{person_name} 的印象更新完成") + + async def _update_impression(self, person_id, current_points, timestamp): + # 获取现有forgotten_points + person_info_manager = get_person_info_manager() + + + person_name = await person_info_manager.get_value(person_id, "person_name") + nickname = await person_info_manager.get_value(person_id, "nickname") + know_times = await person_info_manager.get_value(person_id, "know_times") or 0 + attitude = await person_info_manager.get_value(person_id, "attitude") or 50 + + # 根据熟悉度,调整印象和简短印象的最大长度 + if know_times > 300: + max_impression_length = 2000 + max_short_impression_length = 800 + elif know_times > 100: + max_impression_length = 1000 + max_short_impression_length = 500 + elif know_times > 50: + max_impression_length = 500 + max_short_impression_length = 300 + elif know_times > 10: + max_impression_length = 200 + max_short_impression_length = 100 + else: + max_impression_length = 100 + max_short_impression_length = 50 + + # 根据好感度,调整印象和简短印象的最大长度 + attitude_multiplier = (abs(100-attitude) / 100) + 1 + max_impression_length = max_impression_length * attitude_multiplier + max_short_impression_length = max_short_impression_length * attitude_multiplier + + + + forgotten_points = await person_info_manager.get_value(person_id, "forgotten_points") or [] + if isinstance(forgotten_points, str): + try: + forgotten_points = json.loads(forgotten_points) + except json.JSONDecodeError: + logger.error(f"解析forgotten_points JSON失败: {forgotten_points}") forgotten_points = [] + elif not isinstance(forgotten_points, list): + forgotten_points = [] - # 计算当前时间 - current_time = datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S") + # 计算当前时间 + current_time = datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S") - # 计算每个点的最终权重(原始权重 * 时间权重) - weighted_points = [] - for point in current_points: - time_weight = self.calculate_time_weight(point[2], current_time) - final_weight = point[1] * time_weight - weighted_points.append((point, final_weight)) + # 计算每个点的最终权重(原始权重 * 时间权重) + weighted_points = [] + for point in current_points: + time_weight = self.calculate_time_weight(point[2], current_time) + final_weight = point[1] * time_weight + weighted_points.append((point, final_weight)) - # 计算总权重 - total_weight = sum(w for _, w in weighted_points) + # 计算总权重 + total_weight = sum(w for _, w in weighted_points) - # 按权重随机选择要保留的点 - remaining_points = [] - points_to_move = [] + # 按权重随机选择要保留的点 + remaining_points = [] + points_to_move = [] - # 对每个点进行随机选择 - for point, weight in weighted_points: - # 计算保留概率(权重越高越可能保留) - keep_probability = weight / total_weight + # 对每个点进行随机选择 + for point, weight in weighted_points: + # 计算保留概率(权重越高越可能保留) + keep_probability = weight / total_weight - if len(remaining_points) < 10: - # 如果还没达到30条,直接保留 - remaining_points.append(point) + if len(remaining_points) < 10: + # 如果还没达到30条,直接保留 + remaining_points.append(point) + else: + # 随机决定是否保留 + if random.random() < keep_probability: + # 保留这个点,随机移除一个已保留的点 + idx_to_remove = random.randrange(len(remaining_points)) + points_to_move.append(remaining_points[idx_to_remove]) + remaining_points[idx_to_remove] = point else: - # 随机决定是否保留 - if random.random() < keep_probability: - # 保留这个点,随机移除一个已保留的点 - idx_to_remove = random.randrange(len(remaining_points)) - points_to_move.append(remaining_points[idx_to_remove]) - remaining_points[idx_to_remove] = point - else: - # 不保留这个点 - points_to_move.append(point) + # 不保留这个点 + points_to_move.append(point) - # 更新points和forgotten_points - current_points = remaining_points - forgotten_points.extend(points_to_move) + # 更新points和forgotten_points + current_points = remaining_points + forgotten_points.extend(points_to_move) - # 检查forgotten_points是否达到5条 - if len(forgotten_points) >= 10: - # 构建压缩总结提示词 - alias_str = ", ".join(global_config.bot.alias_names) + # 检查forgotten_points是否达到10条 + if len(forgotten_points) >= 10: + # 构建压缩总结提示词 + alias_str = ", ".join(global_config.bot.alias_names) - # 按时间排序forgotten_points - forgotten_points.sort(key=lambda x: x[2]) + # 按时间排序forgotten_points + forgotten_points.sort(key=lambda x: x[2]) - # 构建points文本 - points_text = "\n".join( - [f"时间:{point[2]}\n权重:{point[1]}\n内容:{point[0]}" for point in forgotten_points] - ) + # 构建points文本 + points_text = "\n".join( + [f"时间:{point[2]}\n权重:{point[1]}\n内容:{point[0]}" for point in forgotten_points] + ) - impression = await person_info_manager.get_value(person_id, "impression") or "" + impression = await person_info_manager.get_value(person_id, "impression") or "" - compress_prompt = f""" + compress_prompt = f""" 你的名字是{global_config.bot.nickname},{global_config.bot.nickname}的别名是{alias_str}。 请不要混淆你自己和{global_config.bot.nickname}和{person_name}。 @@ -466,17 +450,17 @@ class RelationshipManager: 你记得ta最近做的事: {points_text} -请输出一段平文本,以陈诉自白的语气,输出你对{person_name}的了解,不要输出任何其他内容。 +请输出一段{max_impression_length}字左右的平文本,以陈诉自白的语气,输出你对{person_name}的了解,不要输出任何其他内容。 """ - # 调用LLM生成压缩总结 - compressed_summary, _ = await self.relationship_llm.generate_response_async(prompt=compress_prompt) + # 调用LLM生成压缩总结 + compressed_summary, _ = await self.relationship_llm.generate_response_async(prompt=compress_prompt) - current_time = datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S") - compressed_summary = f"截至{current_time},你对{person_name}的了解:{compressed_summary}" + current_time = datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S") + compressed_summary = f"截至{current_time},你对{person_name}的了解:{compressed_summary}" - await person_info_manager.update_one_field(person_id, "impression", compressed_summary) + await person_info_manager.update_one_field(person_id, "impression", compressed_summary) - compress_short_prompt = f""" + compress_short_prompt = f""" 你的名字是{global_config.bot.nickname},{global_config.bot.nickname}的别名是{alias_str}。 请不要混淆你自己和{global_config.bot.nickname}和{person_name}。 @@ -487,107 +471,77 @@ class RelationshipManager: 1.对{person_name}的直观印象 2.{global_config.bot.nickname}与{person_name}的关系 3.{person_name}的关键信息 -请输出一段平文本,以陈诉自白的语气,输出你对{person_name}的概括,不要输出任何其他内容。 +请输出一段{max_short_impression_length}字左右的平文本,以陈诉自白的语气,输出你对{person_name}的概括,不要输出任何其他内容。 """ - compressed_short_summary, _ = await self.relationship_llm.generate_response_async( - prompt=compress_short_prompt - ) + compressed_short_summary, _ = await self.relationship_llm.generate_response_async( + prompt=compress_short_prompt + ) - # current_time = datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S") - # compressed_short_summary = f"截至{current_time},你对{person_name}的了解:{compressed_short_summary}" + # current_time = datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S") + # compressed_short_summary = f"截至{current_time},你对{person_name}的了解:{compressed_short_summary}" - await person_info_manager.update_one_field(person_id, "short_impression", compressed_short_summary) + await person_info_manager.update_one_field(person_id, "short_impression", compressed_short_summary) - relation_value_prompt = f""" + relation_value_prompt = f""" 你的名字是{global_config.bot.nickname}。 你最近对{person_name}的了解如下: {points_text} -请根据以上信息,评估你和{person_name}的关系,给出两个维度的值:熟悉度和好感度。 -1. 了解度 (familiarity_value): 0-100的整数,表示这些信息让你对ta的了解增进程度。 - - 0: 没有任何进一步了解 - - 25: 有点进一步了解 - - 50: 有进一步了解 - - 75: 有更多了解 - - 100: 有了更多重要的了解 +请根据以上信息,评估你和{person_name}的关系,给出你对ta的态度。 -2. **好感度 (liking_value)**: 0-100的整数,表示这些信息让你对ta的喜。 - - 0: 非常厌恶 - - 25: 有点反感 - - 50: 中立/无感(或者文本中无法明显看出) - - 75: 喜欢这个人 - - 100: 非常喜欢/开心对这个人 +态度: 0-100的整数,表示这些信息让你对ta的态度。 +- 0: 非常厌恶 +- 25: 有点反感 +- 50: 中立/无感(或者文本中无法明显看出) +- 75: 喜欢这个人 +- 100: 非常喜欢/开心对这个人 请严格按照json格式输出,不要有其他多余内容: {{ - "familiarity_value": <0-100之间的整数>, - "liking_value": <0-100之间的整数> +"attitude": <0-100之间的整数>, }} """ - try: - relation_value_response, _ = await self.relationship_llm.generate_response_async( - prompt=relation_value_prompt - ) - relation_value_json = json.loads(repair_json(relation_value_response)) - - # 从LLM获取新生成的值 - new_familiarity_value = int(relation_value_json.get("familiarity_value", 0)) - new_liking_value = int(relation_value_json.get("liking_value", 50)) - - # 获取当前的关系值 - old_familiarity_value = await person_info_manager.get_value(person_id, "familiarity_value") or 0 - liking_value = await person_info_manager.get_value(person_id, "liking_value") or 50 - - # 更新熟悉度 - if new_familiarity_value > 25: - familiarity_value = old_familiarity_value + (new_familiarity_value - 25) / 75 - else: - familiarity_value = old_familiarity_value - - # 更新好感度 - if new_liking_value > 50: - liking_value += (new_liking_value - 50) / 50 - elif new_liking_value < 50: - liking_value -= (50 - new_liking_value) / 50 * 1.5 - - await person_info_manager.update_one_field(person_id, "familiarity_value", familiarity_value) - await person_info_manager.update_one_field(person_id, "liking_value", liking_value) - logger.info(f"更新了与 {person_name} 的关系值: 熟悉度={familiarity_value}, 好感度={liking_value}") - except (json.JSONDecodeError, ValueError, TypeError) as e: - logger.error(f"解析relation_value JSON失败或值无效: {e}, 响应: {relation_value_response}") - - forgotten_points = [] - info_list = [] - await person_info_manager.update_one_field( - person_id, "info_list", json.dumps(info_list, ensure_ascii=False, indent=None) + try: + relation_value_response, _ = await self.relationship_llm.generate_response_async( + prompt=relation_value_prompt ) + relation_value_json = json.loads(repair_json(relation_value_response)) + # 从LLM获取新生成的值 + new_attitude = int(relation_value_json.get("attitude", 50)) + + # 获取当前的关系值 + old_attitude = await person_info_manager.get_value(person_id, "attitude") or 50 + + # 更新熟悉度 + if new_attitude > 25: + attitude = old_attitude + (new_attitude - 25) / 75 + else: + attitude = old_attitude + + # 更新好感度 + if new_attitude > 50: + attitude += (new_attitude - 50) / 50 + elif new_attitude < 50: + attitude -= (50 - new_attitude) / 50 * 1.5 + + await person_info_manager.update_one_field(person_id, "attitude", attitude) + logger.info(f"更新了与 {person_name} 的态度: {attitude}") + except (json.JSONDecodeError, ValueError, TypeError) as e: + logger.error(f"解析relation_value JSON失败或值无效: {e}, 响应: {relation_value_response}") + + forgotten_points = [] + info_list = [] await person_info_manager.update_one_field( - person_id, "forgotten_points", json.dumps(forgotten_points, ensure_ascii=False, indent=None) + person_id, "info_list", json.dumps(info_list, ensure_ascii=False, indent=None) ) - # 更新数据库 await person_info_manager.update_one_field( - person_id, "points", json.dumps(current_points, ensure_ascii=False, indent=None) + person_id, "forgotten_points", json.dumps(forgotten_points, ensure_ascii=False, indent=None) ) - know_times = await person_info_manager.get_value(person_id, "know_times") or 0 - await person_info_manager.update_one_field(person_id, "know_times", know_times + 1) - know_since = await person_info_manager.get_value(person_id, "know_since") or 0 - if know_since == 0: - await person_info_manager.update_one_field(person_id, "know_since", timestamp) - await person_info_manager.update_one_field(person_id, "last_know", timestamp) + + return current_points - logger.info(f"{person_name} 的印象更新完成") - - def build_focus_readable_messages(self, messages: list, target_person_id: str = None) -> str: - """格式化消息,处理所有消息内容""" - if not messages: - return "" - - # 直接处理所有消息,不进行过滤 - return build_readable_messages( - messages=messages, replace_bot_name=True, timestamp_mode="normal_no_YMD", truncate=True - ) def calculate_time_weight(self, point_time: str, current_time: str) -> float: """计算基于时间的权重系数""" diff --git a/src/plugins/built_in/core_actions/no_reply.py b/src/plugins/built_in/core_actions/no_reply.py index c3cf0201c..a5c8d637b 100644 --- a/src/plugins/built_in/core_actions/no_reply.py +++ b/src/plugins/built_in/core_actions/no_reply.py @@ -103,6 +103,8 @@ class NoReplyAction(BaseAction): logger.info(f"{self.log_prefix} 选择不回复(第{count}次),开始摸鱼,原因: {reason}") + + # 进入等待状态 while True: current_time = time.time() elapsed_time = current_time - start_time @@ -141,19 +143,9 @@ class NoReplyAction(BaseAction): # 判定条件:累计3条消息或等待超过5秒且有新消息 time_since_last_judge = current_time - last_judge_time - should_judge = ( - new_message_count >= 3 # 累计3条消息 - or (new_message_count > 0 and time_since_last_judge >= 15.0) # 等待超过5秒且有新消息 - ) + should_judge, trigger_reason = self._should_trigger_judge(new_message_count, time_since_last_judge) if should_judge and time_since_last_judge >= min_judge_interval: - # 判断触发原因 - trigger_reason = "" - if new_message_count >= 3: - trigger_reason = f"累计{new_message_count}条消息" - elif time_since_last_judge >= 10.0: - trigger_reason = f"等待{time_since_last_judge:.1f}秒且有新消息" - logger.info(f"{self.log_prefix} 触发判定({trigger_reason}),进行智能判断...") # 获取最近的消息内容用于判断 @@ -166,7 +158,10 @@ class NoReplyAction(BaseAction): if recent_messages: # 使用message_api构建可读的消息字符串 messages_text = message_api.build_readable_messages( - messages=recent_messages, timestamp_mode="normal_no_YMD", truncate=False, show_actions=False + messages=recent_messages, + timestamp_mode="normal_no_YMD", + truncate=False, + show_actions=False, ) # 获取身份信息 @@ -189,81 +184,13 @@ class NoReplyAction(BaseAction): history_block += "\n" # 检查过去10分钟的发言频率 - frequency_block = "" - should_skip_llm_judge = False # 是否跳过LLM判断 - - try: - # 获取过去10分钟的所有消息 - past_10min_time = current_time - 600 # 10分钟前 - all_messages_10min = message_api.get_messages_by_time_in_chat( - chat_id=self.chat_id, - start_time=past_10min_time, - end_time=current_time, - ) - - # 手动过滤bot自己的消息 - bot_message_count = 0 - if all_messages_10min: - user_id = global_config.bot.qq_account - - for message in all_messages_10min: - # 检查消息发送者是否是bot - sender_id = message.get("user_id", "") - - if sender_id == user_id: - bot_message_count += 1 - - talk_frequency_threshold = global_config.chat.get_current_talk_frequency(self.chat_id) * 10 - - if bot_message_count > talk_frequency_threshold: - over_count = bot_message_count - talk_frequency_threshold - - # 根据超过的数量设置不同的提示词和跳过概率 - skip_probability = 0 - if over_count <= 3: - frequency_block = "你感觉稍微有些累,回复的有点多了。\n" - elif over_count <= 5: - frequency_block = "你今天说话比较多,感觉有点疲惫,想要稍微休息一下。\n" - elif over_count <= 8: - frequency_block = "你发现自己说话太多了,感觉很累,想要安静一会儿,除非有重要的事情否则不想回复。\n" - skip_probability = self._skip_probability - else: - frequency_block = "你感觉非常累,想要安静一会儿。\n" - skip_probability = 1 - - # 根据配置和概率决定是否跳过LLM判断 - if self._skip_judge_when_tired and random.random() < skip_probability: - should_skip_llm_judge = True - logger.info( - f"{self.log_prefix} 发言过多(超过{over_count}条),随机决定跳过此次LLM判断(概率{skip_probability * 100:.0f}%)" - ) - - logger.info( - f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,超过阈值{talk_frequency_threshold},添加疲惫提示" - ) - else: - # 回复次数少时的正向提示 - under_count = talk_frequency_threshold - bot_message_count - - if under_count >= talk_frequency_threshold * 0.8: # 回复很少(少于20%) - frequency_block = "你感觉精力充沛,状态很好,积极参与聊天。\n" - elif under_count >= talk_frequency_threshold * 0.5: # 回复较少(少于50%) - frequency_block = "你感觉状态不错。\n" - else: # 刚好达到阈值 - frequency_block = "" - - logger.info( - f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,未超过阈值{talk_frequency_threshold},添加正向提示" - ) - - except Exception as e: - logger.warning(f"{self.log_prefix} 检查发言频率时出错: {e}") - frequency_block = "" + frequency_block, should_skip_llm_judge = self._get_fatigue_status(current_time) # 如果决定跳过LLM判断,直接更新时间并继续等待 - if should_skip_llm_judge: + logger.info(f"{self.log_prefix} 疲劳,继续等待。") last_judge_time = time.time() # 更新判断时间,避免立即重新判断 + start_time = current_time # 更新消息检查的起始时间,以避免重复判断 continue # 跳过本次LLM判断,继续循环等待 # 构建判断上下文 @@ -379,6 +306,105 @@ class NoReplyAction(BaseAction): ) return False, f"不回复动作执行失败: {e}" + def _should_trigger_judge(self, new_message_count: int, time_since_last_judge: float) -> Tuple[bool, str]: + """判断是否应该触发智能判断,并返回触发原因。 + + Args: + new_message_count: 新消息的数量。 + time_since_last_judge: 距离上次判断的时间。 + + Returns: + 一个元组 (should_judge, reason)。 + - should_judge: 一个布尔值,指示是否应该触发判断。 + - reason: 触发判断的原因字符串。 + """ + # 判定条件:累计3条消息或等待超过15秒且有新消息 + should_judge_flag = new_message_count >= 3 or (new_message_count > 0 and time_since_last_judge >= 15.0) + + if not should_judge_flag: + return False, "" + + # 判断触发原因 + if new_message_count >= 3: + return True, f"累计{new_message_count}条消息" + elif new_message_count > 0 and time_since_last_judge >= 15.0: + return True, f"等待{time_since_last_judge:.1f}秒且有新消息" + + return False, "" + + def _get_fatigue_status(self, current_time: float) -> Tuple[str, bool]: + """ + 根据最近的发言频率生成疲劳提示,并决定是否跳过判断。 + + Args: + current_time: 当前时间戳。 + + Returns: + 一个元组 (frequency_block, should_skip_judge)。 + - frequency_block: 疲劳度相关的提示字符串。 + - should_skip_judge: 是否应该跳过LLM判断的布尔值。 + """ + try: + # 获取过去10分钟的所有消息 + past_10min_time = current_time - 600 # 10分钟前 + all_messages_10min = message_api.get_messages_by_time_in_chat( + chat_id=self.chat_id, + start_time=past_10min_time, + end_time=current_time, + ) + + # 手动过滤bot自己的消息 + bot_message_count = 0 + if all_messages_10min: + user_id = global_config.bot.qq_account + for message in all_messages_10min: + sender_id = message.get("user_id", "") + if sender_id == user_id: + bot_message_count += 1 + + talk_frequency_threshold = global_config.chat.get_current_talk_frequency(self.chat_id) * 10 + + if bot_message_count > talk_frequency_threshold: + over_count = bot_message_count - talk_frequency_threshold + skip_probability = 0 + frequency_block = "" + + if over_count <= 3: + frequency_block = "你感觉稍微有些累,回复的有点多了。\n" + elif over_count <= 5: + frequency_block = "你今天说话比较多,感觉有点疲惫,想要稍微休息一下。\n" + elif over_count <= 8: + frequency_block = "你发现自己说话太多了,感觉很累,想要安静一会儿,除非有重要的事情否则不想回复。\n" + skip_probability = self._skip_probability + else: + frequency_block = "你感觉非常累,想要安静一会儿。\n" + skip_probability = 1 + + should_skip_judge = self._skip_judge_when_tired and random.random() < skip_probability + + if should_skip_judge: + logger.info( + f"{self.log_prefix} 发言过多(超过{over_count}条),随机决定跳过此次LLM判断(概率{skip_probability * 100:.0f}%)" + ) + + logger.info(f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,超过阈值{talk_frequency_threshold},添加疲惫提示") + return frequency_block, should_skip_judge + else: + # 回复次数少时的正向提示 + under_count = talk_frequency_threshold - bot_message_count + frequency_block = "" + if under_count >= talk_frequency_threshold * 0.8: + frequency_block = "你感觉精力充沛,状态很好,积极参与聊天。\n" + elif under_count >= talk_frequency_threshold * 0.5: + frequency_block = "你感觉状态不错。\n" + + logger.info(f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,未超过阈值{talk_frequency_threshold},添加正向提示") + return frequency_block, False + + except Exception as e: + logger.warning(f"{self.log_prefix} 检查发言频率时出错: {e}") + return "", False + def _check_no_activity_and_exit_focus(self, current_time: float) -> bool: """检查过去10分钟是否完全没有发言,决定是否退出专注模式 From d49a6b840e1328e4a667f0f3e5be89190803ee4e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 7 Jul 2025 18:04:52 +0000 Subject: [PATCH 4/9] =?UTF-8?q?=F0=9F=A4=96=20=E8=87=AA=E5=8A=A8=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96=E4=BB=A3=E7=A0=81=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../heart_flow/heartflow_message_processor.py | 4 +-- src/chat/normal_chat/normal_chat.py | 4 ++- src/person_info/relationship_manager.py | 26 +++++++------------ src/plugins/built_in/core_actions/no_reply.py | 9 ++++--- 4 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/chat/heart_flow/heartflow_message_processor.py b/src/chat/heart_flow/heartflow_message_processor.py index 5de0d7015..52a9751ea 100644 --- a/src/chat/heart_flow/heartflow_message_processor.py +++ b/src/chat/heart_flow/heartflow_message_processor.py @@ -123,9 +123,7 @@ class HeartFCMessageReceiver: picid_pattern = r"\[picid:([^\]]+)\]" processed_plain_text = re.sub(picid_pattern, "[图片]", message.processed_plain_text) - logger.info( - f"[{mes_name}]{userinfo.user_nickname}:{processed_plain_text}" - ) + logger.info(f"[{mes_name}]{userinfo.user_nickname}:{processed_plain_text}") logger.debug(f"[{mes_name}][当前时段回复频率: {current_talk_frequency}]") diff --git a/src/chat/normal_chat/normal_chat.py b/src/chat/normal_chat/normal_chat.py index 43ab5803e..51642a700 100644 --- a/src/chat/normal_chat/normal_chat.py +++ b/src/chat/normal_chat/normal_chat.py @@ -596,7 +596,9 @@ class NormalChat: timeout_source = " 和 ".join(timeout_details) - logger.warning(f"[{self.stream_name}] {timeout_source} 任务超时 ({global_config.chat.thinking_timeout}秒),正在取消相关任务...") + logger.warning( + f"[{self.stream_name}] {timeout_source} 任务超时 ({global_config.chat.thinking_timeout}秒),正在取消相关任务..." + ) # print(f"111{self.timeout_count}") self.timeout_count += 1 if self.timeout_count > 5: diff --git a/src/person_info/relationship_manager.py b/src/person_info/relationship_manager.py index 813036c69..12891235c 100644 --- a/src/person_info/relationship_manager.py +++ b/src/person_info/relationship_manager.py @@ -1,12 +1,10 @@ from src.common.logger import get_logger -import math from src.person_info.person_info import PersonInfoManager, get_person_info_manager import time import random from src.llm_models.utils_model import LLMRequest from src.config.config import global_config from src.chat.utils.chat_message_builder import build_readable_messages -from src.manager.mood_manager import mood_manager import json from json_repair import repair_json from datetime import datetime @@ -26,7 +24,6 @@ class RelationshipManager: request_type="relationship", # 用于动作规划 ) - @staticmethod async def is_known_some_one(platform, user_id): """判断是否认识某人""" @@ -113,7 +110,6 @@ class RelationshipManager: return relation_prompt - async def update_person_impression(self, person_id, timestamp, bot_engaged_messages=None): """更新用户印象 @@ -173,7 +169,7 @@ class RelationshipManager: user_count += 1 name_mapping[replace_person_name] = f"用户{current_user}{user_count if user_count > 1 else ''}" current_user = chr(ord(current_user) + 1) - + readable_messages = build_readable_messages( messages=user_messages, replace_bot_name=True, timestamp_mode="normal_no_YMD", truncate=True ) @@ -327,7 +323,7 @@ class RelationshipManager: await person_info_manager.update_one_field( person_id, "points", json.dumps(current_points, ensure_ascii=False, indent=None) ) - + await person_info_manager.update_one_field(person_id, "know_times", know_times + 1) know_since = await person_info_manager.get_value(person_id, "know_since") or 0 if know_since == 0: @@ -335,17 +331,16 @@ class RelationshipManager: await person_info_manager.update_one_field(person_id, "last_know", timestamp) logger.debug(f"{person_name} 的印象更新完成") - + async def _update_impression(self, person_id, current_points, timestamp): # 获取现有forgotten_points person_info_manager = get_person_info_manager() - - + person_name = await person_info_manager.get_value(person_id, "person_name") nickname = await person_info_manager.get_value(person_id, "nickname") know_times = await person_info_manager.get_value(person_id, "know_times") or 0 attitude = await person_info_manager.get_value(person_id, "attitude") or 50 - + # 根据熟悉度,调整印象和简短印象的最大长度 if know_times > 300: max_impression_length = 2000 @@ -362,14 +357,12 @@ class RelationshipManager: else: max_impression_length = 100 max_short_impression_length = 50 - + # 根据好感度,调整印象和简短印象的最大长度 - attitude_multiplier = (abs(100-attitude) / 100) + 1 + attitude_multiplier = (abs(100 - attitude) / 100) + 1 max_impression_length = max_impression_length * attitude_multiplier max_short_impression_length = max_short_impression_length * attitude_multiplier - - - + forgotten_points = await person_info_manager.get_value(person_id, "forgotten_points") or [] if isinstance(forgotten_points, str): try: @@ -539,9 +532,8 @@ class RelationshipManager: await person_info_manager.update_one_field( person_id, "forgotten_points", json.dumps(forgotten_points, ensure_ascii=False, indent=None) ) - - return current_points + return current_points def calculate_time_weight(self, point_time: str, current_time: str) -> float: """计算基于时间的权重系数""" diff --git a/src/plugins/built_in/core_actions/no_reply.py b/src/plugins/built_in/core_actions/no_reply.py index a5c8d637b..a573a39fd 100644 --- a/src/plugins/built_in/core_actions/no_reply.py +++ b/src/plugins/built_in/core_actions/no_reply.py @@ -103,7 +103,6 @@ class NoReplyAction(BaseAction): logger.info(f"{self.log_prefix} 选择不回复(第{count}次),开始摸鱼,原因: {reason}") - # 进入等待状态 while True: current_time = time.time() @@ -387,7 +386,9 @@ class NoReplyAction(BaseAction): f"{self.log_prefix} 发言过多(超过{over_count}条),随机决定跳过此次LLM判断(概率{skip_probability * 100:.0f}%)" ) - logger.info(f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,超过阈值{talk_frequency_threshold},添加疲惫提示") + logger.info( + f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,超过阈值{talk_frequency_threshold},添加疲惫提示" + ) return frequency_block, should_skip_judge else: # 回复次数少时的正向提示 @@ -398,7 +399,9 @@ class NoReplyAction(BaseAction): elif under_count >= talk_frequency_threshold * 0.5: frequency_block = "你感觉状态不错。\n" - logger.info(f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,未超过阈值{talk_frequency_threshold},添加正向提示") + logger.info( + f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,未超过阈值{talk_frequency_threshold},添加正向提示" + ) return frequency_block, False except Exception as e: From 7fe3749ae3b08621054f1626965789407dd10750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=99=B4=E7=A9=BA?= <3103908461@qq.com> Date: Tue, 8 Jul 2025 14:43:36 +0800 Subject: [PATCH 5/9] fix: avoid slice error when content is not sliceable --- src/tools/tool_executor.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/tools/tool_executor.py b/src/tools/tool_executor.py index b7b0d8f69..70a1c3eff 100644 --- a/src/tools/tool_executor.py +++ b/src/tools/tool_executor.py @@ -187,7 +187,12 @@ class ToolExecutor: tool_results.append(tool_info) logger.info(f"{self.log_prefix}工具{tool_name}执行成功,类型: {tool_info['type']}") - logger.debug(f"{self.log_prefix}工具{tool_name}结果内容: {tool_info['content'][:200]}...") + content = tool_info['content'] + if isinstance(content, (str, list, tuple)): + preview = content[:200] + else: + preview = str(content)[:200] + logger.debug(f"{self.log_prefix}工具{tool_name}结果内容: {preview}...") except Exception as e: logger.error(f"{self.log_prefix}工具{tool_name}执行失败: {e}") From 239bae6dd310aca39a8abb4b0eca76af69a25653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=99=B4=E7=A9=BA?= <3103908461@qq.com> Date: Tue, 8 Jul 2025 14:56:40 +0800 Subject: [PATCH 6/9] Update tool_executor.py --- src/tools/tool_executor.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/tools/tool_executor.py b/src/tools/tool_executor.py index 70a1c3eff..3bec3d152 100644 --- a/src/tools/tool_executor.py +++ b/src/tools/tool_executor.py @@ -188,10 +188,9 @@ class ToolExecutor: logger.info(f"{self.log_prefix}工具{tool_name}执行成功,类型: {tool_info['type']}") content = tool_info['content'] - if isinstance(content, (str, list, tuple)): - preview = content[:200] - else: - preview = str(content)[:200] + if not isinstance(content, (str, list, tuple)): + content = str(content) + preview = content[:200] logger.debug(f"{self.log_prefix}工具{tool_name}结果内容: {preview}...") except Exception as e: From f669199f7d0f47b8333a212ff9ed96736c20c7e6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 8 Jul 2025 10:58:21 +0000 Subject: [PATCH 7/9] =?UTF-8?q?=F0=9F=A4=96=20=E8=87=AA=E5=8A=A8=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96=E4=BB=A3=E7=A0=81=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tools/tool_executor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tool_executor.py b/src/tools/tool_executor.py index 3bec3d152..29ee8be1b 100644 --- a/src/tools/tool_executor.py +++ b/src/tools/tool_executor.py @@ -187,7 +187,7 @@ class ToolExecutor: tool_results.append(tool_info) logger.info(f"{self.log_prefix}工具{tool_name}执行成功,类型: {tool_info['type']}") - content = tool_info['content'] + content = tool_info["content"] if not isinstance(content, (str, list, tuple)): content = str(content) preview = content[:200] From ca175d206d9bca498db7309f8d89f18f36572484 Mon Sep 17 00:00:00 2001 From: A0000Xz <122650088+A0000Xz@users.noreply.github.com> Date: Tue, 8 Jul 2025 23:15:44 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E5=BA=94=E8=AF=A5=E4=BF=AE=E5=A5=BD?= =?UTF-8?q?=E4=BA=86TTS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/built_in/tts_plugin/plugin.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/built_in/tts_plugin/plugin.py b/src/plugins/built_in/tts_plugin/plugin.py index d60186a13..05adb3cfd 100644 --- a/src/plugins/built_in/tts_plugin/plugin.py +++ b/src/plugins/built_in/tts_plugin/plugin.py @@ -59,6 +59,13 @@ class TTSAction(BaseAction): # 发送TTS消息 await self.send_custom(message_type="tts_text", content=processed_text) + # 记录动作信息 + await self.store_action_info( + action_build_into_prompt=True, + action_prompt_display="已经发送了语音消息。", + action_done=True + ) + logger.info(f"{self.log_prefix} TTS动作执行成功,文本长度: {len(processed_text)}") return True, "TTS动作执行成功" From f1ad595d7105eac710c52d05f69fff6537b200b1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 8 Jul 2025 15:20:49 +0000 Subject: [PATCH 9/9] =?UTF-8?q?=F0=9F=A4=96=20=E8=87=AA=E5=8A=A8=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96=E4=BB=A3=E7=A0=81=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/built_in/tts_plugin/plugin.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/plugins/built_in/tts_plugin/plugin.py b/src/plugins/built_in/tts_plugin/plugin.py index 05adb3cfd..64780cc92 100644 --- a/src/plugins/built_in/tts_plugin/plugin.py +++ b/src/plugins/built_in/tts_plugin/plugin.py @@ -61,10 +61,8 @@ class TTSAction(BaseAction): # 记录动作信息 await self.store_action_info( - action_build_into_prompt=True, - action_prompt_display="已经发送了语音消息。", - action_done=True - ) + action_build_into_prompt=True, action_prompt_display="已经发送了语音消息。", action_done=True + ) logger.info(f"{self.log_prefix} TTS动作执行成功,文本长度: {len(processed_text)}") return True, "TTS动作执行成功"