better 配置文件整理,防止眼花

123
This commit is contained in:
SengokuCola
2025-03-25 21:59:15 +08:00
parent 4e7efb4271
commit c220f4c79e
7 changed files with 446 additions and 148 deletions

179
config/bot_config_test.toml Normal file
View File

@@ -0,0 +1,179 @@
[inner]
version = "0.0.10"
[mai_version]
version = "0.6.0"
version-fix = "snapshot-1"
#以下是给开发人员阅读的,一般用户不需要阅读
#如果你想要修改配置文件请在修改后将version的值进行变更
#如果新增项目请在BotConfig类下新增相应的变量
#1.如果你修改的是[]层级项目,例如你新增了 [memory],那么请在config.py的 load_config函数中的include_configs字典中新增"内容":{
#"func":memory,
#"support":">=0.0.0", #新的版本号
#"necessary":False #是否必须
#}
#2.如果你修改的是[]下的项目,例如你新增了[memory]下的 memory_ban_words ,那么请在config.py的 load_config函数中的 memory函数下新增版本判断:
# if config.INNER_VERSION in SpecifierSet(">=0.0.2"):
# config.memory_ban_words = set(memory_config.get("memory_ban_words", []))
[bot]
qq = 2814567326
nickname = "麦麦"
alias_names = ['牢麦', '麦叠', '哈基麦']
[personality]
prompt_personality = ['曾经是一个学习地质的女大学生,现在学习心理学和脑科学,你会刷贴吧', '是一个女大学生,你有黑色头发,你会刷小红书', '是一个女大学生你会刷b站对ACG文化感兴趣']
personality_1_probability = 0.7 # 第一种人格出现概率
personality_2_probability = 0.1 # 第二种人格出现概率
personality_3_probability = 0.2 # 第三种人格出现概率请确保三个概率相加等于1
prompt_schedule = "一个曾经学习地质,现在学习心理学和脑科学的女大学生喜欢刷qq贴吧知乎和小红书"
[message]
min_text_length = 2 # 与麦麦聊天时麦麦只会回答文本大于等于此数的消息
max_context_size = 10 # 麦麦获得的上文数量
emoji_chance = 0.2 # 麦麦使用表情包的概率
thinking_timeout = 100 # 麦麦思考时间
response_willing_amplifier = 1 # 麦麦回复意愿放大系数一般为1
response_interested_rate_amplifier = 1 # 麦麦回复兴趣度放大系数,听到记忆里的内容时放大系数
down_frequency_rate = 2 # 降低回复频率的群组回复意愿降低系数
ban_words = []
ban_msgs_regex = []
[emoji]
check_interval = 120 # 检查表情包的时间间隔
register_interval = 10 # 注册表情包的时间间隔
auto_save = true # 自动偷表情包
enable_check = false # 是否启用表情包过滤
check_prompt = "符合公序良俗" # 表情包过滤要求
[cq_code]
enable_pic_translate = false
[response]
model_r1_probability = 0.5 # 麦麦回答时选择主要回复模型1 模型的概率
model_v3_probability = 0.5 # 麦麦回答时选择次要回复模型2 模型的概率
model_r1_distill_probability = 0 # 麦麦回答时选择次要回复模型3 模型的概率
max_response_length = 1024 # 麦麦回答的最大token数
[willing]
willing_mode = "classical" # 回复意愿模式 经典模式
# willing_mode = "dynamic" # 动态模式(可能不兼容)
# willing_mode = "custom" # 自定义模式(可自行调整
[memory]
build_memory_interval = 3000 # 记忆构建间隔 单位秒 间隔越低,麦麦学习越多,但是冗余信息也会增多
build_memory_distribution = [4, 4, 0.6, 48, 36, 0.4] # 记忆构建分布参数分布1均值标准差权重分布2均值标准差权重
build_memory_sample_num = 10 # 采样数量,数值越高记忆采样次数越多
build_memory_sample_length = 30 # 采样长度,数值越高一段记忆内容越丰富
memory_compress_rate = 0.1 # 记忆压缩率 控制记忆精简程度 建议保持默认,调高可以获得更多信息,但是冗余信息也会增多
forget_memory_interval = 300 # 记忆遗忘间隔 单位秒 间隔越低,麦麦遗忘越频繁,记忆更精简,但更难学习
memory_forget_time = 24 #多长时间后的记忆会被遗忘 单位小时
memory_forget_percentage = 0.005 # 记忆遗忘比例 控制记忆遗忘程度 越大遗忘越多 建议保持默认
memory_ban_words = ['表情包', '图片', '回复', '聊天记录']
[mood]
mood_update_interval = 1.0 # 情绪更新间隔 单位秒
mood_decay_rate = 0.95 # 情绪衰减率
mood_intensity_factor = 1.0 # 情绪强度因子
[keywords_reaction] # 针对某个关键词作出反应
enable = true # 关键词反应功能的总开关
[[keywords_reaction.rules]]
enable = true
keywords = [ "人机", "bot", "机器", "入机", "robot", "机器人",]
reaction = "有人说你是人机或者机器人,否定这一事实,攻击或反问他。注意,只有认为你是机器人才回复,否则不要否认"
[[keywords_reaction.rules]]
enable = false
keywords = [ "测试关键词回复", "test", "",]
reaction = "回答“测试成功”"
[chinese_typo]
enable = true # 是否启用中文错别字生成器
error_rate=0.01 # 单字替换概率
min_freq=7 # 最小字频阈值
tone_error_rate=0.3 # 声调错误概率
word_replace_rate=0.01 # 整词替换概率
[others]
enable_kuuki_read = true # 是否启用读空气功能
enable_friend_chat = true # 是否启用好友聊天
[groups]
talk_allowed = [571780722,1022489779,534940728, 192194125, 851345375, 739044565, 766798517, 1030993430, 435591861, 708847644, 591693379, 571780722, 1028699246, 571780722, 1015816696] #可以回复消息的群
talk_frequency_down = [1022489779, 571780722] #降低回复频率的群
ban_user_id = [3488737411, 2732836727, 3878664193, 3799953254] #禁止回复和读取消息的QQ号
[remote] #发送统计信息,主要是看全球有多少只麦麦
enable = true
#下面的模型若使用硅基流动则不需要更改使用ds官方则改成.env.prod自定义的宏使用自定义模型则选择定位相似的模型自己填写
#推理模型
[model.llm_reasoning] #回复模型1 主要回复模型
# name = "Pro/deepseek-ai/DeepSeek-R1"
name = "Qwen/QwQ-32B"
provider = "SILICONFLOW"
pri_in = 1.0 #模型的输入价格(非必填,可以记录消耗)
pri_out = 4.0 #模型的输出价格(非必填,可以记录消耗)
[model.llm_reasoning_minor] #回复模型3 次要回复模型
name = "deepseek-ai/DeepSeek-R1-Distill-Qwen-32B"
provider = "SILICONFLOW"
pri_in = 1.26 #模型的输入价格(非必填,可以记录消耗)
pri_out = 1.26 #模型的输出价格(非必填,可以记录消耗)
#非推理模型
[model.llm_normal] #V3 回复模型2 次要回复模型
name = "Qwen/Qwen2.5-32B-Instruct"
provider = "SILICONFLOW"
pri_in = 1.26 #模型的输入价格(非必填,可以记录消耗)
pri_out = 1.26 #模型的输出价格(非必填,可以记录消耗)
[model.llm_emotion_judge] #表情包判断
name = "Qwen/Qwen2.5-14B-Instruct"
provider = "SILICONFLOW"
pri_in = 0.7
pri_out = 0.7
[model.llm_topic_judge] #记忆主题判断建议使用qwen2.5 7b
name = "Pro/Qwen/Qwen2.5-7B-Instruct"
# name = "Qwen/Qwen2-1.5B-Instruct"
provider = "SILICONFLOW"
pri_in = 0.35
pri_out = 0.35
[model.llm_summary_by_topic] #概括模型建议使用qwen2.5 32b 及以上
name = "Qwen/Qwen2.5-32B-Instruct"
provider = "SILICONFLOW"
pri_in = 1.26
pri_out = 1.26
[model.moderation] #内容审核,开发中
name = ""
provider = "SILICONFLOW"
pri_in = 1.0
pri_out = 2.0
# 识图模型
[model.vlm] #图像识别
name = "Pro/Qwen/Qwen2.5-VL-7B-Instruct"
provider = "SILICONFLOW"
pri_in = 0.35
pri_out = 0.35
#嵌入模型
[model.embedding] #嵌入
name = "BAAI/bge-m3"
provider = "SILICONFLOW"

