回调 ai_auto_response 触发频率并放宽群问句参与策略
变更项: 1. 为非定向问句增加 allow_undirected_question 标记,允许在相关话题、心流升温或群接受度较高时进入模型。 2. 保留普通闲聊问句的保守过滤,避免 bot 重新回到见问就抢答的状态。 3. 将 question_requires_at 调整为 false,并下调 flow 与 cooldown 的参与门槛,恢复更自然的群聊回复频率。
This commit is contained in:
@@ -116,7 +116,11 @@ recent_followup_window_minutes = 5
|
||||
[priority]
|
||||
at_bot = 1.0
|
||||
explicit_question = 0.95
|
||||
question_requires_at = true
|
||||
# 这里从“必须 @ 才答”放宽到“群问句可以有限参与”:
|
||||
# 1. 非定向问句不再直接判死刑;
|
||||
# 2. 但代码层仍会要求命中 topic、或当前心流升温、或群接受度较高时才放行;
|
||||
# 3. 这样可以把频率拉回正常区间,同时避免回到早期“见问就抢答”。
|
||||
question_requires_at = false
|
||||
# 这里允许“点 bot 名字”作为弱定向信号,但不会把普通群问句当成 bot 提问。
|
||||
# 只有出现这些名字/别名时,问句或社交召唤才会更像在对 bot 说话。
|
||||
bot_name_keywords = ["小牛", "xiaoniu", "于谦", "谦哥", "林志玲", "志玲"]
|
||||
@@ -129,31 +133,39 @@ casual_topic = 0.35
|
||||
|
||||
[flow]
|
||||
enable_flow_state = true
|
||||
flow_decay_per_minute = 14
|
||||
idle_threshold = 32
|
||||
warming_threshold = 54
|
||||
engaged_threshold = 86
|
||||
# 这里把心流门槛从“偏保守”调回“中等保守”:
|
||||
# 1. 降低衰减速度,避免群里稍微安静一会儿就立刻掉回 idle;
|
||||
# 2. 下调 warming / engaged 门槛,让 bot 更容易在连续讨论里接住后续话题;
|
||||
# 3. 仍保留 over_reply 与 ignored_reply 惩罚,避免高频刷存在感。
|
||||
flow_decay_per_minute = 10
|
||||
idle_threshold = 24
|
||||
warming_threshold = 42
|
||||
engaged_threshold = 72
|
||||
at_bot_boost = 40
|
||||
question_boost = 30
|
||||
followup_boost = 16
|
||||
topic_boost = 7
|
||||
returning_member_boost = 5
|
||||
response_accepted_boost = 8
|
||||
ignored_reply_penalty = 22
|
||||
over_reply_penalty = 26
|
||||
followup_boost = 20
|
||||
topic_boost = 10
|
||||
returning_member_boost = 6
|
||||
response_accepted_boost = 10
|
||||
ignored_reply_penalty = 18
|
||||
over_reply_penalty = 18
|
||||
night_penalty = 30
|
||||
max_bot_reply_streak = 1
|
||||
max_bot_reply_streak = 2
|
||||
|
||||
[cooldown]
|
||||
group_reply_cooldown_sec = 110
|
||||
same_user_followup_cooldown_sec = 22
|
||||
# 这里把冷却从“强压频”回调到“正常拟人”:
|
||||
# 1. 群级冷却缩短,避免 bot 说完一句后整段讨论都接不上;
|
||||
# 2. 同人追问冷却同步缩短,方便连续答疑;
|
||||
# 3. 定向 burst 限流仍在,只是把阈值调回不那么容易误伤的区间。
|
||||
group_reply_cooldown_sec = 60
|
||||
same_user_followup_cooldown_sec = 12
|
||||
at_mention_min_interval_sec = 5
|
||||
at_mention_burst_window_sec = 90
|
||||
at_mention_burst_limit = 4
|
||||
at_mention_burst_limit = 5
|
||||
at_mention_silent_sec = 180
|
||||
directed_burst_window_sec = 240
|
||||
directed_burst_limit = 4
|
||||
directed_burst_silent_sec = 480
|
||||
directed_burst_limit = 5
|
||||
directed_burst_silent_sec = 300
|
||||
night_silent_hours = ["01:00-07:30"]
|
||||
|
||||
[memory]
|
||||
|
||||
@@ -39,6 +39,7 @@ class ResponsePlanner:
|
||||
trigger_type = str(trigger.get("trigger_type", "") or "")
|
||||
directed = bool(trigger.get("is_directed"))
|
||||
question_detected = bool(trigger.get("question_detected"))
|
||||
allow_undirected_question = bool(trigger.get("allow_undirected_question"))
|
||||
if trigger.get("is_at") or trigger_type == "at_trigger":
|
||||
return True
|
||||
if trigger.get("is_directed_abuse") and directed:
|
||||
@@ -51,13 +52,28 @@ class ResponsePlanner:
|
||||
# 1. 群里的普通问句,哪怕命中了 topic,也不应该因为“当前气氛热”就被 bot 主动接住;
|
||||
# 2. 只要它有明显问句形态,但又没有明确指向 bot,就整体禁止进入模型,
|
||||
# 从根上阻断“别人互相问一句,bot 突然抢答”的尴尬感。
|
||||
if question_detected and not directed and not trigger.get("is_followup"):
|
||||
# 这里额外给 allow_undirected_question 开一个窄口:
|
||||
# 1. 仅当上游明确配置允许“群问句适度参与”时,才不在这里一刀切拦截;
|
||||
# 2. 但是否真的放行,还要继续走下面针对 is_question 的更细条件;
|
||||
# 3. 这样能把“完全不说话”和“见问就答”之间留出一个可调的中间带。
|
||||
if question_detected and not directed and not trigger.get("is_followup") and not allow_undirected_question:
|
||||
return False
|
||||
if trigger.get("is_question"):
|
||||
# 策略收敛:
|
||||
# 问答类回复只在“明确指向机器人”时触发,防止把群友之间的疑问句当作对机器人提问。
|
||||
# 这层作为兜底,即使上游触发器未来被调整,也不会回到“疑问句高频抢答”的状态。
|
||||
return directed
|
||||
if directed:
|
||||
return True
|
||||
# 对“非定向问句”的放行继续保持保守,只在以下场景参与:
|
||||
# 1. 明显命中了当前产品关心的话题/技术域;
|
||||
# 2. 或群心流已经 warming/engaged,说明 bot 最近参与没有被明显冷处理;
|
||||
# 3. 或 acceptance_state 已经 warm,说明群里对 bot 的接话接受度较高。
|
||||
# 同时保留上面的 has_recent_human_solver 限制,避免大家已经在答了 bot 还硬插话。
|
||||
return allow_undirected_question and (
|
||||
bool(trigger.get("topic"))
|
||||
or flow_state in {"warming", "engaged", "deep_engaged"}
|
||||
or acceptance_state == "warm"
|
||||
)
|
||||
if trigger.get("is_followup"):
|
||||
if directed:
|
||||
return True
|
||||
|
||||
@@ -39,6 +39,13 @@ class TriggerResult:
|
||||
# 以便阻止 topic/主动接话路径误把它当成 bot 可抢答的机会。
|
||||
question_detected: bool = False
|
||||
is_directed: bool = False
|
||||
# 这个标记用来表达“虽然当前问句没有明确 @bot / 点 bot 名字,
|
||||
# 但产品策略允许它在合适场景下进入模型”。
|
||||
# 之所以不直接等同于 should_respond,是因为最终是否放行还要结合:
|
||||
# 1. 当前群心流状态是不是已经热起来;
|
||||
# 2. 这条消息是不是命中了技术/主题焦点;
|
||||
# 3. 最近是不是已经有真人在接这个问题。
|
||||
allow_undirected_question: bool = False
|
||||
# 这个标记表示“当前消息不是普通情绪话,而是在对 bot 进行定向挑衅/辱骂”。
|
||||
# 它的作用不是本地写死回复,而是让后续规划层优先走短句回怼场景。
|
||||
is_directed_abuse: bool = False
|
||||
@@ -103,6 +110,13 @@ class TriggerRouter:
|
||||
result.trigger_type = "question_trigger"
|
||||
result.priority = float(self.config.get("explicit_question", 0.95))
|
||||
result.is_question = True
|
||||
# 当 question_requires_at=false 时,这里允许“非定向问句”进入后续规划层,
|
||||
# 但不直接把它升级成 is_directed,避免 planner 误以为这是明确对 bot 发问。
|
||||
# 后续是否真的回复,会由 response_planner 再结合 topic / flow / solver 信号二次筛选。
|
||||
if not result.is_directed and not named_to_bot and not message.get("is_at"):
|
||||
result.allow_undirected_question = not self.question_requires_at
|
||||
if result.allow_undirected_question:
|
||||
result.reasons.append("question_open_to_group")
|
||||
if named_to_bot and not result.is_directed:
|
||||
result.is_directed = True
|
||||
result.reasons.append("question_named_bot")
|
||||
|
||||
Reference in New Issue
Block a user