feat:修改log,优化关系构建逻辑,节省token,

This commit is contained in:
SengokuCola
2025-07-08 02:04:31 +08:00
parent 723870bcde
commit f17f5cf46c
10 changed files with 303 additions and 322 deletions

View File

@@ -324,8 +324,6 @@ async def clear_temp_emoji() -> None:
os.remove(file_path)
logger.debug(f"[清理] 删除: {filename}")
logger.info("[清理] 完成")
async def clean_unused_emojis(emoji_dir: str, emoji_objects: List["MaiEmoji"], removed_count: int) -> int:
"""清理指定目录中未被 emoji_objects 追踪的表情包文件"""
@@ -590,7 +588,7 @@ class EmojiManager:
"""定期检查表情包完整性和数量"""
await self.get_all_emoji_from_db()
while True:
logger.info("[扫描] 开始检查表情包完整性...")
# logger.info("[扫描] 开始检查表情包完整性...")
await self.check_emoji_file_integrity()
await clear_temp_emoji()
logger.info("[扫描] 开始扫描新表情包...")

View File

@@ -119,16 +119,16 @@ class HeartFCMessageReceiver:
# current_time = time.strftime("%H:%M:%S", time.localtime(message.message_info.time))
current_talk_frequency = global_config.chat.get_current_talk_frequency(chat.stream_id)
# 如果消息中包含图片标识,则日志展示为图片
# 如果消息中包含图片标识,则将 [picid:...] 替换为 [图片]
picid_pattern = r"\[picid:([^\]]+)\]"
processed_plain_text = re.sub(picid_pattern, "[图片]", message.processed_plain_text)
picid_match = re.search(r"\[picid:([^\]]+)\]", message.processed_plain_text)
if picid_match:
logger.info(f"[{mes_name}]{userinfo.user_nickname}: [图片] [当前回复频率: {current_talk_frequency}]")
else:
logger.info(
f"[{mes_name}]{userinfo.user_nickname}:{message.processed_plain_text}[当前回复频率: {current_talk_frequency}]"
f"[{mes_name}]{userinfo.user_nickname}:{processed_plain_text}"
)
logger.debug(f"[{mes_name}][当前时段回复频率: {current_talk_frequency}]")
# 8. 关系处理
if global_config.relationship.enable_relationship:
await _process_relationship(message)

View File

@@ -131,7 +131,7 @@ class MessageStorage:
if matched_message:
# 更新找到的消息记录
Messages.update(message_id=qq_message_id).where(Messages.id == matched_message.id).execute()
logger.info(f"更新消息ID成功: {matched_message.message_id} -> {qq_message_id}")
logger.debug(f"更新消息ID成功: {matched_message.message_id} -> {qq_message_id}")
else:
logger.debug("未找到匹配的消息")

View File