View File

@@ -77,7 +77,7 @@ async def start_background_tasks():
logger.success("心流系统启动成功") logger.success("心流系统启动成功")
# 只启动表情包管理任务 # 只启动表情包管理任务
asyncio.create_task(emoji_manager.start_periodic_check(interval_MINS=global_config.EMOJI_CHECK_INTERVAL)) asyncio.create_task(emoji_manager.start_periodic_check())
await bot_schedule.initialize() await bot_schedule.initialize()
bot_schedule.print_schedule() bot_schedule.print_schedule()
@@ -105,7 +105,7 @@ async def _(bot: Bot):
_message_manager_started = True _message_manager_started = True
logger.success("-----------消息处理器已启动!-----------") logger.success("-----------消息处理器已启动!-----------")
asyncio.create_task(emoji_manager._periodic_scan(interval_MINS=global_config.EMOJI_REGISTER_INTERVAL)) asyncio.create_task(emoji_manager._periodic_scan())
logger.success("-----------开始偷表情包!-----------") logger.success("-----------开始偷表情包!-----------")
asyncio.create_task(chat_manager._initialize()) asyncio.create_task(chat_manager._initialize())
asyncio.create_task(chat_manager._auto_save_task()) asyncio.create_task(chat_manager._auto_save_task())

View File

@@ -57,9 +57,6 @@ class ChatBot:
self.mood_manager = MoodManager.get_instance() # 获取情绪管理器单例 self.mood_manager = MoodManager.get_instance() # 获取情绪管理器单例
self.mood_manager.start_mood_update() # 启动情绪更新 self.mood_manager.start_mood_update() # 启动情绪更新
self.emoji_chance = 0.2 # 发送表情包的基础概率
# self.message_streams = MessageStreamContainer()
async def _ensure_started(self): async def _ensure_started(self):
"""确保所有任务已启动""" """确保所有任务已启动"""
if not self._started: if not self._started:

View File

