better:更新PFC,现可拥有多目标以及其他优化
This commit is contained in:
@@ -21,12 +21,15 @@ logger = get_module_logger("heartflow", config=heartflow_config)
|
|||||||
|
|
||||||
class CurrentState:
|
class CurrentState:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.willing = 0
|
|
||||||
self.current_state_info = ""
|
self.current_state_info = ""
|
||||||
|
|
||||||
self.mood_manager = MoodManager()
|
self.mood_manager = MoodManager()
|
||||||
self.mood = self.mood_manager.get_prompt()
|
self.mood = self.mood_manager.get_prompt()
|
||||||
|
|
||||||
|
self.attendance_factor = 0
|
||||||
|
self.engagement_factor = 0
|
||||||
|
|
||||||
def update_current_state_info(self):
|
def update_current_state_info(self):
|
||||||
self.current_state_info = self.mood_manager.get_current_mood()
|
self.current_state_info = self.mood_manager.get_current_mood()
|
||||||
|
|
||||||
@@ -41,7 +44,9 @@ class Heartflow:
|
|||||||
)
|
)
|
||||||
|
|
||||||
self._subheartflows: Dict[Any, SubHeartflow] = {}
|
self._subheartflows: Dict[Any, SubHeartflow] = {}
|
||||||
self.active_subheartflows_nums = 0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def _cleanup_inactive_subheartflows(self):
|
async def _cleanup_inactive_subheartflows(self):
|
||||||
"""定期清理不活跃的子心流"""
|
"""定期清理不活跃的子心流"""
|
||||||
@@ -64,10 +69,7 @@ class Heartflow:
|
|||||||
|
|
||||||
await asyncio.sleep(30) # 每分钟检查一次
|
await asyncio.sleep(30) # 每分钟检查一次
|
||||||
|
|
||||||
async def heartflow_start_working(self):
|
async def _sub_heartflow_update(self):
|
||||||
# 启动清理任务
|
|
||||||
asyncio.create_task(self._cleanup_inactive_subheartflows())
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
# 检查是否存在子心流
|
# 检查是否存在子心流
|
||||||
if not self._subheartflows:
|
if not self._subheartflows:
|
||||||
@@ -78,6 +80,17 @@ class Heartflow:
|
|||||||
await self.do_a_thinking()
|
await self.do_a_thinking()
|
||||||
await asyncio.sleep(global_config.heart_flow_update_interval) # 5分钟思考一次
|
await asyncio.sleep(global_config.heart_flow_update_interval) # 5分钟思考一次
|
||||||
|
|
||||||
|
async def heartflow_start_working(self):
|
||||||
|
|
||||||
|
# 启动清理任务
|
||||||
|
asyncio.create_task(self._cleanup_inactive_subheartflows())
|
||||||
|
|
||||||
|
# 启动子心流更新任务
|
||||||
|
asyncio.create_task(self._sub_heartflow_update())
|
||||||
|
|
||||||
|
async def _update_current_state(self):
|
||||||
|
print("TODO")
|
||||||
|
|
||||||
async def do_a_thinking(self):
|
async def do_a_thinking(self):
|
||||||
logger.debug("麦麦大脑袋转起来了")
|
logger.debug("麦麦大脑袋转起来了")
|
||||||
self.current_state.update_current_state_info()
|
self.current_state.update_current_state_info()
|
||||||
@@ -188,17 +201,13 @@ class Heartflow:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if subheartflow_id not in self._subheartflows:
|
if subheartflow_id not in self._subheartflows:
|
||||||
logger.debug(f"创建 subheartflow: {subheartflow_id}")
|
|
||||||
subheartflow = SubHeartflow(subheartflow_id)
|
subheartflow = SubHeartflow(subheartflow_id)
|
||||||
# 创建一个观察对象,目前只可以用chat_id创建观察对象
|
# 创建一个观察对象,目前只可以用chat_id创建观察对象
|
||||||
logger.debug(f"创建 observation: {subheartflow_id}")
|
logger.debug(f"创建 observation: {subheartflow_id}")
|
||||||
observation = ChattingObservation(subheartflow_id)
|
observation = ChattingObservation(subheartflow_id)
|
||||||
|
|
||||||
logger.debug("添加 observation ")
|
|
||||||
subheartflow.add_observation(observation)
|
subheartflow.add_observation(observation)
|
||||||
logger.debug("添加 observation 成功")
|
logger.debug("添加 observation 成功")
|
||||||
# 创建异步任务
|
# 创建异步任务
|
||||||
logger.debug("创建异步任务")
|
|
||||||
asyncio.create_task(subheartflow.subheartflow_start_working())
|
asyncio.create_task(subheartflow.subheartflow_start_working())
|
||||||
logger.debug("创建异步任务 成功")
|
logger.debug("创建异步任务 成功")
|
||||||
self._subheartflows[subheartflow_id] = subheartflow
|
self._subheartflows[subheartflow_id] = subheartflow
|
||||||
|
|||||||
@@ -44,26 +44,31 @@ class ActionPlanner:
|
|||||||
logger.debug(f"开始规划行动:当前目标: {conversation_info.goal_list}")
|
logger.debug(f"开始规划行动:当前目标: {conversation_info.goal_list}")
|
||||||
|
|
||||||
# 构建对话目标
|
# 构建对话目标
|
||||||
|
goals_str = ""
|
||||||
if conversation_info.goal_list:
|
if conversation_info.goal_list:
|
||||||
last_goal = conversation_info.goal_list[-1]
|
for goal_reason in conversation_info.goal_list:
|
||||||
print(last_goal)
|
|
||||||
# 处理字典或元组格式
|
# 处理字典或元组格式
|
||||||
if isinstance(last_goal, tuple) and len(last_goal) == 2:
|
if isinstance(goal_reason, tuple):
|
||||||
goal, reasoning = last_goal
|
# 假设元组的第一个元素是目标,第二个元素是原因
|
||||||
elif isinstance(last_goal, dict) and 'goal' in last_goal and 'reasoning' in last_goal:
|
goal = goal_reason[0]
|
||||||
# 处理字典格式
|
reasoning = goal_reason[1] if len(goal_reason) > 1 else "没有明确原因"
|
||||||
goal = last_goal.get('goal', "目前没有明确对话目标")
|
elif isinstance(goal_reason, dict):
|
||||||
reasoning = last_goal.get('reasoning', "目前没有明确对话目标,最好思考一个对话目标")
|
goal = goal_reason.get('goal')
|
||||||
|
reasoning = goal_reason.get('reasoning', "没有明确原因")
|
||||||
else:
|
else:
|
||||||
# 处理未知格式
|
# 如果是其他类型,尝试转为字符串
|
||||||
goal = "目前没有明确对话目标"
|
goal = str(goal_reason)
|
||||||
reasoning = "目前没有明确对话目标,最好思考一个对话目标"
|
reasoning = "没有明确原因"
|
||||||
|
|
||||||
|
goal_str = f"目标:{goal},产生该对话目标的原因:{reasoning}\n"
|
||||||
|
goals_str += goal_str
|
||||||
else:
|
else:
|
||||||
goal = "目前没有明确对话目标"
|
goal = "目前没有明确对话目标"
|
||||||
reasoning = "目前没有明确对话目标,最好思考一个对话目标"
|
reasoning = "目前没有明确对话目标,最好思考一个对话目标"
|
||||||
|
goals_str = f"目标:{goal},产生该对话目标的原因:{reasoning}\n"
|
||||||
|
|
||||||
# 获取聊天历史记录
|
# 获取聊天历史记录
|
||||||
chat_history_list = observation_info.chat_history
|
chat_history_list = observation_info.chat_history[-20:] if len(observation_info.chat_history) >= 20 else observation_info.chat_history
|
||||||
chat_history_text = ""
|
chat_history_text = ""
|
||||||
for msg in chat_history_list:
|
for msg in chat_history_list:
|
||||||
chat_history_text += f"{msg.get('detailed_plain_text', '')}\n"
|
chat_history_text += f"{msg.get('detailed_plain_text', '')}\n"
|
||||||
@@ -80,15 +85,30 @@ class ActionPlanner:
|
|||||||
personality_text = f"你的名字是{self.name},{self.personality_info}"
|
personality_text = f"你的名字是{self.name},{self.personality_info}"
|
||||||
|
|
||||||
# 构建action历史文本
|
# 构建action历史文本
|
||||||
action_history_list = conversation_info.done_action
|
action_history_list = conversation_info.done_action[-10:] if len(conversation_info.done_action) >= 10 else conversation_info.done_action
|
||||||
action_history_text = "你之前做的事情是:"
|
action_history_text = "你之前做的事情是:"
|
||||||
for action in action_history_list:
|
for action in action_history_list:
|
||||||
action_history_text += f"{action}\n"
|
if isinstance(action, dict):
|
||||||
|
action_type = action.get('action')
|
||||||
|
action_reason = action.get('reason')
|
||||||
|
action_status = action.get('status')
|
||||||
|
if action_status == "recall":
|
||||||
|
action_history_text += f"原本打算:{action_type},但是因为有新消息,你发现这个行动不合适,所以你没做\n"
|
||||||
|
elif action_status == "done":
|
||||||
|
action_history_text += f"你之前做了:{action_type},原因:{action_reason}\n"
|
||||||
|
elif isinstance(action, tuple):
|
||||||
|
# 假设元组的格式是(action_type, action_reason, action_status)
|
||||||
|
action_type = action[0] if len(action) > 0 else "未知行动"
|
||||||
|
action_reason = action[1] if len(action) > 1 else "未知原因"
|
||||||
|
action_status = action[2] if len(action) > 2 else "done"
|
||||||
|
if action_status == "recall":
|
||||||
|
action_history_text += f"原本打算:{action_type},但是因为有新消息,你发现这个行动不合适,所以你没做\n"
|
||||||
|
elif action_status == "done":
|
||||||
|
action_history_text += f"你之前做了:{action_type},原因:{action_reason}\n"
|
||||||
|
|
||||||
prompt = f"""{personality_text}。现在你在参与一场QQ聊天,请分析以下内容,根据信息决定下一步行动:
|
prompt = f"""{personality_text}。现在你在参与一场QQ聊天,请分析以下内容,根据信息决定下一步行动:
|
||||||
|
|
||||||
当前对话目标:{goal}
|
当前对话目标:{goals_str}
|
||||||
产生该对话目标的原因:{reasoning}
|
|
||||||
|
|
||||||
{action_history_text}
|
{action_history_text}
|
||||||
|
|
||||||
@@ -98,10 +118,11 @@ class ActionPlanner:
|
|||||||
请你接下去想想要你要做什么,可以发言,可以等待,可以倾听,可以调取知识。注意不同行动类型的要求,不要重复发言:
|
请你接下去想想要你要做什么,可以发言,可以等待,可以倾听,可以调取知识。注意不同行动类型的要求,不要重复发言:
|
||||||
行动类型:
|
行动类型:
|
||||||
fetch_knowledge: 需要调取知识,当需要专业知识或特定信息时选择
|
fetch_knowledge: 需要调取知识,当需要专业知识或特定信息时选择
|
||||||
wait: 当你做出了发言,对方尚未回复时等待对方的回复
|
wait: 当你做出了发言,对方尚未回复时暂时等待对方的回复
|
||||||
listening: 倾听对方发言,当你认为对方发言尚未结束时采用
|
listening: 倾听对方发言,当你认为对方发言尚未结束时采用
|
||||||
direct_reply: 不符合上述情况,回复对方,注意不要过多或者重复发言
|
direct_reply: 不符合上述情况,回复对方,注意不要过多或者重复发言
|
||||||
rethink_goal: 重新思考对话目标,当发现对话目标不合适时选择,会重新思考对话目标
|
rethink_goal: 重新思考对话目标,当发现对话目标不合适时选择,会重新思考对话目标
|
||||||
|
end_conversation: 结束对话,当你觉得谈话暂时结束时选择,停止该场对话
|
||||||
|
|
||||||
请以JSON格式输出,包含以下字段:
|
请以JSON格式输出,包含以下字段:
|
||||||
1. action: 行动类型,注意你之前的行为
|
1. action: 行动类型,注意你之前的行为
|
||||||
@@ -126,7 +147,7 @@ rethink_goal: 重新思考对话目标,当发现对话目标不合适时选择
|
|||||||
reason = result["reason"]
|
reason = result["reason"]
|
||||||
|
|
||||||
# 验证action类型
|
# 验证action类型
|
||||||
if action not in ["direct_reply", "fetch_knowledge", "wait", "listening", "rethink_goal"]:
|
if action not in ["direct_reply", "fetch_knowledge", "wait", "listening", "rethink_goal", "end_conversation"]:
|
||||||
logger.warning(f"未知的行动类型: {action},默认使用listening")
|
logger.warning(f"未知的行动类型: {action},默认使用listening")
|
||||||
action = "listening"
|
action = "listening"
|
||||||
|
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ class ChatObserver:
|
|||||||
self.last_message_read = new_messages[-1]
|
self.last_message_read = new_messages[-1]
|
||||||
self.last_message_time = new_messages[-1]["time"]
|
self.last_message_time = new_messages[-1]["time"]
|
||||||
|
|
||||||
print(f"获取数据库中找到的新消息: {new_messages}")
|
# print(f"获取数据库中找到的新消息: {new_messages}")
|
||||||
|
|
||||||
return new_messages
|
return new_messages
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import datetime
|
|||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
from ..chat.message import Message
|
from ..chat.message import Message
|
||||||
from .pfc_types import ConversationState
|
from .pfc_types import ConversationState
|
||||||
from .pfc import ChatObserver, GoalAnalyzer, Waiter, DirectMessageSender
|
from .pfc import ChatObserver, GoalAnalyzer, DirectMessageSender
|
||||||
from src.common.logger import get_module_logger
|
from src.common.logger import get_module_logger
|
||||||
from .action_planner import ActionPlanner
|
from .action_planner import ActionPlanner
|
||||||
from .observation_info import ObservationInfo
|
from .observation_info import ObservationInfo
|
||||||
@@ -13,6 +13,8 @@ from ..chat.chat_stream import ChatStream
|
|||||||
from ..message.message_base import UserInfo
|
from ..message.message_base import UserInfo
|
||||||
from src.plugins.chat.chat_stream import chat_manager
|
from src.plugins.chat.chat_stream import chat_manager
|
||||||
from .pfc_KnowledgeFetcher import KnowledgeFetcher
|
from .pfc_KnowledgeFetcher import KnowledgeFetcher
|
||||||
|
from .waiter import Waiter
|
||||||
|
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
logger = get_module_logger("pfc_conversation")
|
logger = get_module_logger("pfc_conversation")
|
||||||
@@ -95,6 +97,15 @@ class Conversation:
|
|||||||
# 执行行动
|
# 执行行动
|
||||||
await self._handle_action(action, reason, self.observation_info, self.conversation_info)
|
await self._handle_action(action, reason, self.observation_info, self.conversation_info)
|
||||||
|
|
||||||
|
for goal in self.conversation_info.goal_list:
|
||||||
|
# 检查goal是否为元组类型,如果是元组则使用索引访问,如果是字典则使用get方法
|
||||||
|
if isinstance(goal, tuple):
|
||||||
|
# 假设元组的第一个元素是目标内容
|
||||||
|
print(f"goal: {goal}")
|
||||||
|
if goal[0] == "结束对话":
|
||||||
|
self.should_continue = False
|
||||||
|
break
|
||||||
|
|
||||||
def _check_new_messages_after_planning(self):
|
def _check_new_messages_after_planning(self):
|
||||||
"""检查在规划后是否有新消息"""
|
"""检查在规划后是否有新消息"""
|
||||||
if self.observation_info.new_messages_count > 0:
|
if self.observation_info.new_messages_count > 0:
|
||||||
@@ -151,14 +162,19 @@ class Conversation:
|
|||||||
|
|
||||||
if self._check_new_messages_after_planning():
|
if self._check_new_messages_after_planning():
|
||||||
logger.info("333333发现新消息,重新考虑行动")
|
logger.info("333333发现新消息,重新考虑行动")
|
||||||
|
conversation_info.done_action[-1].update(
|
||||||
|
{
|
||||||
|
"status": "recall",
|
||||||
|
"time": datetime.datetime.now().strftime("%H:%M:%S"),
|
||||||
|
}
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
await self._send_reply()
|
await self._send_reply()
|
||||||
|
|
||||||
conversation_info.done_action.append(
|
|
||||||
|
conversation_info.done_action[-1].update(
|
||||||
{
|
{
|
||||||
"action": action,
|
|
||||||
"reason": reason,
|
|
||||||
"status": "done",
|
"status": "done",
|
||||||
"time": datetime.datetime.now().strftime("%H:%M:%S"),
|
"time": datetime.datetime.now().strftime("%H:%M:%S"),
|
||||||
}
|
}
|
||||||
@@ -184,16 +200,17 @@ class Conversation:
|
|||||||
elif action == "listening":
|
elif action == "listening":
|
||||||
self.state = ConversationState.LISTENING
|
self.state = ConversationState.LISTENING
|
||||||
logger.info("倾听对方发言...")
|
logger.info("倾听对方发言...")
|
||||||
if await self.waiter.wait(): # 如果返回True表示超时
|
await self.waiter.wait_listening(conversation_info)
|
||||||
await self._send_timeout_message()
|
|
||||||
await self._stop_conversation()
|
|
||||||
|
elif action == "end_conversation":
|
||||||
|
self.should_continue = False
|
||||||
|
logger.info("决定结束对话...")
|
||||||
|
|
||||||
else: # wait
|
else: # wait
|
||||||
self.state = ConversationState.WAITING
|
self.state = ConversationState.WAITING
|
||||||
logger.info("等待更多信息...")
|
logger.info("等待更多信息...")
|
||||||
if await self.waiter.wait(): # 如果返回True表示超时
|
await self.waiter.wait(self.conversation_info)
|
||||||
await self._send_timeout_message()
|
|
||||||
await self._stop_conversation()
|
|
||||||
|
|
||||||
async def _send_timeout_message(self):
|
async def _send_timeout_message(self):
|
||||||
"""发送超时结束消息"""
|
"""发送超时结束消息"""
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class MongoDBMessageStorage(MessageStorage):
|
|||||||
|
|
||||||
async def get_messages_after(self, chat_id: str, message_time: float) -> List[Dict[str, Any]]:
|
async def get_messages_after(self, chat_id: str, message_time: float) -> List[Dict[str, Any]]:
|
||||||
query = {"chat_id": chat_id}
|
query = {"chat_id": chat_id}
|
||||||
print(f"storage_check_message: {message_time}")
|
# print(f"storage_check_message: {message_time}")
|
||||||
|
|
||||||
query["time"] = {"$gt": message_time}
|
query["time"] = {"$gt": message_time}
|
||||||
|
|
||||||
|
|||||||
@@ -157,8 +157,8 @@ class ObservationInfo:
|
|||||||
Args:
|
Args:
|
||||||
message: 消息数据
|
message: 消息数据
|
||||||
"""
|
"""
|
||||||
print("1919810-----------------------------------------------------")
|
# print("1919810-----------------------------------------------------")
|
||||||
logger.debug(f"更新信息from_message: {message}")
|
# logger.debug(f"更新信息from_message: {message}")
|
||||||
self.last_message_time = message["time"]
|
self.last_message_time = message["time"]
|
||||||
self.last_message_id = message["message_id"]
|
self.last_message_id = message["message_id"]
|
||||||
|
|
||||||
|
|||||||
@@ -54,11 +54,28 @@ class GoalAnalyzer:
|
|||||||
Tuple[str, str, str]: (目标, 方法, 原因)
|
Tuple[str, str, str]: (目标, 方法, 原因)
|
||||||
"""
|
"""
|
||||||
# 构建对话目标
|
# 构建对话目标
|
||||||
goal_list = conversation_info.goal_list
|
goals_str = ""
|
||||||
goal_text = ""
|
if conversation_info.goal_list:
|
||||||
for goal, reason in goal_list:
|
for goal_reason in conversation_info.goal_list:
|
||||||
goal_text += f"目标:{goal};"
|
# 处理字典或元组格式
|
||||||
goal_text += f"原因:{reason}\n"
|
if isinstance(goal_reason, tuple):
|
||||||
|
# 假设元组的第一个元素是目标,第二个元素是原因
|
||||||
|
goal = goal_reason[0]
|
||||||
|
reasoning = goal_reason[1] if len(goal_reason) > 1 else "没有明确原因"
|
||||||
|
elif isinstance(goal_reason, dict):
|
||||||
|
goal = goal_reason.get('goal')
|
||||||
|
reasoning = goal_reason.get('reasoning', "没有明确原因")
|
||||||
|
else:
|
||||||
|
# 如果是其他类型,尝试转为字符串
|
||||||
|
goal = str(goal_reason)
|
||||||
|
reasoning = "没有明确原因"
|
||||||
|
|
||||||
|
goal_str = f"目标:{goal},产生该对话目标的原因:{reasoning}\n"
|
||||||
|
goals_str += goal_str
|
||||||
|
else:
|
||||||
|
goal = "目前没有明确对话目标"
|
||||||
|
reasoning = "目前没有明确对话目标,最好思考一个对话目标"
|
||||||
|
goals_str = f"目标:{goal},产生该对话目标的原因:{reasoning}\n"
|
||||||
|
|
||||||
# 获取聊天历史记录
|
# 获取聊天历史记录
|
||||||
chat_history_list = observation_info.chat_history
|
chat_history_list = observation_info.chat_history
|
||||||
@@ -88,7 +105,7 @@ class GoalAnalyzer:
|
|||||||
|
|
||||||
{action_history_text}
|
{action_history_text}
|
||||||
当前对话目标:
|
当前对话目标:
|
||||||
{goal_text}
|
{goals_str}
|
||||||
|
|
||||||
聊天记录:
|
聊天记录:
|
||||||
{chat_history_text}
|
{chat_history_text}
|
||||||
@@ -98,6 +115,7 @@ class GoalAnalyzer:
|
|||||||
2. 修改现有目标
|
2. 修改现有目标
|
||||||
3. 添加新目标
|
3. 添加新目标
|
||||||
4. 删除不再相关的目标
|
4. 删除不再相关的目标
|
||||||
|
5. 如果你想结束对话,请设置一个目标,目标goal为"结束对话",原因reasoning为你希望结束对话
|
||||||
|
|
||||||
请以JSON数组格式输出当前的所有对话目标,每个目标包含以下字段:
|
请以JSON数组格式输出当前的所有对话目标,每个目标包含以下字段:
|
||||||
1. goal: 对话目标(简短的一句话)
|
1. goal: 对话目标(简短的一句话)
|
||||||
@@ -275,38 +293,6 @@ class GoalAnalyzer:
|
|||||||
return False, False, f"分析出错: {str(e)}"
|
return False, False, f"分析出错: {str(e)}"
|
||||||
|
|
||||||
|
|
||||||
class Waiter:
|
|
||||||
"""快 速 等 待"""
|
|
||||||
|
|
||||||
def __init__(self, stream_id: str):
|
|
||||||
self.chat_observer = ChatObserver.get_instance(stream_id)
|
|
||||||
self.personality_info = Individuality.get_instance().get_prompt(type="personality", x_person=2, level=2)
|
|
||||||
self.name = global_config.BOT_NICKNAME
|
|
||||||
|
|
||||||
async def wait(self) -> bool:
|
|
||||||
"""等待
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 是否超时(True表示超时)
|
|
||||||
"""
|
|
||||||
# 使用当前时间作为等待开始时间
|
|
||||||
wait_start_time = time.time()
|
|
||||||
self.chat_observer.waiting_start_time = wait_start_time # 设置等待开始时间
|
|
||||||
|
|
||||||
while True:
|
|
||||||
# 检查是否有新消息
|
|
||||||
if self.chat_observer.new_message_after(wait_start_time):
|
|
||||||
logger.info("等待结束,收到新消息")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 检查是否超时
|
|
||||||
if time.time() - wait_start_time > 300:
|
|
||||||
logger.info("等待超过300秒,结束对话")
|
|
||||||
return True
|
|
||||||
|
|
||||||
await asyncio.sleep(1)
|
|
||||||
logger.info("等待中...")
|
|
||||||
|
|
||||||
|
|
||||||
class DirectMessageSender:
|
class DirectMessageSender:
|
||||||
"""直接发送消息到平台的发送器"""
|
"""直接发送消息到平台的发送器"""
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class PFCManager:
|
|||||||
logger.debug(f"会话实例正在初始化中: {stream_id}")
|
logger.debug(f"会话实例正在初始化中: {stream_id}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if stream_id in self._instances:
|
if stream_id in self._instances and self._instances[stream_id].should_continue:
|
||||||
logger.debug(f"使用现有会话实例: {stream_id}")
|
logger.debug(f"使用现有会话实例: {stream_id}")
|
||||||
return self._instances[stream_id]
|
return self._instances[stream_id]
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class ReplyGenerator:
|
|||||||
|
|
||||||
def __init__(self, stream_id: str):
|
def __init__(self, stream_id: str):
|
||||||
self.llm = LLM_request(
|
self.llm = LLM_request(
|
||||||
model=global_config.llm_normal, temperature=0.7, max_tokens=300, request_type="reply_generation"
|
model=global_config.llm_normal, temperature=0.3, max_tokens=300, request_type="reply_generation"
|
||||||
)
|
)
|
||||||
self.personality_info = Individuality.get_instance().get_prompt(type="personality", x_person=2, level=2)
|
self.personality_info = Individuality.get_instance().get_prompt(type="personality", x_person=2, level=2)
|
||||||
self.name = global_config.BOT_NICKNAME
|
self.name = global_config.BOT_NICKNAME
|
||||||
@@ -39,33 +39,76 @@ class ReplyGenerator:
|
|||||||
# 构建提示词
|
# 构建提示词
|
||||||
logger.debug(f"开始生成回复:当前目标: {conversation_info.goal_list}")
|
logger.debug(f"开始生成回复:当前目标: {conversation_info.goal_list}")
|
||||||
|
|
||||||
goal_list = conversation_info.goal_list
|
# 构建对话目标
|
||||||
goal_text = ""
|
goals_str = ""
|
||||||
for goal, reason in goal_list:
|
if conversation_info.goal_list:
|
||||||
goal_text += f"目标:{goal};"
|
for goal_reason in conversation_info.goal_list:
|
||||||
goal_text += f"原因:{reason}\n"
|
# 处理字典或元组格式
|
||||||
|
if isinstance(goal_reason, tuple):
|
||||||
|
# 假设元组的第一个元素是目标,第二个元素是原因
|
||||||
|
goal = goal_reason[0]
|
||||||
|
reasoning = goal_reason[1] if len(goal_reason) > 1 else "没有明确原因"
|
||||||
|
elif isinstance(goal_reason, dict):
|
||||||
|
goal = goal_reason.get('goal')
|
||||||
|
reasoning = goal_reason.get('reasoning', "没有明确原因")
|
||||||
|
else:
|
||||||
|
# 如果是其他类型,尝试转为字符串
|
||||||
|
goal = str(goal_reason)
|
||||||
|
reasoning = "没有明确原因"
|
||||||
|
|
||||||
|
goal_str = f"目标:{goal},产生该对话目标的原因:{reasoning}\n"
|
||||||
|
goals_str += goal_str
|
||||||
|
else:
|
||||||
|
goal = "目前没有明确对话目标"
|
||||||
|
reasoning = "目前没有明确对话目标,最好思考一个对话目标"
|
||||||
|
goals_str = f"目标:{goal},产生该对话目标的原因:{reasoning}\n"
|
||||||
|
|
||||||
# 获取聊天历史记录
|
# 获取聊天历史记录
|
||||||
chat_history_list = observation_info.chat_history
|
chat_history_list = observation_info.chat_history[-20:] if len(observation_info.chat_history) >= 20 else observation_info.chat_history
|
||||||
chat_history_text = ""
|
chat_history_text = ""
|
||||||
for msg in chat_history_list:
|
for msg in chat_history_list:
|
||||||
chat_history_text += f"{msg}\n"
|
chat_history_text += f"{msg.get('detailed_plain_text', '')}\n"
|
||||||
|
|
||||||
# 整理知识缓存
|
if observation_info.new_messages_count > 0:
|
||||||
knowledge_text = ""
|
new_messages_list = observation_info.unprocessed_messages
|
||||||
knowledge_list = conversation_info.knowledge_list
|
|
||||||
for knowledge in knowledge_list:
|
chat_history_text += f"有{observation_info.new_messages_count}条新消息:\n"
|
||||||
knowledge_text += f"知识:{knowledge}\n"
|
for msg in new_messages_list:
|
||||||
|
chat_history_text += f"{msg.get('detailed_plain_text', '')}\n"
|
||||||
|
|
||||||
|
observation_info.clear_unprocessed_messages()
|
||||||
|
|
||||||
personality_text = f"你的名字是{self.name},{self.personality_info}"
|
personality_text = f"你的名字是{self.name},{self.personality_info}"
|
||||||
|
|
||||||
|
# 构建action历史文本
|
||||||
|
action_history_list = conversation_info.done_action[-10:] if len(conversation_info.done_action) >= 10 else conversation_info.done_action
|
||||||
|
action_history_text = "你之前做的事情是:"
|
||||||
|
for action in action_history_list:
|
||||||
|
if isinstance(action, dict):
|
||||||
|
action_type = action.get('action')
|
||||||
|
action_reason = action.get('reason')
|
||||||
|
action_status = action.get('status')
|
||||||
|
if action_status == "recall":
|
||||||
|
action_history_text += f"原本打算:{action_type},但是因为有新消息,你发现这个行动不合适,所以你没做\n"
|
||||||
|
elif action_status == "done":
|
||||||
|
action_history_text += f"你之前做了:{action_type},原因:{action_reason}\n"
|
||||||
|
elif isinstance(action, tuple):
|
||||||
|
# 假设元组的格式是(action_type, action_reason, action_status)
|
||||||
|
action_type = action[0] if len(action) > 0 else "未知行动"
|
||||||
|
action_reason = action[1] if len(action) > 1 else "未知原因"
|
||||||
|
action_status = action[2] if len(action) > 2 else "done"
|
||||||
|
if action_status == "recall":
|
||||||
|
action_history_text += f"原本打算:{action_type},但是因为有新消息,你发现这个行动不合适,所以你没做\n"
|
||||||
|
elif action_status == "done":
|
||||||
|
action_history_text += f"你之前做了:{action_type},原因:{action_reason}\n"
|
||||||
|
|
||||||
prompt = f"""{personality_text}。现在你在参与一场QQ聊天,请根据以下信息生成回复:
|
prompt = f"""{personality_text}。现在你在参与一场QQ聊天,请根据以下信息生成回复:
|
||||||
|
|
||||||
当前对话目标:{goal_text}
|
当前对话目标:{goals_str}
|
||||||
{knowledge_text}
|
|
||||||
最近的聊天记录:
|
最近的聊天记录:
|
||||||
{chat_history_text}
|
{chat_history_text}
|
||||||
|
|
||||||
|
|
||||||
请根据上述信息,以你的性格特征生成一个自然、得体的回复。回复应该:
|
请根据上述信息,以你的性格特征生成一个自然、得体的回复。回复应该:
|
||||||
1. 符合对话目标,以"你"的角度发言
|
1. 符合对话目标,以"你"的角度发言
|
||||||
2. 体现你的性格特征
|
2. 体现你的性格特征
|
||||||
|
|||||||
@@ -1,46 +1,81 @@
|
|||||||
from src.common.logger import get_module_logger
|
from src.common.logger import get_module_logger
|
||||||
from .chat_observer import ChatObserver
|
from .chat_observer import ChatObserver
|
||||||
|
from .conversation_info import ConversationInfo
|
||||||
|
from src.individuality.individuality import Individuality
|
||||||
|
from ..config.config import global_config
|
||||||
|
import time
|
||||||
|
import asyncio
|
||||||
|
|
||||||
logger = get_module_logger("waiter")
|
logger = get_module_logger("waiter")
|
||||||
|
|
||||||
|
|
||||||
class Waiter:
|
class Waiter:
|
||||||
"""等待器,用于等待对话流中的事件"""
|
"""快 速 等 待"""
|
||||||
|
|
||||||
def __init__(self, stream_id: str):
|
def __init__(self, stream_id: str):
|
||||||
self.stream_id = stream_id
|
|
||||||
self.chat_observer = ChatObserver.get_instance(stream_id)
|
self.chat_observer = ChatObserver.get_instance(stream_id)
|
||||||
|
self.personality_info = Individuality.get_instance().get_prompt(type="personality", x_person=2, level=2)
|
||||||
|
self.name = global_config.BOT_NICKNAME
|
||||||
|
|
||||||
async def wait(self, timeout: float = 20.0) -> bool:
|
async def wait(self, conversation_info: ConversationInfo) -> bool:
|
||||||
"""等待用户回复或超时
|
"""等待
|
||||||
|
|
||||||
Args:
|
|
||||||
timeout: 超时时间(秒)
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: 如果因为超时返回则为True,否则为False
|
bool: 是否超时(True表示超时)
|
||||||
"""
|
"""
|
||||||
try:
|
# 使用当前时间作为等待开始时间
|
||||||
message_before = self.chat_observer.get_last_message()
|
wait_start_time = time.time()
|
||||||
|
self.chat_observer.waiting_start_time = wait_start_time # 设置等待开始时间
|
||||||
|
|
||||||
# 等待新消息
|
while True:
|
||||||
logger.debug(f"等待新消息,超时时间: {timeout}秒")
|
# 检查是否有新消息
|
||||||
|
if self.chat_observer.new_message_after(wait_start_time):
|
||||||
is_timeout = await self.chat_observer.wait_for_update(timeout=timeout)
|
logger.info("等待结束,收到新消息")
|
||||||
if is_timeout:
|
|
||||||
logger.debug("等待超时,没有收到新消息")
|
|
||||||
return True
|
|
||||||
|
|
||||||
# 检查是否是新消息
|
|
||||||
message_after = self.chat_observer.get_last_message()
|
|
||||||
if message_before and message_after and message_before.get("message_id") == message_after.get("message_id"):
|
|
||||||
# 如果消息ID相同,说明没有新消息
|
|
||||||
logger.debug("没有收到新消息")
|
|
||||||
return True
|
|
||||||
|
|
||||||
logger.debug("收到新消息")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
# 检查是否超时
|
||||||
logger.error(f"等待时出错: {str(e)}")
|
if time.time() - wait_start_time > 15:
|
||||||
|
logger.info("等待超过300秒,结束对话")
|
||||||
|
wait_goal = {
|
||||||
|
"goal": "你等待了5分钟,思考接下来要做什么",
|
||||||
|
"reason": "对方很久没有回复你的消息了"
|
||||||
|
}
|
||||||
|
conversation_info.goal_list.append(wait_goal)
|
||||||
|
print(f"添加目标: {wait_goal}")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
logger.info("等待中...")
|
||||||
|
|
||||||
|
async def wait_listening(self, conversation_info: ConversationInfo) -> bool:
|
||||||
|
"""等待倾听
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否超时(True表示超时)
|
||||||
|
"""
|
||||||
|
# 使用当前时间作为等待开始时间
|
||||||
|
wait_start_time = time.time()
|
||||||
|
self.chat_observer.waiting_start_time = wait_start_time # 设置等待开始时间
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# 检查是否有新消息
|
||||||
|
if self.chat_observer.new_message_after(wait_start_time):
|
||||||
|
logger.info("等待结束,收到新消息")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 检查是否超时
|
||||||
|
if time.time() - wait_start_time > 30:
|
||||||
|
logger.info("等待超过300秒,结束对话")
|
||||||
|
wait_goal = {
|
||||||
|
"goal": "你等待了5分钟,思考接下来要做什么",
|
||||||
|
"reason": "对方话说一半消失了,很久没有回复"
|
||||||
|
}
|
||||||
|
conversation_info.goal_list.append(wait_goal)
|
||||||
|
print(f"添加目标: {wait_goal}")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
logger.info("等待中...")
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ logger = get_module_logger("config", config=config_config)
|
|||||||
# 考虑到,实际上配置文件中的mai_version是不会自动更新的,所以采用硬编码
|
# 考虑到,实际上配置文件中的mai_version是不会自动更新的,所以采用硬编码
|
||||||
is_test = True
|
is_test = True
|
||||||
mai_version_main = "0.6.2"
|
mai_version_main = "0.6.2"
|
||||||
mai_version_fix = "snapshot-1"
|
mai_version_fix = "snapshot-2"
|
||||||
|
|
||||||
if mai_version_fix:
|
if mai_version_fix:
|
||||||
if is_test:
|
if is_test:
|
||||||
|
|||||||
@@ -26,22 +26,7 @@ async def test_memory_system():
|
|||||||
|
|
||||||
# 测试记忆检索
|
# 测试记忆检索
|
||||||
test_text = "千石可乐在群里聊天"
|
test_text = "千石可乐在群里聊天"
|
||||||
test_text = """[03-24 10:39:37] 麦麦(ta的id:2814567326): 早说散步结果下雨改成室内运动啊
|
|
||||||
[03-24 10:39:37] 麦麦(ta的id:2814567326): [回复:变量] 变量就像今天计划总变
|
|
||||||
[03-24 10:39:44] 状态异常(ta的id:535554838): 要把本地文件改成弹出来的路径吗
|
|
||||||
[03-24 10:40:35] 状态异常(ta的id:535554838): [图片:这张图片显示的是Windows系统的环境变量设置界面。界面左侧列出了多个环境变量的值,包括Intel Dev Redist、Windows、Windows PowerShell、OpenSSH、NVIDIA Corporation的目录等。右侧有新建、编辑、浏览、删除、上移、下移和编辑文本等操作按钮。图片下方有一个错误提示框,显示"Windows找不到文件'mongodb\\bin\\mongod.exe'。请确定文件名是否正确后,再试一次。"这意味着用户试图运行MongoDB的mongod.exe程序时,系统找不到该文件。这可能是因为MongoDB的安装路径未正确添加到系统环境变量中,或者文件路径有误。
|
|
||||||
图片的含义可能是用户正在尝试设置MongoDB的环境变量,以便在命令行或其他程序中使用MongoDB。如果用户正确设置了环境变量,那么他们应该能够通过命令行或其他方式启动MongoDB服务。]
|
|
||||||
[03-24 10:41:08] 一根猫(ta的id:108886006): [回复 麦麦 的消息: [回复某人消息] 改系统变量或者删库重配 ] [@麦麦] 我中途修改人格,需要重配吗
|
|
||||||
[03-24 10:41:54] 麦麦(ta的id:2814567326): [回复:[回复 麦麦 的消息: [回复某人消息] 改系统变量或者删库重配 ] [@麦麦] 我中途修改人格,需要重配吗] 看情况
|
|
||||||
[03-24 10:41:54] 麦麦(ta的id:2814567326): 难
|
|
||||||
[03-24 10:41:54] 麦麦(ta的id:2814567326): 小改变量就行,大动骨安排重配像游戏副本南度改太大会崩
|
|
||||||
[03-24 10:45:33] 霖泷(ta的id:1967075066): 话说现在思考高达一分钟
|
|
||||||
[03-24 10:45:38] 霖泷(ta的id:1967075066): 是不是哪里出问题了
|
|
||||||
[03-24 10:45:39] 艾卡(ta的id:1786525298): [表情包:这张表情包展示了一个动漫角色,她有着紫色的头发和大大的眼睛,表情显得有些困惑或不解。她的头上有一个问号,进一步强调了她的疑惑。整体情感表达的是困惑或不解。]
|
|
||||||
[03-24 10:46:12] (ta的id:3229291803): [表情包:这张表情包显示了一只手正在做"点赞"的动作,通常表示赞同、喜欢或支持。这个表情包所表达的情感是积极的、赞同的或支持的。]
|
|
||||||
[03-24 10:46:37] 星野風禾(ta的id:2890165435): 还能思考高达
|
|
||||||
[03-24 10:46:39] 星野風禾(ta的id:2890165435): 什么知识库
|
|
||||||
[03-24 10:46:49] ❦幻凌慌てない(ta的id:2459587037): 为什么改了回复系数麦麦还是不怎么回复?大佬们""" # noqa: E501
|
|
||||||
|
|
||||||
# test_text = '''千石可乐:分不清AI的陪伴和人类的陪伴,是这样吗?'''
|
# test_text = '''千石可乐:分不清AI的陪伴和人类的陪伴,是这样吗?'''
|
||||||
print(f"开始测试记忆检索,测试文本: {test_text}\n")
|
print(f"开始测试记忆检索,测试文本: {test_text}\n")
|
||||||
@@ -56,21 +41,6 @@ async def test_memory_system():
|
|||||||
print(f"主题: {topic}")
|
print(f"主题: {topic}")
|
||||||
print(f"- {memory_items}")
|
print(f"- {memory_items}")
|
||||||
|
|
||||||
# 测试记忆遗忘
|
|
||||||
# forget_start_time = time.time()
|
|
||||||
# # print("开始测试记忆遗忘...")
|
|
||||||
# await hippocampus_manager.forget_memory(percentage=0.005)
|
|
||||||
# # print("记忆遗忘完成")
|
|
||||||
# forget_end_time = time.time()
|
|
||||||
# print(f"记忆遗忘耗时: {forget_end_time - forget_start_time:.2f} 秒")
|
|
||||||
|
|
||||||
# 获取所有节点
|
|
||||||
# nodes = hippocampus_manager.get_all_node_names()
|
|
||||||
# print(f"当前记忆系统中的节点数量: {len(nodes)}")
|
|
||||||
# print("节点列表:")
|
|
||||||
# for node in nodes:
|
|
||||||
# print(f"- {node}")
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"测试过程中出现错误: {e}")
|
print(f"测试过程中出现错误: {e}")
|
||||||
raise
|
raise
|
||||||
|
|||||||
Reference in New Issue
Block a user