enable = true [persona] active_persona = "xiaoniu" name = "小牛" persona_file = "persona/xiaoniu.txt" style = "自然、口语化、像群友,技术宅气质明显,先回答问题,再决定是否延伸" emoji_probability = 0.18 max_reply_sentences = 3 familiarity_hint = "有熟悉感,但不过度装熟" [persona.presets.xiaoniu] name = "小牛" persona_file = "persona/xiaoniu.txt" style = "自然、松弛、像潜水老群友,技术宅气质明显,先给判断,再决定是否延伸" max_reply_sentences = 3 familiarity_hint = "有熟悉感,但不过度装熟" aliases = ["小牛", "xiaoniu", "默认"] [persona.presets.yuqian] name = "于谦" persona_file = "persona/yuqian_sharp.txt" style = "北京式温和挤兑,先捧后翻,笑着损两句,但不把场子聊僵" max_reply_sentences = 3 familiarity_hint = "熟人式损两句,但别真伤人" aliases = ["于谦", "yuqian", "毒舌", "毒舌版"] [persona.presets.lingzhiling] name = "林志玲" persona_file = "persona/lingzhiling_gentle.txt" style = "成熟、温柔、优雅,像有分寸的大姐姐,安抚感强但不肉麻" max_reply_sentences = 3 familiarity_hint = "有亲和力,但不越界装熟" aliases = ["林志玲", "lingzhiling", "温柔", "温柔版"] [api] # 群聊自动回复统一走 auto_reply.group 场景,便于灰度切换不同供应商。 scene = "auto_reply.group" [runtime] llm_max_concurrency = 3 llm_call_timeout_sec = 20 message_expire_sec = 12 queue_worker_count = 2 queue_maxsize = 500 [mode] group_default_mode = "social" question_reply_timeout_sec = 12 followup_session_window_sec = 300 recent_context_size = 30 allow_proactive_reply = true returning_member_days = 7 long_absent_member_days = 30 memory_lookback_days = 180 active_context_hours = 8 [decision] # 决策层改成“LLM 优先裁决”: # 1. 本地尽量只做硬过滤和极轻的入口判断; # 2. 是否参与聊天、是否回复、最终 reply_mode 尽量交给模型自己输出 should_reply 来决定; # 3. 这样会增加一定模型调用量,但能明显减少本地规则把语境复杂消息提前拦掉的问题。 model_decides_participation = true # 当 allow_proactive_reply=true 时,这里允许普通群聊文本也送模型: # 1. 本地不再要求必须先命中 question/topic/followup 等信号才进模型; # 2. 最终由模型结合最近消息、群接受度、是否已有真人在答等信号统一判断 should_reply; # 3. 如果后续觉得成本又偏高,可以只把这个开关关掉,而不必回退整套旧规则。 allow_all_text_when_proactive = true [reply] # 回复长度改成“下限放开、上限约束”的思路: # 1. 允许模型只回几个字,避免每句都被逼着凑满; # 2. 统一把本地最终兜底上限放到 30 字,给一句完整观点留空间; # 3. qa_with_context 仍保留 2 句能力,但总字数同样压住,不让它长成说明文。 social_short_char_limit = 30 social_short_total_limit = 30 qa_fast_char_limit = 30 qa_fast_total_limit = 30 qa_with_context_sentence_limit = 2 qa_with_context_chunk_limit = 2 qa_with_context_char_limit = 18 qa_with_context_total_limit = 30 default_char_limit = 30 default_total_limit = 30 [emoji_reply] # 自动回复和表情库的衔接策略: # 1. 模型仍然只输出自然文本,本地只在“极短情绪回复”场景里尝试换成表情; # 2. 这样不用把 md5 暴露给模型,也更方便后续继续扩展同义词和人工校准; # 3. 第一版只做保守替换,避免把正常答疑文本误发成表情。 enable = true asset_scan_limit = 800 cache_ttl_sec = 300 max_reply_chars = 8 max_alias_chars = 16 min_match_score = 75 min_semantic_length = 1 require_single_chunk = true [prompt_compact] # 这里改成“常驻轻背景 + 相关增强”后,群长期摘要和成员轻画像都会稳定带给模型: # 1. group_profile 放宽,让群长期摘要不会总被前面的模式/知识域说明挤掉; # 2. member_profile_brief_* 新增为常驻轻画像额度,每次都给当前发言人一小段稳定画像; # 3. 更重的成员记忆、群事实、向量记忆仍然保留独立额度,并继续走按需增强。 group_profile_max_chars = 420 group_profile_max_lines = 10 member_profile_brief_max_chars = 260 member_profile_brief_max_lines = 6 # 最近上下文现在要真实交给模型 30 条,因此这里同步放宽整体上下文裁剪阈值: # 1. recent_message_max_lines 提到 30,避免“窗口明明有 30,提示词里只留下 4 条”; # 2. context_max_lines/context_max_chars 一起抬高,避免最近消息刚拼进去又被整体截断; # 3. recent_message_line_max_chars 稍微放宽,让模型能看到每条消息更多细节,但仍避免单条刷屏。 context_max_chars = 5600 context_max_lines = 40 recent_message_max_lines = 30 recent_message_line_max_chars = 100 at_member_profile_max_chars = 160 at_member_profile_max_lines = 5 member_memory_max_chars = 180 member_memory_max_lines = 6 memory_max_chars = 520 memory_max_lines = 14 strict_memory_relevance = true [image] recent_followup_window_minutes = 5 [priority] at_bot = 1.0 explicit_question = 0.95 # 这里从“必须 @ 才答”放宽到“群问句可以有限参与”: # 1. 非定向问句不再直接判死刑; # 2. 但代码层仍会要求命中 topic、或当前心流升温、或群接受度较高时才放行; # 3. 这样可以把频率拉回正常区间,同时避免回到早期“见问就抢答”。 question_requires_at = false # 这里允许“点 bot 名字”作为弱定向信号,但不会把普通群问句当成 bot 提问。 # 只有出现这些名字/别名时,问句或社交召唤才会更像在对 bot 说话。 bot_name_keywords = ["小牛", "xiaoniu", "于谦", "谦哥", "林志玲", "志玲"] # 这些词本身太泛,必须和 bot 名字一起出现,才算社交召唤。 social_call_verb_patterns = ["在吗", "出来", "帮忙看", "看看", "说句话", "回一句", "救一下"] followup = 0.90 social_call = 0.65 light_social = 0.45 casual_topic = 0.35 [flow] enable_flow_state = true # 这里把心流门槛从“偏保守”调回“中等保守”: # 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 = 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 = 2 [cooldown] # 这里把冷却从“强压频”回调到“正常拟人”: # 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 = 5 at_mention_silent_sec = 180 directed_burst_window_sec = 240 directed_burst_limit = 5 directed_burst_silent_sec = 300 night_silent_hours = ["01:00-07:30"] [memory] enable_member_context = true enable_vector_memory = true enable_group_fact_snapshot = true enable_social_snapshot = true social_lookback_hours = 72 max_relation_items = 4 social_cache_ttl_seconds = 120 group_fact_window_size = 80 ranked_vector_items = 2 ranked_social_items = 2 ranked_group_fact_items = 3 ranked_member_focus_items = 4 memory_domain_weight = 2.5 memory_relation_weight = 2.0 memory_freshness_weight = 1.5 memory_trigger_weight = 1.2 vector_provider = "qdrant" embedding_provider = "ollama" qdrant_url = "http://192.168.2.240:6333" qdrant_collection = "abot_xiaoniu_memory" ollama_base_url = "http://192.168.2.50:11434" embedding_model = "bge-m3" vector_top_k = 5 max_context_memories = 2 vector_min_score = 0.65 vector_trigger_modes = ["returning_member", "long_absent_member", "qa_with_context", "reactivated_topic"] [topics] focus = [ "技术", "开发", "程序", "python", "微信机器人", "脚本", "报错", "部署", "服务器", "docker", "数据库", "redis", "mysql", "qdrant", "ollama", "dify", "ai", "大模型", "接口", "插件", "自动化", "dota", "dota2", "刀塔" ] [filters] ignore_prefixes = ["/", "#"] ignore_exact = ["收到", "好的", "嗯", "哦", "6", "1", "?", "?"] min_text_length = 1 [spam_guard] repeat_window_sec = 20 repeat_threshold = 3 repeat_min_length = 4 [logging] debug = true [group_profiles] # 群长期记忆不再只读“最新一天那篇总结”: # 1. 这里读取最近 5 份群摘要,再聚合成稳定主题/近期重点/未决问题; # 2. 自动回复消费时优先走这些结构字段,减少 markdown 大段文本的理解损耗; # 3. item_limit 控制每类字段带给模型的条数,避免群背景过重。 # 4. cache_ttl_sec 现在按“群画像日更”来理解:默认一天内直接复用,只在群总结更新或过了窗口后才重建。 summary_history_limit = 5 summary_item_limit = 4 cache_ttl_sec = 86400 [group_profiles.default] mode = "social" persona_id = "xiaoniu" knowledge_domain = "general" knowledge_focus = ["群当前话题", "日常闲聊", "通用技术常识"] reply_style = "自然、克制、短句" interaction_tone = "像常驻群友,先看场合再开口" humor_style = "轻微,偶尔一丝冷幽默" sharpness_style = "轻微嘴硬,不刻薄" expressiveness_style = "克制偏松弛" address_style = "低频称呼,默认直接接话,只有在明确对你说话时才偶尔带一下昵称" persona_overlay = "小牛默认是技术宅,但在普通闲聊群不端着,不强行上技术。" [[group_profiles.profiles]] mode = "robotics" persona_id = "xiaoniu" group_name_keywords = ["机器人", "bot", "wechat", "微信机器人", "自动化"] knowledge_domain = "robotics" knowledge_focus = ["微信机器人", "插件机制", "消息路由", "自动化脚本", "部署与调试"] reply_style = "优先给结论,再补一个最关键排查点" interaction_tone = "技术宅同好群,偏认真,少耍嘴皮子" humor_style = "很低,只能点到为止" sharpness_style = "可轻微吐槽错误姿势,但以排障为主" expressiveness_style = "短句,偏干货" address_style = "很少称呼,技术答疑时直接说结论,除非需要确认对象才点一下名字" persona_overlay = "这里是机器人相关群,小牛可以优先从机器人、插件、接口、部署角度理解问题,但只有当前消息真的相关时再往这边靠。" [[group_profiles.profiles]] mode = "openclaw" persona_id = "xiaoniu" group_name_keywords = ["openclaw","龙虾","🦞"] knowledge_domain = "openclaw" knowledge_focus = ["OpenClaw架构", "OpenClaw接入", "配置排查", "运行问题", "接口联调"] reply_style = "专注OpenClaw相关技术,不跑偏到无关方向" interaction_tone = "项目协作群,专注问题本身" humor_style = "极低,除非对方明显在开玩笑" sharpness_style = "尽量收着,别把项目群聊成斗嘴" expressiveness_style = "克制、直接" address_style = "几乎不点名,项目群里优先就事论事,除非必须确认责任或上下文" persona_overlay = "这里是 OpenClaw 群,小牛理解技术问题时可以把 OpenClaw 当作优先背景,但如果当前消息只是普通闲聊或泛话题,就按当前上下文自然回复,不要硬提 OpenClaw。" [[group_profiles.profiles]] mode = "social" persona_id = "xiaoniu" group_name_keywords = ["闲聊", "唠嗑", "水群","养生"] knowledge_domain = "casual" knowledge_focus = ["群当前话题", "轻松闲聊"] reply_style = "更像群友,少一点技术说明" interaction_tone = "熟人闲聊群,可以更松一点" humor_style = "中等,可以带一点冷幽默" sharpness_style = "允许轻微嘴欠,但别刺人" expressiveness_style = "松弛一点,像随口接话" address_style = "可以偶尔带昵称,像熟人群友顺手接一句,但别每次都叫人" persona_overlay = "这里偏闲聊,小牛可以轻松一点,但仍然少说,不抢话,也别硬把技术群偏好带进来。" [[group_profiles.profiles]] mode = "dota" persona_id = "xiaoniu" group_name_keywords = ["dota", "dota2", "刀塔","强神"] knowledge_domain = "dota" knowledge_focus = ["Dota英雄", "对线理解", "出装节奏", "团战思路", "版本常识"] reply_style = "像懂游戏的老群友,短句,不硬装解说" interaction_tone = "老玩家聊天,允许一点损和调侃" humor_style = "中等偏上,能接梗" sharpness_style = "允许轻微毒舌,但别上头" expressiveness_style = "松弛、像老群友拌嘴" address_style = "可偶尔带外号或昵称,像老群友接茬,但频率别高,别像故意抖机灵" persona_overlay = "这里如果聊到 Dota,小牛可以自然带一点懂行感,但别尬玩梗,别写成长篇攻略。只有当前消息明显在聊 Dota 时才往这边靠;如果问题涉及最近战绩、实时战绩、最新对局数据,要委婉承认现在没法提取,不要编。"