@@ -17,40 +17,99 @@ class BotConfig:
"""机器人配置类""" """机器人配置类"""
INNER_VERSION: Version = None INNER_VERSION: Version = None
MAI_VERSION: Version = None
BOT_QQ: Optional[int] = 1 # bot
BOT_QQ: Optional[int] = 114514
BOT_NICKNAME: Optional[str] = None BOT_NICKNAME: Optional[str] = None
BOT_ALIAS_NAMES: List[str] = field(default_factory=list) # 别名,可以通过这个叫它 BOT_ALIAS_NAMES: List[str] = field(default_factory=list) # 别名,可以通过这个叫它
# 消息处理相关配置 # group
MIN_TEXT_LENGTH: int = 2 # 最小处理文本长度
MAX_CONTEXT_SIZE: int = 15 # 上下文最大消息数
emoji_chance: float = 0.2 # 发送表情包的基础概率
ENABLE_PIC_TRANSLATE: bool = True # 是否启用图片翻译
talk_allowed_groups = set() talk_allowed_groups = set()
talk_frequency_down_groups = set() talk_frequency_down_groups = set()
thinking_timeout: int = 100 # 思考时间
response_willing_amplifier: float = 1.0 # 回复意愿放大系数
response_interested_rate_amplifier: float = 1.0 # 回复兴趣度放大系数
down_frequency_rate: float = 3.5 # 降低回复频率的群组回复意愿降低系数
ban_user_id = set() ban_user_id = set()
#personality
PROMPT_PERSONALITY = [
"用一句话或几句话描述性格特点和其他特征",
"例如,是一个热爱国家热爱党的新时代好青年",
"例如,曾经是一个学习地质的女大学生,现在学习心理学和脑科学,你会刷贴吧"
]
PERSONALITY_1: float = 0.6 # 第一种人格概率
PERSONALITY_2: float = 0.3 # 第二种人格概率
PERSONALITY_3: float = 0.1 # 第三种人格概率
# schedule
ENABLE_SCHEDULE_GEN: bool = False # 是否启用日程生成
PROMPT_SCHEDULE_GEN = "无日程"
# message
MAX_CONTEXT_SIZE: int = 15 # 上下文最大消息数
emoji_chance: float = 0.2 # 发送表情包的基础概率
thinking_timeout: int = 120 # 思考时间
max_response_length: int = 1024 # 最大回复长度
ban_words = set()
ban_msgs_regex = set()
# willing
willing_mode: str = "classical" # 意愿模式
response_willing_amplifier: float = 1.0 # 回复意愿放大系数
response_interested_rate_amplifier: float = 1.0 # 回复兴趣度放大系数
down_frequency_rate: float = 3 # 降低回复频率的群组回复意愿降低系数
# response
MODEL_R1_PROBABILITY: float = 0.8 # R1模型概率
MODEL_V3_PROBABILITY: float = 0.1 # V3模型概率
MODEL_R1_DISTILL_PROBABILITY: float = 0.1 # R1蒸馏模型概率
# emoji
EMOJI_CHECK_INTERVAL: int = 120 # 表情包检查间隔(分钟) EMOJI_CHECK_INTERVAL: int = 120 # 表情包检查间隔(分钟)
EMOJI_REGISTER_INTERVAL: int = 10 # 表情包注册间隔(分钟) EMOJI_REGISTER_INTERVAL: int = 10 # 表情包注册间隔(分钟)
EMOJI_SAVE: bool = True # 偷表情包 EMOJI_SAVE: bool = True # 偷表情包
EMOJI_CHECK: bool = False # 是否开启过滤 EMOJI_CHECK: bool = False # 是否开启过滤
EMOJI_CHECK_PROMPT: str = "符合公序良俗" # 表情包过滤要求 EMOJI_CHECK_PROMPT: str = "符合公序良俗" # 表情包过滤要求
ban_words = set() # memory
ban_msgs_regex = set() build_memory_interval: int = 600 # 记忆构建间隔(秒)
memory_build_distribution: list = field(
default_factory=lambda: [4,2,0.6,24,8,0.4]
) # 记忆构建分布参数分布1均值标准差权重分布2均值标准差权重
build_memory_sample_num: int = 10 # 记忆构建采样数量
build_memory_sample_length: int = 20 # 记忆构建采样长度
memory_compress_rate: float = 0.1 # 记忆压缩率
forget_memory_interval: int = 600 # 记忆遗忘间隔(秒)
memory_forget_time: int = 24 # 记忆遗忘时间(小时)
memory_forget_percentage: float = 0.01 # 记忆遗忘比例
memory_ban_words: list = field(
default_factory=lambda: ["表情包", "图片", "回复", "聊天记录"]
) # 添加新的配置项默认值
# mood
mood_update_interval: float = 1.0 # 情绪更新间隔 单位秒
mood_decay_rate: float = 0.95 # 情绪衰减率
mood_intensity_factor: float = 0.7 # 情绪强度因子
# keywords
keywords_reaction_rules = [] # 关键词回复规则
# chinese_typo
chinese_typo_enable = True # 是否启用中文错别字生成器
chinese_typo_error_rate = 0.03 # 单字替换概率
chinese_typo_min_freq = 7 # 最小字频阈值
chinese_typo_tone_error_rate = 0.2 # 声调错误概率
chinese_typo_word_replace_rate = 0.02 # 整词替换概率
# remote
remote_enable: bool = True # 是否启用远程控制
# experimental
enable_friend_chat: bool = False # 是否启用好友聊天
enable_think_flow: bool = False # 是否启用思考流程
max_response_length: int = 1024 # 最大回复长度
remote_enable: bool = False # 是否启用远程控制
# 模型配置 # 模型配置
llm_reasoning: Dict[str, str] = field(default_factory=lambda: {}) llm_reasoning: Dict[str, str] = field(default_factory=lambda: {})
@@ -59,61 +118,13 @@ class BotConfig:
llm_topic_judge: Dict[str, str] = field(default_factory=lambda: {}) llm_topic_judge: Dict[str, str] = field(default_factory=lambda: {})
llm_summary_by_topic: Dict[str, str] = field(default_factory=lambda: {}) llm_summary_by_topic: Dict[str, str] = field(default_factory=lambda: {})
llm_emotion_judge: Dict[str, str] = field(default_factory=lambda: {}) llm_emotion_judge: Dict[str, str] = field(default_factory=lambda: {})
llm_outer_world: Dict[str, str] = field(default_factory=lambda: {})
embedding: Dict[str, str] = field(default_factory=lambda: {}) embedding: Dict[str, str] = field(default_factory=lambda: {})
vlm: Dict[str, str] = field(default_factory=lambda: {}) vlm: Dict[str, str] = field(default_factory=lambda: {})
moderation: Dict[str, str] = field(default_factory=lambda: {}) moderation: Dict[str, str] = field(default_factory=lambda: {})
MODEL_R1_PROBABILITY: float = 0.8 # R1模型概率 # 实验性
MODEL_V3_PROBABILITY: float = 0.1 # V3模型概率 llm_outer_world: Dict[str, str] = field(default_factory=lambda: {})
MODEL_R1_DISTILL_PROBABILITY: float = 0.1 # R1蒸馏模型概率
# enable_advance_output: bool = False # 是否启用高级输出
enable_kuuki_read: bool = True # 是否启用读空气功能
# enable_debug_output: bool = False # 是否启用调试输出
enable_friend_chat: bool = False # 是否启用好友聊天
mood_update_interval: float = 1.0 # 情绪更新间隔 单位秒
mood_decay_rate: float = 0.95 # 情绪衰减率
mood_intensity_factor: float = 0.7 # 情绪强度因子
willing_mode: str = "classical" # 意愿模式
keywords_reaction_rules = [] # 关键词回复规则
chinese_typo_enable = True # 是否启用中文错别字生成器
chinese_typo_error_rate = 0.03 # 单字替换概率
chinese_typo_min_freq = 7 # 最小字频阈值
chinese_typo_tone_error_rate = 0.2 # 声调错误概率
chinese_typo_word_replace_rate = 0.02 # 整词替换概率
# 默认人设
PROMPT_PERSONALITY = [
"曾经是一个学习地质的女大学生,现在学习心理学和脑科学,你会刷贴吧",
"是一个女大学生,你有黑色头发,你会刷小红书",
"是一个女大学生你会刷b站对ACG文化感兴趣",
]
PROMPT_SCHEDULE_GEN = "一个曾经学习地质,现在学习心理学和脑科学的女大学生喜欢刷qq贴吧知乎和小红书"
PERSONALITY_1: float = 0.6 # 第一种人格概率
PERSONALITY_2: float = 0.3 # 第二种人格概率
PERSONALITY_3: float = 0.1 # 第三种人格概率
build_memory_interval: int = 600 # 记忆构建间隔(秒)
forget_memory_interval: int = 600 # 记忆遗忘间隔(秒)
memory_forget_time: int = 24 # 记忆遗忘时间(小时)
memory_forget_percentage: float = 0.01 # 记忆遗忘比例
memory_compress_rate: float = 0.1 # 记忆压缩率
build_memory_sample_num: int = 10 # 记忆构建采样数量
build_memory_sample_length: int = 20 # 记忆构建采样长度
memory_build_distribution: list = field(
default_factory=lambda: [4,2,0.6,24,8,0.4]
) # 记忆构建分布参数分布1均值标准差权重分布2均值标准差权重
memory_ban_words: list = field(
default_factory=lambda: ["表情包", "图片", "回复", "聊天记录"]
) # 添加新的配置项默认值
@staticmethod @staticmethod
def get_config_dir() -> str: def get_config_dir() -> str:
@@ -184,14 +195,18 @@ class BotConfig:
if len(personality) >= 2: if len(personality) >= 2:
logger.debug(f"载入自定义人格:{personality}") logger.debug(f"载入自定义人格:{personality}")
config.PROMPT_PERSONALITY = personality_config.get("prompt_personality", config.PROMPT_PERSONALITY) config.PROMPT_PERSONALITY = personality_config.get("prompt_personality", config.PROMPT_PERSONALITY)
logger.info(f"载入自定义日程prompt:{personality_config.get('prompt_schedule', config.PROMPT_SCHEDULE_GEN)}")
config.PROMPT_SCHEDULE_GEN = personality_config.get("prompt_schedule", config.PROMPT_SCHEDULE_GEN)
if config.INNER_VERSION in SpecifierSet(">=0.0.2"): if config.INNER_VERSION in SpecifierSet(">=0.0.2"):
config.PERSONALITY_1 = personality_config.get("personality_1_probability", config.PERSONALITY_1) config.PERSONALITY_1 = personality_config.get("personality_1_probability", config.PERSONALITY_1)
config.PERSONALITY_2 = personality_config.get("personality_2_probability", config.PERSONALITY_2) config.PERSONALITY_2 = personality_config.get("personality_2_probability", config.PERSONALITY_2)
config.PERSONALITY_3 = personality_config.get("personality_3_probability", config.PERSONALITY_3) config.PERSONALITY_3 = personality_config.get("personality_3_probability", config.PERSONALITY_3)
def schedule(parent: dict):
schedule_config = parent["schedule"]
config.ENABLE_SCHEDULE_GEN = schedule_config.get("enable_schedule_gen", config.ENABLE_SCHEDULE_GEN)
config.PROMPT_SCHEDULE_GEN = schedule_config.get("prompt_schedule_gen", config.PROMPT_SCHEDULE_GEN)
logger.info(f"载入自定义日程prompt:{schedule_config.get('prompt_schedule_gen', config.PROMPT_SCHEDULE_GEN)}")
def emoji(parent: dict): def emoji(parent: dict):
emoji_config = parent["emoji"] emoji_config = parent["emoji"]
config.EMOJI_CHECK_INTERVAL = emoji_config.get("check_interval", config.EMOJI_CHECK_INTERVAL) config.EMOJI_CHECK_INTERVAL = emoji_config.get("check_interval", config.EMOJI_CHECK_INTERVAL)
@@ -200,10 +215,6 @@ class BotConfig:
config.EMOJI_SAVE = emoji_config.get("auto_save", config.EMOJI_SAVE) config.EMOJI_SAVE = emoji_config.get("auto_save", config.EMOJI_SAVE)
config.EMOJI_CHECK = emoji_config.get("enable_check", config.EMOJI_CHECK) config.EMOJI_CHECK = emoji_config.get("enable_check", config.EMOJI_CHECK)
def cq_code(parent: dict):
cq_code_config = parent["cq_code"]
config.ENABLE_PIC_TRANSLATE = cq_code_config.get("enable_pic_translate", config.ENABLE_PIC_TRANSLATE)
def bot(parent: dict): def bot(parent: dict):
# 机器人基础配置 # 机器人基础配置
bot_config = parent["bot"] bot_config = parent["bot"]
@@ -227,6 +238,11 @@ class BotConfig:
willing_config = parent["willing"] willing_config = parent["willing"]
config.willing_mode = willing_config.get("willing_mode", config.willing_mode) config.willing_mode = willing_config.get("willing_mode", config.willing_mode)
if config.INNER_VERSION in SpecifierSet(">=0.0.11"):
config.response_willing_amplifier = willing_config.get("response_willing_amplifier", config.response_willing_amplifier)
config.response_interested_rate_amplifier = willing_config.get("response_interested_rate_amplifier", config.response_interested_rate_amplifier)
config.down_frequency_rate = willing_config.get("down_frequency_rate", config.down_frequency_rate)
def model(parent: dict): def model(parent: dict):
# 加载模型配置 # 加载模型配置
model_config: dict = parent["model"] model_config: dict = parent["model"]
@@ -238,10 +254,10 @@ class BotConfig:
"llm_topic_judge", "llm_topic_judge",
"llm_summary_by_topic", "llm_summary_by_topic",
"llm_emotion_judge", "llm_emotion_judge",
"llm_outer_world",
"vlm", "vlm",
"embedding", "embedding",
"moderation", "moderation",
"llm_outer_world",
] ]
for item in config_list: for item in config_list:
@@ -282,12 +298,11 @@ class BotConfig:
# 如果 列表中的项目在 model_config 中,利用反射来设置对应项目 # 如果 列表中的项目在 model_config 中,利用反射来设置对应项目
setattr(config, item, cfg_target) setattr(config, item, cfg_target)
else: else:
logger.error(f"模型 {item} 在config中不存在请检查") logger.error(f"模型 {item} 在config中不存在请检查,或尝试更新配置文件")
raise KeyError(f"模型 {item} 在config中不存在请检查") raise KeyError(f"模型 {item} 在config中不存在请检查,或尝试更新配置文件")
def message(parent: dict): def message(parent: dict):
msg_config = parent["message"] msg_config = parent["message"]
config.MIN_TEXT_LENGTH = msg_config.get("min_text_length", config.MIN_TEXT_LENGTH)
config.MAX_CONTEXT_SIZE = msg_config.get("max_context_size", config.MAX_CONTEXT_SIZE) config.MAX_CONTEXT_SIZE = msg_config.get("max_context_size", config.MAX_CONTEXT_SIZE)
config.emoji_chance = msg_config.get("emoji_chance", config.emoji_chance) config.emoji_chance = msg_config.get("emoji_chance", config.emoji_chance)
config.ban_words = msg_config.get("ban_words", config.ban_words) config.ban_words = msg_config.get("ban_words", config.ban_words)
@@ -305,6 +320,8 @@ class BotConfig:
if config.INNER_VERSION in SpecifierSet(">=0.0.6"): if config.INNER_VERSION in SpecifierSet(">=0.0.6"):
config.ban_msgs_regex = msg_config.get("ban_msgs_regex", config.ban_msgs_regex) config.ban_msgs_regex = msg_config.get("ban_msgs_regex", config.ban_msgs_regex)
if config.INNER_VERSION in SpecifierSet(">=0.0.11"):
config.max_response_length = msg_config.get("max_response_length", config.max_response_length)
def memory(parent: dict): def memory(parent: dict):
memory_config = parent["memory"] memory_config = parent["memory"]
config.build_memory_interval = memory_config.get("build_memory_interval", config.build_memory_interval) config.build_memory_interval = memory_config.get("build_memory_interval", config.build_memory_interval)
@@ -368,13 +385,9 @@ class BotConfig:
config.talk_frequency_down_groups = set(groups_config.get("talk_frequency_down", [])) config.talk_frequency_down_groups = set(groups_config.get("talk_frequency_down", []))
config.ban_user_id = set(groups_config.get("ban_user_id", [])) config.ban_user_id = set(groups_config.get("ban_user_id", []))
def others(parent: dict): def experimental(parent: dict):
others_config = parent["others"] experimental_config = parent["experimental"]
# config.enable_advance_output = others_config.get("enable_advance_output", config.enable_advance_output) config.enable_friend_chat = experimental_config.get("enable_friend_chat", config.enable_friend_chat)
config.enable_kuuki_read = others_config.get("enable_kuuki_read", config.enable_kuuki_read)
if config.INNER_VERSION in SpecifierSet(">=0.0.7"):
# config.enable_debug_output = others_config.get("enable_debug_output", config.enable_debug_output)
config.enable_friend_chat = others_config.get("enable_friend_chat", config.enable_friend_chat)
# 版本表达式:>=1.0.0,<2.0.0 # 版本表达式:>=1.0.0,<2.0.0
# 允许字段func: method, support: str, notice: str, necessary: bool # 允许字段func: method, support: str, notice: str, necessary: bool
@@ -382,21 +395,21 @@ class BotConfig:
# 例如:"notice": "personality 将在 1.3.2 后被移除",那么在有效版本中的用户就会虽然可以 # 例如:"notice": "personality 将在 1.3.2 后被移除",那么在有效版本中的用户就会虽然可以
# 正常执行程序,但是会看到这条自定义提示 # 正常执行程序,但是会看到这条自定义提示
include_configs = { include_configs = {
"personality": {"func": personality, "support": ">=0.0.0"},
"emoji": {"func": emoji, "support": ">=0.0.0"},
"cq_code": {"func": cq_code, "support": ">=0.0.0"},
"bot": {"func": bot, "support": ">=0.0.0"}, "bot": {"func": bot, "support": ">=0.0.0"},
"response": {"func": response, "support": ">=0.0.0"}, "groups": {"func": groups, "support": ">=0.0.0"},
"willing": {"func": willing, "support": ">=0.0.9", "necessary": False}, "personality": {"func": personality, "support": ">=0.0.0"},
"model": {"func": model, "support": ">=0.0.0"}, "schedule": {"func": schedule, "support": ">=0.0.11", "necessary": False},
"message": {"func": message, "support": ">=0.0.0"}, "message": {"func": message, "support": ">=0.0.0"},
"willing": {"func": willing, "support": ">=0.0.9", "necessary": False},
"emoji": {"func": emoji, "support": ">=0.0.0"},
"response": {"func": response, "support": ">=0.0.0"},
"model": {"func": model, "support": ">=0.0.0"},
"memory": {"func": memory, "support": ">=0.0.0", "necessary": False}, "memory": {"func": memory, "support": ">=0.0.0", "necessary": False},
"mood": {"func": mood, "support": ">=0.0.0"}, "mood": {"func": mood, "support": ">=0.0.0"},
"remote": {"func": remote, "support": ">=0.0.10", "necessary": False}, "remote": {"func": remote, "support": ">=0.0.10", "necessary": False},
"keywords_reaction": {"func": keywords_reaction, "support": ">=0.0.2", "necessary": False}, "keywords_reaction": {"func": keywords_reaction, "support": ">=0.0.2", "necessary": False},
"chinese_typo": {"func": chinese_typo, "support": ">=0.0.3", "necessary": False}, "chinese_typo": {"func": chinese_typo, "support": ">=0.0.3", "necessary": False},
"groups": {"func": groups, "support": ">=0.0.0"}, "experimental": {"func": experimental, "support": ">=0.0.11", "necessary": False},
"others": {"func": others, "support": ">=0.0.0"},
} }
# 原地修改,将 字符串版本表达式 转换成 版本对象 # 原地修改,将 字符串版本表达式 转换成 版本对象
@@ -454,14 +467,13 @@ class BotConfig:
# 获取配置文件路径 # 获取配置文件路径
bot_config_floder_path = BotConfig.get_config_dir() bot_config_floder_path = BotConfig.get_config_dir()
logger.debug(f"正在品鉴配置文件目录: {bot_config_floder_path}") logger.info(f"正在品鉴配置文件目录: {bot_config_floder_path}")
bot_config_path = os.path.join(bot_config_floder_path, "bot_config.toml") bot_config_path = os.path.join(bot_config_floder_path, "bot_config.toml")
if os.path.exists(bot_config_path): if os.path.exists(bot_config_path):
# 如果开发环境配置文件不存在,则使用默认配置文件 # 如果开发环境配置文件不存在,则使用默认配置文件
logger.debug(f"异常的新鲜,异常的美味: {bot_config_path}") logger.info(f"异常的新鲜,异常的美味: {bot_config_path}")
logger.info("使用bot配置文件")
else: else:
# 配置文件不存在 # 配置文件不存在
logger.error("配置文件不存在,请检查路径: {bot_config_path}") logger.error("配置文件不存在,请检查路径: {bot_config_path}")

