为拆分heartFC_chat后的几个文件 添加亿点注释

This commit is contained in:
Furina-1013-create
2025-08-21 14:55:58 +08:00
parent 9c3b750328
commit 4c51f59c96
9 changed files with 669 additions and 5 deletions

View File

@@ -21,6 +21,14 @@ logger = get_logger("hfc.processor")
class CycleProcessor:
def __init__(self, context: HfcContext, response_handler: ResponseHandler, cycle_tracker: CycleTracker):
"""
初始化循环处理器
Args:
context: HFC聊天上下文对象包含聊天流、能量值等信息
response_handler: 响应处理器,负责生成和发送回复
cycle_tracker: 循环跟踪器,负责记录和管理每次思考循环的信息
"""
self.context = context
self.response_handler = response_handler
self.cycle_tracker = cycle_tracker
@@ -28,6 +36,22 @@ class CycleProcessor:
self.action_modifier = ActionModifier(action_manager=self.context.action_manager, chat_id=self.context.stream_id)
async def observe(self, message_data: Optional[Dict[str, Any]] = None) -> bool:
"""
观察和处理单次思考循环的核心方法
Args:
message_data: 可选的消息数据字典,包含用户消息、平台信息等
Returns:
bool: 处理是否成功
功能说明:
- 开始新的思考循环并记录计时
- 修改可用动作并获取动作列表
- 根据聊天模式和提及情况决定是否跳过规划器
- 执行动作规划或直接回复
- 根据动作类型分发到相应的处理方法
"""
if not message_data:
message_data = {}
@@ -105,6 +129,24 @@ class CycleProcessor:
return True
async def _handle_reply_action(self, message_data, available_actions, gen_task, loop_start_time, cycle_timers, thinking_id, plan_result):
"""
处理回复类型的动作
Args:
message_data: 消息数据
available_actions: 可用动作列表
gen_task: 预先创建的生成任务可能为None
loop_start_time: 循环开始时间
cycle_timers: 循环计时器
thinking_id: 思考ID
plan_result: 规划结果
功能说明:
- 根据聊天模式决定是否使用预生成的回复或实时生成
- 在NORMAL模式下使用异步生成提高效率
- 在FOCUS模式下同步生成确保及时响应
- 发送生成的回复并结束循环
"""
if self.context.loop_mode == ChatMode.NORMAL:
if not gen_task:
reply_to_str = await self._build_reply_to_str(message_data)
@@ -136,6 +178,27 @@ class CycleProcessor:
self.cycle_tracker.end_cycle(loop_info, cycle_timers)
async def _handle_other_actions(self, action_type, reasoning, action_data, is_parallel, gen_task, action_message, cycle_timers, thinking_id, plan_result, loop_start_time):
"""
处理非回复类型的动作如no_reply、自定义动作等
Args:
action_type: 动作类型
reasoning: 动作理由
action_data: 动作数据
is_parallel: 是否并行执行
gen_task: 生成任务
action_message: 动作消息
cycle_timers: 循环计时器
thinking_id: 思考ID
plan_result: 规划结果
loop_start_time: 循环开始时间
功能说明:
- 在NORMAL模式下可能并行执行回复生成和动作处理
- 等待所有异步任务完成
- 整合回复和动作的执行结果
- 构建最终循环信息并结束循环
"""
background_reply_task = None
if self.context.loop_mode == ChatMode.NORMAL and is_parallel and gen_task:
background_reply_task = asyncio.create_task(self._handle_parallel_reply(gen_task, loop_start_time, action_message, cycle_timers, thinking_id, plan_result))
@@ -172,6 +235,26 @@ class CycleProcessor:
self.cycle_tracker.end_cycle(loop_info, cycle_timers)
async def _handle_parallel_reply(self, gen_task, loop_start_time, action_message, cycle_timers, thinking_id, plan_result):
"""
处理并行回复生成
Args:
gen_task: 回复生成任务
loop_start_time: 循环开始时间
action_message: 动作消息
cycle_timers: 循环计时器
thinking_id: 思考ID
plan_result: 规划结果
Returns:
tuple: (循环信息, 回复文本, 计时器信息) 或 None
功能说明:
- 等待并行回复生成任务完成(带超时)
- 构建回复目标字符串
- 发送生成的回复
- 返回循环信息供上级方法使用
"""
try:
response_set = await asyncio.wait_for(gen_task, timeout=global_config.chat.thinking_timeout)
except asyncio.TimeoutError:
@@ -186,6 +269,25 @@ class CycleProcessor:
)
async def _handle_action(self, action, reasoning, action_data, cycle_timers, thinking_id, action_message) -> tuple[bool, str, str]:
"""
处理具体的动作执行
Args:
action: 动作名称
reasoning: 执行理由
action_data: 动作数据
cycle_timers: 循环计时器
thinking_id: 思考ID
action_message: 动作消息
Returns:
tuple: (执行是否成功, 回复文本, 命令文本)
功能说明:
- 创建对应的动作处理器
- 执行动作并捕获异常
- 返回执行结果供上级方法整合
"""
if not self.context.chat_stream:
return False, "", ""
try:
@@ -210,6 +312,19 @@ class CycleProcessor:
return False, "", ""
def _get_direct_reply_plan(self, loop_start_time):
"""
获取直接回复的规划结果
Args:
loop_start_time: 循环开始时间
Returns:
dict: 包含直接回复动作的规划结果
功能说明:
- 在某些情况下跳过复杂规划,直接返回回复动作
- 主要用于NORMAL模式下没有其他可用动作时的简化处理
"""
return {
"action_result": {
"action_type": "reply",
@@ -222,6 +337,20 @@ class CycleProcessor:
}
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")
@@ -231,6 +360,24 @@ class CycleProcessor:
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):
"""
构建最终的循环信息
Args:
reply_loop_info: 回复循环信息可能为None
action_success: 动作执行是否成功
action_reply_text: 动作回复文本
action_command: 动作命令
plan_result: 规划结果
Returns:
dict: 完整的循环信息,包含规划信息和动作信息
功能说明:
- 如果有回复循环信息,则在其基础上添加动作信息
- 如果没有回复信息,则创建新的循环信息结构
- 整合所有执行结果供循环跟踪器记录
"""
if reply_loop_info:
loop_info = reply_loop_info
loop_info["loop_action_info"].update({

View File

@@ -9,9 +9,31 @@ logger = get_logger("hfc.cycle")
class CycleTracker:
def __init__(self, context: HfcContext):
"""
初始化循环跟踪器
Args:
context: HFC聊天上下文对象
功能说明:
- 负责跟踪和记录每次思考循环的详细信息
- 管理循环的开始、结束和信息存储
"""
self.context = context
def start_cycle(self) -> Tuple[Dict[str, float], str]:
"""
开始新的思考循环
Returns:
tuple: (循环计时器字典, 思考ID字符串)
功能说明:
- 增加循环计数器
- 创建新的循环详情对象
- 生成唯一的思考ID
- 初始化循环计时器
"""
self.context.cycle_counter += 1
self.context.current_cycle_detail = CycleDetail(self.context.cycle_counter)
self.context.current_cycle_detail.thinking_id = f"tid{str(round(time.time(), 2))}"
@@ -19,6 +41,19 @@ class CycleTracker:
return cycle_timers, self.context.current_cycle_detail.thinking_id
def end_cycle(self, loop_info: Dict[str, Any], cycle_timers: Dict[str, float]):
"""
结束当前思考循环
Args:
loop_info: 循环信息,包含规划和动作信息
cycle_timers: 循环计时器,记录各阶段耗时
功能说明:
- 设置循环详情的完整信息
- 将当前循环加入历史记录
- 记录计时器和结束时间
- 打印循环统计信息
"""
if self.context.current_cycle_detail:
self.context.current_cycle_detail.set_loop_info(loop_info)
self.context.history_loop.append(self.context.current_cycle_detail)
@@ -27,6 +62,18 @@ class CycleTracker:
self.print_cycle_info(cycle_timers)
def print_cycle_info(self, cycle_timers: Dict[str, float]):
"""
打印循环统计信息
Args:
cycle_timers: 循环计时器字典
功能说明:
- 格式化各阶段的耗时信息
- 计算总体循环持续时间
- 输出详细的性能统计日志
- 显示选择的动作类型
"""
if not self.context.current_cycle_detail:
return

View File

@@ -10,24 +10,63 @@ logger = get_logger("hfc.energy")
class EnergyManager:
def __init__(self, context: HfcContext):
"""
初始化能量管理器
Args:
context: HFC聊天上下文对象
功能说明:
- 管理聊天机器人的能量值系统
- 根据聊天模式自动调整能量消耗
- 控制能量值的衰减和记录
"""
self.context = context
self._energy_task: Optional[asyncio.Task] = None
self.last_energy_log_time = 0
self.energy_log_interval = 90
async def start(self):
"""
启动能量管理器
功能说明:
- 检查运行状态,避免重复启动
- 创建能量循环异步任务
- 设置任务完成回调
- 记录启动日志
"""
if self.context.running and not self._energy_task:
self._energy_task = asyncio.create_task(self._energy_loop())
self._energy_task.add_done_callback(self._handle_energy_completion)
logger.info(f"{self.context.log_prefix} 能量管理器已启动")
async def stop(self):
"""
停止能量管理器
功能说明:
- 取消正在运行的能量循环任务
- 等待任务完全停止
- 记录停止日志
"""
if self._energy_task and not self._energy_task.done():
self._energy_task.cancel()
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}")
@@ -37,6 +76,16 @@ class EnergyManager:
logger.info(f"{self.context.log_prefix} 能量循环被取消")
async def _energy_loop(self):
"""
能量管理的主循环
功能说明:
- 每10秒执行一次能量更新
- 根据群聊配置设置固定的聊天模式和能量值
- 在自动模式下根据聊天模式进行能量衰减
- NORMAL模式每次衰减0.3FOCUS模式每次衰减0.6
- 确保能量值不低于0.3的最小值
"""
while self.context.running:
await asyncio.sleep(10)
@@ -63,6 +112,17 @@ class EnergyManager:
self._log_energy_change("能量值衰减")
def _should_log_energy(self) -> bool:
"""
判断是否应该记录能量变化日志
Returns:
bool: 如果距离上次记录超过间隔时间则返回True
功能说明:
- 控制能量日志的记录频率,避免日志过于频繁
- 默认间隔90秒记录一次详细日志
- 其他时间使用调试级别日志
"""
current_time = time.time()
if current_time - self.last_energy_log_time >= self.energy_log_interval:
self.last_energy_log_time = current_time
@@ -70,6 +130,18 @@ class EnergyManager:
return False
def _log_energy_change(self, action: str, reason: str = ""):
"""
记录能量变化日志
Args:
action: 能量变化的动作描述
reason: 可选的变化原因
功能说明:
- 根据时间间隔决定使用info还是debug级别的日志
- 格式化能量值显示(保留一位小数)
- 可选择性地包含变化原因
"""
if self._should_log_energy():
log_message = f"{self.context.log_prefix} {action},当前能量值:{self.context.energy_value:.1f}"
if reason:

View File

@@ -24,6 +24,18 @@ logger = get_logger("hfc")
class HeartFChatting:
def __init__(self, chat_id: str):
"""
初始化心跳聊天管理器
Args:
chat_id: 聊天ID标识符
功能说明:
- 创建聊天上下文和所有子管理器
- 初始化循环跟踪器、响应处理器、循环处理器等核心组件
- 设置能量管理器、主动思考器和普通模式处理器
- 初始化聊天模式并记录初始化完成日志
"""
self.context = HfcContext(chat_id)
self.cycle_tracker = CycleTracker(self.context)
@@ -39,6 +51,16 @@ class HeartFChatting:
logger.info(f"{self.context.log_prefix} HeartFChatting 初始化完成")
def _initialize_chat_mode(self):
"""
初始化聊天模式
功能说明:
- 检测是否为群聊环境
- 根据全局配置设置强制聊天模式
- 在focus模式下设置能量值为35
- 在normal模式下设置能量值为15
- 如果是auto模式则保持默认设置
"""
is_group_chat = self.context.chat_stream.group_info is not None if self.context.chat_stream else False
if is_group_chat and global_config.chat.group_chat_mode != "auto":
if global_config.chat.group_chat_mode == "focus":
@@ -49,6 +71,16 @@ class HeartFChatting:
self.context.energy_value = 15
async def start(self):
"""
启动心跳聊天系统
功能说明:
- 检查是否已经在运行,避免重复启动
- 初始化关系构建器和表达学习器
- 启动能量管理器和主动思考器
- 创建主聊天循环任务并设置完成回调
- 记录启动完成日志
"""
if self.context.running:
return
self.context.running = True
@@ -64,6 +96,16 @@ class HeartFChatting:
logger.info(f"{self.context.log_prefix} HeartFChatting 启动完成")
async def stop(self):
"""
停止心跳聊天系统
功能说明:
- 检查是否正在运行,避免重复停止
- 设置运行状态为False
- 停止能量管理器和主动思考器
- 取消主聊天循环任务
- 记录停止完成日志
"""
if not self.context.running:
return
self.context.running = False
@@ -77,6 +119,18 @@ class HeartFChatting:
logger.info(f"{self.context.log_prefix} HeartFChatting 已停止")
def _handle_loop_completion(self, task: asyncio.Task):
"""
处理主循环任务完成
Args:
task: 完成的异步任务对象
功能说明:
- 处理任务异常完成的情况
- 区分正常停止和异常终止
- 记录相应的日志信息
- 处理取消任务的情况
"""
try:
if exception := task.exception():
logger.error(f"{self.context.log_prefix} HeartFChatting: 脱离了聊天(异常): {exception}")
@@ -87,6 +141,16 @@ class HeartFChatting:
logger.info(f"{self.context.log_prefix} HeartFChatting: 结束了聊天")
async def _main_chat_loop(self):
"""
主聊天循环
功能说明:
- 持续运行聊天处理循环
- 每次循环调用_loop_body处理消息
- 处理取消和异常情况
- 在异常时尝试重新启动循环
- 记录循环结束日志
"""
try:
while self.context.running:
await self._loop_body()
@@ -101,6 +165,17 @@ class HeartFChatting:
logger.error(f"{self.context.log_prefix} 结束了当前聊天循环")
async def _loop_body(self):
"""
单次循环体处理
功能说明:
- 检查是否处于睡眠模式,如果是则跳过处理
- 获取最近的新消息(过滤机器人自己的消息和命令)
- 更新最后消息时间和读取时间
- 根据当前聊天模式执行不同的处理逻辑
- FOCUS模式直接处理所有消息并检查退出条件
- NORMAL模式检查进入FOCUS模式的条件并通过normal_mode_handler处理消息
"""
if schedule_manager.is_sleeping():
return
@@ -129,6 +204,15 @@ class HeartFChatting:
await self.normal_mode_handler.handle_message(message)
def _check_focus_exit(self):
"""
检查是否应该退出FOCUS模式
功能说明:
- 区分私聊和群聊环境
- 在强制私聊focus模式下能量值低于1时重置为5但不退出
- 在群聊focus模式下如果配置为focus则不退出
- 其他情况下能量值低于1时退出到NORMAL模式
"""
is_private_chat = self.context.chat_stream.group_info is None if self.context.chat_stream else False
is_group_chat = not is_private_chat
@@ -145,6 +229,19 @@ class HeartFChatting:
self.context.loop_mode = ChatMode.NORMAL
def _check_focus_entry(self, new_message_count: int):
"""
检查是否应该进入FOCUS模式
Args:
new_message_count: 新消息数量
功能说明:
- 区分私聊和群聊环境
- 强制私聊focus模式直接进入FOCUS模式并设置能量值为10
- 群聊normal模式不进入FOCUS模式
- 根据focus_value配置和消息数量决定是否进入FOCUS模式
- 当消息数量超过阈值或能量值达到30时进入FOCUS模式
"""
is_private_chat = self.context.chat_stream.group_info is None if self.context.chat_stream else False
is_group_chat = not is_private_chat

View File

@@ -9,6 +9,21 @@ from src.chat.chat_loop.hfc_utils import CycleDetail
class HfcContext:
def __init__(self, chat_id: str):
"""
初始化HFC聊天上下文
Args:
chat_id: 聊天ID标识符
功能说明:
- 存储和管理单个聊天会话的所有状态信息
- 包含聊天流、关系构建器、表达学习器等核心组件
- 管理聊天模式、能量值、时间戳等关键状态
- 提供循环历史记录和当前循环详情的存储
Raises:
ValueError: 如果找不到对应的聊天流
"""
self.stream_id: str = chat_id
self.chat_stream: Optional[ChatStream] = get_chat_manager().get_stream(self.stream_id)
if not self.chat_stream:

View File

@@ -13,9 +13,28 @@ logger = get_logger(__name__)
class CycleDetail:
"""循环信息记录类"""
"""
循环信息记录类
功能说明:
- 记录单次思考循环的详细信息
- 包含循环ID、思考ID、时间戳等基本信息
- 存储循环的规划信息和动作信息
- 提供序列化和转换功能
"""
def __init__(self, cycle_id: int):
"""
初始化循环详情记录
Args:
cycle_id: 循环ID用于标识循环的顺序
功能说明:
- 设置循环基本标识信息
- 初始化时间戳和计时器
- 准备循环信息存储容器
"""
self.cycle_id = cycle_id
self.thinking_id = ""
self.start_time = time.time()
@@ -26,7 +45,18 @@ class CycleDetail:
self.loop_action_info: Dict[str, Any] = {}
def to_dict(self) -> Dict[str, Any]:
"""将循环信息转换为字典格式"""
"""
将循环信息转换为字典格式
Returns:
dict: 包含所有循环信息的字典,已处理循环引用和序列化问题
功能说明:
- 递归转换复杂对象为可序列化格式
- 防止循环引用导致的无限递归
- 限制递归深度避免栈溢出
- 只保留基本数据类型和可序列化的值
"""
def convert_to_serializable(obj, depth=0, seen=None):
if seen is None:
@@ -79,18 +109,36 @@ class CycleDetail:
}
def set_loop_info(self, loop_info: Dict[str, Any]):
"""设置循环信息"""
"""
设置循环信息
Args:
loop_info: 包含循环规划和动作信息的字典
功能说明:
- 从传入的循环信息中提取规划和动作信息
- 更新当前循环详情的相关字段
"""
self.loop_plan_info = loop_info["loop_plan_info"]
self.loop_action_info = loop_info["loop_action_info"]
def get_recent_message_stats(minutes: float = 30, chat_id: Optional[str] = None) -> dict:
"""
获取最近消息统计信息
Args:
minutes (float): 检索的分钟数默认30分钟
chat_id (str, optional): 指定的chat_id仅统计该chat下的消息。为None时统计全部
minutes: 检索的分钟数默认30分钟
chat_id: 指定的chat_id仅统计该chat下的消息。为None时统计全部
Returns:
dict: {"bot_reply_count": int, "total_message_count": int}
功能说明:
- 统计指定时间范围内的消息数量
- 区分机器人回复和总消息数
- 可以针对特定聊天或全局统计
- 用于分析聊天活跃度和机器人参与度
"""
now = time.time()
@@ -112,6 +160,15 @@ def get_recent_message_stats(minutes: float = 30, chat_id: Optional[str] = None)
async def send_typing():
"""
发送打字状态指示
功能说明:
- 创建内心聊天流(用于状态显示)
- 发送typing状态消息
- 不存储到消息记录中
- 用于S4U功能的视觉反馈
"""
group_info = GroupInfo(platform="amaidesu_default", group_id="114514", group_name="内心")
chat = await get_chat_manager().get_or_create_stream(
@@ -125,6 +182,15 @@ async def send_typing():
)
async def stop_typing():
"""
停止打字状态指示
功能说明:
- 创建内心聊天流(用于状态显示)
- 发送stop_typing状态消息
- 不存储到消息记录中
- 结束S4U功能的视觉反馈
"""
group_info = GroupInfo(platform="amaidesu_default", group_id="114514", group_name="内心")
chat = await get_chat_manager().get_or_create_stream(

View File

@@ -13,11 +13,40 @@ 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

View File

@@ -15,6 +15,19 @@ logger = get_logger("hfc.proactive")
class ProactiveThinker:
def __init__(self, context: HfcContext, cycle_processor: "CycleProcessor"):
"""
初始化主动思考器
Args:
context: HFC聊天上下文对象
cycle_processor: 循环处理器,用于执行主动思考的结果
功能说明:
- 管理机器人的主动发言功能
- 根据沉默时间和配置触发主动思考
- 提供私聊和群聊不同的思考提示模板
- 使用3-sigma规则计算动态思考间隔
"""
self.context = context
self.cycle_processor = cycle_processor
self._proactive_thinking_task: Optional[asyncio.Task] = None
@@ -35,18 +48,47 @@ class ProactiveThinker:
}
async def start(self):
"""
启动主动思考器
功能说明:
- 检查运行状态和配置,避免重复启动
- 只有在启用主动思考功能时才启动
- 创建主动思考循环异步任务
- 设置任务完成回调处理
- 记录启动日志
"""
if self.context.running and not self._proactive_thinking_task and global_config.chat.enable_proactive_thinking:
self._proactive_thinking_task = asyncio.create_task(self._proactive_thinking_loop())
self._proactive_thinking_task.add_done_callback(self._handle_proactive_thinking_completion)
logger.info(f"{self.context.log_prefix} 主动思考器已启动")
async def stop(self):
"""
停止主动思考器
功能说明:
- 取消正在运行的主动思考任务
- 等待任务完全停止
- 记录停止日志
"""
if self._proactive_thinking_task and not self._proactive_thinking_task.done():
self._proactive_thinking_task.cancel()
await asyncio.sleep(0)
logger.info(f"{self.context.log_prefix} 主动思考器已停止")
def _handle_proactive_thinking_completion(self, task: asyncio.Task):
"""
处理主动思考任务完成
Args:
task: 完成的异步任务对象
功能说明:
- 处理任务正常完成或异常情况
- 记录相应的日志信息
- 区分取消和异常终止的情况
"""
try:
if exception := task.exception():
logger.error(f"{self.context.log_prefix} 主动思考循环异常: {exception}")
@@ -56,6 +98,17 @@ class ProactiveThinker:
logger.info(f"{self.context.log_prefix} 主动思考循环被取消")
async def _proactive_thinking_loop(self):
"""
主动思考的主循环
功能说明:
- 每15秒检查一次是否需要主动思考
- 只在FOCUS模式下进行主动思考
- 检查是否启用主动思考功能
- 计算沉默时间并与动态间隔比较
- 达到条件时执行主动思考并更新最后消息时间
- 处理执行过程中的异常
"""
while self.context.running:
await asyncio.sleep(15)
@@ -79,6 +132,19 @@ class ProactiveThinker:
logger.error(traceback.format_exc())
def _should_enable_proactive_thinking(self) -> bool:
"""
检查是否应该启用主动思考
Returns:
bool: 如果应该启用主动思考则返回True
功能说明:
- 检查聊天流是否存在
- 检查当前聊天是否在启用列表中(如果配置了列表)
- 根据聊天类型(群聊/私聊)和配置决定是否启用
- 群聊需要proactive_thinking_in_group为True
- 私聊需要proactive_thinking_in_private为True
"""
if not self.context.chat_stream:
return False
@@ -101,6 +167,19 @@ class ProactiveThinker:
return True
def _get_dynamic_thinking_interval(self) -> float:
"""
获取动态思考间隔
Returns:
float: 计算得出的思考间隔时间(秒)
功能说明:
- 使用3-sigma规则计算正态分布的思考间隔
- 基于base_interval和delta_sigma配置计算
- 处理特殊情况为0或负数的配置
- 如果timing_utils不可用则使用固定间隔
- 间隔范围被限制在1秒到86400秒1天之间
"""
try:
from src.utils.timing_utils import get_normal_distributed_interval
@@ -131,6 +210,21 @@ class ProactiveThinker:
return max(300, abs(global_config.chat.proactive_thinking_interval))
def _format_duration(self, seconds: float) -> str:
"""
格式化持续时间为中文描述
Args:
seconds: 持续时间(秒)
Returns:
str: 格式化后的时间字符串,如"1小时30分45秒"
功能说明:
- 将秒数转换为小时、分钟、秒的组合
- 只显示非零的时间单位
- 如果所有单位都为0则显示"0秒"
- 用于主动思考日志的时间显示
"""
hours = int(seconds // 3600)
minutes = int((seconds % 3600) // 60)
secs = int(seconds % 60)
@@ -146,6 +240,19 @@ class ProactiveThinker:
return "".join(parts)
async def _execute_proactive_thinking(self, silence_duration: float):
"""
执行主动思考
Args:
silence_duration: 沉默持续时间(秒)
功能说明:
- 格式化沉默时间并记录触发日志
- 获取适当的思考提示模板
- 创建主动思考类型的消息数据
- 调用循环处理器执行思考和可能的回复
- 处理执行过程中的异常
"""
formatted_time = self._format_duration(silence_duration)
logger.info(f"{self.context.log_prefix} 触发主动思考,已沉默{formatted_time}")
@@ -172,6 +279,21 @@ class ProactiveThinker:
logger.error(traceback.format_exc())
def _get_proactive_prompt(self, formatted_time: str) -> str:
"""
获取主动思考的提示模板
Args:
formatted_time: 格式化后的沉默时间字符串
Returns:
str: 填充了时间信息的提示模板
功能说明:
- 优先使用自定义的提示模板(如果配置了)
- 根据聊天类型(群聊/私聊)选择默认模板
- 将格式化的时间信息填入模板
- 返回完整的主动思考提示文本
"""
if hasattr(global_config.chat, 'proactive_thinking_prompt_template') and global_config.chat.proactive_thinking_prompt_template.strip():
return global_config.chat.proactive_thinking_prompt_template.format(time=formatted_time)

View File

@@ -13,6 +13,17 @@ logger = get_logger("hfc.response")
class ResponseHandler:
def __init__(self, context: HfcContext):
"""
初始化响应处理器
Args:
context: HFC聊天上下文对象
功能说明:
- 负责生成和发送机器人的回复
- 处理回复的格式化和发送逻辑
- 管理回复状态和日志记录
"""
self.context = context
async def generate_and_send_reply(
@@ -25,6 +36,27 @@ class ResponseHandler:
thinking_id,
plan_result,
) -> Tuple[Dict[str, Any], str, Dict[str, float]]:
"""
生成并发送回复的主方法
Args:
response_set: 生成的回复内容集合
reply_to_str: 回复目标字符串
loop_start_time: 循环开始时间
action_message: 动作消息数据
cycle_timers: 循环计时器
thinking_id: 思考ID
plan_result: 规划结果
Returns:
tuple: (循环信息, 回复文本, 计时器信息)
功能说明:
- 发送生成的回复内容
- 存储动作信息到数据库
- 构建并返回完整的循环信息
- 用于上级方法的状态跟踪
"""
reply_text = await self._send_response(response_set, reply_to_str, loop_start_time, action_message)
person_info_manager = get_person_info_manager()
@@ -65,6 +97,25 @@ class ResponseHandler:
return loop_info, reply_text, cycle_timers
async def _send_response(self, reply_set, reply_to, thinking_start_time, message_data) -> str:
"""
发送回复内容的具体实现
Args:
reply_set: 回复内容集合,包含多个回复段
reply_to: 回复目标
thinking_start_time: 思考开始时间
message_data: 消息数据
Returns:
str: 完整的回复文本
功能说明:
- 检查是否有新消息需要回复
- 处理主动思考的"沉默"决定
- 根据消息数量决定是否添加回复引用
- 逐段发送回复内容,支持打字效果
- 正确处理元组格式的回复段
"""
current_time = time.time()
new_message_count = message_api.count_new_messages(
chat_id=self.context.stream_id, start_time=thinking_start_time, end_time=current_time
@@ -131,6 +182,24 @@ class ResponseHandler:
reply_to: str,
request_type: str = "chat.replyer.normal",
) -> Optional[list]:
"""
生成回复内容
Args:
message_data: 消息数据
available_actions: 可用动作列表
reply_to: 回复目标
request_type: 请求类型,默认为普通回复
Returns:
list: 生成的回复内容列表失败时返回None
功能说明:
- 调用生成器API生成回复
- 根据配置启用或禁用工具功能
- 处理生成失败的情况
- 记录生成过程中的错误和异常
"""
try:
success, reply_set, _ = await generator_api.generate_reply(
chat_stream=self.context.chat_stream,