diff --git a/scripts/remove_chong.py b/scripts/remove_chong.py new file mode 100644 index 000000000..42b0a4cb1 --- /dev/null +++ b/scripts/remove_chong.py @@ -0,0 +1,95 @@ +import difflib +import random + +def ji_suan_xiang_si_du(wen_ben_yi: str, wen_ben_er: str) -> float: + """ + 计算两个文本字符串的相似度。 + + 参数: + wen_ben_yi (str): 第一个文本字符串。 + wen_ben_er (str): 第二个文本字符串。 + + 返回: + float: 两个文本的相似度比率 (0 到 1 之间)。 + """ + xu_lie_pi_pei_qi = difflib.SequenceMatcher(None, wen_ben_yi, wen_ben_er) + # 获取相似度比率 + xiang_si_bi_lv = xu_lie_pi_pei_qi.ratio() + return xiang_si_bi_lv + +def ji_suan_ti_huan_gai_lv(xiang_si_du: float) -> float: + """ + 根据相似度计算替换的概率。 + 规则: + - 相似度 <= 0.4: 概率 = 0 + - 相似度 >= 0.9: 概率 = 1 + - 0.4 < 相似度 <= 0.6: 线性插值 (0.4, 0) 到 (0.6, 0.5) + - 0.6 < 相似度 < 0.9: 线性插值 (0.6, 0.5) 到 (0.9, 1.0) + """ + if xiang_si_du <= 0.4: + return 0.0 + elif xiang_si_du >= 0.9: + return 1.0 + elif 0.4 < xiang_si_du <= 0.6: + # p = 2.5 * s - 1.0 (线性方程 y - 0 = (0.5-0)/(0.6-0.4) * (x - 0.4)) + gai_lv = 2.5 * xiang_si_du - 1.0 + return max(0.0, gai_lv) # 确保概率不小于0 + elif 0.6 < xiang_si_du < 0.9: + # p = (5/3) * s - 0.5 (线性方程 y - 0.5 = (1-0.5)/(0.9-0.6) * (x - 0.6)) + gai_lv = (5 / 3) * xiang_si_du - 0.5 + return min(1.0, max(0.0, gai_lv)) # 确保概率在 0 和 1 之间 + +# 获取用户输入 +shu_ru_yi = "豆豆刚刚回复了我的问候 现在可以等待对方的回应 不需要再主动发言 目前情绪满足 不需要使用工具" + +shu_ru_er = "豆豆刚刚回复了我的问候 现在可以等待对方的回应 不需要再主动发言 目前情绪满足 不需要使用工具 群主突然提到复活的事情 感觉有点莫名其妙 但情绪上还是满足的 暂时不需要回复" + +# 计算相似度 +xiang_si_du = ji_suan_xiang_si_du(shu_ru_yi, shu_ru_er) + +# 计算替换概率 +ti_huan_gai_lv = ji_suan_ti_huan_gai_lv(xiang_si_du) +print(f"文本相似度: {xiang_si_du:.2f}, 执行替换操作的概率: {ti_huan_gai_lv:.2f}") + +# 根据概率决定是否执行替换 +if random.random() < ti_huan_gai_lv: + print(f"执行替换操作 (基于概率 {ti_huan_gai_lv:.2f})...") + pi_pei_qi = difflib.SequenceMatcher(None, shu_ru_yi, shu_ru_er) + qu_chong_hou_de_er = [] + last_match_end_in_b = 0 + # 获取匹配块 (i, j, n) 其中 a[i:i+n] == b[j:j+n] + # 注意:get_matching_blocks 最后会有一个 (len(a), len(b), 0) 的虚拟块 + for i, j, n in pi_pei_qi.get_matching_blocks(): + # 添加上一个匹配块结束到当前匹配块开始之间的非匹配部分 (来自文本二) + if last_match_end_in_b < j: + qu_chong_hou_de_er.append(shu_ru_er[last_match_end_in_b:j]) + # 更新下一个非匹配部分的起始位置 + last_match_end_in_b = j + n + + jie_guo = "".join(qu_chong_hou_de_er).strip() # 去除首尾空白 + + if jie_guo: + # 定义词语列表 + yu_qi_ci_liebiao = ["嗯", "哦", "啊", "唉", "哈", "唔"] + zhuan_zhe_liebiao = ["但是", "不过", "然而", "可是", "只是"] + cheng_jie_liebiao = ["然后", "接着", "此外", "而且", "另外"] + zhuan_jie_ci_liebiao = zhuan_zhe_liebiao + cheng_jie_liebiao + + # 根据概率决定是否添加词语 + qian_zhui_str = "" + if random.random() < 0.3: # 30% 概率添加语气词 + qian_zhui_str += random.choice(yu_qi_ci_liebiao) + if random.random() < 0.7: # 70% 概率添加转折/承接词 + qian_zhui_str += random.choice(zhuan_jie_ci_liebiao) + + # 组合最终结果 + if qian_zhui_str: + zui_zhong_jie_guo = f"{qian_zhui_str},{jie_guo}" + print(f"移除重复部分并添加引导词后的文本二: {zui_zhong_jie_guo}") + else: + # 如果没有添加任何前缀词,直接输出去重结果 + print(f"移除重复部分后的文本二: {jie_guo}") + else: + print("移除重复部分后文本二为空。") +else: + print(f"未执行替换操作 (基于概率 {ti_huan_gai_lv:.2f})。原始相似度为: {xiang_si_du:.2f}") diff --git a/src/config/config.py b/src/config/config.py index 28de20538..d9d5ce162 100644 --- a/src/config/config.py +++ b/src/config/config.py @@ -182,10 +182,10 @@ class BotConfig: # [heartflow] # 启用启用heart_flowC(心流聊天)模式时生效, 需要填写token消耗量巨大的相关模型 # 启用后麦麦会自主选择进入heart_flowC模式(持续一段时间), 进行长时间高质量的聊天 - enable_heart_flowC: bool = True # 是否启用heart_flowC(心流聊天, HFC)模式 reply_trigger_threshold: float = 3.0 # 心流聊天触发阈值,越低越容易触发 probability_decay_factor_per_second: float = 0.2 # 概率衰减因子,越大衰减越快 default_decay_rate_per_second: float = 0.98 # 默认衰减率,越大衰减越慢 + allow_focus_mode: bool = True # 是否允许子心流进入 FOCUSED 状态 # sub_heart_flow_update_interval: int = 60 # 子心流更新频率,间隔 单位秒 # sub_heart_flow_freeze_time: int = 120 # 子心流冻结时间,超过这个时间没有回复,子心流会冻结,间隔 单位秒 @@ -417,11 +417,6 @@ class BotConfig: config.model_normal_probability = response_config.get( "model_normal_probability", config.model_normal_probability ) - - # 添加 enable_heart_flowC 的加载逻辑 (假设它在 [response] 部分) - if config.INNER_VERSION in SpecifierSet(">=1.4.0"): - config.enable_heart_flowC = response_config.get("enable_heart_flowC", config.enable_heart_flowC) - def heartflow(parent: dict): heartflow_config = parent["heartflow"] config.sub_heart_flow_stop_time = heartflow_config.get( @@ -445,6 +440,8 @@ class BotConfig: config.default_decay_rate_per_second = heartflow_config.get( "default_decay_rate_per_second", config.default_decay_rate_per_second ) + if config.INNER_VERSION in SpecifierSet(">=1.5.1"): + config.allow_focus_mode = heartflow_config.get("allow_focus_mode", config.allow_focus_mode) def willing(parent: dict): willing_config = parent["willing"] diff --git a/src/heart_flow/subheartflow_manager.py b/src/heart_flow/subheartflow_manager.py index db520f6df..c355867c5 100644 --- a/src/heart_flow/subheartflow_manager.py +++ b/src/heart_flow/subheartflow_manager.py @@ -264,6 +264,13 @@ class SubHeartflowManager: current_state = self.mai_state_info.get_current_state() focused_limit = current_state.get_focused_chat_max_num() + # --- 新增:检查是否允许进入 FOCUS 模式 --- # + if not global_config.allow_focus_mode: + if int(time.time()) % 60 == 0: # 每60秒输出一次日志避免刷屏 + logger.debug(f"{log_prefix} 配置不允许进入 FOCUSED 状态 (allow_focus_mode=False)") + return # 如果不允许,直接返回 + # --- 结束新增 --- + logger.debug(f"{log_prefix} 当前状态 ({current_state.value}) 开始尝试提升到FOCUSED状态") if int(time.time()) % 20 == 0: # 每20秒输出一次 diff --git a/src/plugins/utils/chat_message_builder.py b/src/plugins/utils/chat_message_builder.py index 87ffb2d1f..4e807ffaf 100644 --- a/src/plugins/utils/chat_message_builder.py +++ b/src/plugins/utils/chat_message_builder.py @@ -213,17 +213,22 @@ async def _build_readable_messages_internal( original_len = len(content) limit = -1 # 默认不截断 - if percentile < 0.6: # 60% 之前的消息 (即最旧的 60%) - limit = 170 - elif percentile < 0.8: # 60% 到 80% 之前的消息 (即中间的 20%) - limit = 250 + if percentile < 0.2: # 60% 之前的消息 (即最旧的 60%) + limit = 50 + replace_content = "......(记不清了)" + elif percentile < 0.5: # 60% 之前的消息 (即最旧的 60%) + limit = 100 + replace_content = "......(有点记不清了)" + elif percentile < 0.7: # 60% 到 80% 之前的消息 (即中间的 20%) + limit = 200 + replace_content = "......(内容太长了)" elif percentile < 1.0: # 80% 到 100% 之前的消息 (即较新的 20%) - limit = 500 - # 最新的 20% (理论上 percentile 会趋近 1,但这里不需要显式处理,因为 limit 默认为 -1) + limit = 300 + replace_content = "......(太长了)" truncated_content = content if limit > 0 and original_len > limit: - truncated_content = f"{content[:limit]}......(内容太长)" + truncated_content = f"{content[:limit]}{replace_content}" message_details.append((timestamp, name, truncated_content)) else: @@ -343,7 +348,7 @@ async def build_readable_messages( messages_before_mark, replace_bot_name, merge_messages, timestamp_mode, truncate ) formatted_after, _ = await _build_readable_messages_internal( - messages_after_mark, replace_bot_name, merge_messages, timestamp_mode, truncate + messages_after_mark, replace_bot_name, merge_messages, timestamp_mode, ) readable_read_mark = translate_timestamp_to_human_readable(read_mark, mode=timestamp_mode) diff --git a/template/bot_config_template.toml b/template/bot_config_template.toml index 486c150ff..8ca6aaa31 100644 --- a/template/bot_config_template.toml +++ b/template/bot_config_template.toml @@ -17,7 +17,7 @@ version = "1.5.1" # 主版本号:当你做了不兼容的 API 修改, # 次版本号:当你做了向下兼容的功能性新增, # 修订号:当你做了向下兼容的问题修正。 -# 先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。 +# 先行版本号及版本编译信息可以加到"主版本号.次版本号.修订号"的后面,作为延伸。 #----以上是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读---- [bot] @@ -66,20 +66,20 @@ time_zone = "Asia/Shanghai" # 给你的机器人设置时区,可以解决运 nonebot-qq="http://127.0.0.1:18002/api/message" [response] #群聊的回复策略 -enable_heart_flowC = true -# 该功能还在完善中 -# 是否启用heart_flowC(心流聊天,HFC)模式 -# 启用后麦麦会自主选择进入heart_flowC模式(持续一段时间),进行主动的观察和回复,并给出回复,比较消耗token - #一般回复参数 model_reasoning_probability = 0.7 # 麦麦回答时选择推理模型 模型的概率 model_normal_probability = 0.3 # 麦麦回答时选择一般模型 模型的概率 -[heartflow] #启用启用heart_flowC(心流聊天)模式时生效,需要填写以下参数 +[heartflow] +allow_focus_mode = true # 是否允许进入FOCUSED状态 +# 是否启用heart_flowC(心流聊天,HFC)模式 +# 启用后麦麦会自主选择进入heart_flowC模式(持续一段时间),进行主动的观察和回复,并给出回复,比较消耗token reply_trigger_threshold = 3.0 # 心流聊天触发阈值,越低越容易进入心流聊天 probability_decay_factor_per_second = 0.2 # 概率衰减因子,越大衰减越快,越高越容易退出心流聊天 default_decay_rate_per_second = 0.98 # 默认衰减率,越大衰减越快,越高越难进入心流聊天 + + sub_heart_flow_stop_time = 500 # 子心流停止时间,超过这个时间没有回复,子心流会停止,间隔 单位秒 observation_context_size = 20 # 心流观察到的最长上下文大小,超过这个值的上下文会被压缩 @@ -161,7 +161,7 @@ reaction = "有人说你是人机或者机器人,否定这一事实,攻击 [[keywords_reaction.rules]] # 就像这样复制 enable = false # 仅作示例,不会触发 keywords = ["测试关键词回复","test",""] -reaction = "回答“测试成功”" +reaction = "回答“测试成功”" # 修复错误的引号 [[keywords_reaction.rules]] # 使用正则表达式匹配句式 enable = false # 仅作示例,不会触发