View File

@@ -340,12 +340,12 @@ class EmojiManager:
except Exception: except Exception:
logger.exception("[错误] 扫描表情包失败") logger.exception("[错误] 扫描表情包失败")
async def _periodic_scan(self, interval_MINS: int = 10): async def _periodic_scan(self):
"""定期扫描新表情包""" """定期扫描新表情包"""
while True: while True:
logger.info("[扫描] 开始扫描新表情包...") logger.info("[扫描] 开始扫描新表情包...")
await self.scan_new_emojis() await self.scan_new_emojis()
await asyncio.sleep(interval_MINS * 60) # 每600秒扫描一次 await asyncio.sleep(global_config.EMOJI_CHECK_INTERVAL * 60)
def check_emoji_file_integrity(self): def check_emoji_file_integrity(self):
"""检查表情包文件完整性 """检查表情包文件完整性
@@ -418,10 +418,10 @@ class EmojiManager:
logger.error(f"[错误] 检查表情包完整性失败: {str(e)}") logger.error(f"[错误] 检查表情包完整性失败: {str(e)}")
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
async def start_periodic_check(self, interval_MINS: int = 120): async def start_periodic_check(self):
while True: while True:
self.check_emoji_file_integrity() self.check_emoji_file_integrity()
await asyncio.sleep(interval_MINS * 60) await asyncio.sleep(global_config.EMOJI_CHECK_INTERVAL * 60)
# 创建全局单例 # 创建全局单例

