Merge branch 'dev' of https://github.com/MoFox-Studio/MoFox_Bot into dev
This commit is contained in:
@@ -127,7 +127,7 @@ class ChatterActionPlanner:
|
||||
}
|
||||
)
|
||||
|
||||
logger.debug(
|
||||
logger.info(
|
||||
f"消息 {message.message_id} 兴趣度: {message_interest:.3f}, 应回复: {message.should_reply}"
|
||||
)
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ logger = get_logger(__name__)
|
||||
class ProactiveThinkerPlugin(BasePlugin):
|
||||
"""一个主动思考的插件,但现在还只是个空壳子"""
|
||||
plugin_name: str = "proactive_thinker"
|
||||
enable_plugin: bool = True
|
||||
enable_plugin: bool = False
|
||||
dependencies: list[str] = []
|
||||
python_dependencies: list[str] = []
|
||||
config_file_name: str = "config.toml"
|
||||
|
||||
@@ -1,23 +1,220 @@
|
||||
import asyncio
|
||||
import random
|
||||
import time
|
||||
from datetime import datetime
|
||||
from typing import List, Union, Type, Optional
|
||||
|
||||
from maim_message import UserInfo
|
||||
|
||||
from src.chat.message_receive.chat_stream import get_chat_manager
|
||||
from src.common.logger import get_logger
|
||||
from src.config.config import global_config
|
||||
from src.manager.async_task_manager import async_task_manager, AsyncTask
|
||||
from src.plugin_system import EventType, BaseEventHandler
|
||||
from src.plugin_system.apis import chat_api, person_api
|
||||
from src.plugin_system.base.base_event import HandlerResult
|
||||
from .proactive_thinker_executor import ProactiveThinkerExecutor
|
||||
|
||||
logger = get_logger(__name__)
|
||||
from src.plugin_system import (
|
||||
EventType,
|
||||
BaseEventHandler,
|
||||
HandlerResult,
|
||||
)
|
||||
|
||||
|
||||
class ColdStartTask(AsyncTask):
|
||||
"""
|
||||
冷启动任务,专门用于处理那些在白名单里,但从未与机器人发生过交互的用户。
|
||||
它的核心职责是“破冰”,主动创建聊天流并发起第一次问候。
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(task_name="ColdStartTask")
|
||||
self.chat_manager = get_chat_manager()
|
||||
self.executor = ProactiveThinkerExecutor()
|
||||
|
||||
async def run(self):
|
||||
"""任务主循环,周期性地检查是否有需要“破冰”的新用户。"""
|
||||
logger.info("冷启动任务已启动,将周期性检查白名单中的新朋友。")
|
||||
# 初始等待一段时间,确保其他服务(如数据库)完全启动
|
||||
await asyncio.sleep(20)
|
||||
|
||||
while True:
|
||||
try:
|
||||
logger.info("【冷启动】开始扫描白名单,寻找从未聊过的用户...")
|
||||
|
||||
# 从全局配置中获取私聊白名单
|
||||
enabled_private_chats = global_config.proactive_thinking.enabled_private_chats
|
||||
if not enabled_private_chats:
|
||||
logger.debug("【冷启动】私聊白名单为空,任务暂停一小时。")
|
||||
await asyncio.sleep(3600) # 白名单为空时,没必要频繁检查
|
||||
continue
|
||||
|
||||
# 遍历白名单中的每一个用户
|
||||
for chat_id in enabled_private_chats:
|
||||
try:
|
||||
platform, user_id_str = chat_id.split(":")
|
||||
user_id = int(user_id_str)
|
||||
|
||||
# 【核心逻辑】使用 chat_api 检查该用户是否已经存在聊天流(ChatStream)
|
||||
# 如果返回了 ChatStream 对象,说明已经聊过天了,不是本次任务的目标
|
||||
if chat_api.get_stream_by_user_id(user_id_str, platform):
|
||||
continue # 跳过已存在的用户
|
||||
|
||||
logger.info(f"【冷启动】发现白名单新用户 {chat_id},准备发起第一次问候。")
|
||||
|
||||
# 【增强体验】尝试从关系数据库中获取该用户的昵称
|
||||
# 这样打招呼时可以更亲切,而不是只知道一个冷冰冰的ID
|
||||
person_id = person_api.get_person_id(platform, user_id)
|
||||
nickname = await person_api.get_person_value(person_id, "nickname")
|
||||
|
||||
# 如果数据库里有昵称,就用数据库里的;如果没有,就用 "用户+ID" 作为备用
|
||||
user_nickname = nickname or f"用户{user_id}"
|
||||
|
||||
# 创建 UserInfo 对象,这是创建聊天流的必要信息
|
||||
user_info = UserInfo(platform=platform, user_id=str(user_id), user_nickname=user_nickname)
|
||||
|
||||
# 【关键步骤】主动创建聊天流。
|
||||
# 创建后,该用户就进入了机器人的“好友列表”,后续将由 ProactiveThinkingTask 接管
|
||||
stream = await self.chat_manager.get_or_create_stream(platform, user_info)
|
||||
|
||||
await self.executor.execute(stream_id=stream.stream_id, start_mode="cold_start")
|
||||
logger.info(f"【冷启动】已为新用户 {chat_id} (昵称: {user_nickname}) 创建聊天流并发送问候。")
|
||||
|
||||
except ValueError:
|
||||
logger.warning(f"【冷启动】白名单条目格式错误或用户ID无效,已跳过: {chat_id}")
|
||||
except Exception as e:
|
||||
logger.error(f"【冷启动】处理用户 {chat_id} 时发生未知错误: {e}", exc_info=True)
|
||||
|
||||
# 完成一轮检查后,进入长时休眠
|
||||
await asyncio.sleep(3600)
|
||||
|
||||
except asyncio.CancelledError:
|
||||
logger.info("冷启动任务被正常取消。")
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error(f"【冷启动】任务出现严重错误,将在5分钟后重试: {e}", exc_info=True)
|
||||
await asyncio.sleep(300)
|
||||
|
||||
|
||||
class ProactiveThinkingTask(AsyncTask):
|
||||
"""
|
||||
主动思考的后台任务(日常唤醒),负责在聊天“冷却”后重新活跃气氛。
|
||||
它只处理已经存在的聊天流。
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(task_name="ProactiveThinkingTask")
|
||||
self.chat_manager = get_chat_manager()
|
||||
self.executor = ProactiveThinkerExecutor()
|
||||
|
||||
def _get_next_interval(self) -> float:
|
||||
"""
|
||||
动态计算下一次执行的时间间隔,模拟人类行为的随机性。
|
||||
结合了基础间隔、随机偏移和每日不同时段的活跃度调整。
|
||||
"""
|
||||
# 从配置中读取基础间隔和随机范围
|
||||
base_interval = global_config.proactive_thinking.interval
|
||||
sigma = global_config.proactive_thinking.interval_sigma
|
||||
|
||||
# 1. 在 [base - sigma, base + sigma] 范围内随机取一个值
|
||||
interval = random.uniform(base_interval - sigma, base_interval + sigma)
|
||||
|
||||
# 2. 根据当前时间,应用活跃度调整因子
|
||||
now = datetime.now()
|
||||
current_time_str = now.strftime("%H:%M")
|
||||
|
||||
adjust_rules = global_config.proactive_thinking.talk_frequency_adjust
|
||||
if adjust_rules and adjust_rules[0]:
|
||||
# 按时间对规则排序,确保能找到正确的时间段
|
||||
rules = sorted([rule.split(",") for rule in adjust_rules[0][1:]], key=lambda x: x[0])
|
||||
|
||||
factor = 1.0
|
||||
# 找到最后一个小于等于当前时间的规则
|
||||
for time_str, factor_str in rules:
|
||||
if current_time_str >= time_str:
|
||||
factor = float(factor_str)
|
||||
else:
|
||||
break # 后面的时间都比当前晚,无需再找
|
||||
# factor > 1 表示更活跃,所以用除法来缩短间隔
|
||||
interval /= factor
|
||||
|
||||
# 保证最小间隔,防止过于频繁的骚扰
|
||||
return max(60.0, interval)
|
||||
|
||||
async def run(self):
|
||||
"""任务主循环,周期性地检查所有已存在的聊天是否需要“唤醒”。"""
|
||||
logger.info("日常唤醒任务已启动,将根据动态间隔检查聊天活跃度。")
|
||||
await asyncio.sleep(15) # 初始等待
|
||||
|
||||
while True:
|
||||
# 计算下一次检查前的休眠时间
|
||||
next_interval = self._get_next_interval()
|
||||
try:
|
||||
logger.debug(f"【日常唤醒】下一次检查将在 {next_interval:.2f} 秒后进行。")
|
||||
await asyncio.sleep(next_interval)
|
||||
|
||||
logger.info("【日常唤醒】开始检查不活跃的聊天...")
|
||||
|
||||
# 加载白名单配置
|
||||
enabled_private = set(global_config.proactive_thinking.enabled_private_chats)
|
||||
enabled_groups = set(global_config.proactive_thinking.enabled_group_chats)
|
||||
|
||||
# 获取当前所有聊天流的快照
|
||||
all_streams = list(self.chat_manager.streams.values())
|
||||
|
||||
for stream in all_streams:
|
||||
# 1. 检查该聊天是否在白名单内(或白名单为空时默认允许)
|
||||
is_whitelisted = False
|
||||
if stream.group_info: # 群聊
|
||||
if not enabled_groups or f"qq:{stream.group_info.group_id}" in enabled_groups:
|
||||
is_whitelisted = True
|
||||
else: # 私聊
|
||||
if not enabled_private or f"qq:{stream.user_info.user_id}" in enabled_private:
|
||||
is_whitelisted = True
|
||||
|
||||
if not is_whitelisted:
|
||||
continue # 不在白名单内,跳过
|
||||
|
||||
# 2. 【核心逻辑】检查聊天冷却时间是否足够长
|
||||
time_since_last_active = time.time() - stream.last_active_time
|
||||
if time_since_last_active > next_interval:
|
||||
logger.info(f"【日常唤醒】聊天流 {stream.stream_id} 已冷却 {time_since_last_active:.2f} 秒,触发主动对话。")
|
||||
|
||||
await self.executor.execute(stream_id=stream.stream_id, start_mode="wake_up")
|
||||
|
||||
# 【关键步骤】在触发后,立刻更新活跃时间并保存。
|
||||
# 这可以防止在同一个检查周期内,对同一个目标因为意外的延迟而发送多条消息。
|
||||
stream.update_active_time()
|
||||
await self.chat_manager._save_stream(stream)
|
||||
|
||||
except asyncio.CancelledError:
|
||||
logger.info("日常唤醒任务被正常取消。")
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error(f"【日常唤醒】任务出现错误,将在60秒后重试: {e}", exc_info=True)
|
||||
await asyncio.sleep(60)
|
||||
|
||||
|
||||
class ProactiveThinkerEventHandler(BaseEventHandler):
|
||||
"""主动思考需要的启动时触发的事件处理器"""
|
||||
"""主动思考插件的启动事件处理器,负责根据配置启动一个或两个后台任务。"""
|
||||
|
||||
handler_name: str = "proactive_thinker_on_start"
|
||||
handler_description: str = "主动思考插件的启动事件处理器"
|
||||
init_subscribe: List[Union[EventType, str]] = [EventType.ON_START]
|
||||
|
||||
async def execute(self, kwargs: dict | None) -> "HandlerResult":
|
||||
"""执行事件处理"""
|
||||
logger.info("ProactiveThinkerPlugin on_start event triggered.")
|
||||
# 返回 (是否执行成功, 是否需要继续处理, 可选的返回消息)
|
||||
"""在机器人启动时执行,根据配置决定是否启动后台任务。"""
|
||||
logger.info("检测到插件启动事件,正在初始化【主动思考】插件...")
|
||||
# 检查总开关
|
||||
if global_config.proactive_thinking.enable:
|
||||
# 启动负责“日常唤醒”的核心任务
|
||||
logger.info("【主动思考】功能已启用,正在启动“日常唤醒”任务...")
|
||||
proactive_task = ProactiveThinkingTask()
|
||||
await async_task_manager.add_task(proactive_task)
|
||||
|
||||
# 检查“冷启动”功能的独立开关
|
||||
if global_config.proactive_thinking.enable_cold_start:
|
||||
logger.info("“冷启动”功能已启用,正在启动“破冰”任务...")
|
||||
cold_start_task = ColdStartTask()
|
||||
await async_task_manager.add_task(cold_start_task)
|
||||
|
||||
else:
|
||||
logger.info("【主动思考】功能未启用,所有任务均跳过启动。")
|
||||
return HandlerResult(success=True, continue_process=True, message=None)
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
import orjson
|
||||
from typing import Optional, Dict, Any
|
||||
from datetime import datetime
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system.apis import chat_api, person_api, schedule_api, send_api, llm_api, message_api, generator_api, database_api
|
||||
from src.config.config import global_config, model_config
|
||||
from src.person_info.person_info import get_person_info_manager
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
class ProactiveThinkerExecutor:
|
||||
"""
|
||||
主动思考执行器 V2
|
||||
- 统一执行入口
|
||||
- 引入决策模块,判断是否及如何发起对话
|
||||
- 结合人设、日程、关系信息生成更具情境的对话
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# 可以在此初始化所需模块,例如LLM请求器等
|
||||
pass
|
||||
|
||||
async def execute(self, stream_id: str, start_mode: str = "wake_up"):
|
||||
"""
|
||||
统一执行入口
|
||||
Args:
|
||||
stream_id: 聊天流ID
|
||||
start_mode: 启动模式, 'cold_start' 或 'wake_up'
|
||||
"""
|
||||
logger.info(f"开始为聊天流 {stream_id} 执行主动思考,模式: {start_mode}")
|
||||
|
||||
# 1. 信息收集
|
||||
context = await self._gather_context(stream_id)
|
||||
if not context:
|
||||
return
|
||||
|
||||
# 2. 决策阶段
|
||||
decision_result = await self._make_decision(context, start_mode)
|
||||
|
||||
|
||||
if not decision_result or not decision_result.get("should_reply"):
|
||||
reason = decision_result.get("reason", "未提供") if decision_result else "决策过程返回None"
|
||||
logger.info(f"决策结果为:不回复。原因: {reason}")
|
||||
await database_api.store_action_info(
|
||||
chat_stream=self._get_stream_from_id(stream_id),
|
||||
action_name="proactive_decision",
|
||||
action_prompt_display=f"主动思考决定不回复,原因: {reason}",
|
||||
action_done = True,
|
||||
action_data=decision_result
|
||||
)
|
||||
return
|
||||
|
||||
# 3. 规划与执行阶段
|
||||
topic = decision_result.get("topic", "打个招呼")
|
||||
reason = decision_result.get("reason", "无")
|
||||
await database_api.store_action_info(
|
||||
chat_stream=self._get_stream_from_id(stream_id),
|
||||
action_name="proactive_decision",
|
||||
action_prompt_display=f"主动思考决定回复,原因: {reason},话题:{topic}",
|
||||
action_done = True,
|
||||
action_data=decision_result
|
||||
)
|
||||
logger.info(f"决策结果为:回复。话题: {topic}")
|
||||
|
||||
plan_prompt = self._build_plan_prompt(context, start_mode, topic, reason)
|
||||
|
||||
is_success, response, _, _ = await llm_api.generate_with_model(prompt=plan_prompt, model_config=model_config.model_task_config.utils)
|
||||
|
||||
if is_success and response:
|
||||
stream = self._get_stream_from_id(stream_id)
|
||||
if stream:
|
||||
# 使用消息分割器处理并发送消息
|
||||
reply_set = generator_api.process_human_text(response, enable_splitter=True, enable_chinese_typo=False)
|
||||
for reply_type, content in reply_set:
|
||||
if reply_type == "text":
|
||||
await send_api.text_to_stream(stream_id=stream.stream_id, text=content)
|
||||
else:
|
||||
logger.warning(f"无法发送消息,因为找不到 stream_id 为 {stream_id} 的聊天流")
|
||||
|
||||
def _get_stream_from_id(self, stream_id: str):
|
||||
"""根据stream_id解析并获取stream对象"""
|
||||
try:
|
||||
platform, chat_id, stream_type = stream_id.split(":")
|
||||
if stream_type == "private":
|
||||
return chat_api.ChatManager.get_private_stream_by_user_id(platform, chat_id)
|
||||
elif stream_type == "group":
|
||||
return chat_api.ChatManager.get_group_stream_by_group_id(platform, chat_id)
|
||||
except Exception as e:
|
||||
logger.error(f"解析 stream_id ({stream_id}) 或获取 stream 失败: {e}")
|
||||
return None
|
||||
|
||||
async def _gather_context(self, stream_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
收集构建提示词所需的所有上下文信息
|
||||
"""
|
||||
stream = self._get_stream_from_id(stream_id)
|
||||
if not stream:
|
||||
logger.warning(f"无法找到 stream_id 为 {stream_id} 的聊天流")
|
||||
return None
|
||||
|
||||
user_info = stream.user_info
|
||||
if not user_info or not user_info.platform or not user_info.user_id:
|
||||
logger.warning(f"Stream {stream_id} 的 user_info 不完整")
|
||||
return None
|
||||
|
||||
person_id = person_api.get_person_id(user_info.platform, int(user_info.user_id))
|
||||
person_info_manager = get_person_info_manager()
|
||||
|
||||
# 获取日程
|
||||
schedules = await schedule_api.ScheduleAPI.get_today_schedule()
|
||||
schedule_context = "\n".join([f"- {s['title']} ({s['start_time']}-{s['end_time']})" for s in schedules]) if schedules else "今天没有日程安排。"
|
||||
|
||||
# 获取关系信息
|
||||
short_impression = await person_info_manager.get_value(person_id, "short_impression") or "无"
|
||||
impression = await person_info_manager.get_value(person_id, "impression") or "无"
|
||||
attitude = await person_info_manager.get_value(person_id, "attitude") or 50
|
||||
|
||||
# 获取最近聊天记录
|
||||
recent_messages = await message_api.get_recent_messages(stream_id, limit=10)
|
||||
recent_chat_history = await message_api.build_readable_messages_to_str(recent_messages) if recent_messages else "无"
|
||||
|
||||
# 获取最近的动作历史
|
||||
action_history = await database_api.db_query(
|
||||
database_api.MODEL_MAPPING["ActionRecords"],
|
||||
filters={"chat_id": stream_id, "action_name": "proactive_decision"},
|
||||
limit=3,
|
||||
order_by=["-time"]
|
||||
)
|
||||
action_history_context = "无"
|
||||
if isinstance(action_history, list):
|
||||
action_history_context = "\n".join([f"- {a['action_data']}" for a in action_history if isinstance(a, dict)]) or "无"
|
||||
|
||||
return {
|
||||
"person_id": person_id,
|
||||
"user_info": user_info,
|
||||
"schedule_context": schedule_context,
|
||||
"recent_chat_history": recent_chat_history,
|
||||
"action_history_context": action_history_context,
|
||||
"relationship": {
|
||||
"short_impression": short_impression,
|
||||
"impression": impression,
|
||||
"attitude": attitude
|
||||
},
|
||||
"persona": {
|
||||
"core": global_config.personality.personality_core,
|
||||
"side": global_config.personality.personality_side,
|
||||
"identity": global_config.personality.identity,
|
||||
},
|
||||
"current_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
}
|
||||
|
||||
async def _make_decision(self, context: Dict[str, Any], start_mode: str) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
决策模块:判断是否应该主动发起对话,以及聊什么话题
|
||||
"""
|
||||
persona = context['persona']
|
||||
user_info = context['user_info']
|
||||
relationship = context['relationship']
|
||||
|
||||
prompt = f"""
|
||||
# 角色
|
||||
你的名字是{global_config.bot.nickname},你的人设如下:
|
||||
- 核心人设: {persona['core']}
|
||||
- 侧面人设: {persona['side']}
|
||||
- 身份: {persona['identity']}
|
||||
|
||||
# 任务
|
||||
现在是 {context['current_time']},你需要根据当前的情境,决定是否要主动向用户 '{user_info.user_nickname}' 发起对话。
|
||||
|
||||
# 情境分析
|
||||
1. **启动模式**: {start_mode} ({'初次见面/很久未见' if start_mode == 'cold_start' else '日常唤醒'})
|
||||
2. **你的日程**:
|
||||
{context['schedule_context']}
|
||||
3. **你和Ta的关系**:
|
||||
- 简短印象: {relationship['short_impression']}
|
||||
- 详细印象: {relationship['impression']}
|
||||
- 好感度: {relationship['attitude']}/100
|
||||
4. **最近的聊天摘要**:
|
||||
{context['recent_chat_history']}
|
||||
|
||||
# 决策指令
|
||||
请综合以上所有信息,做出决策。你的决策需要以JSON格式输出,包含以下字段:
|
||||
- `should_reply`: bool, 是否应该发起对话。
|
||||
- `topic`: str, 如果 `should_reply` 为 true,你打算聊什么话题?(例如:问候一下今天的日程、关心一下昨天的某件事、分享一个你自己的趣事等)
|
||||
- `reason`: str, 做出此决策的简要理由。
|
||||
|
||||
---
|
||||
示例1 (应该回复):
|
||||
{{
|
||||
"should_reply": true,
|
||||
"topic": "提醒Ta今天下午有'项目会议'的日程",
|
||||
"reason": "现在是上午,Ta下午有个重要会议,我觉得应该主动提醒一下,这会显得我很贴心。"
|
||||
}}
|
||||
|
||||
示例2 (不应回复):
|
||||
{{
|
||||
"should_reply": false,
|
||||
"topic": null,
|
||||
"reason": "虽然我们的关系不错,但现在是深夜,而且Ta今天的日程都已经完成了,我没有合适的理由去打扰Ta。"
|
||||
}}
|
||||
---
|
||||
|
||||
请输出你的决策:
|
||||
"""
|
||||
|
||||
is_success, response, _, _ = await llm_api.generate_with_model(prompt=prompt, model_config=model_config.model_task_config.utils)
|
||||
|
||||
if not is_success:
|
||||
return {"should_reply": False, "reason": "决策模型生成失败"}
|
||||
|
||||
try:
|
||||
# 假设LLM返回JSON格式的决策结果
|
||||
decision = orjson.loads(response)
|
||||
return decision
|
||||
except orjson.JSONDecodeError:
|
||||
logger.error(f"决策LLM返回的JSON格式无效: {response}")
|
||||
return {"should_reply": False, "reason": "决策模型返回格式错误"}
|
||||
|
||||
def _build_plan_prompt(self, context: Dict[str, Any], start_mode: str, topic: str, reason: str) -> str:
|
||||
"""
|
||||
根据启动模式和决策话题,构建最终的规划提示词
|
||||
"""
|
||||
persona = context['persona']
|
||||
user_info = context['user_info']
|
||||
relationship = context['relationship']
|
||||
|
||||
if start_mode == "cold_start":
|
||||
prompt = f"""
|
||||
# 角色
|
||||
你的名字是{global_config.bot.nickname},你的人设如下:
|
||||
- 核心人设: {persona['core']}
|
||||
- 侧面人设: {persona['side']}
|
||||
- 身份: {persona['identity']}
|
||||
|
||||
# 任务
|
||||
你需要主动向一个新朋友 '{user_info.user_nickname}' 发起对话。这是你们的第一次交流,或者很久没聊了。
|
||||
|
||||
# 决策上下文
|
||||
- **决策理由**: {reason}
|
||||
- **你和Ta的关系**:
|
||||
- 简短印象: {relationship['short_impression']}
|
||||
- 详细印象: {relationship['impression']}
|
||||
- 好感度: {relationship['attitude']}/100
|
||||
|
||||
# 对话指引
|
||||
- 你的目标是“破冰”,让对话自然地开始。
|
||||
- 你应该围绕这个话题展开: {topic}
|
||||
- 你的语气应该符合你的人设,友好且真诚。
|
||||
- 直接输出你要说的第一句话,不要包含任何额外的前缀或解释。
|
||||
"""
|
||||
else: # wake_up
|
||||
prompt = f"""
|
||||
# 角色
|
||||
你的名字是{global_config.bot.nickname},你的人设如下:
|
||||
- 核心人设: {persona['core']}
|
||||
- 侧面人设: {persona['side']}
|
||||
- 身份: {persona['identity']}
|
||||
|
||||
# 任务
|
||||
现在是 {context['current_time']},你需要主动向你的朋友 '{user_info.user_nickname}' 发起对话。
|
||||
|
||||
# 决策上下文
|
||||
- **决策理由**: {reason}
|
||||
|
||||
# 情境分析
|
||||
1. **你的日程**:
|
||||
{context['schedule_context']}
|
||||
2. **你和Ta的关系**:
|
||||
- 详细印象: {relationship['impression']}
|
||||
- 好感度: {relationship['attitude']}/100
|
||||
3. **最近的聊天摘要**:
|
||||
{context['recent_chat_history']}
|
||||
4. **你最近的相关动作**:
|
||||
{context['action_history_context']}
|
||||
|
||||
# 对话指引
|
||||
- 你决定和Ta聊聊关于“{topic}”的话题。
|
||||
- 请结合以上所有情境信息,自然地开启对话。
|
||||
- 你的语气应该符合你的人设以及你对Ta的好感度。
|
||||
- 直接输出你要说的第一句话,不要包含任何额外的前缀或解释。
|
||||
"""
|
||||
return prompt
|
||||
@@ -319,7 +319,7 @@ class SetEmojiLikeAction(BaseAction):
|
||||
|
||||
try:
|
||||
success = await self.send_command(
|
||||
command_name="set_msg_emoji_like",
|
||||
command_name="set_emoji_like",
|
||||
args={"message_id": message_id, "emoji_id": emoji_id, "set": set_like},
|
||||
storage_message=False,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user