feat(core): 实现消息异步处理并引入LLM驱动的智能表情回应
本次更新对系统核心处理流程和插件功能进行了重要升级,主要包含以下两方面:
1. **消息处理异步化**:
- 在 `main.py` 中引入了 `asyncio.create_task` 机制,将每条消息的处理过程包装成一个独立的后台任务。
- 这解决了长时间运行的AI或插件操作可能阻塞主事件循环的问题,显著提升了机器人的响应速度和系统稳定性。
- 为后台任务添加了完成回调,现在可以详细地记录每个消息处理任务的成功、失败或取消状态及其耗时,便于监控和调试。
2. **`set_emoji_like` 插件智能化**:
- 为 `set_emoji_like` 插件增加了LLM驱动的表情选择功能。当动作指令未指定具体表情时,插件会自动构建包含聊天上下文、情绪和人设的提示,请求LLM选择一个最合适的表情进行回应。
- 为支持此功能,对AFC规划器的提示词进行了优化,为LLM提供了更清晰的参数示例和规则,提高了动作生成的准确性。
此外,为了统一日志规范,将 `[所见]` 消息接收日志集中到 `bot.py` 中,确保在任何过滤逻辑执行前记录所有收到的消息,并移除了插件中重复的日志。
This commit is contained in:
@@ -64,10 +64,6 @@ class AffinityChatter(BaseChatter):
|
||||
try:
|
||||
unread_messages = context.get_unread_messages()
|
||||
|
||||
# 像hfc一样,打印收到的消息
|
||||
for msg in unread_messages:
|
||||
logger.info(f"{SOFT_GREEN}[所见] {msg.user_info.user_nickname}:{msg.processed_plain_text}{RESET_COLOR}")
|
||||
|
||||
# 使用增强版规划器处理消息
|
||||
actions, target_message = await self.planner.plan(context=context)
|
||||
self.stats["plans_created"] += 1
|
||||
|
||||
@@ -5,6 +5,7 @@ PlanFilter: 接收 Plan 对象,根据不同模式的逻辑进行筛选,决
|
||||
import orjson
|
||||
import time
|
||||
import traceback
|
||||
import re
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
@@ -430,8 +431,12 @@ class ChatterPlanFilter:
|
||||
continue
|
||||
|
||||
action = single_action_obj.get("action_type", "no_action")
|
||||
reasoning = single_action_obj.get("reason", "未提供原因")
|
||||
action_data = {k: v for k, v in single_action_obj.items() if k not in ["action_type", "reason"]}
|
||||
reasoning = single_action_obj.get("reasoning", "未提供原因") # 兼容旧的reason字段
|
||||
action_data = single_action_obj.get("action_data", {})
|
||||
|
||||
# 为了向后兼容,如果action_data不存在,则从顶层字段获取
|
||||
if not action_data:
|
||||
action_data = {k: v for k, v in single_action_obj.items() if k not in ["action_type", "reason", "reasoning", "thinking"]}
|
||||
|
||||
# 保留原始的thinking字段(如果有)
|
||||
thinking = action_json.get("thinking", "")
|
||||
@@ -536,7 +541,13 @@ class ChatterPlanFilter:
|
||||
if action_info.action_parameters:
|
||||
for p_name, p_desc in action_info.action_parameters.items():
|
||||
# 为参数描述添加一个通用示例值
|
||||
example_value = f"<{p_desc}>"
|
||||
if action_name == "set_emoji_like" and p_name == "emoji":
|
||||
# 特殊处理set_emoji_like的emoji参数
|
||||
from plugins.set_emoji_like.qq_emoji_list import qq_face
|
||||
emoji_options = [re.search(r"\[表情:(.+?)\]", name).group(1) for name in qq_face.values() if re.search(r"\[表情:(.+?)\]", name)]
|
||||
example_value = f"<从'{', '.join(emoji_options[:10])}...'中选择一个>"
|
||||
else:
|
||||
example_value = f"<{p_desc}>"
|
||||
params_json_list.append(f' "{p_name}": "{example_value}"')
|
||||
|
||||
# 基础动作信息
|
||||
|
||||
@@ -88,6 +88,7 @@ def init_prompts():
|
||||
|
||||
**强制规则**:
|
||||
- 对于每一个需要目标消息的动作(如`reply`, `poke_user`, `set_emoji_like`),你 **必须** 在`action_data`中提供准确的`target_message_id`,这个ID来源于`## 未读历史消息`中消息前的`<m...>`标签。
|
||||
- 当你选择的动作需要参数时(例如 `set_emoji_like` 需要 `emoji` 参数),你 **必须** 在 `action_data` 中提供所有必需的参数及其对应的值。
|
||||
|
||||
如果没有合适的回复对象或不需要回复,输出空的 actions 数组:
|
||||
```json
|
||||
|
||||
Reference in New Issue
Block a user