View File

@@ -0,0 +1,102 @@
import asyncio
from typing import Dict
from ..chat.chat_stream import ChatStream
class WillingManager:
def __init__(self):
self.chat_reply_willing: Dict[str, float] = {} # 存储每个聊天流的回复意愿
self._decay_task = None
self._started = False
async def _decay_reply_willing(self):
"""定期衰减回复意愿"""
while True:
await asyncio.sleep(1)
for chat_id in self.chat_reply_willing:
self.chat_reply_willing[chat_id] = max(0, self.chat_reply_willing[chat_id] * 0.9)
def get_willing(self, chat_stream: ChatStream) -> float:
"""获取指定聊天流的回复意愿"""
if chat_stream:
return self.chat_reply_willing.get(chat_stream.stream_id, 0)
return 0
def set_willing(self, chat_id: str, willing: float):
"""设置指定聊天流的回复意愿"""
self.chat_reply_willing[chat_id] = willing
async def change_reply_willing_received(
self,
chat_stream: ChatStream,
is_mentioned_bot: bool = False,
config=None,
is_emoji: bool = False,
interested_rate: float = 0,
sender_id: str = None,
) -> float:
"""改变指定聊天流的回复意愿并返回回复概率"""
chat_id = chat_stream.stream_id
current_willing = self.chat_reply_willing.get(chat_id, 0)
interested_rate = interested_rate * config.response_interested_rate_amplifier
if interested_rate > 0.4:
current_willing += interested_rate - 0.3
if is_mentioned_bot and current_willing < 1.0:
current_willing += 1
elif is_mentioned_bot:
current_willing += 0.05
if is_emoji:
current_willing *= 0.2
self.chat_reply_willing[chat_id] = min(current_willing, 3.0)
reply_probability = min(max((current_willing - 0.5), 0.01) * config.response_willing_amplifier * 2, 1)
# 检查群组权限(如果是群聊)
if chat_stream.group_info and config:
if chat_stream.group_info.group_id not in config.talk_allowed_groups:
current_willing = 0
reply_probability = 0
if chat_stream.group_info.group_id in config.talk_frequency_down_groups:
reply_probability = reply_probability / config.down_frequency_rate
return reply_probability
def change_reply_willing_sent(self, chat_stream: ChatStream):
"""发送消息后降低聊天流的回复意愿"""
if chat_stream:
chat_id = chat_stream.stream_id
current_willing = self.chat_reply_willing.get(chat_id, 0)
self.chat_reply_willing[chat_id] = max(0, current_willing - 1.8)
def change_reply_willing_not_sent(self, chat_stream: ChatStream):
"""未发送消息后降低聊天流的回复意愿"""
if chat_stream:
chat_id = chat_stream.stream_id
current_willing = self.chat_reply_willing.get(chat_id, 0)
self.chat_reply_willing[chat_id] = max(0, current_willing - 0)
def change_reply_willing_after_sent(self, chat_stream: ChatStream):
"""发送消息后提高聊天流的回复意愿"""
if chat_stream:
chat_id = chat_stream.stream_id
current_willing = self.chat_reply_willing.get(chat_id, 0)
if current_willing < 1:
self.chat_reply_willing[chat_id] = min(1, current_willing + 0.4)
async def ensure_started(self):
"""确保衰减任务已启动"""
if not self._started:
if self._decay_task is None:
self._decay_task = asyncio.create_task(self._decay_reply_willing())
self._started = True
# 创建全局实例
willing_manager = WillingManager()

