feat:允许关闭FOCUS模式

This commit is contained in:
SengokuCola
2025-04-29 20:38:12 +08:00
parent 315b0490fe
commit dec2e4f442
5 changed files with 126 additions and 22 deletions

95
scripts/remove_chong.py Normal file
View File

@@ -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}")

View File

@@ -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"]

View File

@@ -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秒输出一次

View File

@@ -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)

View File

@@ -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 # 仅作示例,不会触发