fix:修复引用回复逻辑

This commit is contained in:
SengokuCola
2025-05-02 02:03:24 +08:00
parent 1ca736cc32
commit 974839c1b5
14 changed files with 194 additions and 155 deletions

View File

@@ -82,15 +82,14 @@ class ChatBot:
if userinfo.user_id in global_config.ban_user_id:
logger.debug(f"用户{userinfo.user_id}被禁止回复")
return
if groupinfo is None:
logger.trace("检测到私聊消息,检查")
# 好友黑名单拦截
# 好友黑名单拦截
if userinfo.user_id not in global_config.talk_allowed_private:
logger.debug(f"用户{userinfo.user_id}没有私聊权限")
return
# 群聊黑名单拦截
if groupinfo is not None and groupinfo.group_id not in global_config.talk_allowed_groups:
logger.trace(f"{groupinfo.group_id}被禁止回复")

View File

@@ -294,7 +294,9 @@ class MessageSending(MessageProcessBase):
def set_reply(self, reply: Optional["MessageRecv"] = None):
"""设置回复消息"""
if self.message_info.format_info is not None and "reply" in self.message_info.format_info.accept_format:
# print(f"set_reply: {reply}")
# if self.message_info.format_info is not None and "reply" in self.message_info.format_info.accept_format:
if True:
if reply:
self.reply = reply
if self.reply:

View File

@@ -209,24 +209,31 @@ class MessageManager:
_ = message.update_thinking_time() # 更新思考时间
thinking_start_time = message.thinking_start_time
now_time = time.time()
logger.debug(f"thinking_start_time:{thinking_start_time},now_time:{now_time}")
thinking_messages_count, thinking_messages_length = count_messages_between(
start_time=thinking_start_time, end_time=now_time, stream_id=message.chat_stream.stream_id
)
# print(f"message.reply:{message.reply}")
# --- 条件应用 set_reply 逻辑 ---
logger.debug(
f"[message.apply_set_reply_logic:{message.apply_set_reply_logic},message.is_head:{message.is_head},thinking_messages_count:{thinking_messages_count},thinking_messages_length:{thinking_messages_length},message.is_private_message():{message.is_private_message()}]"
)
if (
message.apply_set_reply_logic # 检查标记
and message.is_head
and (thinking_messages_count > 4 or thinking_messages_length > 250)
and (thinking_messages_count > 1 or thinking_messages_length > 20)
and not message.is_private_message()
):
logger.debug(
f"[{message.chat_stream.stream_id}] 应用 set_reply 逻辑: {message.processed_plain_text[:20]}..."
)
message.set_reply()
message.set_reply(message.reply)
# --- 结束条件 set_reply ---
await message.process() # 预处理消息内容
logger.debug(f"{message}")
# 使用全局 message_sender 实例
await send_message(message)

View File