View File

@@ -1,6 +1,10 @@
[inner] [inner]
version = "0.0.11" version = "0.0.11"
[mai_version]
version = "0.6.0"
version-fix = "snapshot-1"
#以下是给开发人员阅读的,一般用户不需要阅读 #以下是给开发人员阅读的,一般用户不需要阅读
#如果你想要修改配置文件请在修改后将version的值进行变更 #如果你想要修改配置文件请在修改后将version的值进行变更
#如果新增项目请在BotConfig类下新增相应的变量 #如果新增项目请在BotConfig类下新增相应的变量
@@ -14,30 +18,37 @@ version = "0.0.11"
# config.memory_ban_words = set(memory_config.get("memory_ban_words", [])) # config.memory_ban_words = set(memory_config.get("memory_ban_words", []))
[bot] [bot]
qq = 123 qq = 114514
nickname = "麦麦" nickname = "麦麦"
alias_names = ["麦叠", "牢麦"] alias_names = ["麦叠", "牢麦"]
[groups]
talk_allowed = [
123,
123,
] #可以回复消息的群号码
talk_frequency_down = [] #降低回复频率的群号码
ban_user_id = [] #禁止回复和读取消息的QQ号
[personality] [personality]
prompt_personality = [ prompt_personality = [
"用一句话或几句话描述性格特点和其他特征", "用一句话或几句话描述性格特点和其他特征",
"用一句话或几句话描述性格特点和其他特征", "例如,是一个热爱国家热爱党的新时代好青年",
"例如,是一个热爱国家热爱党的新时代好青年" "例如,曾经是一个学习地质的女大学生,现在学习心理学和脑科学,你会刷贴吧"
] ]
personality_1_probability = 0.7 # 第一种人格出现概率 personality_1_probability = 0.7 # 第一种人格出现概率
personality_2_probability = 0.2 # 第二种人格出现概率 personality_2_probability = 0.2 # 第二种人格出现概率可以为0
personality_3_probability = 0.1 # 第三种人格出现概率请确保三个概率相加等于1 personality_3_probability = 0.1 # 第三种人格出现概率请确保三个概率相加等于1
prompt_schedule = "用一句话或几句话描述描述性格特点和其他特征"
[schedule]
enable_schedule_gen = true # 是否启用日程表
prompt_schedule_gen = "用几句话描述描述性格特点或行动规律,这个特征会用来生成日程表"
[message] [message]
min_text_length = 2 # 麦麦聊天时麦麦只会回答文本大于等于此数的消息 max_context_size = 15 # 麦麦获得的上文数量建议15太短太长都会导致脑袋尖尖
max_context_size = 15 # 麦麦获得的上文数量
emoji_chance = 0.2 # 麦麦使用表情包的概率 emoji_chance = 0.2 # 麦麦使用表情包的概率
thinking_timeout = 120 # 麦麦思考时间 thinking_timeout = 120 # 麦麦最长思考时间,超过这个时间的思考会放弃
max_response_length = 1024 # 麦麦回答的最大token数
response_willing_amplifier = 1 # 麦麦回复意愿放大系数一般为1
response_interested_rate_amplifier = 1 # 麦麦回复兴趣度放大系数,听到记忆里的内容时放大系数
down_frequency_rate = 3 # 降低回复频率的群组回复意愿降低系数 除法
ban_words = [ ban_words = [
# "403","张三" # "403","张三"
] ]
@@ -49,26 +60,25 @@ ban_msgs_regex = [
# "\\[CQ:at,qq=\\d+\\]" # 匹配@ # "\\[CQ:at,qq=\\d+\\]" # 匹配@
] ]
[emoji] [willing]
check_interval = 300 # 检查表情包的时间间隔 willing_mode = "classical" # 回复意愿模式 经典模式
register_interval = 20 # 注册表情包的时间间隔 # willing_mode = "dynamic" # 动态模式(可能不兼容)
auto_save = true # 自动偷表情包 # willing_mode = "custom" # 自定义模式(可自行调整
enable_check = false # 是否启用表情包过滤 response_willing_amplifier = 1 # 麦麦回复意愿放大系数一般为1
check_prompt = "符合公序良俗" # 表情包过滤要求 response_interested_rate_amplifier = 1 # 麦麦回复兴趣度放大系数,听到记忆里的内容时放大系数
down_frequency_rate = 3 # 降低回复频率的群组回复意愿降低系数 除法
[cq_code]
enable_pic_translate = false
[response] [response]
model_r1_probability = 0.8 # 麦麦回答时选择主要回复模型1 模型的概率 model_r1_probability = 0.8 # 麦麦回答时选择主要回复模型1 模型的概率
model_v3_probability = 0.1 # 麦麦回答时选择次要回复模型2 模型的概率 model_v3_probability = 0.1 # 麦麦回答时选择次要回复模型2 模型的概率
model_r1_distill_probability = 0.1 # 麦麦回答时选择次要回复模型3 模型的概率 model_r1_distill_probability = 0.1 # 麦麦回答时选择次要回复模型3 模型的概率
max_response_length = 1024 # 麦麦回答的最大token数
[willing] [emoji]
willing_mode = "classical" # 回复意愿模式 经典模式 check_interval = 15 # 检查破损表情包的时间间隔(分钟)
# willing_mode = "dynamic" # 动态模式(可能不兼容) register_interval = 60 # 注册表情包的时间间隔(分钟)
# willing_mode = "custom" # 自定义模式(可自行调整 auto_save = true # 是否保存表情包和图片
enable_check = false # 是否启用表情包过滤
check_prompt = "符合公序良俗" # 表情包过滤要求
[memory] [memory]
build_memory_interval = 2000 # 记忆构建间隔 单位秒 间隔越低,麦麦学习越多,但是冗余信息也会增多 build_memory_interval = 2000 # 记忆构建间隔 单位秒 间隔越低,麦麦学习越多,但是冗余信息也会增多
@@ -81,7 +91,6 @@ forget_memory_interval = 1000 # 记忆遗忘间隔 单位秒 间隔越低,
memory_forget_time = 24 #多长时间后的记忆会被遗忘 单位小时 memory_forget_time = 24 #多长时间后的记忆会被遗忘 单位小时
memory_forget_percentage = 0.01 # 记忆遗忘比例 控制记忆遗忘程度 越大遗忘越多 建议保持默认 memory_forget_percentage = 0.01 # 记忆遗忘比例 控制记忆遗忘程度 越大遗忘越多 建议保持默认
memory_ban_words = [ #不希望记忆的词 memory_ban_words = [ #不希望记忆的词
# "403","张三" # "403","张三"
] ]
@@ -106,26 +115,17 @@ reaction = "回答“测试成功”"
[chinese_typo] [chinese_typo]
enable = true # 是否启用中文错别字生成器 enable = true # 是否启用中文错别字生成器
error_rate=0.002 # 单字替换概率 error_rate=0.001 # 单字替换概率
min_freq=9 # 最小字频阈值 min_freq=9 # 最小字频阈值
tone_error_rate=0.2 # 声调错误概率 tone_error_rate=0.1 # 声调错误概率
word_replace_rate=0.006 # 整词替换概率 word_replace_rate=0.006 # 整词替换概率
[others]
enable_kuuki_read = true # 是否启用读空气功能
enable_friend_chat = false # 是否启用好友聊天
[groups]
talk_allowed = [
123,
123,
] #可以回复消息的群
talk_frequency_down = [] #降低回复频率的群
ban_user_id = [] #禁止回复和读取消息的QQ号
[remote] #发送统计信息,主要是看全球有多少只麦麦 [remote] #发送统计信息,主要是看全球有多少只麦麦
enable = true enable = true
[experimental]
enable_friend_chat = false # 是否启用好友聊天
enable_thinkflow = false # 是否启用思维流
#下面的模型若使用硅基流动则不需要更改使用ds官方则改成.env.prod自定义的宏使用自定义模型则选择定位相似的模型自己填写 #下面的模型若使用硅基流动则不需要更改使用ds官方则改成.env.prod自定义的宏使用自定义模型则选择定位相似的模型自己填写
#推理模型 #推理模型
@@ -188,3 +188,11 @@ pri_out = 0.35
[model.embedding] #嵌入 [model.embedding] #嵌入
name = "BAAI/bge-m3" name = "BAAI/bge-m3"
provider = "SILICONFLOW" provider = "SILICONFLOW"
#测试模型给think_glow用如果你没开实验性功能随便写就行但是要有
[model.llm_outer_world] #外世界判断建议使用qwen2.5 7b
# name = "Pro/Qwen/Qwen2.5-7B-Instruct"
name = "Qwen/Qwen2.5-7B-Instruct"
provider = "SILICONFLOW"
pri_in = 0
pri_out = 0