diff --git a/src/plugins/willing/mode_llmcheck.py b/src/plugins/willing/mode_llmcheck.py index 6c3e135f9..4f472e87f 100644 --- a/src/plugins/willing/mode_llmcheck.py +++ b/src/plugins/willing/mode_llmcheck.py @@ -1,68 +1,87 @@ +""" +llmcheck 模式: +此模式的一些参数不会在配置文件中显示,要修改请在可变参数下修改 +此模式的特点: +1.在群聊内的连续对话场景下,使用大语言模型来判断回复概率 +2.非连续对话场景,使用mxp模式的意愿管理器(可另外配置) +3.默认配置的是model_v3,当前参数适用于deepseek-v3-0324 + +继承自其他模式,实质上仅重写get_reply_probability方法,未来可能重构成一个插件,可方便地组装到其他意愿模式上。 +目前的使用方式是拓展到其他意愿管理模式 + +""" import time from loguru import logger -from ..schedule.schedule_generator import bot_schedule from ..models.utils_model import LLM_request - from ..config.config import global_config from ..chat.chat_stream import ChatStream -from .mode_classical import WillingManager from ..chat.utils import get_recent_group_detailed_plain_text - - +from .willing_manager import BaseWillingManager +from .mode_mxp import MxpWillingManager import re -from src.common.logger import get_module_logger, CHAT_STYLE_CONFIG, LogConfig +from functools import wraps -# 定义日志配置 -chat_config = LogConfig( - # 使用消息发送专用样式 - console_format=CHAT_STYLE_CONFIG["console_format"], - file_format=CHAT_STYLE_CONFIG["file_format"], -) -# 配置主程序日志格式 -logger = get_module_logger("llm_willing", config=chat_config) +def is_continuous_chat(self, message_id: str): + # 判断是否是连续对话,出于成本考虑,默认限制5条 + willing_info = self.ongoing_messages[message_id] + chat_id = willing_info.chat_id + group_info = willing_info.chat_id + config = self.global_config + length = 5 + if chat_id: + chat_talking_text = get_recent_group_detailed_plain_text( + chat_id, limit=length, combine=True + ) + if group_info: + if str(config.BOT_QQ) in chat_talking_text: + return True + else: + return False + return False -class WillingManager(WillingManager): +def llmcheck_decorator(trigger_condition_func): + def decorator(func): + @wraps(func) + def wrapper(self, message_id: str): + if trigger_condition_func(self, message_id): + # 满足条件,走llm流程 + return self.get_llmreply_probability(message_id) + else: + # 不满足条件,走默认流程 + return func(self, message_id) + return wrapper + return decorator + + +class LlmcheckWillingManager(MxpWillingManager): def __init__(self): super().__init__() self.model_v3 = LLM_request(model=global_config.llm_normal, temperature=0.3) - 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, - **kwargs) -> float: - stream_id = chat_stream.stream_id - if chat_stream.group_info and config: - if chat_stream.group_info.group_id not in config.talk_allowed_groups: + + + async def get_llmreply_probability(self, message_id: str): + message_info = self.ongoing_messages[message_id] + chat_id = message_info.chat_id + config = self.global_config + # 获取信息的长度 + length = 5 + if message_info.group_info and config: + if message_info.group_info.group_id not in config.talk_allowed_groups: reply_probability = 0 return reply_probability current_date = time.strftime("%Y-%m-%d", time.localtime()) current_time = time.strftime("%H:%M:%S", time.localtime()) - chat_in_group = True chat_talking_prompt = "" - if stream_id: + if chat_id: chat_talking_prompt = get_recent_group_detailed_plain_text( - stream_id, limit=5, combine=True + chat_id, limit=length, combine=True ) - if chat_stream.group_info: - if str(config.BOT_QQ) in chat_talking_prompt: - pass - # logger.info(f"{chat_talking_prompt}") - # logger.info(f"bot在群聊中5条内发过言,启动llm计算回复概率") - else: - return self.default_change_reply_willing_received( - chat_stream=chat_stream, - is_mentioned_bot=is_mentioned_bot, - config=config, - is_emoji=is_emoji, - interested_rate=interested_rate, - sender_id=sender_id, - ) - else: - chat_in_group = False - chat_talking_prompt = chat_talking_prompt - # print(f"\033[1;34m[调试]\033[0m 已从数据库获取群 {group_id} 的消息记录:{chat_talking_prompt}") + else: + return 0 # if is_mentioned_bot: # return 1.0 @@ -76,21 +95,12 @@ class WillingManager(WillingManager): 仅输出在0到1区间内的概率值,不要给出你的判断依据。 """ - # 非群聊的意愿管理 未来可能可以用对话缓冲区来确定合适的回复时机 - if not chat_in_group: - prompt = f""" - 假设你在和网友聊天,网名叫{global_config.BOT_NICKNAME},你还有很多别名: {"/".join(global_config.BOT_ALIAS_NAMES)}, - 现在你和朋友私聊的内容是{chat_talking_prompt}, - 今天是{current_date},现在是{current_time}。 - 综合以上的内容,给出你认为最新的消息是在和你交流的概率,数值在0到1之间。如果现在是个人休息时间,直接概率为0,请注意是决定是否需要发言,而不是编写回复内容, - 仅输出在0到1区间内的概率值,不要给出你的判断依据。 - """ content_check, reasoning_check, _ = await self.model_v3.generate_response(prompt) # logger.info(f"{prompt}") logger.info(f"{content_check} {reasoning_check}") probability = self.extract_marked_probability(content_check) # 兴趣系数修正 无关激活效率太高,暂时停用,待新记忆系统上线后调整 - probability += (interested_rate * 0.25) + probability += (message_info.interested_rate * 0.25) probability = min(1.0, probability) if probability <= 0.1: probability = min(0.03, probability) @@ -98,8 +108,8 @@ class WillingManager(WillingManager): probability = max(probability, 0.90) # 当前表情包理解能力较差,少说就少错 - if is_emoji: - probability *= 0.1 + if message_info.is_emoji: + probability *= global_config.emoji_response_penalty return probability @@ -143,21 +153,8 @@ class WillingManager(WillingManager): except (ValueError, ZeroDivisionError): return 0 - def default_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, - **kwargs) -> float: - - current_willing = self.chat_reply_willing.get(chat_stream.stream_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.5 - self.chat_reply_willing[chat_stream.stream_id] = min(current_willing, 3.0) - reply_probability = min(max((current_willing - 0.5), 0.01) * config.response_willing_amplifier * 2, 1) - - return reply_probability + @llmcheck_decorator(is_continuous_chat) + def get_reply_probability(self, message_id): + return super().get_reply_probability( + message_id + )