mirror of https://github.com/Mai-with-u/MaiBot.git
before merge commit
parent
ce74df51db
commit
5427e2448c
|
|
@ -1,6 +1,7 @@
|
|||
import asyncio
|
||||
import time
|
||||
import traceback
|
||||
import math
|
||||
import random
|
||||
from typing import List, Optional, Dict, Any, Tuple
|
||||
from rich.traceback import install
|
||||
|
|
@ -8,6 +9,7 @@ from collections import deque
|
|||
|
||||
from src.config.config import global_config
|
||||
from src.common.logger import get_logger
|
||||
from src.common.data_models.database_data_model import DatabaseMessages
|
||||
from src.chat.message_receive.chat_stream import ChatStream, get_chat_manager
|
||||
from src.chat.utils.prompt_builder import global_prompt_manager
|
||||
from src.chat.utils.timer_calculator import Timer
|
||||
|
|
@ -15,21 +17,19 @@ from src.chat.planner_actions.planner import ActionPlanner
|
|||
from src.chat.planner_actions.action_modifier import ActionModifier
|
||||
from src.chat.planner_actions.action_manager import ActionManager
|
||||
from src.chat.chat_loop.hfc_utils import CycleDetail
|
||||
from src.person_info.relationship_builder_manager import relationship_builder_manager
|
||||
from src.chat.chat_loop.hfc_utils import send_typing, stop_typing
|
||||
from src.chat.memory_system.Hippocampus import hippocampus_manager
|
||||
from src.chat.frequency_control.talk_frequency_control import talk_frequency_control
|
||||
from src.chat.frequency_control.focus_value_control import focus_value_control
|
||||
from src.chat.express.expression_learner import expression_learner_manager
|
||||
from src.person_info.relationship_builder_manager import relationship_builder_manager
|
||||
from src.person_info.person_info import Person
|
||||
from src.plugin_system.base.component_types import ChatMode, EventType
|
||||
from src.plugin_system.core import events_manager
|
||||
from src.plugin_system.apis import generator_api, send_api, message_api, database_api
|
||||
from src.mais4u.mai_think import mai_thinking_manager
|
||||
import math
|
||||
from src.mais4u.s4u_config import s4u_config
|
||||
# no_action逻辑已集成到heartFC_chat.py中,不再需要导入
|
||||
from src.chat.chat_loop.hfc_utils import send_typing, stop_typing
|
||||
# 导入记忆系统
|
||||
from src.chat.memory_system.Hippocampus import hippocampus_manager
|
||||
from src.chat.frequency_control.talk_frequency_control import talk_frequency_control
|
||||
from src.chat.frequency_control.focus_value_control import focus_value_control
|
||||
|
||||
|
||||
ERROR_LOOP_INFO = {
|
||||
"loop_plan_info": {
|
||||
|
|
@ -62,10 +62,7 @@ class HeartFChatting:
|
|||
其生命周期现在由其关联的 SubHeartflow 的 FOCUSED 状态控制。
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
chat_id: str,
|
||||
):
|
||||
def __init__(self, chat_id: str):
|
||||
"""
|
||||
HeartFChatting 初始化函数
|
||||
|
||||
|
|
@ -83,7 +80,7 @@ class HeartFChatting:
|
|||
|
||||
self.relationship_builder = relationship_builder_manager.get_or_create_builder(self.stream_id)
|
||||
self.expression_learner = expression_learner_manager.get_expression_learner(self.stream_id)
|
||||
|
||||
|
||||
self.talk_frequency_control = talk_frequency_control.get_talk_frequency_control(self.stream_id)
|
||||
self.focus_value_control = focus_value_control.get_focus_value_control(self.stream_id)
|
||||
|
||||
|
|
@ -104,7 +101,7 @@ class HeartFChatting:
|
|||
self.plan_timeout_count = 0
|
||||
|
||||
self.last_read_time = time.time() - 1
|
||||
|
||||
|
||||
self.focus_energy = 1
|
||||
self.no_action_consecutive = 0
|
||||
# 最近三次no_action的新消息兴趣度记录
|
||||
|
|
@ -166,27 +163,26 @@ class HeartFChatting:
|
|||
|
||||
# 获取动作类型,兼容新旧格式
|
||||
action_type = "未知动作"
|
||||
if hasattr(self, '_current_cycle_detail') and self._current_cycle_detail:
|
||||
if hasattr(self, "_current_cycle_detail") and self._current_cycle_detail:
|
||||
loop_plan_info = self._current_cycle_detail.loop_plan_info
|
||||
if isinstance(loop_plan_info, dict):
|
||||
action_result = loop_plan_info.get('action_result', {})
|
||||
action_result = loop_plan_info.get("action_result", {})
|
||||
if isinstance(action_result, dict):
|
||||
# 旧格式:action_result是字典
|
||||
action_type = action_result.get('action_type', '未知动作')
|
||||
action_type = action_result.get("action_type", "未知动作")
|
||||
elif isinstance(action_result, list) and action_result:
|
||||
# 新格式:action_result是actions列表
|
||||
action_type = action_result[0].get('action_type', '未知动作')
|
||||
action_type = action_result[0].get("action_type", "未知动作")
|
||||
elif isinstance(loop_plan_info, list) and loop_plan_info:
|
||||
# 直接是actions列表的情况
|
||||
action_type = loop_plan_info[0].get('action_type', '未知动作')
|
||||
action_type = loop_plan_info[0].get("action_type", "未知动作")
|
||||
|
||||
logger.info(
|
||||
f"{self.log_prefix} 第{self._current_cycle_detail.cycle_id}次思考,"
|
||||
f"耗时: {self._current_cycle_detail.end_time - self._current_cycle_detail.start_time:.1f}秒, " # type: ignore
|
||||
f"选择动作: {action_type}"
|
||||
+ (f"\n详情: {'; '.join(timer_strings)}" if timer_strings else "")
|
||||
f"选择动作: {action_type}" + (f"\n详情: {'; '.join(timer_strings)}" if timer_strings else "")
|
||||
)
|
||||
|
||||
|
||||
def _determine_form_type(self) -> None:
|
||||
"""判断使用哪种形式的no_action"""
|
||||
# 如果连续no_action次数少于3次,使用waiting形式
|
||||
|
|
@ -195,42 +191,44 @@ class HeartFChatting:
|
|||
else:
|
||||
# 计算最近三次记录的兴趣度总和
|
||||
total_recent_interest = sum(self.recent_interest_records)
|
||||
|
||||
|
||||
# 计算调整后的阈值
|
||||
adjusted_threshold = 1 / self.talk_frequency_control.get_current_talk_frequency()
|
||||
|
||||
logger.info(f"{self.log_prefix} 最近三次兴趣度总和: {total_recent_interest:.2f}, 调整后阈值: {adjusted_threshold:.2f}")
|
||||
|
||||
|
||||
logger.info(
|
||||
f"{self.log_prefix} 最近三次兴趣度总和: {total_recent_interest:.2f}, 调整后阈值: {adjusted_threshold:.2f}"
|
||||
)
|
||||
|
||||
# 如果兴趣度总和小于阈值,进入breaking形式
|
||||
if total_recent_interest < adjusted_threshold:
|
||||
logger.info(f"{self.log_prefix} 兴趣度不足,进入休息")
|
||||
self.focus_energy = random.randint(3, 6)
|
||||
else:
|
||||
logger.info(f"{self.log_prefix} 兴趣度充足,等待新消息")
|
||||
self.focus_energy = 1
|
||||
|
||||
async def _should_process_messages(self, new_message: List[Dict[str, Any]]) -> tuple[bool,float]:
|
||||
self.focus_energy = 1
|
||||
|
||||
async def _should_process_messages(self, new_message: List[DatabaseMessages]) -> tuple[bool, float]:
|
||||
"""
|
||||
判断是否应该处理消息
|
||||
|
||||
|
||||
Args:
|
||||
new_message: 新消息列表
|
||||
mode: 当前聊天模式
|
||||
|
||||
|
||||
Returns:
|
||||
bool: 是否应该处理消息
|
||||
"""
|
||||
new_message_count = len(new_message)
|
||||
talk_frequency = self.talk_frequency_control.get_current_talk_frequency()
|
||||
|
||||
|
||||
modified_exit_count_threshold = self.focus_energy * 0.5 / talk_frequency
|
||||
modified_exit_interest_threshold = 1.5 / talk_frequency
|
||||
total_interest = 0.0
|
||||
for msg_dict in new_message:
|
||||
interest_value = msg_dict.get("interest_value")
|
||||
if interest_value is not None and msg_dict.get("processed_plain_text", ""):
|
||||
for msg in new_message:
|
||||
interest_value = msg.interest_value
|
||||
if interest_value is not None and msg.processed_plain_text:
|
||||
total_interest += float(interest_value)
|
||||
|
||||
|
||||
if new_message_count >= modified_exit_count_threshold:
|
||||
self.recent_interest_records.append(total_interest)
|
||||
logger.info(
|
||||
|
|
@ -244,9 +242,11 @@ class HeartFChatting:
|
|||
if new_message_count > 0:
|
||||
# 只在兴趣值变化时输出log
|
||||
if not hasattr(self, "_last_accumulated_interest") or total_interest != self._last_accumulated_interest:
|
||||
logger.info(f"{self.log_prefix} 休息中,新消息:{new_message_count}条,累计兴趣值: {total_interest:.2f}, 活跃度: {talk_frequency:.1f}")
|
||||
logger.info(
|
||||
f"{self.log_prefix} 休息中,新消息:{new_message_count}条,累计兴趣值: {total_interest:.2f}, 活跃度: {talk_frequency:.1f}"
|
||||
)
|
||||
self._last_accumulated_interest = total_interest
|
||||
|
||||
|
||||
if total_interest >= modified_exit_interest_threshold:
|
||||
# 记录兴趣度到列表
|
||||
self.recent_interest_records.append(total_interest)
|
||||
|
|
@ -261,29 +261,25 @@ class HeartFChatting:
|
|||
f"{self.log_prefix} 已等待{time.time() - self.last_read_time:.0f}秒,累计{new_message_count}条消息,累计兴趣{total_interest:.1f},继续等待..."
|
||||
)
|
||||
await asyncio.sleep(0.5)
|
||||
|
||||
return False,0.0
|
||||
|
||||
return False, 0.0
|
||||
|
||||
async def _loopbody(self):
|
||||
recent_messages_dict = message_api.get_messages_by_time_in_chat(
|
||||
chat_id=self.stream_id,
|
||||
start_time=self.last_read_time,
|
||||
end_time=time.time(),
|
||||
limit = 10,
|
||||
limit=10,
|
||||
limit_mode="latest",
|
||||
filter_mai=True,
|
||||
filter_command=True,
|
||||
)
|
||||
# TODO: 修复!
|
||||
from src.common.data_models import temporarily_transform_class_to_dict
|
||||
temp_recent_messages_dict = [temporarily_transform_class_to_dict(msg) for msg in recent_messages_dict]
|
||||
)
|
||||
# 统一的消息处理逻辑
|
||||
should_process,interest_value = await self._should_process_messages(temp_recent_messages_dict)
|
||||
should_process, interest_value = await self._should_process_messages(recent_messages_dict)
|
||||
|
||||
if should_process:
|
||||
self.last_read_time = time.time()
|
||||
await self._observe(interest_value = interest_value)
|
||||
await self._observe(interest_value=interest_value)
|
||||
|
||||
else:
|
||||
# Normal模式:消息数量不足,等待
|
||||
|
|
@ -298,22 +294,21 @@ class HeartFChatting:
|
|||
cycle_timers: Dict[str, float],
|
||||
thinking_id,
|
||||
actions,
|
||||
selected_expressions:List[int] = None,
|
||||
selected_expressions: List[int] = None,
|
||||
) -> Tuple[Dict[str, Any], str, Dict[str, float]]:
|
||||
|
||||
with Timer("回复发送", cycle_timers):
|
||||
reply_text = await self._send_response(
|
||||
reply_set=response_set,
|
||||
message_data=action_message,
|
||||
selected_expressions=selected_expressions,
|
||||
)
|
||||
|
||||
|
||||
# 获取 platform,如果不存在则从 chat_stream 获取,如果还是 None 则使用默认值
|
||||
platform = action_message.get("chat_info_platform")
|
||||
if platform is None:
|
||||
platform = getattr(self.chat_stream, "platform", "unknown")
|
||||
|
||||
person = Person(platform = platform ,user_id = action_message.get("user_id", ""))
|
||||
|
||||
person = Person(platform=platform, user_id=action_message.get("user_id", ""))
|
||||
person_name = person.person_name
|
||||
action_prompt_display = f"你对{person_name}进行了回复:{reply_text}"
|
||||
|
||||
|
|
@ -342,12 +337,10 @@ class HeartFChatting:
|
|||
|
||||
return loop_info, reply_text, cycle_timers
|
||||
|
||||
async def _observe(self,interest_value:float = 0.0) -> bool:
|
||||
|
||||
async def _observe(self, interest_value: float = 0.0) -> bool:
|
||||
action_type = "no_action"
|
||||
reply_text = "" # 初始化reply_text变量,避免UnboundLocalError
|
||||
|
||||
|
||||
# 使用sigmoid函数将interest_value转换为概率
|
||||
# 当interest_value为0时,概率接近0(使用Focus模式)
|
||||
# 当interest_value很高时,概率接近1(使用Normal模式)
|
||||
|
|
@ -360,13 +353,19 @@ class HeartFChatting:
|
|||
k = 2.0 # 控制曲线陡峭程度
|
||||
x0 = 1.0 # 控制曲线中心点
|
||||
return 1.0 / (1.0 + math.exp(-k * (interest_val - x0)))
|
||||
|
||||
normal_mode_probability = calculate_normal_mode_probability(interest_value) * 0.5 / self.talk_frequency_control.get_current_talk_frequency()
|
||||
|
||||
|
||||
normal_mode_probability = (
|
||||
calculate_normal_mode_probability(interest_value)
|
||||
* 0.5
|
||||
/ self.talk_frequency_control.get_current_talk_frequency()
|
||||
)
|
||||
|
||||
# 根据概率决定使用哪种模式
|
||||
if random.random() < normal_mode_probability:
|
||||
mode = ChatMode.NORMAL
|
||||
logger.info(f"{self.log_prefix} 有兴趣({interest_value:.2f}),在{normal_mode_probability*100:.0f}%概率下选择回复")
|
||||
logger.info(
|
||||
f"{self.log_prefix} 有兴趣({interest_value:.2f}),在{normal_mode_probability * 100:.0f}%概率下选择回复"
|
||||
)
|
||||
else:
|
||||
mode = ChatMode.FOCUS
|
||||
|
||||
|
|
@ -387,10 +386,9 @@ class HeartFChatting:
|
|||
await hippocampus_manager.build_memory_for_chat(self.stream_id)
|
||||
except Exception as e:
|
||||
logger.error(f"{self.log_prefix} 记忆构建失败: {e}")
|
||||
|
||||
|
||||
if random.random() > self.focus_value_control.get_current_focus_value() and mode == ChatMode.FOCUS:
|
||||
#如果激活度没有激活,并且聊天活跃度低,有可能不进行plan,相当于不在电脑前,不进行认真思考
|
||||
# 如果激活度没有激活,并且聊天活跃度低,有可能不进行plan,相当于不在电脑前,不进行认真思考
|
||||
actions = [
|
||||
{
|
||||
"action_type": "no_action",
|
||||
|
|
@ -420,23 +418,21 @@ class HeartFChatting:
|
|||
):
|
||||
return False
|
||||
with Timer("规划器", cycle_timers):
|
||||
actions, _= await self.action_planner.plan(
|
||||
actions, _ = await self.action_planner.plan(
|
||||
mode=mode,
|
||||
loop_start_time=self.last_read_time,
|
||||
available_actions=available_actions,
|
||||
)
|
||||
|
||||
|
||||
|
||||
# 3. 并行执行所有动作
|
||||
async def execute_action(action_info,actions):
|
||||
async def execute_action(action_info, actions):
|
||||
"""执行单个动作的通用函数"""
|
||||
try:
|
||||
if action_info["action_type"] == "no_action":
|
||||
# 直接处理no_action逻辑,不再通过动作系统
|
||||
reason = action_info.get("reasoning", "选择不回复")
|
||||
logger.info(f"{self.log_prefix} 选择不回复,原因: {reason}")
|
||||
|
||||
|
||||
# 存储no_action信息到数据库
|
||||
await database_api.store_action_info(
|
||||
chat_stream=self.chat_stream,
|
||||
|
|
@ -447,13 +443,8 @@ class HeartFChatting:
|
|||
action_data={"reason": reason},
|
||||
action_name="no_action",
|
||||
)
|
||||
|
||||
return {
|
||||
"action_type": "no_action",
|
||||
"success": True,
|
||||
"reply_text": "",
|
||||
"command": ""
|
||||
}
|
||||
|
||||
return {"action_type": "no_action", "success": True, "reply_text": "", "command": ""}
|
||||
elif action_info["action_type"] != "reply":
|
||||
# 执行普通动作
|
||||
with Timer("动作执行", cycle_timers):
|
||||
|
|
@ -463,20 +454,19 @@ class HeartFChatting:
|
|||
action_info["action_data"],
|
||||
cycle_timers,
|
||||
thinking_id,
|
||||
action_info["action_message"]
|
||||
action_info["action_message"],
|
||||
)
|
||||
return {
|
||||
"action_type": action_info["action_type"],
|
||||
"success": success,
|
||||
"reply_text": reply_text,
|
||||
"command": command
|
||||
"command": command,
|
||||
}
|
||||
else:
|
||||
|
||||
try:
|
||||
success, response_set, prompt_selected_expressions = await generator_api.generate_reply(
|
||||
chat_stream=self.chat_stream,
|
||||
reply_message = action_info["action_message"],
|
||||
reply_message=action_info["action_message"],
|
||||
available_actions=available_actions,
|
||||
choosen_actions=actions,
|
||||
reply_reason=action_info.get("reasoning", ""),
|
||||
|
|
@ -485,29 +475,21 @@ class HeartFChatting:
|
|||
from_plugin=False,
|
||||
return_expressions=True,
|
||||
)
|
||||
|
||||
|
||||
if prompt_selected_expressions and len(prompt_selected_expressions) > 1:
|
||||
_,selected_expressions = prompt_selected_expressions
|
||||
_, selected_expressions = prompt_selected_expressions
|
||||
else:
|
||||
selected_expressions = []
|
||||
|
||||
if not success or not response_set:
|
||||
logger.info(f"对 {action_info['action_message'].get('processed_plain_text')} 的回复生成失败")
|
||||
return {
|
||||
"action_type": "reply",
|
||||
"success": False,
|
||||
"reply_text": "",
|
||||
"loop_info": None
|
||||
}
|
||||
|
||||
logger.info(
|
||||
f"对 {action_info['action_message'].get('processed_plain_text')} 的回复生成失败"
|
||||
)
|
||||
return {"action_type": "reply", "success": False, "reply_text": "", "loop_info": None}
|
||||
|
||||
except asyncio.CancelledError:
|
||||
logger.debug(f"{self.log_prefix} 并行执行:回复生成任务已被取消")
|
||||
return {
|
||||
"action_type": "reply",
|
||||
"success": False,
|
||||
"reply_text": "",
|
||||
"loop_info": None
|
||||
}
|
||||
return {"action_type": "reply", "success": False, "reply_text": "", "loop_info": None}
|
||||
|
||||
loop_info, reply_text, cycle_timers_reply = await self._send_and_store_reply(
|
||||
response_set=response_set,
|
||||
|
|
@ -521,7 +503,7 @@ class HeartFChatting:
|
|||
"action_type": "reply",
|
||||
"success": True,
|
||||
"reply_text": reply_text,
|
||||
"loop_info": loop_info
|
||||
"loop_info": loop_info,
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"{self.log_prefix} 执行动作时出错: {e}")
|
||||
|
|
@ -531,26 +513,26 @@ class HeartFChatting:
|
|||
"success": False,
|
||||
"reply_text": "",
|
||||
"loop_info": None,
|
||||
"error": str(e)
|
||||
"error": str(e),
|
||||
}
|
||||
|
||||
action_tasks = [asyncio.create_task(execute_action(action,actions)) for action in actions]
|
||||
|
||||
|
||||
action_tasks = [asyncio.create_task(execute_action(action, actions)) for action in actions]
|
||||
|
||||
# 并行执行所有任务
|
||||
results = await asyncio.gather(*action_tasks, return_exceptions=True)
|
||||
|
||||
|
||||
# 处理执行结果
|
||||
reply_loop_info = None
|
||||
reply_text_from_reply = ""
|
||||
action_success = False
|
||||
action_reply_text = ""
|
||||
action_command = ""
|
||||
|
||||
|
||||
for i, result in enumerate(results):
|
||||
if isinstance(result, BaseException):
|
||||
logger.error(f"{self.log_prefix} 动作执行异常: {result}")
|
||||
continue
|
||||
|
||||
|
||||
_cur_action = actions[i]
|
||||
if result["action_type"] != "reply":
|
||||
action_success = result["success"]
|
||||
|
|
@ -590,7 +572,6 @@ class HeartFChatting:
|
|||
},
|
||||
}
|
||||
reply_text = action_reply_text
|
||||
|
||||
|
||||
if s4u_config.enable_s4u:
|
||||
await stop_typing()
|
||||
|
|
@ -602,7 +583,7 @@ class HeartFChatting:
|
|||
# await self.willing_manager.after_generate_reply_handle(message_data.get("message_id", ""))
|
||||
|
||||
action_type = actions[0]["action_type"] if actions else "no_action"
|
||||
|
||||
|
||||
# 管理no_action计数器:当执行了非no_action动作时,重置计数器
|
||||
if action_type != "no_action":
|
||||
# no_action逻辑已集成到heartFC_chat.py中,直接重置计数器
|
||||
|
|
@ -610,7 +591,7 @@ class HeartFChatting:
|
|||
self.no_action_consecutive = 0
|
||||
logger.debug(f"{self.log_prefix} 执行了{action_type}动作,重置no_action计数器")
|
||||
return True
|
||||
|
||||
|
||||
if action_type == "no_action":
|
||||
self.no_action_consecutive += 1
|
||||
self._determine_form_type()
|
||||
|
|
@ -692,11 +673,12 @@ class HeartFChatting:
|
|||
traceback.print_exc()
|
||||
return False, "", ""
|
||||
|
||||
async def _send_response(self,
|
||||
reply_set,
|
||||
message_data,
|
||||
selected_expressions:List[int] = None,
|
||||
) -> str:
|
||||
async def _send_response(
|
||||
self,
|
||||
reply_set,
|
||||
message_data,
|
||||
selected_expressions: List[int] = None,
|
||||
) -> str:
|
||||
new_message_count = message_api.count_new_messages(
|
||||
chat_id=self.chat_stream.stream_id, start_time=self.last_read_time, end_time=time.time()
|
||||
)
|
||||
|
|
@ -714,7 +696,7 @@ class HeartFChatting:
|
|||
await send_api.text_to_stream(
|
||||
text=data,
|
||||
stream_id=self.chat_stream.stream_id,
|
||||
reply_message = message_data,
|
||||
reply_message=message_data,
|
||||
set_reply=need_reply,
|
||||
typing=False,
|
||||
selected_expressions=selected_expressions,
|
||||
|
|
@ -724,7 +706,7 @@ class HeartFChatting:
|
|||
await send_api.text_to_stream(
|
||||
text=data,
|
||||
stream_id=self.chat_stream.stream_id,
|
||||
reply_message = message_data,
|
||||
reply_message=message_data,
|
||||
set_reply=False,
|
||||
typing=True,
|
||||
selected_expressions=selected_expressions,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from typing import List, Dict, Optional, Any, Tuple
|
|||
|
||||
from src.common.logger import get_logger
|
||||
from src.common.database.database_model import Expression
|
||||
from src.common.data_models.database_data_model import DatabaseMessages
|
||||
from src.llm_models.utils_model import LLMRequest
|
||||
from src.config.config import model_config, global_config
|
||||
from src.chat.utils.chat_message_builder import get_raw_msg_by_timestamp_with_chat_inclusive, build_anonymous_messages
|
||||
|
|
@ -346,21 +347,17 @@ class ExpressionLearner:
|
|||
current_time = time.time()
|
||||
|
||||
# 获取上次学习时间
|
||||
random_msg_temp = get_raw_msg_by_timestamp_with_chat_inclusive(
|
||||
random_msg = get_raw_msg_by_timestamp_with_chat_inclusive(
|
||||
chat_id=self.chat_id,
|
||||
timestamp_start=self.last_learning_time,
|
||||
timestamp_end=current_time,
|
||||
limit=num,
|
||||
)
|
||||
# TODO: 修复!
|
||||
from src.common.data_models import temporarily_transform_class_to_dict
|
||||
random_msg: Optional[List[Dict[str, Any]]] = [temporarily_transform_class_to_dict(msg) for msg in random_msg_temp] if random_msg_temp else None
|
||||
|
||||
# print(random_msg)
|
||||
if not random_msg or random_msg == []:
|
||||
return None
|
||||
# 转化成str
|
||||
chat_id: str = random_msg[0]["chat_id"]
|
||||
chat_id: str = random_msg[0].chat_id
|
||||
# random_msg_str: str = build_readable_messages(random_msg, timestamp_mode="normal")
|
||||
random_msg_str: str = await build_anonymous_messages(random_msg)
|
||||
# print(f"random_msg_str:{random_msg_str}")
|
||||
|
|
|
|||
|
|
@ -70,11 +70,9 @@ class ActionModifier:
|
|||
timestamp=time.time(),
|
||||
limit=min(int(global_config.chat.max_context_size * 0.33), 10),
|
||||
)
|
||||
# TODO: 修复!
|
||||
from src.common.data_models import temporarily_transform_class_to_dict
|
||||
temp_msg_list_before_now_half = [temporarily_transform_class_to_dict(msg) for msg in message_list_before_now_half]
|
||||
|
||||
chat_content = build_readable_messages(
|
||||
temp_msg_list_before_now_half,
|
||||
message_list_before_now_half,
|
||||
replace_bot_name=True,
|
||||
merge_messages=False,
|
||||
timestamp_mode="relative",
|
||||
|
|
|
|||
|
|
@ -280,11 +280,8 @@ class ActionPlanner:
|
|||
timestamp=time.time(),
|
||||
limit=int(global_config.chat.max_context_size * 0.6),
|
||||
)
|
||||
# TODO: 修复!
|
||||
from src.common.data_models import temporarily_transform_class_to_dict
|
||||
temp_msg_list_before_now = [temporarily_transform_class_to_dict(msg) for msg in message_list_before_now]
|
||||
chat_content_block, message_id_list = build_readable_messages_with_id(
|
||||
messages=temp_msg_list_before_now,
|
||||
messages=message_list_before_now,
|
||||
timestamp_mode="normal_no_YMD",
|
||||
read_mark=self.last_obs_time_mark,
|
||||
truncate=True,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ from typing import List, Dict, Any, Tuple, Optional, Callable
|
|||
from rich.traceback import install
|
||||
|
||||
from src.config.config import global_config
|
||||
from src.common.logger import get_logger
|
||||
from src.common.message_repository import find_messages, count_messages
|
||||
from src.common.data_models.database_data_model import DatabaseMessages
|
||||
from src.common.database.database_model import ActionRecords
|
||||
|
|
@ -14,6 +15,7 @@ from src.person_info.person_info import Person, get_person_id
|
|||
from src.chat.utils.utils import translate_timestamp_to_human_readable, assign_message_ids
|
||||
|
||||
install(extra_lines=3)
|
||||
logger = get_logger("chat_message_builder")
|
||||
|
||||
|
||||
def replace_user_references_sync(
|
||||
|
|
@ -349,7 +351,9 @@ def get_raw_msg_before_timestamp_with_chat(chat_id: str, timestamp: float, limit
|
|||
return find_messages(message_filter=filter_query, sort=sort_order, limit=limit)
|
||||
|
||||
|
||||
def get_raw_msg_before_timestamp_with_users(timestamp: float, person_ids: list, limit: int = 0) -> List[DatabaseMessages]:
|
||||
def get_raw_msg_before_timestamp_with_users(
|
||||
timestamp: float, person_ids: list, limit: int = 0
|
||||
) -> List[DatabaseMessages]:
|
||||
"""获取指定时间戳之前的消息,按时间升序排序,返回消息列表
|
||||
limit: 限制返回的消息数量,0为不限制
|
||||
"""
|
||||
|
|
@ -776,7 +780,7 @@ async def build_readable_messages_with_list(
|
|||
|
||||
|
||||
def build_readable_messages_with_id(
|
||||
messages: List[Dict[str, Any]],
|
||||
messages: List[DatabaseMessages],
|
||||
replace_bot_name: bool = True,
|
||||
merge_messages: bool = False,
|
||||
timestamp_mode: str = "relative",
|
||||
|
|
@ -807,7 +811,7 @@ def build_readable_messages_with_id(
|
|||
|
||||
|
||||
def build_readable_messages(
|
||||
messages: List[Dict[str, Any]],
|
||||
messages: List[DatabaseMessages],
|
||||
replace_bot_name: bool = True,
|
||||
merge_messages: bool = False,
|
||||
timestamp_mode: str = "relative",
|
||||
|
|
@ -835,15 +839,15 @@ def build_readable_messages(
|
|||
if not messages:
|
||||
return ""
|
||||
|
||||
copy_messages = [msg.copy() for msg in messages]
|
||||
copy_messages = list(messages)
|
||||
|
||||
if show_actions and copy_messages:
|
||||
# 获取所有消息的时间范围
|
||||
min_time = min(msg.get("time", 0) for msg in copy_messages)
|
||||
max_time = max(msg.get("time", 0) for msg in copy_messages)
|
||||
min_time = min(msg.time or 0 for msg in copy_messages)
|
||||
max_time = max(msg.time or 0 for msg in copy_messages)
|
||||
|
||||
# 从第一条消息中获取chat_id
|
||||
chat_id = copy_messages[0].get("chat_id") if copy_messages else None
|
||||
chat_id = copy_messages[0].chat_id if copy_messages else None
|
||||
|
||||
# 获取这个时间范围内的动作记录,并匹配chat_id
|
||||
actions_in_range = (
|
||||
|
|
@ -883,7 +887,7 @@ def build_readable_messages(
|
|||
copy_messages.append(action_msg)
|
||||
|
||||
# 重新按时间排序
|
||||
copy_messages.sort(key=lambda x: x.get("time", 0))
|
||||
copy_messages.sort(key=lambda x: x.time or 0)
|
||||
|
||||
if read_mark <= 0:
|
||||
# 没有有效的 read_mark,直接格式化所有消息
|
||||
|
|
@ -905,8 +909,8 @@ def build_readable_messages(
|
|||
return formatted_string
|
||||
else:
|
||||
# 按 read_mark 分割消息
|
||||
messages_before_mark = [msg for msg in copy_messages if msg.get("time", 0) <= read_mark]
|
||||
messages_after_mark = [msg for msg in copy_messages if msg.get("time", 0) > read_mark]
|
||||
messages_before_mark = [msg for msg in copy_messages if (msg.time or 0) <= read_mark]
|
||||
messages_after_mark = [msg for msg in copy_messages if (msg.time or 0) > read_mark]
|
||||
|
||||
# 共享的图片映射字典和计数器
|
||||
pic_id_mapping = {}
|
||||
|
|
@ -960,13 +964,13 @@ def build_readable_messages(
|
|||
return "".join(result_parts)
|
||||
|
||||
|
||||
async def build_anonymous_messages(messages: List[Dict[str, Any]]) -> str:
|
||||
async def build_anonymous_messages(messages: List[DatabaseMessages]) -> str:
|
||||
"""
|
||||
构建匿名可读消息,将不同人的名称转为唯一占位符(A、B、C...),bot自己用SELF。
|
||||
处理 回复<aaa:bbb> 和 @<aaa:bbb> 字段,将bbb映射为匿名占位符。
|
||||
"""
|
||||
if not messages:
|
||||
print("111111111111没有消息,无法构建匿名消息")
|
||||
logger.warning("没有消息,无法构建匿名消息")
|
||||
return ""
|
||||
|
||||
person_map = {}
|
||||
|
|
@ -1017,14 +1021,9 @@ async def build_anonymous_messages(messages: List[Dict[str, Any]]) -> str:
|
|||
|
||||
for msg in messages:
|
||||
try:
|
||||
platform: str = msg.get("chat_info_platform") # type: ignore
|
||||
user_id = msg.get("user_id")
|
||||
_timestamp = msg.get("time")
|
||||
content: str = ""
|
||||
if msg.get("display_message"):
|
||||
content = msg.get("display_message", "")
|
||||
else:
|
||||
content = msg.get("processed_plain_text", "")
|
||||
platform = msg.chat_info.platform
|
||||
user_id = msg.user_info.user_id
|
||||
content = msg.display_message or msg.processed_plain_text or ""
|
||||
|
||||
if "ᶠ" in content:
|
||||
content = content.replace("ᶠ", "")
|
||||
|
|
|
|||
Loading…
Reference in New Issue