@@ -6,13 +6,13 @@ from collections import Counter
import jieba
import numpy as np
from src.common.logger import get_module_logger
from pymongo.errors import PyMongoError
from ..models.utils_model import LLMRequest
from ..utils.typo_generator import ChineseTypoGenerator
from ...config.config import global_config
from .message import MessageRecv, Message
from .message import MessageRecv
from maim_message import UserInfo
from .chat_stream import ChatStream
from ..moods.moods import MoodManager
from ...common.database import db
@@ -107,8 +107,6 @@ async def get_embedding(text, request_type="embedding"):
return embedding
def get_recent_group_detailed_plain_text(chat_stream_id: str, limit: int = 12, combine=False):
recent_messages = list(
db.messages.find(
@@ -566,93 +564,45 @@ def count_messages_between(start_time: float, end_time: float, stream_id: str) -
"""计算两个时间点之间的消息数量和文本总长度
Args:
start_time (float): 起始时间戳
end_time (float): 结束时间戳
start_time (float): 起始时间戳 (不包含)
end_time (float): 结束时间戳 (包含)
stream_id (str): 聊天流ID
Returns:
tuple[int, int]: (消息数量, 文本总长度)
- 消息数量:包含起始时间的消息,不包含结束时间的消息
- 文本总长度所有消息的processed_plain_text长度之和
"""
count = 0
total_length = 0
# 参数校验 (可选但推荐)
if start_time >= end_time:
# logger.debug(f"开始时间 {start_time} 大于或等于结束时间 {end_time},返回 0, 0")
return 0, 0
if not stream_id:
logger.error("stream_id 不能为空")
return 0, 0
# 直接查询时间范围内的消息
# time > start_time AND time <= end_time
query = {"chat_id": stream_id, "time": {"$gt": start_time, "$lte": end_time}}
try:
# 获取开始时间之前最新的一条消息
start_message = db.messages.find_one(
{"chat_id": stream_id, "time": {"$lte": start_time}},
sort=[("time", -1), ("_id", -1)], # 按时间倒序_id倒序最后插入的在前
)
# 执行查询
messages_cursor = db.messages.find(query)
# 获取结束时间最近的一条消息
# 先找到结束时间点的所有消息
end_time_messages = list(
db.messages.find(
{"chat_id": stream_id, "time": {"$lte": end_time}},
sort=[("time", -1)], # 先按时间倒序
).limit(10)
) # 限制查询数量,避免性能问题
if not end_time_messages:
logger.warning(f"未找到结束时间 {end_time} 之前的消息")
return 0, 0
# 找到最大时间
max_time = end_time_messages[0]["time"]
# 在最大时间的消息中找最后插入的_id最大的
end_message = max([msg for msg in end_time_messages if msg["time"] == max_time], key=lambda x: x["_id"])
if not start_message:
logger.warning(f"未找到开始时间 {start_time} 之前的消息")
return 0, 0
# 调试输出
# print("\n=== 消息范围信息 ===")
# print("Start message:", {
# "message_id": start_message.get("message_id"),
# "time": start_message.get("time"),
# "text": start_message.get("processed_plain_text", ""),
# "_id": str(start_message.get("_id"))
# })
# print("End message:", {
# "message_id": end_message.get("message_id"),
# "time": end_message.get("time"),
# "text": end_message.get("processed_plain_text", ""),
# "_id": str(end_message.get("_id"))
# })
# print("Stream ID:", stream_id)
# 如果结束消息的时间等于开始时间返回0
if end_message["time"] == start_message["time"]:
return 0, 0
# 获取并打印这个时间范围内的所有消息
# print("\n=== 时间范围内的所有消息 ===")
all_messages = list(
db.messages.find(
{"chat_id": stream_id, "time": {"$gte": start_message["time"], "$lte": end_message["time"]}},
sort=[("time", 1), ("_id", 1)], # 按时间正序_id正序
)
)
count = 0
total_length = 0
for msg in all_messages:
# 遍历结果计算数量和长度
for msg in messages_cursor:
count += 1
text_length = len(msg.get("processed_plain_text", ""))
total_length += text_length
# print(f"\n消息 {count}:")
# print({
# "message_id": msg.get("message_id"),
# "time": msg.get("time"),
# "text": msg.get("processed_plain_text", ""),
# "text_length": text_length,
# "_id": str(msg.get("_id"))
# })
total_length += len(msg.get("processed_plain_text", ""))
# 如果时间不同需要把end_message本身也计入
return count - 1, total_length
# logger.debug(f"查询范围 ({start_time}, {end_time}] 内找到 {count} 条消息,总长度 {total_length}")
return count, total_length
except Exception as e:
logger.error(f"计算消息数量时出错: {str(e)}")
except PyMongoError as e:
logger.error(f"查询 stream_id={stream_id} 在 ({start_time}, {end_time}] 范围内的消息时出错: {e}")
return 0, 0
except Exception as e: # 保留一个通用异常捕获以防万一
logger.error(f"计算消息数量时发生意外错误: {e}")
return 0, 0

View File

@@ -372,6 +372,7 @@ class PromptBuilder:
memory_prompt = await global_prompt_manager.format_prompt(
"memory_prompt", related_memory_info=related_memory_info
)
message_list_before_now = get_raw_msg_before_timestamp_with_chat(
chat_id=chat_stream.stream_id,
timestamp=time.time(),

View File

@@ -86,11 +86,12 @@ class NormalChat:
bot_user_info=bot_user_info,
reply=message,
thinking_start_time=thinking_time_point,
timestamp=timestamp if timestamp is not None else None
timestamp=timestamp if timestamp is not None else None,
)
await message_manager.add_message(thinking_message)
return thinking_id
# 改为实例方法
async def _add_messages_to_manager(
self, message: MessageRecv, response_set: List[str], thinking_id
@@ -206,7 +207,10 @@ class NormalChat:
try:
# 处理消息
await self.normal_response(
message=message, is_mentioned=is_mentioned, interested_rate=interest_value, rewind_response = False
message=message,
is_mentioned=is_mentioned,
interested_rate=interest_value,
rewind_response=False,
)
except Exception as e:
logger.error(f"[{self.stream_name}] 处理兴趣消息{msg_id}时出错: {e}\n{traceback.format_exc()}")
@@ -214,7 +218,9 @@ class NormalChat:
self.interest_dict.pop(msg_id, None)
# 改为实例方法, 移除 chat 参数
async def normal_response(self, message: MessageRecv, is_mentioned: bool, interested_rate: float, rewind_response: bool = False) -> None:
async def normal_response(
self, message: MessageRecv, is_mentioned: bool, interested_rate: float, rewind_response: bool = False
) -> None:
# 检查收到的消息是否属于当前实例处理的 chat stream
if message.chat_stream.stream_id != self.stream_id:
logger.error(
@@ -393,13 +399,17 @@ class NormalChat:
try:
logger.info(f"[{self.stream_name}] 处理初始高兴趣消息 {msg_id} (兴趣值: {interest_value:.2f})")
await self.normal_response(message=message, is_mentioned=is_mentioned, interested_rate=interest_value, rewind_response = True)
await self.normal_response(
message=message, is_mentioned=is_mentioned, interested_rate=interest_value, rewind_response=True
)
processed_count += 1
except Exception as e:
logger.error(f"[{self.stream_name}] 处理初始兴趣消息 {msg_id} 时出错: {e}\\n{traceback.format_exc()}")
# --- 新增:处理完后清空整个字典 ---
logger.info(f"[{self.stream_name}] 处理了 {processed_count} 条初始高兴趣消息。现在清空所有剩余的初始兴趣消息...")
logger.info(
f"[{self.stream_name}] 处理了 {processed_count} 条初始高兴趣消息。现在清空所有剩余的初始兴趣消息..."
)
self.interest_dict.clear()
# --- 新增结束 ---

View File

@@ -188,7 +188,9 @@ class PersonInfoManager:
logger.warning(f"无法从文本中提取有效的JSON字典: {text}")
return {"nickname": "", "reason": ""}
async def qv_person_name(self, person_id: str, user_nickname: str, user_cardname: str, user_avatar: str, request: str = ""):
async def qv_person_name(
self, person_id: str, user_nickname: str, user_cardname: str, user_avatar: str, request: str = ""
):
"""给某个用户取名"""
if not person_id:
logger.debug("取名失败person_id不能为空")
@@ -214,7 +216,7 @@ class PersonInfoManager:
qv_name_prompt += f"你之前叫他{old_name},是因为{old_reason}"
qv_name_prompt += f"\n其他取名的要求是:{request}"
qv_name_prompt += "\n请根据以上用户信息想想你叫他什么比较好请最好使用用户的qq昵称可以稍作修改"
if existing_names:
qv_name_prompt += f"\n请注意,以下名称已被使用,不要使用以下昵称:{existing_names}\n"
@@ -526,7 +528,7 @@ class PersonInfoManager:
for pid, name in self.person_name_list.items():
if name == person_name:
found_person_id = pid
break # 找到第一个匹配就停止
break # 找到第一个匹配就停止
if not found_person_id:
# 如果内存没有,尝试数据库查询(可能内存未及时更新或启动时未加载)
@@ -535,21 +537,21 @@ class PersonInfoManager:
found_person_id = document.get("person_id")
else:
logger.debug(f"数据库中也未找到名为 '{person_name}' 的用户")
return None # 数据库也找不到
return None # 数据库也找不到
# 根据找到的 person_id 获取所需信息
if found_person_id:
required_fields = ["person_id", "platform", "user_id", "nickname", "user_cardname", "user_avatar"]
person_data = await self.get_values(found_person_id, required_fields)
if person_data: # 确保 get_values 成功返回
if person_data: # 确保 get_values 成功返回
return person_data
else:
logger.warning(f"找到了 person_id '{found_person_id}' 但获取详细信息失败")
return None
else:
# 这理论上不应该发生,因为上面已经处理了找不到的情况
logger.error(f"逻辑错误:未能为 '{person_name}' 确定 person_id")
return None
# 这理论上不应该发生,因为上面已经处理了找不到的情况
logger.error(f"逻辑错误:未能为 '{person_name}' 确定 person_id")
return None
person_info_manager = PersonInfoManager()