diff --git a/src/chat/focus_chat/hfc_version_manager.py b/src/chat/focus_chat/hfc_version_manager.py index b391481bb..fd283e3a0 100644 --- a/src/chat/focus_chat/hfc_version_manager.py +++ b/src/chat/focus_chat/hfc_version_manager.py @@ -20,7 +20,7 @@ class HFCVersionManager: """HFC版本号管理器""" # 默认版本号 - DEFAULT_VERSION = "v3.0.0" + DEFAULT_VERSION = "v3.1.0" # 当前运行时版本号 _current_version: Optional[str] = None diff --git a/src/chat/focus_chat/info_processors/relationship_processor.py b/src/chat/focus_chat/info_processors/relationship_processor.py index e90c7fcff..e9ea6d913 100644 --- a/src/chat/focus_chat/info_processors/relationship_processor.py +++ b/src/chat/focus_chat/info_processors/relationship_processor.py @@ -774,7 +774,7 @@ class PersonImpressionpProcessor(BaseProcessor): chat_id: 聊天ID segments: 消息段列表 """ - logger.info(f"开始为 {person_id} 基于 {len(segments)} 个消息段更新印象") + logger.debug(f"开始为 {person_id} 基于 {len(segments)} 个消息段更新印象") try: processed_messages = [] diff --git a/src/chat/focus_chat/memory_activator.py b/src/chat/focus_chat/memory_activator.py index 310fcda0e..fb92c0024 100644 --- a/src/chat/focus_chat/memory_activator.py +++ b/src/chat/focus_chat/memory_activator.py @@ -99,7 +99,7 @@ class MemoryActivator: for working_info_item in working_info: obs_info_text += f"{working_info_item['type']}: {working_info_item['content']}\n" - logger.info(f"回忆待检索内容:obs_info_text: {obs_info_text}") + # logger.info(f"回忆待检索内容:obs_info_text: {obs_info_text}") # 将缓存的关键词转换为字符串,用于prompt cached_keywords_str = ", ".join(self.cached_keywords) if self.cached_keywords else "暂无历史关键词" diff --git a/src/chat/focus_chat/planners/modify_actions.py b/src/chat/focus_chat/planners/modify_actions.py index 6f096eebc..f9d347fc6 100644 --- a/src/chat/focus_chat/planners/modify_actions.py +++ b/src/chat/focus_chat/planners/modify_actions.py @@ -68,7 +68,7 @@ class ActionModifier: hfc_obs = obs if isinstance(obs, ChattingObservation): chat_obs = obs - chat_content = obs.talking_message_str_truncate + chat_content = obs.talking_message_str_truncate_short # 合并所有动作变更 merged_action_changes = {"add": [], "remove": []} diff --git a/src/chat/normal_chat/normal_chat.py b/src/chat/normal_chat/normal_chat.py index e1b5def95..37e55f3cb 100644 --- a/src/chat/normal_chat/normal_chat.py +++ b/src/chat/normal_chat/normal_chat.py @@ -1008,21 +1008,21 @@ class NormalChat: # 计算回复频率 _reply_frequency = bot_reply_count / total_message_count - differ = global_config.normal_chat.talk_frequency - (bot_reply_count / duration) + differ = global_config.chat.talk_frequency - (bot_reply_count / duration) # 如果回复频率低于0.5,增加回复概率 if differ > 0.1: mapped = 1 + (differ - 0.1) * 4 / 0.9 mapped = max(1, min(5, mapped)) logger.debug( - f"[{self.stream_name}] 回复频率低于{global_config.normal_chat.talk_frequency},增加回复概率,differ={differ:.3f},映射值={mapped:.2f}" + f"[{self.stream_name}] 回复频率低于{global_config.chat.talk_frequency},增加回复概率,differ={differ:.3f},映射值={mapped:.2f}" ) self.willing_amplifier += mapped * 0.1 # 你可以根据实际需要调整系数 elif differ < -0.1: mapped = 1 - (differ + 0.1) * 4 / 0.9 mapped = max(1, min(5, mapped)) logger.debug( - f"[{self.stream_name}] 回复频率高于{global_config.normal_chat.talk_frequency},减少回复概率,differ={differ:.3f},映射值={mapped:.2f}" + f"[{self.stream_name}] 回复频率高于{global_config.chat.talk_frequency},减少回复概率,differ={differ:.3f},映射值={mapped:.2f}" ) self.willing_amplifier -= mapped * 0.1 @@ -1120,7 +1120,7 @@ class NormalChat: if not segments: return - logger.info(f"[{self.stream_name}] 开始为 {person_id} 基于 {len(segments)} 个消息段更新印象") + logger.debug(f"[{self.stream_name}] 开始为 {person_id} 基于 {len(segments)} 个消息段更新印象") try: processed_messages = [] @@ -1132,7 +1132,7 @@ class NormalChat: # 获取该段的消息(包含边界) segment_messages = get_raw_msg_by_timestamp_with_chat_inclusive(self.stream_id, start_time, end_time) - logger.info( + logger.debug( f"[{self.stream_name}] 消息段 {i + 1}: {start_date} - {time.strftime('%Y-%m-%d %H:%M', time.localtime(end_time))}, 消息数: {len(segment_messages)}" ) @@ -1160,7 +1160,7 @@ class NormalChat: # 按时间排序所有消息(包括间隔标识) processed_messages.sort(key=lambda x: x["time"]) - logger.info( + logger.debug( f"[{self.stream_name}] 为 {person_id} 获取到总共 {len(processed_messages)} 条消息(包含间隔标识)用于印象更新" ) relationship_manager = get_relationship_manager() @@ -1170,7 +1170,7 @@ class NormalChat: person_id=person_id, timestamp=time.time(), bot_engaged_messages=processed_messages ) else: - logger.info(f"[{self.stream_name}] 没有找到 {person_id} 的消息段对应的消息,不更新印象") + logger.debug(f"[{self.stream_name}] 没有找到 {person_id} 的消息段对应的消息,不更新印象") except Exception as e: logger.error(f"[{self.stream_name}] 为 {person_id} 更新印象时发生错误: {e}") diff --git a/src/chat/normal_chat/willing/mode_classical.py b/src/chat/normal_chat/willing/mode_classical.py index 5ef1ed387..067b0a0ac 100644 --- a/src/chat/normal_chat/willing/mode_classical.py +++ b/src/chat/normal_chat/willing/mode_classical.py @@ -52,7 +52,7 @@ class ClassicalWillingManager(BaseWillingManager): # 检查群组权限(如果是群聊) if ( willing_info.group_info - and willing_info.group_info.group_id in global_config.normal_chat.talk_frequency_down_groups + and willing_info.group_info.group_id in global_config.chat.talk_frequency_down_groups ): reply_probability = reply_probability / global_config.normal_chat.down_frequency_rate diff --git a/src/chat/normal_chat/willing/mode_mxp.py b/src/chat/normal_chat/willing/mode_mxp.py index 2a294d0c5..41bb22aa7 100644 --- a/src/chat/normal_chat/willing/mode_mxp.py +++ b/src/chat/normal_chat/willing/mode_mxp.py @@ -179,7 +179,7 @@ class MxpWillingManager(BaseWillingManager): if w_info.is_picid: probability = 0 # picid格式消息直接不回复 - if w_info.group_info and w_info.group_info.group_id in global_config.normal_chat.talk_frequency_down_groups: + if w_info.group_info and w_info.group_info.group_id in global_config.chat.talk_frequency_down_groups: probability /= global_config.normal_chat.down_frequency_rate self.temporary_willing = current_willing diff --git a/src/chat/utils/chat_message_builder.py b/src/chat/utils/chat_message_builder.py index 5a7a2a729..84593bcff 100644 --- a/src/chat/utils/chat_message_builder.py +++ b/src/chat/utils/chat_message_builder.py @@ -487,7 +487,7 @@ def build_pic_mapping_info(pic_id_mapping: Dict[str, str]) -> str: for pic_id, display_name in sorted_items: # 从数据库中获取图片描述 - description = "内容正在阅读" + description = "内容正在阅读,请稍等" try: image = Images.get_or_none(Images.image_id == pic_id) if image and image.description: diff --git a/src/config/official_configs.py b/src/config/official_configs.py index 368b6127c..1bf34d87e 100644 --- a/src/config/official_configs.py +++ b/src/config/official_configs.py @@ -69,6 +69,9 @@ class ChatConfig(ConfigBase): chat_mode: str = "normal" """聊天模式""" + talk_frequency: float = 1 + """回复频率阈值""" + auto_focus_threshold: float = 1.0 """自动切换到专注聊天的阈值,越低越容易进入专注聊天""" @@ -112,8 +115,7 @@ class NormalChatConfig(ConfigBase): willing_mode: str = "classical" """意愿模式""" - talk_frequency: float = 1 - """回复频率阈值""" + response_interested_rate_amplifier: float = 1.0 """回复兴趣度放大系数""" diff --git a/src/llm_models/utils_model.py b/src/llm_models/utils_model.py index 2dae39517..377fd3813 100644 --- a/src/llm_models/utils_model.py +++ b/src/llm_models/utils_model.py @@ -488,8 +488,8 @@ class LLMRequest: logger.error( f"模型 {self.model_name} 错误码: {response.status} - {error_code_mapping.get(response.status)}" ) - print(request_content) - print(response) + # print(request_content) + # print(response) # 尝试获取并记录服务器返回的详细错误信息 try: error_json = await response.json() diff --git a/src/plugins/built_in/core_actions/plugin.py b/src/plugins/built_in/core_actions/plugin.py index 9775aad64..0c5560ae0 100644 --- a/src/plugins/built_in/core_actions/plugin.py +++ b/src/plugins/built_in/core_actions/plugin.py @@ -5,6 +5,7 @@ 这是系统的内置插件,提供基础的聊天交互功能 """ +import random import time import json from typing import List, Tuple, Type @@ -76,7 +77,7 @@ class ReplyAction(BaseAction): ) # 根据新消息数量决定是否使用reply_to - need_reply = new_message_count >= 4 + need_reply = new_message_count >= random.randint(2, 5) logger.info( f"{self.log_prefix} 从{start_time}到{current_time}共有{new_message_count}条新消息,{'使用' if need_reply else '不使用'}reply_to" ) @@ -170,13 +171,16 @@ class NoReplyAction(BaseAction): last_judge_time = 0 # 上次进行LLM判断的时间 min_judge_interval = self._min_judge_interval # 最小判断间隔,从配置获取 check_interval = 0.2 # 检查新消息的间隔,设为0.2秒提高响应性 + + # 累积判断历史 + judge_history = [] # 存储每次判断的结果和理由 - # 获取no_reply开始时的上下文消息(5条),用于后续记录 + # 获取no_reply开始时的上下文消息(10条),用于后续记录 context_messages = message_api.get_messages_by_time_in_chat( chat_id=self.chat_id, - start_time=start_time - 300, # 获取开始前5分钟内的消息 + start_time=start_time - 600, # 获取开始前10分钟内的消息 end_time=start_time, - limit=5, + limit=10, limit_mode="latest", ) @@ -184,7 +188,7 @@ class NoReplyAction(BaseAction): context_str = "" if context_messages: context_str = message_api.build_readable_messages( - messages=context_messages, timestamp_mode="normal_no_YMD", truncate=False, show_actions=False + messages=context_messages, timestamp_mode="normal_no_YMD", truncate=False, show_actions=True ) context_str = f"当时选择no_reply前的聊天上下文:\n{context_str}\n" @@ -252,23 +256,83 @@ class NoReplyAction(BaseAction): bot_core_personality = global_config.personality.personality_core identity_block = f"你的名字是{bot_name}{bot_nickname},你{bot_core_personality}" + # 构建判断历史字符串 + history_block = "" + if judge_history: + history_block = "之前的判断历史:\n" + for i, (timestamp, judge_result, reason) in enumerate(judge_history, 1): + elapsed_seconds = int(timestamp - start_time) + history_block += f"{i}. 等待{elapsed_seconds}秒时判断:{judge_result},理由:{reason}\n" + history_block += "\n" + + # 检查过去10分钟的发言频率 + frequency_block = "" + 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 + + print(bot_message_count) + + talk_frequency_threshold = global_config.chat.talk_frequency * 10 + + if bot_message_count > talk_frequency_threshold: + over_count = bot_message_count - talk_frequency_threshold + + # 根据超过的数量设置不同的提示词 + if over_count <= 5: + frequency_block = "你感觉稍微有些累,回复的有点多了。\n" + elif over_count <= 10: + frequency_block = "你今天说话比较多,感觉有点疲惫,想要稍微休息一下。\n" + elif over_count <= 20: + frequency_block = "你发现自己说话太多了,感觉很累,需要好好休息一下,不想频繁回复。\n" + else: + frequency_block = "你感到非常疲惫,今天话说得太多了,想要安静一会儿,除非有重要的事情否则不想回复。\n" + + logger.info(f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,超过阈值{talk_frequency_threshold},添加疲惫提示") + else: + 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 = "" + # 构建判断上下文 judge_prompt = f""" {time_block} {identity_block} +你现在正在QQ群参与聊天,以下是聊天内容: {context_str} 在以上的聊天中,你选择了暂时不回复,现在,你看到了新的聊天消息如下: {messages_text} +{history_block} +请注意:{frequency_block} 请你判断,是否要结束不回复的状态,重新加入聊天讨论。 判断标准: 1. 如果有人直接@你、提到你的名字或明确向你询问,应该回复 2. 如果话题发生重要变化,需要你参与讨论,应该回复 -3. 如果出现了紧急或重要的情况,应该回复 -4. 如果只是普通闲聊、重复内容或与你无关的讨论,不需要回复 -5. 如果消息内容过于简单(如单纯的表情、"哈哈"等),不需要回复 +3. 如果只是普通闲聊、重复内容或与你无关的讨论,不需要回复 +4. 如果消息内容过于简单(如单纯的表情、"哈哈"等),不需要回复 +5. 参考之前的判断历史,如果情况有明显变化或持续等待时间过长,考虑调整判断 请用JSON格式回复你的判断,严格按照以下格式: {{ @@ -284,6 +348,8 @@ class NoReplyAction(BaseAction): # 使用 utils_small 模型 small_model = getattr(available_models, "utils_small", None) + print(judge_prompt) + if small_model: # 使用小模型进行判断 success, response, reasoning, model_name = await llm_api.generate_with_model( @@ -307,9 +373,22 @@ class NoReplyAction(BaseAction): f"{self.log_prefix} JSON解析结果 - 判断: {judge_result}, 理由: {reason}" ) + # 将判断结果保存到历史中 + judge_history.append((current_time, judge_result, reason)) + if judge_result == "需要回复": logger.info(f"{self.log_prefix} 模型判断需要回复,结束等待") - full_prompt = f"{global_config.bot.nickname}(你)的想法是:{reason}" + + # 构建包含判断历史的详细信息 + history_summary = "" + if len(judge_history) > 1: + history_summary = f"\n\n判断过程:\n" + for i, (timestamp, past_result, past_reason) in enumerate(judge_history[:-1], 1): + elapsed_seconds = int(timestamp - start_time) + history_summary += f"{i}. 等待{elapsed_seconds}秒时:{past_result},理由:{past_reason}\n" + history_summary += f"{len(judge_history)}. 等待{elapsed_time:.0f}秒时:{judge_result},理由:{reason}" + + full_prompt = f"{global_config.bot.nickname}(你)的想法是:{reason}{history_summary}" await self.store_action_info( action_build_into_prompt=True, action_prompt_display=full_prompt, diff --git a/template/bot_config_template.toml b/template/bot_config_template.toml index 31cf14e7e..1c27bdc03 100644 --- a/template/bot_config_template.toml +++ b/template/bot_config_template.toml @@ -1,5 +1,5 @@ [inner] -version = "2.25.0" +version = "2.26.0" #----以下是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读---- #如果你想要修改配置文件,请在修改后将version的值进行变更 @@ -60,6 +60,8 @@ chat_mode = "normal" # 聊天模式 —— 普通模式:normal,专注模式 # chat_mode = "focus" # chat_mode = "auto" +talk_frequency = 1 # 麦麦回复频率,越高,麦麦回复越频繁 + auto_focus_threshold = 1 # 自动切换到专注聊天的阈值,越低越容易进入专注聊天 exit_focus_threshold = 1 # 自动退出专注聊天的阈值,越低越容易退出专注聊天 # 普通模式下,麦麦会针对感兴趣的消息进行回复,token消耗量较低 @@ -86,7 +88,7 @@ emoji_chance = 0.2 # 麦麦一般回复时使用表情包的概率,设置为1 thinking_timeout = 120 # 麦麦最长思考时间,超过这个时间的思考会放弃(往往是api反应太慢) willing_mode = "classical" # 回复意愿模式 —— 经典模式:classical,mxp模式:mxp,自定义模式:custom(需要你自己实现) -talk_frequency = 1 # 麦麦回复频率,一般为1,默认频率下,30分钟麦麦回复30条(约数) + response_interested_rate_amplifier = 1 # 麦麦回复兴趣度放大系数