@@ -585,10 +585,19 @@ class NormalChat:
)
response_set, plan_result = results
except asyncio.TimeoutError:
logger.warning(
f"[{self.stream_name}] 并行执行回复生成和动作规划超时 ({gather_timeout}秒),正在取消相关任务..."
)
print(f"111{self.timeout_count}")
gen_timed_out = not gen_task.done()
plan_timed_out = not plan_task.done()
timeout_details = []
if gen_timed_out:
timeout_details.append("回复生成(gen)")
if plan_timed_out:
timeout_details.append("动作规划(plan)")
timeout_source = "".join(timeout_details)
logger.warning(f"[{self.stream_name}] {timeout_source} 任务超时 ({global_config.chat.thinking_timeout}秒),正在取消相关任务...")
# print(f"111{self.timeout_count}")
self.timeout_count += 1
if self.timeout_count > 5:
logger.warning(

View File

@@ -551,6 +551,9 @@ def build_readable_messages(
show_actions: 是否显示动作记录
"""
# 创建messages的深拷贝避免修改原始列表
if not messages:
return ""
copy_messages = [msg.copy() for msg in messages]
if show_actions and copy_messages:

View File

@@ -252,8 +252,7 @@ class PersonInfo(BaseModel):
know_times = FloatField(null=True) # 认识时间 (时间戳)
know_since = FloatField(null=True) # 首次印象总结时间
last_know = FloatField(null=True) # 最后一次印象总结时间
familiarity_value = IntegerField(null=True, default=0) # 熟悉0-100完全陌生到非常熟悉
liking_value = IntegerField(null=True, default=50) # 好感度0-100从非常厌恶到十分喜欢
attitude = IntegerField(null=True, default=50) # 0-100非常厌恶到十分喜欢
class Meta:
# database = db # 继承自 BaseModel

View File

@@ -321,14 +321,13 @@ MODULE_COLORS = {
# 核心模块
"main": "\033[1;97m", # 亮白色+粗体 (主程序)
"api": "\033[92m", # 亮绿色
"emoji": "\033[92m", # 亮绿色
"emoji": "\033[33m", # 亮绿色
"chat": "\033[92m", # 亮蓝色
"config": "\033[93m", # 亮黄色
"common": "\033[95m", # 亮紫色
"tools": "\033[96m", # 亮青色
"lpmm": "\033[96m",
"plugin_system": "\033[91m", # 亮红色
"experimental": "\033[97m", # 亮白色
"person_info": "\033[32m", # 绿色
"individuality": "\033[34m", # 蓝色
"manager": "\033[35m", # 紫色
@@ -339,8 +338,7 @@ MODULE_COLORS = {
"planner": "\033[36m",
"memory": "\033[34m",
"hfc": "\033[96m",
"base_action": "\033[96m",
"action_manager": "\033[32m",
"action_manager": "\033[38;5;166m",
# 关系系统
"relation": "\033[38;5;201m", # 深粉色
# 聊天相关模块
@@ -356,11 +354,9 @@ MODULE_COLORS = {
"message_storage": "\033[38;5;33m", # 深蓝色
# 专注聊天模块
"replyer": "\033[38;5;166m", # 橙色
"expressor": "\033[38;5;172m", # 黄橙色
"processor": "\033[38;5;184m", # 黄绿色
"base_processor": "\033[38;5;190m", # 绿黄色
"working_memory": "\033[38;5;22m", # 深绿色
"memory_activator": "\033[38;5;28m", # 绿色
"memory_activator": "\033[34m", # 绿色
# 插件系统
"plugin_manager": "\033[38;5;208m", # 红色
"base_plugin": "\033[38;5;202m", # 橙红色
@@ -386,11 +382,9 @@ MODULE_COLORS = {
"tool_executor": "\033[38;5;64m", # 深绿色
"base_tool": "\033[38;5;70m", # 绿色
# 工具和实用模块
"prompt": "\033[38;5;99m", # 紫色
"prompt_build": "\033[38;5;105m", # 紫色
"chat_utils": "\033[38;5;111m", # 蓝色
"chat_image": "\033[38;5;117m", # 浅蓝色
"typo_gen": "\033[38;5;123m", # 青绿色
"maibot_statistic": "\033[38;5;129m", # 紫色
# 特殊功能插件
"mute_plugin": "\033[38;5;240m", # 灰色
@@ -402,16 +396,13 @@ MODULE_COLORS = {
# 数据库和消息
"database_model": "\033[38;5;94m", # 橙褐色
"maim_message": "\033[38;5;100m", # 绿褐色
# 实验性模块
"pfc": "\033[38;5;252m", # 浅灰色
# 日志系统
"logger": "\033[38;5;8m", # 深灰色
"demo": "\033[38;5;15m", # 白色
"confirm": "\033[1;93m", # 黄色+粗体
# 模型相关
"model_utils": "\033[38;5;164m", # 紫红色
"relationship_fetcher": "\033[38;5;170m", # 浅紫色
"relationship_builder": "\033[38;5;117m", # 浅蓝色
"relationship_builder": "\033[38;5;93m", # 浅蓝色
}
RESET_COLOR = "\033[0m"

View File

@@ -48,6 +48,7 @@ person_info_default = {
"points": None,
"forgotten_points": None,
"relation_value": None,
"attitude": 50,
}

View File

@@ -21,66 +21,11 @@ logger = get_logger("relation")
class RelationshipManager:
def __init__(self):
self.positive_feedback_value = 0 # 正反馈系统
self.gain_coefficient = [1.0, 1.0, 1.1, 1.2, 1.4, 1.7, 1.9, 2.0]
self._mood_manager = None
self.relationship_llm = LLMRequest(
model=global_config.model.relation,
request_type="relationship", # 用于动作规划
)
@property
def mood_manager(self):
if self._mood_manager is None:
self._mood_manager = mood_manager
return self._mood_manager
def positive_feedback_sys(self, label: str, stance: str):
"""正反馈系统,通过正反馈系数增益情绪变化,根据情绪再影响关系变更"""
positive_list = [
"开心",
"惊讶",
"害羞",
]
negative_list = [
"愤怒",
"悲伤",
"恐惧",
"厌恶",
]
if label in positive_list:
if 7 > self.positive_feedback_value >= 0:
self.positive_feedback_value += 1
elif self.positive_feedback_value < 0:
self.positive_feedback_value = 0
elif label in negative_list:
if -7 < self.positive_feedback_value <= 0:
self.positive_feedback_value -= 1
elif self.positive_feedback_value > 0:
self.positive_feedback_value = 0
if abs(self.positive_feedback_value) > 1:
logger.debug(f"触发mood变更增益当前增益系数{self.gain_coefficient[abs(self.positive_feedback_value)]}")
def mood_feedback(self, value):
"""情绪反馈"""
mood_manager = self.mood_manager
mood_gain = mood_manager.current_mood.valence**2 * math.copysign(1, value * mood_manager.current_mood.valence)
value += value * mood_gain
logger.debug(f"当前relationship增益系数{mood_gain:.3f}")
return value
def feedback_to_mood(self, mood_value):
"""对情绪的反馈"""
coefficient = self.gain_coefficient[abs(self.positive_feedback_value)]
if mood_value > 0 and self.positive_feedback_value > 0 or mood_value < 0 and self.positive_feedback_value < 0:
return mood_value * coefficient
else:
return mood_value / coefficient
@staticmethod
async def is_known_some_one(platform, user_id):
@@ -168,18 +113,6 @@ class RelationshipManager:
return relation_prompt
async def _update_list_field(self, person_id: str, field_name: str, new_items: list) -> None:
"""更新列表类型的字段,将新项目添加到现有列表中
Args:
person_id: 用户ID
field_name: 字段名称
new_items: 新的项目列表
"""
person_info_manager = get_person_info_manager()
old_items = await person_info_manager.get_value(person_id, field_name) or []
updated_items = list(set(old_items + [item for item in new_items if isinstance(item, str) and item]))
await person_info_manager.update_one_field(person_id, field_name, updated_items)
async def update_person_impression(self, person_id, timestamp, bot_engaged_messages=None):
"""更新用户印象
@@ -194,6 +127,7 @@ class RelationshipManager:
person_info_manager = get_person_info_manager()
person_name = await person_info_manager.get_value(person_id, "person_name")
nickname = await person_info_manager.get_value(person_id, "nickname")
know_times = await person_info_manager.get_value(person_id, "know_times") or 0
alias_str = ", ".join(global_config.bot.alias_names)
# personality_block =get_individuality().get_personality_prompt(x_person=2, level=2)
@@ -240,7 +174,9 @@ class RelationshipManager:
name_mapping[replace_person_name] = f"用户{current_user}{user_count if user_count > 1 else ''}"
current_user = chr(ord(current_user) + 1)
readable_messages = self.build_focus_readable_messages(messages=user_messages, target_person_id=person_id)
readable_messages = build_readable_messages(
messages=user_messages, replace_bot_name=True, timestamp_mode="normal_no_YMD", truncate=True
)
if not readable_messages:
return
@@ -385,7 +321,55 @@ class RelationshipManager:
# 如果points超过10条按权重随机选择多余的条目移动到forgotten_points
if len(current_points) > 10:
current_points = await self._update_impression(person_id, current_points, timestamp)
# 更新数据库
await person_info_manager.update_one_field(
person_id, "points", json.dumps(current_points, ensure_ascii=False, indent=None)
)
await person_info_manager.update_one_field(person_id, "know_times", know_times + 1)
know_since = await person_info_manager.get_value(person_id, "know_since") or 0
if know_since == 0:
await person_info_manager.update_one_field(person_id, "know_since", timestamp)
await person_info_manager.update_one_field(person_id, "last_know", timestamp)
logger.debug(f"{person_name} 的印象更新完成")
async def _update_impression(self, person_id, current_points, timestamp):
# 获取现有forgotten_points
person_info_manager = get_person_info_manager()
person_name = await person_info_manager.get_value(person_id, "person_name")
nickname = await person_info_manager.get_value(person_id, "nickname")
know_times = await person_info_manager.get_value(person_id, "know_times") or 0
attitude = await person_info_manager.get_value(person_id, "attitude") or 50
# 根据熟悉度,调整印象和简短印象的最大长度
if know_times > 300:
max_impression_length = 2000
max_short_impression_length = 800
elif know_times > 100:
max_impression_length = 1000
max_short_impression_length = 500
elif know_times > 50:
max_impression_length = 500
max_short_impression_length = 300
elif know_times > 10:
max_impression_length = 200
max_short_impression_length = 100
else:
max_impression_length = 100
max_short_impression_length = 50
# 根据好感度,调整印象和简短印象的最大长度
attitude_multiplier = (abs(100-attitude) / 100) + 1
max_impression_length = max_impression_length * attitude_multiplier
max_short_impression_length = max_short_impression_length * attitude_multiplier
forgotten_points = await person_info_manager.get_value(person_id, "forgotten_points") or []
if isinstance(forgotten_points, str):
try:
@@ -436,7 +420,7 @@ class RelationshipManager:
current_points = remaining_points
forgotten_points.extend(points_to_move)
# 检查forgotten_points是否达到5
# 检查forgotten_points是否达到10
if len(forgotten_points) >= 10:
# 构建压缩总结提示词
alias_str = ", ".join(global_config.bot.alias_names)
@@ -466,7 +450,7 @@ class RelationshipManager:
你记得ta最近做的事
{points_text}
请输出一段平文本,以陈诉自白的语气,输出你对{person_name}的了解,不要输出任何其他内容。
请输出一段{max_impression_length}字左右的平文本,以陈诉自白的语气,输出你对{person_name}的了解,不要输出任何其他内容。
"""
# 调用LLM生成压缩总结
compressed_summary, _ = await self.relationship_llm.generate_response_async(prompt=compress_prompt)
@@ -487,7 +471,7 @@ class RelationshipManager:
1.对{person_name}的直观印象
2.{global_config.bot.nickname}{person_name}的关系
3.{person_name}的关键信息
请输出一段平文本,以陈诉自白的语气,输出你对{person_name}的概括,不要输出任何其他内容。
请输出一段{max_short_impression_length}字左右的平文本,以陈诉自白的语气,输出你对{person_name}的概括,不要输出任何其他内容。
"""
compressed_short_summary, _ = await self.relationship_llm.generate_response_async(
prompt=compress_short_prompt
@@ -503,25 +487,18 @@ class RelationshipManager:
你最近对{person_name}的了解如下:
{points_text}
请根据以上信息,评估你和{person_name}的关系,给出两个维度的值:熟悉度和好感度。
1. 了解度 (familiarity_value): 0-100的整数表示这些信息让你对ta的了解增进程度。
- 0: 没有任何进一步了解
- 25: 有点进一步了解
- 50: 有进一步了解
- 75: 有更多了解
- 100: 有了更多重要的了解
请根据以上信息,评估你和{person_name}的关系,给出你对ta的态度。
2. **好感度 (liking_value)**: 0-100的整数表示这些信息让你对ta的
- 0: 非常厌恶
- 25: 有点反感
- 50: 中立/无感(或者文本中无法明显看出)
- 75: 喜欢这个人
- 100: 非常喜欢/开心对这个人
态度: 0-100的整数表示这些信息让你对ta的态度
- 0: 非常厌恶
- 25: 有点反感
- 50: 中立/无感(或者文本中无法明显看出)
- 75: 喜欢这个人
- 100: 非常喜欢/开心对这个人
请严格按照json格式输出不要有其他多余内容
{{
"familiarity_value": <0-100之间的整数>,
"liking_value": <0-100之间的整数>
"attitude": <0-100之间的整数>,
}}
"""
try:
@@ -531,28 +508,25 @@ class RelationshipManager:
relation_value_json = json.loads(repair_json(relation_value_response))
# 从LLM获取新生成的值
new_familiarity_value = int(relation_value_json.get("familiarity_value", 0))
new_liking_value = int(relation_value_json.get("liking_value", 50))
new_attitude = int(relation_value_json.get("attitude", 50))
# 获取当前的关系值
old_familiarity_value = await person_info_manager.get_value(person_id, "familiarity_value") or 0
liking_value = await person_info_manager.get_value(person_id, "liking_value") or 50
old_attitude = await person_info_manager.get_value(person_id, "attitude") or 50
# 更新熟悉度
if new_familiarity_value > 25:
familiarity_value = old_familiarity_value + (new_familiarity_value - 25) / 75
if new_attitude > 25:
attitude = old_attitude + (new_attitude - 25) / 75
else:
familiarity_value = old_familiarity_value
attitude = old_attitude
# 更新好感度
if new_liking_value > 50:
liking_value += (new_liking_value - 50) / 50
elif new_liking_value < 50:
liking_value -= (50 - new_liking_value) / 50 * 1.5
if new_attitude > 50:
attitude += (new_attitude - 50) / 50
elif new_attitude < 50:
attitude -= (50 - new_attitude) / 50 * 1.5
await person_info_manager.update_one_field(person_id, "familiarity_value", familiarity_value)
await person_info_manager.update_one_field(person_id, "liking_value", liking_value)
logger.info(f"更新了与 {person_name} 的关系值: 熟悉度={familiarity_value}, 好感度={liking_value}")
await person_info_manager.update_one_field(person_id, "attitude", attitude)
logger.info(f"更新了与 {person_name} 的态度: {attitude}")
except (json.JSONDecodeError, ValueError, TypeError) as e:
logger.error(f"解析relation_value JSON失败或值无效: {e}, 响应: {relation_value_response}")
@@ -566,28 +540,8 @@ class RelationshipManager:
person_id, "forgotten_points", json.dumps(forgotten_points, ensure_ascii=False, indent=None)
)
# 更新数据库
await person_info_manager.update_one_field(
person_id, "points", json.dumps(current_points, ensure_ascii=False, indent=None)
)
know_times = await person_info_manager.get_value(person_id, "know_times") or 0
await person_info_manager.update_one_field(person_id, "know_times", know_times + 1)
know_since = await person_info_manager.get_value(person_id, "know_since") or 0
if know_since == 0:
await person_info_manager.update_one_field(person_id, "know_since", timestamp)
await person_info_manager.update_one_field(person_id, "last_know", timestamp)
return current_points
logger.info(f"{person_name} 的印象更新完成")
def build_focus_readable_messages(self, messages: list, target_person_id: str = None) -> str:
"""格式化消息,处理所有消息内容"""
if not messages:
return ""
# 直接处理所有消息,不进行过滤
return build_readable_messages(
messages=messages, replace_bot_name=True, timestamp_mode="normal_no_YMD", truncate=True
)
def calculate_time_weight(self, point_time: str, current_time: str) -> float:
"""计算基于时间的权重系数"""

View File

@@ -103,6 +103,8 @@ class NoReplyAction(BaseAction):
logger.info(f"{self.log_prefix} 选择不回复(第{count}次),开始摸鱼,原因: {reason}")
# 进入等待状态
while True:
current_time = time.time()
elapsed_time = current_time - start_time
@@ -141,19 +143,9 @@ class NoReplyAction(BaseAction):
# 判定条件累计3条消息或等待超过5秒且有新消息
time_since_last_judge = current_time - last_judge_time
should_judge = (
new_message_count >= 3 # 累计3条消息
or (new_message_count > 0 and time_since_last_judge >= 15.0) # 等待超过5秒且有新消息
)
should_judge, trigger_reason = self._should_trigger_judge(new_message_count, time_since_last_judge)
if should_judge and time_since_last_judge >= min_judge_interval:
# 判断触发原因
trigger_reason = ""
if new_message_count >= 3:
trigger_reason = f"累计{new_message_count}条消息"
elif time_since_last_judge >= 10.0:
trigger_reason = f"等待{time_since_last_judge:.1f}秒且有新消息"
logger.info(f"{self.log_prefix} 触发判定({trigger_reason}),进行智能判断...")
# 获取最近的消息内容用于判断
@@ -166,7 +158,10 @@ class NoReplyAction(BaseAction):
if recent_messages:
# 使用message_api构建可读的消息字符串
messages_text = message_api.build_readable_messages(
messages=recent_messages, timestamp_mode="normal_no_YMD", truncate=False, show_actions=False
messages=recent_messages,
timestamp_mode="normal_no_YMD",
truncate=False,
show_actions=False,
)
# 获取身份信息
@@ -189,81 +184,13 @@ class NoReplyAction(BaseAction):
history_block += "\n"
# 检查过去10分钟的发言频率
frequency_block = ""
should_skip_llm_judge = False # 是否跳过LLM判断
try:
# 获取过去10分钟的所有消息
past_10min_time = current_time - 600 # 10分钟前
all_messages_10min = message_api.get_messages_by_time_in_chat(
chat_id=self.chat_id,
start_time=past_10min_time,
end_time=current_time,
)
# 手动过滤bot自己的消息
bot_message_count = 0
if all_messages_10min:
user_id = global_config.bot.qq_account
for message in all_messages_10min:
# 检查消息发送者是否是bot
sender_id = message.get("user_id", "")
if sender_id == user_id:
bot_message_count += 1
talk_frequency_threshold = global_config.chat.get_current_talk_frequency(self.chat_id) * 10
if bot_message_count > talk_frequency_threshold:
over_count = bot_message_count - talk_frequency_threshold
# 根据超过的数量设置不同的提示词和跳过概率
skip_probability = 0
if over_count <= 3:
frequency_block = "你感觉稍微有些累,回复的有点多了。\n"
elif over_count <= 5:
frequency_block = "你今天说话比较多,感觉有点疲惫,想要稍微休息一下。\n"
elif over_count <= 8:
frequency_block = "你发现自己说话太多了,感觉很累,想要安静一会儿,除非有重要的事情否则不想回复。\n"
skip_probability = self._skip_probability
else:
frequency_block = "你感觉非常累,想要安静一会儿。\n"
skip_probability = 1
# 根据配置和概率决定是否跳过LLM判断
if self._skip_judge_when_tired and random.random() < skip_probability:
should_skip_llm_judge = True
logger.info(
f"{self.log_prefix} 发言过多(超过{over_count}条)随机决定跳过此次LLM判断(概率{skip_probability * 100:.0f}%)"
)
logger.info(
f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,超过阈值{talk_frequency_threshold},添加疲惫提示"
)
else:
# 回复次数少时的正向提示
under_count = talk_frequency_threshold - bot_message_count
if under_count >= talk_frequency_threshold * 0.8: # 回复很少少于20%
frequency_block = "你感觉精力充沛,状态很好,积极参与聊天。\n"
elif under_count >= talk_frequency_threshold * 0.5: # 回复较少少于50%
frequency_block = "你感觉状态不错。\n"
else: # 刚好达到阈值
frequency_block = ""
logger.info(
f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,未超过阈值{talk_frequency_threshold},添加正向提示"
)
except Exception as e:
logger.warning(f"{self.log_prefix} 检查发言频率时出错: {e}")
frequency_block = ""
frequency_block, should_skip_llm_judge = self._get_fatigue_status(current_time)
# 如果决定跳过LLM判断直接更新时间并继续等待
if should_skip_llm_judge:
logger.info(f"{self.log_prefix} 疲劳,继续等待。")
last_judge_time = time.time() # 更新判断时间,避免立即重新判断
start_time = current_time # 更新消息检查的起始时间,以避免重复判断
continue # 跳过本次LLM判断继续循环等待
# 构建判断上下文
@@ -379,6 +306,105 @@ class NoReplyAction(BaseAction):
)
return False, f"不回复动作执行失败: {e}"
def _should_trigger_judge(self, new_message_count: int, time_since_last_judge: float) -> Tuple[bool, str]:
"""判断是否应该触发智能判断,并返回触发原因。
Args:
new_message_count: 新消息的数量。
time_since_last_judge: 距离上次判断的时间。
Returns:
一个元组 (should_judge, reason)。
- should_judge: 一个布尔值,指示是否应该触发判断。
- reason: 触发判断的原因字符串。
"""
# 判定条件累计3条消息或等待超过15秒且有新消息
should_judge_flag = new_message_count >= 3 or (new_message_count > 0 and time_since_last_judge >= 15.0)
if not should_judge_flag:
return False, ""
# 判断触发原因
if new_message_count >= 3:
return True, f"累计{new_message_count}条消息"
elif new_message_count > 0 and time_since_last_judge >= 15.0:
return True, f"等待{time_since_last_judge:.1f}秒且有新消息"
return False, ""
def _get_fatigue_status(self, current_time: float) -> Tuple[str, bool]:
"""
根据最近的发言频率生成疲劳提示,并决定是否跳过判断。
Args:
current_time: 当前时间戳。
Returns:
一个元组 (frequency_block, should_skip_judge)。
- frequency_block: 疲劳度相关的提示字符串。
- should_skip_judge: 是否应该跳过LLM判断的布尔值。
"""
try:
# 获取过去10分钟的所有消息
past_10min_time = current_time - 600 # 10分钟前
all_messages_10min = message_api.get_messages_by_time_in_chat(
chat_id=self.chat_id,
start_time=past_10min_time,
end_time=current_time,
)
# 手动过滤bot自己的消息
bot_message_count = 0
if all_messages_10min:
user_id = global_config.bot.qq_account
for message in all_messages_10min:
sender_id = message.get("user_id", "")
if sender_id == user_id:
bot_message_count += 1
talk_frequency_threshold = global_config.chat.get_current_talk_frequency(self.chat_id) * 10
if bot_message_count > talk_frequency_threshold:
over_count = bot_message_count - talk_frequency_threshold
skip_probability = 0
frequency_block = ""
if over_count <= 3:
frequency_block = "你感觉稍微有些累,回复的有点多了。\n"
elif over_count <= 5:
frequency_block = "你今天说话比较多,感觉有点疲惫,想要稍微休息一下。\n"
elif over_count <= 8:
frequency_block = "你发现自己说话太多了,感觉很累,想要安静一会儿,除非有重要的事情否则不想回复。\n"
skip_probability = self._skip_probability
else:
frequency_block = "你感觉非常累,想要安静一会儿。\n"
skip_probability = 1
should_skip_judge = self._skip_judge_when_tired and random.random() < skip_probability
if should_skip_judge:
logger.info(
f"{self.log_prefix} 发言过多(超过{over_count}条)随机决定跳过此次LLM判断(概率{skip_probability * 100:.0f}%)"
)
logger.info(f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,超过阈值{talk_frequency_threshold},添加疲惫提示")
return frequency_block, should_skip_judge
else:
# 回复次数少时的正向提示
under_count = talk_frequency_threshold - bot_message_count
frequency_block = ""
if under_count >= talk_frequency_threshold * 0.8:
frequency_block = "你感觉精力充沛,状态很好,积极参与聊天。\n"
elif under_count >= talk_frequency_threshold * 0.5:
frequency_block = "你感觉状态不错。\n"
logger.info(f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,未超过阈值{talk_frequency_threshold},添加正向提示")
return frequency_block, False
except Exception as e:
logger.warning(f"{self.log_prefix} 检查发言频率时出错: {e}")
return "", False
def _check_no_activity_and_exit_focus(self, current_time: float) -> bool:
"""检查过去10分钟是否完全没有发言决定是否退出专注模式