迁移:1f91967(remove:移除willing系统,移除reply2,移除能量值,移除reply_to改为message)
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import asyncio
|
||||
import time
|
||||
import traceback
|
||||
import math
|
||||
import random
|
||||
from typing import Optional, Dict, Any, Tuple
|
||||
|
||||
from src.chat.message_receive.chat_stream import get_chat_manager
|
||||
@@ -10,7 +12,7 @@ from src.config.config import global_config
|
||||
from src.chat.planner_actions.planner import ActionPlanner
|
||||
from src.chat.planner_actions.action_modifier import ActionModifier
|
||||
from src.person_info.person_info import get_person_info_manager
|
||||
from src.plugin_system.apis import database_api
|
||||
from src.plugin_system.apis import database_api, generator_api
|
||||
from src.plugin_system.base.component_types import ChatMode
|
||||
from src.mais4u.constant_s4u import ENABLE_S4U
|
||||
from src.chat.chat_loop.hfc_utils import send_typing, stop_typing
|
||||
@@ -44,7 +46,6 @@ class CycleProcessor:
|
||||
async def _send_and_store_reply(
|
||||
self,
|
||||
response_set,
|
||||
reply_to_str,
|
||||
loop_start_time,
|
||||
action_message,
|
||||
cycle_timers: Dict[str, float],
|
||||
@@ -52,7 +53,7 @@ class CycleProcessor:
|
||||
actions,
|
||||
) -> Tuple[Dict[str, Any], str, Dict[str, float]]:
|
||||
with Timer("回复发送", cycle_timers):
|
||||
reply_text = await self.response_handler.send_response(response_set, reply_to_str, loop_start_time, action_message)
|
||||
reply_text = await self.response_handler.send_response(response_set, loop_start_time, action_message)
|
||||
|
||||
# 存储reply action信息
|
||||
person_info_manager = get_person_info_manager()
|
||||
@@ -60,7 +61,7 @@ class CycleProcessor:
|
||||
# 获取 platform,如果不存在则从 chat_stream 获取,如果还是 None 则使用默认值
|
||||
platform = action_message.get("chat_info_platform")
|
||||
if platform is None:
|
||||
platform = getattr(self.chat_stream, "platform", "unknown")
|
||||
platform = getattr(self.context.chat_stream, "platform", "unknown")
|
||||
|
||||
person_id = person_info_manager.get_person_id(
|
||||
platform,
|
||||
@@ -75,7 +76,7 @@ class CycleProcessor:
|
||||
action_prompt_display=action_prompt_display,
|
||||
action_done=True,
|
||||
thinking_id=thinking_id,
|
||||
action_data={"reply_text": reply_text, "reply_to": reply_to_str},
|
||||
action_data={"reply_text": reply_text},
|
||||
action_name="reply",
|
||||
)
|
||||
|
||||
@@ -113,12 +114,6 @@ class CycleProcessor:
|
||||
"""
|
||||
action_type = "no_action"
|
||||
reply_text = "" # 初始化reply_text变量,避免UnboundLocalError
|
||||
reply_to_str = "" # 初始化reply_to_str变量
|
||||
|
||||
# 根据interest_value计算概率,决定使用哪种planner模式
|
||||
# interest_value越高,越倾向于使用Normal模式
|
||||
import random
|
||||
import math
|
||||
|
||||
# 使用sigmoid函数将interest_value转换为概率
|
||||
# 当interest_value为0时,概率接近0(使用Focus模式)
|
||||
@@ -224,40 +219,23 @@ class CycleProcessor:
|
||||
"command": command
|
||||
}
|
||||
else:
|
||||
# 执行回复动作
|
||||
try:
|
||||
reply_to_str = await self._build_reply_to_str(action_info["action_message"])
|
||||
except UserWarning:
|
||||
logger.warning("选取了自己作为回复对象,跳过回复生成")
|
||||
return {
|
||||
"action_type": "reply",
|
||||
"success": False,
|
||||
"reply_text": "",
|
||||
"loop_info": None
|
||||
}
|
||||
|
||||
# 生成回复
|
||||
gather_timeout = global_config.chat.thinking_timeout
|
||||
try:
|
||||
response_set = await asyncio.wait_for(
|
||||
self.response_handler.generate_response(
|
||||
message_data=action_info["action_message"],
|
||||
available_actions=action_info["available_actions"],
|
||||
reply_to=reply_to_str,
|
||||
request_type="chat.replyer",
|
||||
),
|
||||
timeout=gather_timeout
|
||||
)
|
||||
except asyncio.TimeoutError:
|
||||
logger.warning(
|
||||
f"{self.log_prefix} 并行执行:回复生成超时>{global_config.chat.thinking_timeout}s,已跳过"
|
||||
)
|
||||
return {
|
||||
"action_type": "reply",
|
||||
"success": False,
|
||||
"reply_text": "",
|
||||
"loop_info": None
|
||||
}
|
||||
success, response_set, _ = await generator_api.generate_reply(
|
||||
chat_stream=self.context.chat_stream,
|
||||
reply_message = action_info["action_message"],
|
||||
available_actions=available_actions,
|
||||
enable_tool=global_config.tool.enable_tool,
|
||||
request_type="chat.replyer",
|
||||
from_plugin=False,
|
||||
)
|
||||
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
|
||||
}
|
||||
except asyncio.CancelledError:
|
||||
logger.debug(f"{self.log_prefix} 并行执行:回复生成任务已被取消")
|
||||
return {
|
||||
@@ -267,18 +245,8 @@ class CycleProcessor:
|
||||
"loop_info": None
|
||||
}
|
||||
|
||||
if not response_set:
|
||||
logger.warning(f"{self.log_prefix} 模型超时或生成回复内容为空")
|
||||
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,
|
||||
reply_to_str,
|
||||
loop_start_time,
|
||||
action_info["action_message"],
|
||||
cycle_timers,
|
||||
@@ -303,7 +271,6 @@ class CycleProcessor:
|
||||
}
|
||||
|
||||
# 创建所有动作的后台任务
|
||||
|
||||
action_tasks = [asyncio.create_task(execute_action(action)) for action in actions]
|
||||
|
||||
# 并行执行所有任务
|
||||
@@ -367,7 +334,6 @@ class CycleProcessor:
|
||||
self.context.chat_instance.cycle_tracker.end_cycle(loop_info, cycle_timers)
|
||||
self.context.chat_instance.cycle_tracker.print_cycle_info(cycle_timers)
|
||||
|
||||
# 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_reply计数器:当执行了非no_reply动作时,重置计数器
|
||||
if action_type != "no_reply":
|
||||
@@ -688,36 +654,6 @@ class CycleProcessor:
|
||||
"action_prompt": "",
|
||||
}
|
||||
|
||||
async def _build_reply_to_str(self, message_data: dict):
|
||||
"""
|
||||
构建回复目标字符串
|
||||
|
||||
Args:
|
||||
message_data: 消息数据字典
|
||||
|
||||
Returns:
|
||||
str: 格式化的回复目标字符串,格式为"用户名:消息内容"
|
||||
|
||||
功能说明:
|
||||
- 从消息数据中提取平台和用户ID信息
|
||||
- 通过人员信息管理器获取用户昵称
|
||||
- 构建用于回复显示的格式化字符串
|
||||
"""
|
||||
from src.person_info.person_info import get_person_info_manager
|
||||
|
||||
person_info_manager = get_person_info_manager()
|
||||
platform = (
|
||||
message_data.get("chat_info_platform")
|
||||
or message_data.get("user_platform")
|
||||
or (self.context.chat_stream.platform if self.context.chat_stream else "default")
|
||||
)
|
||||
user_id = message_data.get("user_id", "")
|
||||
if user_id == str(global_config.bot.qq_account) and platform == global_config.bot.platform:
|
||||
raise UserWarning
|
||||
person_id = person_info_manager.get_person_id(platform, user_id)
|
||||
person_name = await person_info_manager.get_value(person_id, "person_name")
|
||||
return f"{person_name}:{message_data.get('processed_plain_text')}"
|
||||
|
||||
def _build_final_loop_info(self, reply_loop_info, action_success, action_reply_text, action_command, plan_result):
|
||||
"""
|
||||
构建最终的循环信息
|
||||
|
||||
@@ -57,26 +57,6 @@ class EnergyManager:
|
||||
await asyncio.sleep(0)
|
||||
logger.info(f"{self.context.log_prefix} 能量管理器已停止")
|
||||
|
||||
def _handle_energy_completion(self, task: asyncio.Task):
|
||||
"""
|
||||
处理能量循环任务完成
|
||||
|
||||
Args:
|
||||
task: 完成的异步任务对象
|
||||
|
||||
功能说明:
|
||||
- 处理任务正常完成或异常情况
|
||||
- 记录相应的日志信息
|
||||
- 区分取消和异常终止的情况
|
||||
"""
|
||||
try:
|
||||
if exception := task.exception():
|
||||
logger.error(f"{self.context.log_prefix} 能量循环异常: {exception}")
|
||||
else:
|
||||
logger.info(f"{self.context.log_prefix} 能量循环正常结束")
|
||||
except asyncio.CancelledError:
|
||||
logger.info(f"{self.context.log_prefix} 能量循环被取消")
|
||||
|
||||
async def _energy_loop(self):
|
||||
"""
|
||||
能量与睡眠压力管理的主循环
|
||||
|
||||
@@ -12,14 +12,12 @@ from src.chat.express.expression_learner import expression_learner_manager
|
||||
from src.plugin_system.base.component_types import ChatMode
|
||||
from src.schedule.schedule_manager import schedule_manager, SleepState
|
||||
from src.plugin_system.apis import message_api
|
||||
from src.chat.willing.willing_manager import get_willing_manager
|
||||
|
||||
from .hfc_context import HfcContext
|
||||
from .energy_manager import EnergyManager
|
||||
from .proactive_thinker import ProactiveThinker
|
||||
from .cycle_processor import CycleProcessor
|
||||
from .response_handler import ResponseHandler
|
||||
from .normal_mode_handler import NormalModeHandler
|
||||
from .cycle_tracker import CycleTracker
|
||||
from .wakeup_manager import WakeUpManager
|
||||
|
||||
@@ -47,7 +45,6 @@ class HeartFChatting:
|
||||
self.cycle_processor = CycleProcessor(self.context, self.response_handler, self.cycle_tracker)
|
||||
self.energy_manager = EnergyManager(self.context)
|
||||
self.proactive_thinker = ProactiveThinker(self.context, self.cycle_processor)
|
||||
self.normal_mode_handler = NormalModeHandler(self.context, self.cycle_processor)
|
||||
self.wakeup_manager = WakeUpManager(self.context)
|
||||
|
||||
# 将唤醒度管理器设置到上下文中
|
||||
@@ -60,7 +57,6 @@ class HeartFChatting:
|
||||
|
||||
# 记录最近3次的兴趣度
|
||||
self.recent_interest_records: deque = deque(maxlen=3)
|
||||
self.willing_manager = get_willing_manager()
|
||||
self._initialize_chat_mode()
|
||||
logger.info(f"{self.context.log_prefix} HeartFChatting 初始化完成")
|
||||
|
||||
@@ -97,7 +93,7 @@ class HeartFChatting:
|
||||
self.context.relationship_builder = relationship_builder_manager.get_or_create_builder(self.context.stream_id)
|
||||
self.context.expression_learner = expression_learner_manager.get_expression_learner(self.context.stream_id)
|
||||
|
||||
await self.energy_manager.start()
|
||||
#await self.energy_manager.start()
|
||||
await self.proactive_thinker.start()
|
||||
await self.wakeup_manager.start()
|
||||
|
||||
@@ -120,7 +116,7 @@ class HeartFChatting:
|
||||
return
|
||||
self.context.running = False
|
||||
|
||||
await self.energy_manager.stop()
|
||||
#await self.energy_manager.stop()
|
||||
await self.proactive_thinker.stop()
|
||||
await self.wakeup_manager.stop()
|
||||
|
||||
@@ -245,8 +241,6 @@ class HeartFChatting:
|
||||
# 统一使用 _should_process_messages 判断是否应该处理
|
||||
should_process,interest_value = await self._should_process_messages(recent_messages if has_new_messages else None)
|
||||
if should_process:
|
||||
#earliest_message_data = recent_messages[0]
|
||||
#self.last_read_time = earliest_message_data.get("time")
|
||||
self.context.last_read_time = time.time()
|
||||
await self.cycle_processor.observe(interest_value = interest_value)
|
||||
else:
|
||||
@@ -418,6 +412,7 @@ class HeartFChatting:
|
||||
# talk_frequency = global_config.chat.get_current_talk_frequency(self.context.chat_stream.stream_id)
|
||||
modified_exit_count_threshold = self.context.focus_energy / global_config.chat.focus_value
|
||||
|
||||
modified_exit_interest_threshold = 3 / global_config.chat.focus_value
|
||||
total_interest = 0.0
|
||||
for msg_dict in new_message:
|
||||
interest_value = msg_dict.get("interest_value", 0.0)
|
||||
@@ -441,11 +436,11 @@ class HeartFChatting:
|
||||
if not hasattr(self, "_last_accumulated_interest") or total_interest != self._last_accumulated_interest:
|
||||
logger.info(f"{self.context.log_prefix} breaking形式当前累计兴趣值: {total_interest:.2f}, 专注度: {global_config.chat.focus_value:.1f}")
|
||||
self._last_accumulated_interest = total_interest
|
||||
if total_interest >= 3 / global_config.chat.focus_value:
|
||||
if total_interest >= modified_exit_interest_threshold:
|
||||
# 记录兴趣度到列表
|
||||
self.recent_interest_records.append(total_interest)
|
||||
logger.info(
|
||||
f"{self.context.log_prefix} 累计兴趣值达到{total_interest:.2f}(>{3 / global_config.chat.focus_value}),结束等待"
|
||||
f"{self.context.log_prefix} 累计兴趣值达到{total_interest:.2f}(>{modified_exit_interest_threshold:.1f}),结束等待"
|
||||
)
|
||||
return True,total_interest/new_message_count
|
||||
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
import random
|
||||
from typing import Dict, Any, TYPE_CHECKING
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.config.config import global_config
|
||||
from src.chat.willing.willing_manager import get_willing_manager
|
||||
from .hfc_context import HfcContext
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .cycle_processor import CycleProcessor
|
||||
|
||||
logger = get_logger("hfc.normal_mode")
|
||||
|
||||
|
||||
class NormalModeHandler:
|
||||
def __init__(self, context: HfcContext, cycle_processor: "CycleProcessor"):
|
||||
"""
|
||||
初始化普通模式处理器
|
||||
|
||||
Args:
|
||||
context: HFC聊天上下文对象
|
||||
cycle_processor: 循环处理器,用于处理决定回复的消息
|
||||
|
||||
功能说明:
|
||||
- 处理NORMAL模式下的消息
|
||||
- 根据兴趣度和回复概率决定是否回复
|
||||
- 管理意愿系统和回复概率计算
|
||||
"""
|
||||
self.context = context
|
||||
self.cycle_processor = cycle_processor
|
||||
self.willing_manager = get_willing_manager()
|
||||
|
||||
async def handle_message(self, message_data: Dict[str, Any]) -> bool:
|
||||
"""
|
||||
处理NORMAL模式下的单条消息
|
||||
|
||||
Args:
|
||||
message_data: 消息数据字典,包含用户信息、消息内容、兴趣值等
|
||||
|
||||
Returns:
|
||||
bool: 是否进行了回复处理
|
||||
|
||||
功能说明:
|
||||
- 计算消息的兴趣度和基础回复概率
|
||||
- 应用谈话频率调整回复概率
|
||||
- 过滤表情和图片消息(设置回复概率为0)
|
||||
- 根据概率随机决定是否回复
|
||||
- 如果决定回复则调用循环处理器进行处理
|
||||
- 记录详细的决策日志
|
||||
"""
|
||||
if not self.context.chat_stream:
|
||||
return False
|
||||
|
||||
interested_rate = message_data.get("interest_value") or 0.0
|
||||
self.willing_manager.setup(message_data, self.context.chat_stream)
|
||||
reply_probability = await self.willing_manager.get_reply_probability(message_data.get("message_id", ""))
|
||||
|
||||
if reply_probability < 1:
|
||||
additional_config = message_data.get("additional_config", {})
|
||||
if additional_config and "maimcore_reply_probability_gain" in additional_config:
|
||||
reply_probability += additional_config["maimcore_reply_probability_gain"]
|
||||
reply_probability = min(max(reply_probability, 0), 1)
|
||||
|
||||
talk_frequency = global_config.chat.get_current_talk_frequency(self.context.stream_id)
|
||||
reply_probability = talk_frequency * reply_probability
|
||||
|
||||
if message_data.get("is_emoji") or message_data.get("is_picid"):
|
||||
reply_probability = 0
|
||||
|
||||
mes_name = self.context.chat_stream.group_info.group_name if self.context.chat_stream.group_info else "私聊"
|
||||
if reply_probability > 0.05:
|
||||
logger.info(
|
||||
f"[{mes_name}]"
|
||||
f"{message_data.get('user_nickname')}:"
|
||||
f"{message_data.get('processed_plain_text')}[兴趣:{interested_rate:.2f}][回复概率:{reply_probability * 100:.1f}%]"
|
||||
)
|
||||
|
||||
if random.random() < reply_probability:
|
||||
await self.willing_manager.before_generate_reply_handle(message_data.get("message_id", ""))
|
||||
await self.cycle_processor.observe(message_data=message_data)
|
||||
return True
|
||||
|
||||
self.willing_manager.delete(message_data.get("message_id", ""))
|
||||
return False
|
||||
@@ -105,7 +105,7 @@ class ResponseHandler:
|
||||
|
||||
return loop_info, reply_text, cycle_timers
|
||||
|
||||
async def send_response(self, reply_set, reply_to, thinking_start_time, message_data) -> str:
|
||||
async def send_response(self, reply_set, thinking_start_time, message_data) -> str:
|
||||
"""
|
||||
发送回复内容的具体实现
|
||||
|
||||
@@ -129,9 +129,6 @@ class ResponseHandler:
|
||||
new_message_count = message_api.count_new_messages(
|
||||
chat_id=self.context.stream_id, start_time=thinking_start_time, end_time=current_time
|
||||
)
|
||||
platform = message_data.get("user_platform", "")
|
||||
user_id = message_data.get("user_id", "")
|
||||
reply_to_platform_id = f"{platform}:{user_id}"
|
||||
|
||||
need_reply = new_message_count >= random.randint(2, 4)
|
||||
|
||||
@@ -157,32 +154,26 @@ class ResponseHandler:
|
||||
continue
|
||||
|
||||
if not first_replied:
|
||||
if need_reply:
|
||||
await send_api.text_to_stream(
|
||||
text=data,
|
||||
stream_id=self.context.stream_id,
|
||||
reply_to=reply_to,
|
||||
reply_to_platform_id=reply_to_platform_id,
|
||||
typing=False,
|
||||
)
|
||||
else:
|
||||
await send_api.text_to_stream(
|
||||
text=data,
|
||||
stream_id=self.context.stream_id,
|
||||
reply_to_platform_id=reply_to_platform_id,
|
||||
typing=False,
|
||||
)
|
||||
await send_api.text_to_stream(
|
||||
text=data,
|
||||
stream_id=self.context.stream_id,
|
||||
reply_to_message = message_data,
|
||||
set_reply=need_reply,
|
||||
typing=False,
|
||||
)
|
||||
first_replied = True
|
||||
else:
|
||||
await send_api.text_to_stream(
|
||||
text=data,
|
||||
stream_id=self.context.stream_id,
|
||||
reply_to_platform_id=reply_to_platform_id,
|
||||
reply_to_message = message_data,
|
||||
set_reply=need_reply,
|
||||
typing=True,
|
||||
)
|
||||
|
||||
return reply_text
|
||||
|
||||
# TODO: 已废弃
|
||||
async def generate_response(
|
||||
self,
|
||||
message_data: dict,
|
||||
|
||||
Reference in New Issue
Block a user