🤖 自动格式化代码 [skip ci]
This commit is contained in:
@@ -17,13 +17,12 @@ from src.chat.focus_chat.hfc_utils import CycleDetail
|
|||||||
import random
|
import random
|
||||||
from src.chat.focus_chat.hfc_utils import get_recent_message_stats
|
from src.chat.focus_chat.hfc_utils import get_recent_message_stats
|
||||||
from src.person_info.person_info import get_person_info_manager
|
from src.person_info.person_info import get_person_info_manager
|
||||||
from src.plugin_system.apis import generator_api,send_api,message_api
|
from src.plugin_system.apis import generator_api, send_api, message_api
|
||||||
from src.chat.willing.willing_manager import get_willing_manager
|
from src.chat.willing.willing_manager import get_willing_manager
|
||||||
from .priority_manager import PriorityManager
|
from .priority_manager import PriorityManager
|
||||||
from src.chat.utils.chat_message_builder import get_raw_msg_by_timestamp_with_chat
|
from src.chat.utils.chat_message_builder import get_raw_msg_by_timestamp_with_chat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ERROR_LOOP_INFO = {
|
ERROR_LOOP_INFO = {
|
||||||
"loop_plan_info": {
|
"loop_plan_info": {
|
||||||
"action_result": {
|
"action_result": {
|
||||||
@@ -93,7 +92,6 @@ class HeartFChatting:
|
|||||||
self._message_threshold = max(10, int(30 * global_config.chat.exit_focus_threshold))
|
self._message_threshold = max(10, int(30 * global_config.chat.exit_focus_threshold))
|
||||||
self._fatigue_triggered = False # 是否已触发疲惫退出
|
self._fatigue_triggered = False # 是否已触发疲惫退出
|
||||||
|
|
||||||
|
|
||||||
self.action_manager = ActionManager()
|
self.action_manager = ActionManager()
|
||||||
self.action_planner = ActionPlanner(chat_id=self.stream_id, action_manager=self.action_manager)
|
self.action_planner = ActionPlanner(chat_id=self.stream_id, action_manager=self.action_manager)
|
||||||
self.action_modifier = ActionModifier(action_manager=self.action_manager, chat_id=self.stream_id)
|
self.action_modifier = ActionModifier(action_manager=self.action_manager, chat_id=self.stream_id)
|
||||||
@@ -110,13 +108,11 @@ class HeartFChatting:
|
|||||||
self.reply_timeout_count = 0
|
self.reply_timeout_count = 0
|
||||||
self.plan_timeout_count = 0
|
self.plan_timeout_count = 0
|
||||||
|
|
||||||
self.last_read_time = time.time()-1
|
self.last_read_time = time.time() - 1
|
||||||
|
|
||||||
|
|
||||||
self.willing_amplifier = 1
|
self.willing_amplifier = 1
|
||||||
self.willing_manager = get_willing_manager()
|
self.willing_manager = get_willing_manager()
|
||||||
|
|
||||||
|
|
||||||
self.reply_mode = self.chat_stream.context.get_priority_mode()
|
self.reply_mode = self.chat_stream.context.get_priority_mode()
|
||||||
if self.reply_mode == "priority":
|
if self.reply_mode == "priority":
|
||||||
self.priority_manager = PriorityManager(
|
self.priority_manager = PriorityManager(
|
||||||
@@ -126,12 +122,10 @@ class HeartFChatting:
|
|||||||
else:
|
else:
|
||||||
self.priority_manager = None
|
self.priority_manager = None
|
||||||
|
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"{self.log_prefix} HeartFChatting 初始化完成,消息疲惫阈值: {self._message_threshold}条(基于exit_focus_threshold={global_config.chat.exit_focus_threshold}计算,仅在auto模式下生效)"
|
f"{self.log_prefix} HeartFChatting 初始化完成,消息疲惫阈值: {self._message_threshold}条(基于exit_focus_threshold={global_config.chat.exit_focus_threshold}计算,仅在auto模式下生效)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
self.energy_value = 100
|
self.energy_value = 100
|
||||||
|
|
||||||
async def start(self):
|
async def start(self):
|
||||||
@@ -176,41 +170,42 @@ class HeartFChatting:
|
|||||||
cycle_timers = {}
|
cycle_timers = {}
|
||||||
return cycle_timers, self._current_cycle_detail.thinking_id
|
return cycle_timers, self._current_cycle_detail.thinking_id
|
||||||
|
|
||||||
def end_cycle(self,loop_info,cycle_timers):
|
def end_cycle(self, loop_info, cycle_timers):
|
||||||
self._current_cycle_detail.set_loop_info(loop_info)
|
self._current_cycle_detail.set_loop_info(loop_info)
|
||||||
self.history_loop.append(self._current_cycle_detail)
|
self.history_loop.append(self._current_cycle_detail)
|
||||||
self._current_cycle_detail.timers = cycle_timers
|
self._current_cycle_detail.timers = cycle_timers
|
||||||
self._current_cycle_detail.end_time = time.time()
|
self._current_cycle_detail.end_time = time.time()
|
||||||
|
|
||||||
def print_cycle_info(self,cycle_timers):
|
def print_cycle_info(self, cycle_timers):
|
||||||
# 记录循环信息和计时器结果
|
# 记录循环信息和计时器结果
|
||||||
timer_strings = []
|
timer_strings = []
|
||||||
for name, elapsed in cycle_timers.items():
|
for name, elapsed in cycle_timers.items():
|
||||||
formatted_time = f"{elapsed * 1000:.2f}毫秒" if elapsed < 1 else f"{elapsed:.2f}秒"
|
formatted_time = f"{elapsed * 1000:.2f}毫秒" if elapsed < 1 else f"{elapsed:.2f}秒"
|
||||||
timer_strings.append(f"{name}: {formatted_time}")
|
timer_strings.append(f"{name}: {formatted_time}")
|
||||||
|
|
||||||
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}秒, "
|
|
||||||
f"选择动作: {self._current_cycle_detail.loop_plan_info.get('action_result', {}).get('action_type', '未知动作')}"
|
|
||||||
+ (f"\n详情: {'; '.join(timer_strings)}" if timer_strings else "")
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
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}秒, "
|
||||||
|
f"选择动作: {self._current_cycle_detail.loop_plan_info.get('action_result', {}).get('action_type', '未知动作')}"
|
||||||
|
+ (f"\n详情: {'; '.join(timer_strings)}" if timer_strings else "")
|
||||||
|
)
|
||||||
|
|
||||||
async def _loopbody(self):
|
async def _loopbody(self):
|
||||||
if self.loop_mode == "focus":
|
if self.loop_mode == "focus":
|
||||||
|
self.energy_value -= 5 * (1 / global_config.chat.exit_focus_threshold)
|
||||||
self.energy_value -= 5 * (1/global_config.chat.exit_focus_threshold)
|
|
||||||
if self.energy_value <= 0:
|
if self.energy_value <= 0:
|
||||||
self.loop_mode = "normal"
|
self.loop_mode = "normal"
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
return await self._observe()
|
return await self._observe()
|
||||||
elif self.loop_mode == "normal":
|
elif self.loop_mode == "normal":
|
||||||
new_messages_data = get_raw_msg_by_timestamp_with_chat(
|
new_messages_data = get_raw_msg_by_timestamp_with_chat(
|
||||||
chat_id=self.stream_id, timestamp_start=self.last_read_time, timestamp_end=time.time(),limit=10,limit_mode="earliest",fliter_bot=True
|
chat_id=self.stream_id,
|
||||||
|
timestamp_start=self.last_read_time,
|
||||||
|
timestamp_end=time.time(),
|
||||||
|
limit=10,
|
||||||
|
limit_mode="earliest",
|
||||||
|
fliter_bot=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(new_messages_data) > 4 * global_config.chat.auto_focus_threshold:
|
if len(new_messages_data) > 4 * global_config.chat.auto_focus_threshold:
|
||||||
@@ -229,7 +224,7 @@ class HeartFChatting:
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def build_reply_to_str(self,message_data:dict):
|
async def build_reply_to_str(self, message_data: dict):
|
||||||
person_info_manager = get_person_info_manager()
|
person_info_manager = get_person_info_manager()
|
||||||
person_id = person_info_manager.get_person_id(
|
person_id = person_info_manager.get_person_id(
|
||||||
message_data.get("chat_info_platform"), message_data.get("user_id")
|
message_data.get("chat_info_platform"), message_data.get("user_id")
|
||||||
@@ -238,18 +233,13 @@ class HeartFChatting:
|
|||||||
reply_to_str = f"{person_name}:{message_data.get('processed_plain_text')}"
|
reply_to_str = f"{person_name}:{message_data.get('processed_plain_text')}"
|
||||||
return reply_to_str
|
return reply_to_str
|
||||||
|
|
||||||
|
async def _observe(self, message_data: dict = None):
|
||||||
async def _observe(self,message_data:dict = None):
|
|
||||||
# 创建新的循环信息
|
# 创建新的循环信息
|
||||||
cycle_timers, thinking_id = self.start_cycle()
|
cycle_timers, thinking_id = self.start_cycle()
|
||||||
|
|
||||||
logger.info(f"{self.log_prefix} 开始第{self._cycle_counter}次思考[模式:{self.loop_mode}]")
|
logger.info(f"{self.log_prefix} 开始第{self._cycle_counter}次思考[模式:{self.loop_mode}]")
|
||||||
|
|
||||||
|
async with global_prompt_manager.async_message_scope(self.chat_stream.context.get_template_name()):
|
||||||
async with global_prompt_manager.async_message_scope(
|
|
||||||
self.chat_stream.context.get_template_name()
|
|
||||||
):
|
|
||||||
|
|
||||||
loop_start_time = time.time()
|
loop_start_time = time.time()
|
||||||
# await self.loop_info.observe()
|
# await self.loop_info.observe()
|
||||||
await self.relationship_builder.build_relation()
|
await self.relationship_builder.build_relation()
|
||||||
@@ -262,17 +252,14 @@ class HeartFChatting:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"{self.log_prefix} 动作修改失败: {e}")
|
logger.error(f"{self.log_prefix} 动作修改失败: {e}")
|
||||||
|
|
||||||
#如果normal,开始一个回复生成进程,先准备好回复(其实是和planer同时进行的)
|
# 如果normal,开始一个回复生成进程,先准备好回复(其实是和planer同时进行的)
|
||||||
if self.loop_mode == "normal":
|
if self.loop_mode == "normal":
|
||||||
reply_to_str = await self.build_reply_to_str(message_data)
|
reply_to_str = await self.build_reply_to_str(message_data)
|
||||||
gen_task = asyncio.create_task(self._generate_response(message_data, available_actions,reply_to_str))
|
gen_task = asyncio.create_task(self._generate_response(message_data, available_actions, reply_to_str))
|
||||||
|
|
||||||
|
|
||||||
with Timer("规划器", cycle_timers):
|
with Timer("规划器", cycle_timers):
|
||||||
plan_result = await self.action_planner.plan(mode=self.loop_mode)
|
plan_result = await self.action_planner.plan(mode=self.loop_mode)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
action_result = plan_result.get("action_result", {})
|
action_result = plan_result.get("action_result", {})
|
||||||
action_type, action_data, reasoning, is_parallel = (
|
action_type, action_data, reasoning, is_parallel = (
|
||||||
action_result.get("action_type", "error"),
|
action_result.get("action_type", "error"),
|
||||||
@@ -293,8 +280,6 @@ class HeartFChatting:
|
|||||||
else:
|
else:
|
||||||
logger.info(f"[{self.log_prefix}] {global_config.bot.nickname} 决定执行{action_type}动作")
|
logger.info(f"[{self.log_prefix}] {global_config.bot.nickname} 决定执行{action_type}动作")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if action_type == "no_action":
|
if action_type == "no_action":
|
||||||
# 等待回复生成完毕
|
# 等待回复生成完毕
|
||||||
gather_timeout = global_config.chat.thinking_timeout
|
gather_timeout = global_config.chat.thinking_timeout
|
||||||
@@ -307,9 +292,7 @@ class HeartFChatting:
|
|||||||
content = " ".join([item[1] for item in response_set if item[0] == "text"])
|
content = " ".join([item[1] for item in response_set if item[0] == "text"])
|
||||||
|
|
||||||
# 模型炸了,没有回复内容生成
|
# 模型炸了,没有回复内容生成
|
||||||
if not response_set or (
|
if not response_set or (action_type not in ["no_action"] and not is_parallel):
|
||||||
action_type not in ["no_action"] and not is_parallel
|
|
||||||
):
|
|
||||||
if not response_set:
|
if not response_set:
|
||||||
logger.warning(f"[{self.log_prefix}] 模型未生成回复内容")
|
logger.warning(f"[{self.log_prefix}] 模型未生成回复内容")
|
||||||
elif action_type not in ["no_action"] and not is_parallel:
|
elif action_type not in ["no_action"] and not is_parallel:
|
||||||
@@ -320,14 +303,11 @@ class HeartFChatting:
|
|||||||
|
|
||||||
logger.info(f"[{self.log_prefix}] {global_config.bot.nickname} 决定的回复内容: {content}")
|
logger.info(f"[{self.log_prefix}] {global_config.bot.nickname} 决定的回复内容: {content}")
|
||||||
|
|
||||||
|
|
||||||
# 发送回复 (不再需要传入 chat)
|
# 发送回复 (不再需要传入 chat)
|
||||||
await self._send_response(response_set, reply_to_str, loop_start_time)
|
await self._send_response(response_set, reply_to_str, loop_start_time)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# 动作执行计时
|
# 动作执行计时
|
||||||
with Timer("动作执行", cycle_timers):
|
with Timer("动作执行", cycle_timers):
|
||||||
@@ -350,9 +330,9 @@ class HeartFChatting:
|
|||||||
if loop_info["loop_action_info"]["command"] == "stop_focus_chat":
|
if loop_info["loop_action_info"]["command"] == "stop_focus_chat":
|
||||||
logger.info(f"{self.log_prefix} 麦麦决定停止专注聊天")
|
logger.info(f"{self.log_prefix} 麦麦决定停止专注聊天")
|
||||||
return False
|
return False
|
||||||
#停止该聊天模式的循环
|
# 停止该聊天模式的循环
|
||||||
|
|
||||||
self.end_cycle(loop_info,cycle_timers)
|
self.end_cycle(loop_info, cycle_timers)
|
||||||
self.print_cycle_info(cycle_timers)
|
self.print_cycle_info(cycle_timers)
|
||||||
|
|
||||||
if self.loop_mode == "normal":
|
if self.loop_mode == "normal":
|
||||||
@@ -360,8 +340,6 @@ class HeartFChatting:
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def _main_chat_loop(self):
|
async def _main_chat_loop(self):
|
||||||
"""主循环,持续进行计划并可能回复消息,直到被外部取消。"""
|
"""主循环,持续进行计划并可能回复消息,直到被外部取消。"""
|
||||||
try:
|
try:
|
||||||
@@ -447,8 +425,6 @@ class HeartFChatting:
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return False, "", ""
|
return False, "", ""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def shutdown(self):
|
async def shutdown(self):
|
||||||
"""优雅关闭HeartFChatting实例,取消活动循环任务"""
|
"""优雅关闭HeartFChatting实例,取消活动循环任务"""
|
||||||
logger.info(f"{self.log_prefix} 正在关闭HeartFChatting...")
|
logger.info(f"{self.log_prefix} 正在关闭HeartFChatting...")
|
||||||
@@ -483,7 +459,6 @@ class HeartFChatting:
|
|||||||
|
|
||||||
logger.info(f"{self.log_prefix} HeartFChatting关闭完成")
|
logger.info(f"{self.log_prefix} HeartFChatting关闭完成")
|
||||||
|
|
||||||
|
|
||||||
def adjust_reply_frequency(self):
|
def adjust_reply_frequency(self):
|
||||||
"""
|
"""
|
||||||
根据预设规则动态调整回复意愿(willing_amplifier)。
|
根据预设规则动态调整回复意愿(willing_amplifier)。
|
||||||
@@ -554,8 +529,6 @@ class HeartFChatting:
|
|||||||
f"意愿放大器更新为: {self.willing_amplifier:.2f}"
|
f"意愿放大器更新为: {self.willing_amplifier:.2f}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def normal_response(self, message_data: dict) -> None:
|
async def normal_response(self, message_data: dict) -> None:
|
||||||
"""
|
"""
|
||||||
处理接收到的消息。
|
处理接收到的消息。
|
||||||
@@ -587,7 +560,6 @@ class HeartFChatting:
|
|||||||
if message_data.get("is_emoji") or message_data.get("is_picid"):
|
if message_data.get("is_emoji") or message_data.get("is_picid"):
|
||||||
reply_probability = 0
|
reply_probability = 0
|
||||||
|
|
||||||
|
|
||||||
# 打印消息信息
|
# 打印消息信息
|
||||||
mes_name = self.chat_stream.group_info.group_name if self.chat_stream.group_info else "私聊"
|
mes_name = self.chat_stream.group_info.group_name if self.chat_stream.group_info else "私聊"
|
||||||
if reply_probability > 0.1:
|
if reply_probability > 0.1:
|
||||||
@@ -599,16 +571,15 @@ class HeartFChatting:
|
|||||||
|
|
||||||
if random.random() < reply_probability:
|
if random.random() < reply_probability:
|
||||||
await self.willing_manager.before_generate_reply_handle(message_data.get("message_id"))
|
await self.willing_manager.before_generate_reply_handle(message_data.get("message_id"))
|
||||||
await self._observe(message_data = message_data)
|
await self._observe(message_data=message_data)
|
||||||
|
|
||||||
# 意愿管理器:注销当前message信息 (无论是否回复,只要处理过就删除)
|
# 意愿管理器:注销当前message信息 (无论是否回复,只要处理过就删除)
|
||||||
self.willing_manager.delete(message_data.get("message_id"))
|
self.willing_manager.delete(message_data.get("message_id"))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def _generate_response(
|
async def _generate_response(
|
||||||
self, message_data: dict, available_actions: Optional[list],reply_to:str
|
self, message_data: dict, available_actions: Optional[list], reply_to: str
|
||||||
) -> Optional[list]:
|
) -> Optional[list]:
|
||||||
"""生成普通回复"""
|
"""生成普通回复"""
|
||||||
try:
|
try:
|
||||||
@@ -630,10 +601,7 @@ class HeartFChatting:
|
|||||||
logger.error(f"[{self.log_prefix}] 回复生成出现错误:{str(e)} {traceback.format_exc()}")
|
logger.error(f"[{self.log_prefix}] 回复生成出现错误:{str(e)} {traceback.format_exc()}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
async def _send_response(self, reply_set, reply_to, thinking_start_time):
|
||||||
async def _send_response(
|
|
||||||
self, reply_set, reply_to, thinking_start_time
|
|
||||||
):
|
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
new_message_count = message_api.count_new_messages(
|
new_message_count = message_api.count_new_messages(
|
||||||
chat_id=self.chat_stream.stream_id, start_time=thinking_start_time, end_time=current_time
|
chat_id=self.chat_stream.stream_id, start_time=thinking_start_time, end_time=current_time
|
||||||
@@ -651,7 +619,9 @@ class HeartFChatting:
|
|||||||
data = reply_seg[1]
|
data = reply_seg[1]
|
||||||
if not first_replyed:
|
if not first_replyed:
|
||||||
if need_reply:
|
if need_reply:
|
||||||
await send_api.text_to_stream(text=data, stream_id=self.chat_stream.stream_id, reply_to=reply_to, typing=False)
|
await send_api.text_to_stream(
|
||||||
|
text=data, stream_id=self.chat_stream.stream_id, reply_to=reply_to, typing=False
|
||||||
|
)
|
||||||
first_replyed = True
|
first_replyed = True
|
||||||
else:
|
else:
|
||||||
await send_api.text_to_stream(text=data, stream_id=self.chat_stream.stream_id, typing=False)
|
await send_api.text_to_stream(text=data, stream_id=self.chat_stream.stream_id, typing=False)
|
||||||
@@ -661,5 +631,3 @@ class HeartFChatting:
|
|||||||
reply_text += data
|
reply_text += data
|
||||||
|
|
||||||
return reply_text
|
return reply_text
|
||||||
|
|
||||||
|
|
||||||
@@ -6,7 +6,6 @@ from src.config.config import global_config
|
|||||||
from src.common.message_repository import count_messages
|
from src.common.message_repository import count_messages
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -82,7 +81,6 @@ class CycleDetail:
|
|||||||
self.loop_action_info = loop_info["loop_action_info"]
|
self.loop_action_info = loop_info["loop_action_info"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_recent_message_stats(minutes: int = 30, chat_id: str = None) -> dict:
|
def get_recent_message_stats(minutes: int = 30, chat_id: str = None) -> dict:
|
||||||
"""
|
"""
|
||||||
Args:
|
Args:
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ class SubHeartflow:
|
|||||||
self.subheartflow_id = subheartflow_id
|
self.subheartflow_id = subheartflow_id
|
||||||
self.chat_id = subheartflow_id
|
self.chat_id = subheartflow_id
|
||||||
|
|
||||||
|
|
||||||
self.is_group_chat, self.chat_target_info = get_chat_type_and_target_info(self.chat_id)
|
self.is_group_chat, self.chat_target_info = get_chat_type_and_target_info(self.chat_id)
|
||||||
self.log_prefix = get_chat_manager().get_stream_name(self.subheartflow_id) or self.subheartflow_id
|
self.log_prefix = get_chat_manager().get_stream_name(self.subheartflow_id) or self.subheartflow_id
|
||||||
|
|
||||||
@@ -38,16 +37,13 @@ class SubHeartflow:
|
|||||||
# 随便水群 normal_chat 和 认真水群 focus_chat 实例
|
# 随便水群 normal_chat 和 认真水群 focus_chat 实例
|
||||||
# CHAT模式激活 随便水群 FOCUS模式激活 认真水群
|
# CHAT模式激活 随便水群 FOCUS模式激活 认真水群
|
||||||
self.heart_fc_instance: Optional[HeartFChatting] = HeartFChatting(
|
self.heart_fc_instance: Optional[HeartFChatting] = HeartFChatting(
|
||||||
chat_id=self.subheartflow_id,
|
chat_id=self.subheartflow_id,
|
||||||
) # 该sub_heartflow的HeartFChatting实例
|
) # 该sub_heartflow的HeartFChatting实例
|
||||||
|
|
||||||
async def initialize(self):
|
async def initialize(self):
|
||||||
"""异步初始化方法,创建兴趣流并确定聊天类型"""
|
"""异步初始化方法,创建兴趣流并确定聊天类型"""
|
||||||
await self.heart_fc_instance.start()
|
await self.heart_fc_instance.start()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def _stop_heart_fc_chat(self):
|
async def _stop_heart_fc_chat(self):
|
||||||
"""停止并清理 HeartFChatting 实例"""
|
"""停止并清理 HeartFChatting 实例"""
|
||||||
if self.heart_fc_instance.running:
|
if self.heart_fc_instance.running:
|
||||||
@@ -86,7 +82,6 @@ class SubHeartflow:
|
|||||||
logger.error(traceback.format_exc())
|
logger.error(traceback.format_exc())
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def is_in_focus_cooldown(self) -> bool:
|
def is_in_focus_cooldown(self) -> bool:
|
||||||
"""检查是否在focus模式的冷却期内
|
"""检查是否在focus模式的冷却期内
|
||||||
|
|
||||||
|
|||||||
@@ -444,11 +444,8 @@ class MessageSet:
|
|||||||
|
|
||||||
|
|
||||||
def message_recv_from_dict(message_dict: dict) -> MessageRecv:
|
def message_recv_from_dict(message_dict: dict) -> MessageRecv:
|
||||||
return MessageRecv(
|
return MessageRecv(message_dict)
|
||||||
|
|
||||||
message_dict
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
def message_from_db_dict(db_dict: dict) -> MessageRecv:
|
def message_from_db_dict(db_dict: dict) -> MessageRecv:
|
||||||
"""从数据库字典创建MessageRecv实例"""
|
"""从数据库字典创建MessageRecv实例"""
|
||||||
|
|||||||
@@ -84,4 +84,3 @@ class HeartFCSender:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"[{chat_id}] 处理或存储消息 {message_id} 时出错: {e}")
|
logger.error(f"[{chat_id}] 处理或存储消息 {message_id} 时出错: {e}")
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ logger = get_logger("normal_chat")
|
|||||||
|
|
||||||
LOOP_INTERVAL = 0.3
|
LOOP_INTERVAL = 0.3
|
||||||
|
|
||||||
|
|
||||||
class NormalChat:
|
class NormalChat:
|
||||||
"""
|
"""
|
||||||
普通聊天处理类,负责处理非核心对话的聊天逻辑。
|
普通聊天处理类,负责处理非核心对话的聊天逻辑。
|
||||||
@@ -43,7 +44,7 @@ class NormalChat:
|
|||||||
"""
|
"""
|
||||||
self.chat_stream = chat_stream
|
self.chat_stream = chat_stream
|
||||||
self.stream_id = chat_stream.stream_id
|
self.stream_id = chat_stream.stream_id
|
||||||
self.last_read_time = time.time()-1
|
self.last_read_time = time.time() - 1
|
||||||
|
|
||||||
self.stream_name = get_chat_manager().get_stream_name(self.stream_id) or self.stream_id
|
self.stream_name = get_chat_manager().get_stream_name(self.stream_id) or self.stream_id
|
||||||
|
|
||||||
@@ -86,7 +87,7 @@ class NormalChat:
|
|||||||
|
|
||||||
# 任务管理
|
# 任务管理
|
||||||
self._chat_task: Optional[asyncio.Task] = None
|
self._chat_task: Optional[asyncio.Task] = None
|
||||||
self._priority_chat_task: Optional[asyncio.Task] = None # for priority mode consumer
|
self._priority_chat_task: Optional[asyncio.Task] = None # for priority mode consumer
|
||||||
self._disabled = False # 停用标志
|
self._disabled = False # 停用标志
|
||||||
|
|
||||||
# 新增:回复模式和优先级管理器
|
# 新增:回复模式和优先级管理器
|
||||||
@@ -134,7 +135,6 @@ class NormalChat:
|
|||||||
# except Exception as e:
|
# except Exception as e:
|
||||||
# logger.error(f"[{self.stream_name}] 处理消息时出错: {e} {traceback.format_exc()}")
|
# logger.error(f"[{self.stream_name}] 处理消息时出错: {e} {traceback.format_exc()}")
|
||||||
|
|
||||||
|
|
||||||
# except asyncio.CancelledError:
|
# except asyncio.CancelledError:
|
||||||
# logger.info(f"[{self.stream_name}] 兴趣模式轮询任务被取消")
|
# logger.info(f"[{self.stream_name}] 兴趣模式轮询任务被取消")
|
||||||
# return False
|
# return False
|
||||||
@@ -143,35 +143,34 @@ class NormalChat:
|
|||||||
# await asyncio.sleep(10)
|
# await asyncio.sleep(10)
|
||||||
|
|
||||||
async def _priority_mode_loopbody(self):
|
async def _priority_mode_loopbody(self):
|
||||||
try:
|
try:
|
||||||
await asyncio.sleep(LOOP_INTERVAL)
|
await asyncio.sleep(LOOP_INTERVAL)
|
||||||
|
|
||||||
if self._disabled:
|
if self._disabled:
|
||||||
return False
|
|
||||||
|
|
||||||
now = time.time()
|
|
||||||
new_messages_data = get_raw_msg_by_timestamp_with_chat_inclusive(
|
|
||||||
chat_id=self.stream_id, timestamp_start=self.last_read_time, timestamp_end=now, limit_mode="earliest"
|
|
||||||
)
|
|
||||||
|
|
||||||
if new_messages_data:
|
|
||||||
self.last_read_time = now
|
|
||||||
|
|
||||||
for msg_data in new_messages_data:
|
|
||||||
try:
|
|
||||||
if self.priority_manager:
|
|
||||||
self.priority_manager.add_message(msg_data, msg_data.get("interest_rate", 0.0))
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"[{self.stream_name}] 添加消息到优先级队列时出错: {e} {traceback.format_exc()}")
|
|
||||||
|
|
||||||
|
|
||||||
except asyncio.CancelledError:
|
|
||||||
logger.info(f"[{self.stream_name}] 优先级消息生产者任务被取消")
|
|
||||||
return False
|
return False
|
||||||
except Exception:
|
|
||||||
logger.error(f"[{self.stream_name}] 优先级消息生产者循环出现错误: {traceback.format_exc()}", exc_info=True)
|
now = time.time()
|
||||||
await asyncio.sleep(10)
|
new_messages_data = get_raw_msg_by_timestamp_with_chat_inclusive(
|
||||||
|
chat_id=self.stream_id, timestamp_start=self.last_read_time, timestamp_end=now, limit_mode="earliest"
|
||||||
|
)
|
||||||
|
|
||||||
|
if new_messages_data:
|
||||||
|
self.last_read_time = now
|
||||||
|
|
||||||
|
for msg_data in new_messages_data:
|
||||||
|
try:
|
||||||
|
if self.priority_manager:
|
||||||
|
self.priority_manager.add_message(msg_data, msg_data.get("interest_rate", 0.0))
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[{self.stream_name}] 添加消息到优先级队列时出错: {e} {traceback.format_exc()}")
|
||||||
|
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
logger.info(f"[{self.stream_name}] 优先级消息生产者任务被取消")
|
||||||
|
return False
|
||||||
|
except Exception:
|
||||||
|
logger.error(f"[{self.stream_name}] 优先级消息生产者循环出现错误: {traceback.format_exc()}", exc_info=True)
|
||||||
|
await asyncio.sleep(10)
|
||||||
|
|
||||||
# async def _interest_message_polling_loop(self):
|
# async def _interest_message_polling_loop(self):
|
||||||
# """
|
# """
|
||||||
@@ -188,9 +187,6 @@ class NormalChat:
|
|||||||
# except asyncio.CancelledError:
|
# except asyncio.CancelledError:
|
||||||
# logger.info(f"[{self.stream_name}] 兴趣模式消息轮询任务被优雅地取消了")
|
# logger.info(f"[{self.stream_name}] 兴趣模式消息轮询任务被优雅地取消了")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def _priority_chat_loop(self):
|
async def _priority_chat_loop(self):
|
||||||
"""
|
"""
|
||||||
使用优先级队列的消息处理循环。
|
使用优先级队列的消息处理循环。
|
||||||
@@ -275,7 +271,6 @@ class NormalChat:
|
|||||||
|
|
||||||
# reply = message_from_db_dict(message_data)
|
# reply = message_from_db_dict(message_data)
|
||||||
|
|
||||||
|
|
||||||
# mark_head = False
|
# mark_head = False
|
||||||
# first_bot_msg = None
|
# first_bot_msg = None
|
||||||
# for msg in response_set:
|
# for msg in response_set:
|
||||||
@@ -652,7 +647,9 @@ class NormalChat:
|
|||||||
# Start consumer loop
|
# Start consumer loop
|
||||||
consumer_task = asyncio.create_task(self._priority_chat_loop())
|
consumer_task = asyncio.create_task(self._priority_chat_loop())
|
||||||
self._priority_chat_task = consumer_task
|
self._priority_chat_task = consumer_task
|
||||||
self._priority_chat_task.add_done_callback(lambda t: self._handle_task_completion(t, "priority_consumer"))
|
self._priority_chat_task.add_done_callback(
|
||||||
|
lambda t: self._handle_task_completion(t, "priority_consumer")
|
||||||
|
)
|
||||||
else: # Interest mode
|
else: # Interest mode
|
||||||
polling_task = asyncio.create_task(self._interest_message_polling_loop())
|
polling_task = asyncio.create_task(self._interest_message_polling_loop())
|
||||||
self._chat_task = polling_task
|
self._chat_task = polling_task
|
||||||
@@ -712,7 +709,6 @@ class NormalChat:
|
|||||||
self._chat_task = None
|
self._chat_task = None
|
||||||
self._priority_chat_task = None
|
self._priority_chat_task = None
|
||||||
|
|
||||||
|
|
||||||
# def adjust_reply_frequency(self):
|
# def adjust_reply_frequency(self):
|
||||||
# """
|
# """
|
||||||
# 根据预设规则动态调整回复意愿(willing_amplifier)。
|
# 根据预设规则动态调整回复意愿(willing_amplifier)。
|
||||||
|
|||||||
@@ -82,9 +82,9 @@ class ActionModifier:
|
|||||||
|
|
||||||
# === 第一阶段:传统观察处理 ===
|
# === 第一阶段:传统观察处理 ===
|
||||||
# if history_loop:
|
# if history_loop:
|
||||||
# removals_from_loop = await self.analyze_loop_actions(history_loop)
|
# removals_from_loop = await self.analyze_loop_actions(history_loop)
|
||||||
# if removals_from_loop:
|
# if removals_from_loop:
|
||||||
# removals_s1.extend(removals_from_loop)
|
# removals_s1.extend(removals_from_loop)
|
||||||
|
|
||||||
# 检查动作的关联类型
|
# 检查动作的关联类型
|
||||||
chat_context = self.chat_stream.context
|
chat_context = self.chat_stream.context
|
||||||
@@ -500,7 +500,7 @@ class ActionModifier:
|
|||||||
|
|
||||||
return removals
|
return removals
|
||||||
|
|
||||||
def get_available_actions_count(self,mode:str = "focus") -> int:
|
def get_available_actions_count(self, mode: str = "focus") -> int:
|
||||||
"""获取当前可用动作数量(排除默认的no_action)"""
|
"""获取当前可用动作数量(排除默认的no_action)"""
|
||||||
current_actions = self.action_manager.get_using_actions_for_mode(mode)
|
current_actions = self.action_manager.get_using_actions_for_mode(mode)
|
||||||
# 排除no_action(如果存在)
|
# 排除no_action(如果存在)
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class ActionPlanner:
|
|||||||
|
|
||||||
self.last_obs_time_mark = 0.0
|
self.last_obs_time_mark = 0.0
|
||||||
|
|
||||||
async def plan(self,mode:str = "focus") -> Dict[str, Any]:
|
async def plan(self, mode: str = "focus") -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
规划器 (Planner): 使用LLM根据上下文决定做出什么动作。
|
规划器 (Planner): 使用LLM根据上下文决定做出什么动作。
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -506,7 +506,6 @@ class DefaultReplyer:
|
|||||||
show_actions=True,
|
show_actions=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
message_list_before_short = get_raw_msg_before_timestamp_with_chat(
|
message_list_before_short = get_raw_msg_before_timestamp_with_chat(
|
||||||
chat_id=chat_id,
|
chat_id=chat_id,
|
||||||
timestamp=time.time(),
|
timestamp=time.time(),
|
||||||
|
|||||||
@@ -28,7 +28,12 @@ def get_raw_msg_by_timestamp(
|
|||||||
|
|
||||||
|
|
||||||
def get_raw_msg_by_timestamp_with_chat(
|
def get_raw_msg_by_timestamp_with_chat(
|
||||||
chat_id: str, timestamp_start: float, timestamp_end: float, limit: int = 0, limit_mode: str = "latest", fliter_bot = False
|
chat_id: str,
|
||||||
|
timestamp_start: float,
|
||||||
|
timestamp_end: float,
|
||||||
|
limit: int = 0,
|
||||||
|
limit_mode: str = "latest",
|
||||||
|
fliter_bot=False,
|
||||||
) -> List[Dict[str, Any]]:
|
) -> List[Dict[str, Any]]:
|
||||||
"""获取在特定聊天从指定时间戳到指定时间戳的消息,按时间升序排序,返回消息列表
|
"""获取在特定聊天从指定时间戳到指定时间戳的消息,按时间升序排序,返回消息列表
|
||||||
limit: 限制返回的消息数量,0为不限制
|
limit: 限制返回的消息数量,0为不限制
|
||||||
@@ -38,11 +43,18 @@ def get_raw_msg_by_timestamp_with_chat(
|
|||||||
# 只有当 limit 为 0 时才应用外部 sort
|
# 只有当 limit 为 0 时才应用外部 sort
|
||||||
sort_order = [("time", 1)] if limit == 0 else None
|
sort_order = [("time", 1)] if limit == 0 else None
|
||||||
# 直接将 limit_mode 传递给 find_messages
|
# 直接将 limit_mode 传递给 find_messages
|
||||||
return find_messages(message_filter=filter_query, sort=sort_order, limit=limit, limit_mode=limit_mode, fliter_bot=fliter_bot)
|
return find_messages(
|
||||||
|
message_filter=filter_query, sort=sort_order, limit=limit, limit_mode=limit_mode, fliter_bot=fliter_bot
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_raw_msg_by_timestamp_with_chat_inclusive(
|
def get_raw_msg_by_timestamp_with_chat_inclusive(
|
||||||
chat_id: str, timestamp_start: float, timestamp_end: float, limit: int = 0, limit_mode: str = "latest", fliter_bot = False
|
chat_id: str,
|
||||||
|
timestamp_start: float,
|
||||||
|
timestamp_end: float,
|
||||||
|
limit: int = 0,
|
||||||
|
limit_mode: str = "latest",
|
||||||
|
fliter_bot=False,
|
||||||
) -> List[Dict[str, Any]]:
|
) -> List[Dict[str, Any]]:
|
||||||
"""获取在特定聊天从指定时间戳到指定时间戳的消息(包含边界),按时间升序排序,返回消息列表
|
"""获取在特定聊天从指定时间戳到指定时间戳的消息(包含边界),按时间升序排序,返回消息列表
|
||||||
limit: 限制返回的消息数量,0为不限制
|
limit: 限制返回的消息数量,0为不限制
|
||||||
@@ -53,7 +65,9 @@ def get_raw_msg_by_timestamp_with_chat_inclusive(
|
|||||||
sort_order = [("time", 1)] if limit == 0 else None
|
sort_order = [("time", 1)] if limit == 0 else None
|
||||||
# 直接将 limit_mode 传递给 find_messages
|
# 直接将 limit_mode 传递给 find_messages
|
||||||
|
|
||||||
return find_messages(message_filter=filter_query, sort=sort_order, limit=limit, limit_mode=limit_mode, fliter_bot=fliter_bot)
|
return find_messages(
|
||||||
|
message_filter=filter_query, sort=sort_order, limit=limit, limit_mode=limit_mode, fliter_bot=fliter_bot
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_raw_msg_by_timestamp_with_chat_users(
|
def get_raw_msg_by_timestamp_with_chat_users(
|
||||||
@@ -584,7 +598,6 @@ def build_readable_actions(actions: List[Dict[str, Any]]) -> str:
|
|||||||
if action_name == "no_action" or action_name == "no_reply":
|
if action_name == "no_action" or action_name == "no_reply":
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
action_prompt_display = action.get("action_prompt_display", "无具体内容")
|
action_prompt_display = action.get("action_prompt_display", "无具体内容")
|
||||||
|
|
||||||
time_diff_seconds = current_time - action_time
|
time_diff_seconds = current_time - action_time
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ def find_messages(
|
|||||||
sort: Optional[List[tuple[str, int]]] = None,
|
sort: Optional[List[tuple[str, int]]] = None,
|
||||||
limit: int = 0,
|
limit: int = 0,
|
||||||
limit_mode: str = "latest",
|
limit_mode: str = "latest",
|
||||||
fliter_bot = False
|
fliter_bot=False,
|
||||||
) -> List[dict[str, Any]]:
|
) -> List[dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
根据提供的过滤器、排序和限制条件查找消息。
|
根据提供的过滤器、排序和限制条件查找消息。
|
||||||
|
|||||||
@@ -278,7 +278,6 @@ class NormalChatConfig(ConfigBase):
|
|||||||
"""@bot 必然回复"""
|
"""@bot 必然回复"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class FocusChatConfig(ConfigBase):
|
class FocusChatConfig(ConfigBase):
|
||||||
"""专注聊天配置类"""
|
"""专注聊天配置类"""
|
||||||
|
|||||||
@@ -125,7 +125,6 @@ class MainSystem:
|
|||||||
logger.info("个体特征初始化成功")
|
logger.info("个体特征初始化成功")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
init_time = int(1000 * (time.time() - init_start_time))
|
init_time = int(1000 * (time.time() - init_start_time))
|
||||||
logger.info(f"初始化完成,神经元放电{init_time}次")
|
logger.info(f"初始化完成,神经元放电{init_time}次")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -56,7 +56,12 @@ def get_messages_by_time(
|
|||||||
|
|
||||||
|
|
||||||
def get_messages_by_time_in_chat(
|
def get_messages_by_time_in_chat(
|
||||||
chat_id: str, start_time: float, end_time: float, limit: int = 0, limit_mode: str = "latest", filter_mai: bool = False
|
chat_id: str,
|
||||||
|
start_time: float,
|
||||||
|
end_time: float,
|
||||||
|
limit: int = 0,
|
||||||
|
limit_mode: str = "latest",
|
||||||
|
filter_mai: bool = False,
|
||||||
) -> List[Dict[str, Any]]:
|
) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
获取指定聊天中指定时间范围内的消息
|
获取指定聊天中指定时间范围内的消息
|
||||||
@@ -78,7 +83,12 @@ def get_messages_by_time_in_chat(
|
|||||||
|
|
||||||
|
|
||||||
def get_messages_by_time_in_chat_inclusive(
|
def get_messages_by_time_in_chat_inclusive(
|
||||||
chat_id: str, start_time: float, end_time: float, limit: int = 0, limit_mode: str = "latest", filter_mai: bool = False
|
chat_id: str,
|
||||||
|
start_time: float,
|
||||||
|
end_time: float,
|
||||||
|
limit: int = 0,
|
||||||
|
limit_mode: str = "latest",
|
||||||
|
filter_mai: bool = False,
|
||||||
) -> List[Dict[str, Any]]:
|
) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
获取指定聊天中指定时间范围内的消息(包含边界)
|
获取指定聊天中指定时间范围内的消息(包含边界)
|
||||||
@@ -95,7 +105,9 @@ def get_messages_by_time_in_chat_inclusive(
|
|||||||
消息列表
|
消息列表
|
||||||
"""
|
"""
|
||||||
if filter_mai:
|
if filter_mai:
|
||||||
return filter_mai_messages(get_raw_msg_by_timestamp_with_chat_inclusive(chat_id, start_time, end_time, limit, limit_mode))
|
return filter_mai_messages(
|
||||||
|
get_raw_msg_by_timestamp_with_chat_inclusive(chat_id, start_time, end_time, limit, limit_mode)
|
||||||
|
)
|
||||||
return get_raw_msg_by_timestamp_with_chat_inclusive(chat_id, start_time, end_time, limit, limit_mode)
|
return get_raw_msg_by_timestamp_with_chat_inclusive(chat_id, start_time, end_time, limit, limit_mode)
|
||||||
|
|
||||||
|
|
||||||
@@ -181,7 +193,9 @@ def get_messages_before_time(timestamp: float, limit: int = 0, filter_mai: bool
|
|||||||
return get_raw_msg_before_timestamp(timestamp, limit)
|
return get_raw_msg_before_timestamp(timestamp, limit)
|
||||||
|
|
||||||
|
|
||||||
def get_messages_before_time_in_chat(chat_id: str, timestamp: float, limit: int = 0, filter_mai: bool = False) -> List[Dict[str, Any]]:
|
def get_messages_before_time_in_chat(
|
||||||
|
chat_id: str, timestamp: float, limit: int = 0, filter_mai: bool = False
|
||||||
|
) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
获取指定聊天中指定时间戳之前的消息
|
获取指定聊天中指定时间戳之前的消息
|
||||||
|
|
||||||
@@ -342,10 +356,12 @@ async def get_person_ids_from_messages(messages: List[Dict[str, Any]]) -> List[s
|
|||||||
"""
|
"""
|
||||||
return await get_person_id_list(messages)
|
return await get_person_id_list(messages)
|
||||||
|
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# 消息过滤函数
|
# 消息过滤函数
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
|
|
||||||
def filter_mai_messages(messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
def filter_mai_messages(messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
从消息列表中移除麦麦的消息
|
从消息列表中移除麦麦的消息
|
||||||
|
|||||||
Reference in New Issue
Block a user