fix:修改版本和小问题
This commit is contained in:
@@ -1,145 +0,0 @@
|
|||||||
{
|
|
||||||
"测试时间": "2025-04-28 14:12:36",
|
|
||||||
"测试迭代次数": 10,
|
|
||||||
"不使用工具调用": {
|
|
||||||
"平均耗时": 4.596814393997192,
|
|
||||||
"最短耗时": 2.957131862640381,
|
|
||||||
"最长耗时": 10.121938705444336,
|
|
||||||
"标准差": 2.1705468730949593,
|
|
||||||
"所有耗时": [
|
|
||||||
3.18,
|
|
||||||
4.65,
|
|
||||||
10.12,
|
|
||||||
3.5,
|
|
||||||
4.46,
|
|
||||||
4.24,
|
|
||||||
3.23,
|
|
||||||
6.2,
|
|
||||||
2.96,
|
|
||||||
3.42
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"不使用工具调用_详细响应": [
|
|
||||||
{
|
|
||||||
"内容摘要": "```json\n{\n \"action\": \"text_reply\",\n \"content\": \"怎么啦?\",\n \"emoji_query\": \"友好地询问\"\n}\n```",
|
|
||||||
"推理内容摘要": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "decide_reply_action(\n action=\"text_reply\",\n reasoning=\"千石连续两次叫了我的名字,显然是想引起我的注意或有事要说,作为礼貌应当回应\",\n emoji_query=\"友善的回应\"\n)",
|
|
||||||
"推理内容摘要": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "```json\n{\n \"action\": \"text_reply\",\n \"content\": \"怎么啦?我在呢~\",\n \"emoji_query\": \"友好的询问\",\n \"reasoning\": \"由于对方连续两次提到我的名字,显然是想与我交流,应当及时给予友好回应避免冷场\"\n}\n```",
|
|
||||||
"推理内容摘要": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "```json\n{\n \"action\": \"text_reply\",\n \"content\": \"在呢在呢~怎么啦?\",\n \"emoji_query\": \"好奇的回应\"\n}\n```",
|
|
||||||
"推理内容摘要": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "decide_reply_action(\n action=\"text_reply\",\n reasoning=\"千石连续两次提到我的名字,显然需要我回应。文字回复更正式且能明确表示我在关注他的信息。\",\n emoji_query=\"友好的回应\"\n)",
|
|
||||||
"推理内容摘要": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "```json\n{\n \"action\": \"text_reply\",\n \"reasoning\": \"千石连续两次提到我的名字,显然是需要我的回应。作为日常交流,应该给予友善简短的答复。\",\n \"emoji_query\": \"疑惑的歪头\"\n}\n```",
|
|
||||||
"推理内容摘要": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "```json\n{\n \"action\": \"text_reply\",\n \"content\": \"咋啦千石~\",\n \"emoji_query\": \"好奇的询问\"\n}\n```",
|
|
||||||
"推理内容摘要": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "decide_reply_action\n```json\n{\n \"action\": \"text_reply\",\n \"content\": \"我在呢~怎么啦?\",\n \"emoji_query\": \"友好的关心\",\n \"reasoning\": \"千石连续两次呼唤我的名字,显然是有事情要找我或想引起我的注意。根据回复原则2(有人提到你但未回应),应该用友善的文字进行回应,并附上表达关心的表情符号来延...",
|
|
||||||
"推理内容摘要": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "```json\n{\n \"action\": \"text_reply\",\n \"content\": \"千石怎么啦~\",\n \"emoji_query\": \"好奇的探询\"\n}\n```",
|
|
||||||
"推理内容摘要": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "```json\n{\n \"action\": \"text_reply\",\n \"content\": \"怎么啦?突然叫我两次\",\n \"emoji_query\": \"好奇的疑问\"\n}\n```",
|
|
||||||
"推理内容摘要": ""
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"使用工具调用": {
|
|
||||||
"平均耗时": 8.139546775817871,
|
|
||||||
"最短耗时": 4.9980738162994385,
|
|
||||||
"最长耗时": 18.803313732147217,
|
|
||||||
"标准差": 4.008772720760647,
|
|
||||||
"所有耗时": [
|
|
||||||
5.81,
|
|
||||||
18.8,
|
|
||||||
6.06,
|
|
||||||
8.06,
|
|
||||||
10.07,
|
|
||||||
6.34,
|
|
||||||
7.9,
|
|
||||||
6.66,
|
|
||||||
5.0,
|
|
||||||
6.69
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"使用工具调用_详细响应": [
|
|
||||||
{
|
|
||||||
"内容摘要": "",
|
|
||||||
"推理内容摘要": "",
|
|
||||||
"工具调用数量": 0,
|
|
||||||
"工具调用详情": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "",
|
|
||||||
"推理内容摘要": "",
|
|
||||||
"工具调用数量": 0,
|
|
||||||
"工具调用详情": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "",
|
|
||||||
"推理内容摘要": "",
|
|
||||||
"工具调用数量": 0,
|
|
||||||
"工具调用详情": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "",
|
|
||||||
"推理内容摘要": "",
|
|
||||||
"工具调用数量": 0,
|
|
||||||
"工具调用详情": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "",
|
|
||||||
"推理内容摘要": "",
|
|
||||||
"工具调用数量": 0,
|
|
||||||
"工具调用详情": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "",
|
|
||||||
"推理内容摘要": "",
|
|
||||||
"工具调用数量": 0,
|
|
||||||
"工具调用详情": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "",
|
|
||||||
"推理内容摘要": "",
|
|
||||||
"工具调用数量": 0,
|
|
||||||
"工具调用详情": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "",
|
|
||||||
"推理内容摘要": "",
|
|
||||||
"工具调用数量": 0,
|
|
||||||
"工具调用详情": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "",
|
|
||||||
"推理内容摘要": "",
|
|
||||||
"工具调用数量": 0,
|
|
||||||
"工具调用详情": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容摘要": "",
|
|
||||||
"推理内容摘要": "",
|
|
||||||
"工具调用数量": 0,
|
|
||||||
"工具调用详情": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"差异百分比": 77.07
|
|
||||||
}
|
|
||||||
@@ -25,7 +25,7 @@ logger = get_logger("config")
|
|||||||
# 考虑到,实际上配置文件中的mai_version是不会自动更新的,所以采用硬编码
|
# 考虑到,实际上配置文件中的mai_version是不会自动更新的,所以采用硬编码
|
||||||
is_test = False
|
is_test = False
|
||||||
mai_version_main = "0.6.3"
|
mai_version_main = "0.6.3"
|
||||||
mai_version_fix = "fix-2"
|
mai_version_fix = "fix-3"
|
||||||
|
|
||||||
if mai_version_fix:
|
if mai_version_fix:
|
||||||
if is_test:
|
if is_test:
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ class SubHeartflow:
|
|||||||
logger.error(f"{self.log_prefix} 停止 NormalChat 监控任务时出错: {e}")
|
logger.error(f"{self.log_prefix} 停止 NormalChat 监控任务时出错: {e}")
|
||||||
logger.error(traceback.format_exc())
|
logger.error(traceback.format_exc())
|
||||||
|
|
||||||
async def _start_normal_chat(self) -> bool:
|
async def _start_normal_chat(self, rewind = False) -> bool:
|
||||||
"""
|
"""
|
||||||
启动 NormalChat 实例,并进行异步初始化。
|
启动 NormalChat 实例,并进行异步初始化。
|
||||||
进入 CHAT 状态时使用。
|
进入 CHAT 状态时使用。
|
||||||
@@ -125,8 +125,11 @@ class SubHeartflow:
|
|||||||
if not chat_stream:
|
if not chat_stream:
|
||||||
logger.error(f"{log_prefix} 无法获取 chat_stream,无法启动 NormalChat。")
|
logger.error(f"{log_prefix} 无法获取 chat_stream,无法启动 NormalChat。")
|
||||||
return False
|
return False
|
||||||
|
if rewind:
|
||||||
self.normal_chat_instance = NormalChat(chat_stream=chat_stream, interest_dict=self.get_interest_dict())
|
self.normal_chat_instance = NormalChat(chat_stream=chat_stream, interest_dict=self.get_interest_dict())
|
||||||
|
else:
|
||||||
|
|
||||||
|
self.normal_chat_instance = NormalChat(chat_stream=chat_stream)
|
||||||
|
|
||||||
# 进行异步初始化
|
# 进行异步初始化
|
||||||
await self.normal_chat_instance.initialize()
|
await self.normal_chat_instance.initialize()
|
||||||
@@ -218,11 +221,20 @@ class SubHeartflow:
|
|||||||
if new_state == ChatState.CHAT:
|
if new_state == ChatState.CHAT:
|
||||||
# 移除限额检查逻辑
|
# 移除限额检查逻辑
|
||||||
logger.debug(f"{log_prefix} 准备进入或保持 聊天 状态")
|
logger.debug(f"{log_prefix} 准备进入或保持 聊天 状态")
|
||||||
if await self._start_normal_chat():
|
if current_state == ChatState.FOCUSED:
|
||||||
|
if await self._start_normal_chat(rewind=False):
|
||||||
# logger.info(f"{log_prefix} 成功进入或保持 NormalChat 状态。")
|
# logger.info(f"{log_prefix} 成功进入或保持 NormalChat 状态。")
|
||||||
state_changed = True
|
state_changed = True
|
||||||
else:
|
else:
|
||||||
logger.error(f"{log_prefix} 启动 NormalChat 失败,无法进入 CHAT 状态。")
|
logger.error(f"{log_prefix} 从FOCUSED状态启动 NormalChat 失败,无法进入 CHAT 状态。")
|
||||||
|
# 考虑是否需要回滚状态或采取其他措施
|
||||||
|
return # 启动失败,不改变状态
|
||||||
|
else:
|
||||||
|
if await self._start_normal_chat(rewind=True):
|
||||||
|
# logger.info(f"{log_prefix} 成功进入或保持 NormalChat 状态。")
|
||||||
|
state_changed = True
|
||||||
|
else:
|
||||||
|
logger.error(f"{log_prefix} 从ABSENT状态启动 NormalChat 失败,无法进入 CHAT 状态。")
|
||||||
# 考虑是否需要回滚状态或采取其他措施
|
# 考虑是否需要回滚状态或采取其他措施
|
||||||
return # 启动失败,不改变状态
|
return # 启动失败,不改变状态
|
||||||
|
|
||||||
@@ -239,6 +251,8 @@ class SubHeartflow:
|
|||||||
|
|
||||||
elif new_state == ChatState.ABSENT:
|
elif new_state == ChatState.ABSENT:
|
||||||
logger.info(f"{log_prefix} 进入 ABSENT 状态,停止所有聊天活动...")
|
logger.info(f"{log_prefix} 进入 ABSENT 状态,停止所有聊天活动...")
|
||||||
|
await self.clear_interest_dict()
|
||||||
|
|
||||||
await self._stop_normal_chat()
|
await self._stop_normal_chat()
|
||||||
await self._stop_heart_fc_chat()
|
await self._stop_heart_fc_chat()
|
||||||
state_changed = True # 总是可以成功转换到 ABSENT
|
state_changed = True # 总是可以成功转换到 ABSENT
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ from src.plugins.chat.chat_stream import chat_manager
|
|||||||
from src.plugins.heartFC_chat.heartFC_Cycleinfo import CycleInfo
|
from src.plugins.heartFC_chat.heartFC_Cycleinfo import CycleInfo
|
||||||
import difflib
|
import difflib
|
||||||
from src.plugins.person_info.relationship_manager import relationship_manager
|
from src.plugins.person_info.relationship_manager import relationship_manager
|
||||||
|
from src.plugins.memory_system.Hippocampus import HippocampusManager
|
||||||
|
import jieba
|
||||||
|
|
||||||
|
|
||||||
logger = get_logger("sub_heartflow")
|
logger = get_logger("sub_heartflow")
|
||||||
@@ -223,7 +225,56 @@ class SubMind:
|
|||||||
chat_observe_info = observation.get_observe_info()
|
chat_observe_info = observation.get_observe_info()
|
||||||
person_list = observation.person_list
|
person_list = observation.person_list
|
||||||
|
|
||||||
# ---------- 2. 准备工具和个性化数据 ----------
|
# ---------- 2. 获取记忆 ----------
|
||||||
|
try:
|
||||||
|
# 从聊天内容中提取关键词
|
||||||
|
chat_words = set(jieba.cut(chat_observe_info))
|
||||||
|
# 过滤掉停用词和单字词
|
||||||
|
keywords = [word for word in chat_words if len(word) > 1]
|
||||||
|
# 去重并限制数量
|
||||||
|
keywords = list(set(keywords))[:5]
|
||||||
|
|
||||||
|
logger.debug(f"{self.log_prefix} 提取的关键词: {keywords}")
|
||||||
|
# 检查已有记忆,过滤掉已存在的主题
|
||||||
|
existing_topics = set()
|
||||||
|
for item in self.structured_info:
|
||||||
|
if item["type"] == "memory":
|
||||||
|
existing_topics.add(item["id"])
|
||||||
|
|
||||||
|
# 过滤掉已存在的主题
|
||||||
|
filtered_keywords = [k for k in keywords if k not in existing_topics]
|
||||||
|
|
||||||
|
if not filtered_keywords:
|
||||||
|
logger.debug(f"{self.log_prefix} 所有关键词对应的记忆都已存在,跳过记忆提取")
|
||||||
|
else:
|
||||||
|
# 调用记忆系统获取相关记忆
|
||||||
|
related_memory = await HippocampusManager.get_instance().get_memory_from_topic(
|
||||||
|
valid_keywords=filtered_keywords,
|
||||||
|
max_memory_num=3,
|
||||||
|
max_memory_length=2,
|
||||||
|
max_depth=3
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.debug(f"{self.log_prefix} 获取到的记忆: {related_memory}")
|
||||||
|
|
||||||
|
if related_memory:
|
||||||
|
for topic, memory in related_memory:
|
||||||
|
new_item = {
|
||||||
|
"type": "memory",
|
||||||
|
"id": topic,
|
||||||
|
"content": memory,
|
||||||
|
"ttl": 3
|
||||||
|
}
|
||||||
|
self.structured_info.append(new_item)
|
||||||
|
logger.debug(f"{self.log_prefix} 添加新记忆: {topic} - {memory}")
|
||||||
|
else:
|
||||||
|
logger.debug(f"{self.log_prefix} 没有找到相关记忆")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"{self.log_prefix} 获取记忆时出错: {e}")
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
|
|
||||||
|
# ---------- 3. 准备工具和个性化数据 ----------
|
||||||
# 初始化工具
|
# 初始化工具
|
||||||
tool_instance = ToolUser()
|
tool_instance = ToolUser()
|
||||||
tools = tool_instance._define_tools()
|
tools = tool_instance._define_tools()
|
||||||
@@ -244,7 +295,7 @@ class SubMind:
|
|||||||
# 获取当前时间
|
# 获取当前时间
|
||||||
time_now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
time_now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||||
|
|
||||||
# ---------- 3. 构建思考指导部分 ----------
|
# ---------- 4. 构建思考指导部分 ----------
|
||||||
# 创建本地随机数生成器,基于分钟数作为种子
|
# 创建本地随机数生成器,基于分钟数作为种子
|
||||||
local_random = random.Random()
|
local_random = random.Random()
|
||||||
current_minute = int(time.strftime("%M"))
|
current_minute = int(time.strftime("%M"))
|
||||||
@@ -328,7 +379,7 @@ class SubMind:
|
|||||||
[option[0] for option in hf_options], weights=[option[1] for option in hf_options], k=1
|
[option[0] for option in hf_options], weights=[option[1] for option in hf_options], k=1
|
||||||
)[0]
|
)[0]
|
||||||
|
|
||||||
# ---------- 4. 构建最终提示词 ----------
|
# ---------- 5. 构建最终提示词 ----------
|
||||||
# --- Choose template based on chat type ---
|
# --- Choose template based on chat type ---
|
||||||
logger.debug(f"is_group_chat: {is_group_chat}")
|
logger.debug(f"is_group_chat: {is_group_chat}")
|
||||||
if is_group_chat:
|
if is_group_chat:
|
||||||
@@ -363,7 +414,7 @@ class SubMind:
|
|||||||
)
|
)
|
||||||
# --- End choosing template ---
|
# --- End choosing template ---
|
||||||
|
|
||||||
# ---------- 5. 执行LLM请求并处理响应 ----------
|
# ---------- 6. 执行LLM请求并处理响应 ----------
|
||||||
content = "" # 初始化内容变量
|
content = "" # 初始化内容变量
|
||||||
_reasoning_content = "" # 初始化推理内容变量
|
_reasoning_content = "" # 初始化推理内容变量
|
||||||
|
|
||||||
@@ -412,7 +463,7 @@ class SubMind:
|
|||||||
content = "(不知道该想些什么...)"
|
content = "(不知道该想些什么...)"
|
||||||
logger.warning(f"{self.log_prefix} LLM返回空结果,思考失败。")
|
logger.warning(f"{self.log_prefix} LLM返回空结果,思考失败。")
|
||||||
|
|
||||||
# ---------- 6. 应用概率性去重和修饰 ----------
|
# ---------- 7. 应用概率性去重和修饰 ----------
|
||||||
new_content = content # 保存 LLM 直接输出的结果
|
new_content = content # 保存 LLM 直接输出的结果
|
||||||
try:
|
try:
|
||||||
similarity = calculate_similarity(previous_mind, new_content)
|
similarity = calculate_similarity(previous_mind, new_content)
|
||||||
@@ -485,7 +536,7 @@ class SubMind:
|
|||||||
# 出错时保留原始 content
|
# 出错时保留原始 content
|
||||||
content = new_content
|
content = new_content
|
||||||
|
|
||||||
# ---------- 7. 更新思考状态并返回结果 ----------
|
# ---------- 8. 更新思考状态并返回结果 ----------
|
||||||
logger.info(f"{self.log_prefix} 最终心流思考结果: {content}")
|
logger.info(f"{self.log_prefix} 最终心流思考结果: {content}")
|
||||||
# 更新当前思考内容
|
# 更新当前思考内容
|
||||||
self.update_current_mind(content)
|
self.update_current_mind(content)
|
||||||
|
|||||||
@@ -274,19 +274,17 @@ class SubHeartflowManager:
|
|||||||
async def sbhf_absent_into_focus(self):
|
async def sbhf_absent_into_focus(self):
|
||||||
"""评估子心流兴趣度,满足条件且未达上限则提升到FOCUSED状态(基于start_hfc_probability)"""
|
"""评估子心流兴趣度,满足条件且未达上限则提升到FOCUSED状态(基于start_hfc_probability)"""
|
||||||
try:
|
try:
|
||||||
log_prefix = "[兴趣评估]"
|
|
||||||
# 使用 self.mai_state_info 获取当前状态和限制
|
|
||||||
current_state = self.mai_state_info.get_current_state()
|
current_state = self.mai_state_info.get_current_state()
|
||||||
focused_limit = current_state.get_focused_chat_max_num()
|
focused_limit = current_state.get_focused_chat_max_num()
|
||||||
|
|
||||||
# --- 新增:检查是否允许进入 FOCUS 模式 --- #
|
# --- 新增:检查是否允许进入 FOCUS 模式 --- #
|
||||||
if not global_config.allow_focus_mode:
|
if not global_config.allow_focus_mode:
|
||||||
if int(time.time()) % 60 == 0: # 每60秒输出一次日志避免刷屏
|
if int(time.time()) % 60 == 0: # 每60秒输出一次日志避免刷屏
|
||||||
logger.debug(f"{log_prefix} 配置不允许进入 FOCUSED 状态 (allow_focus_mode=False)")
|
logger.trace(f"未开启 FOCUSED 状态 (allow_focus_mode=False)")
|
||||||
return # 如果不允许,直接返回
|
return # 如果不允许,直接返回
|
||||||
# --- 结束新增 ---
|
# --- 结束新增 ---
|
||||||
|
|
||||||
logger.debug(f"{log_prefix} 当前状态 ({current_state.value}) 可以在{focused_limit}个群激情聊天")
|
logger.info(f"当前状态 ({current_state.value}) 可以在{focused_limit}个群 专注聊天")
|
||||||
|
|
||||||
if focused_limit <= 0:
|
if focused_limit <= 0:
|
||||||
# logger.debug(f"{log_prefix} 当前状态 ({current_state.value}) 不允许 FOCUSED 子心流")
|
# logger.debug(f"{log_prefix} 当前状态 ({current_state.value}) 不允许 FOCUSED 子心流")
|
||||||
@@ -294,35 +292,36 @@ class SubHeartflowManager:
|
|||||||
|
|
||||||
current_focused_count = self.count_subflows_by_state(ChatState.FOCUSED)
|
current_focused_count = self.count_subflows_by_state(ChatState.FOCUSED)
|
||||||
if current_focused_count >= focused_limit:
|
if current_focused_count >= focused_limit:
|
||||||
logger.debug(f"{log_prefix} 已达专注上限 ({current_focused_count}/{focused_limit})")
|
logger.debug(f"已达专注上限 ({current_focused_count}/{focused_limit})")
|
||||||
return
|
return
|
||||||
|
|
||||||
for sub_hf in list(self.subheartflows.values()):
|
for sub_hf in list(self.subheartflows.values()):
|
||||||
flow_id = sub_hf.subheartflow_id
|
flow_id = sub_hf.subheartflow_id
|
||||||
stream_name = chat_manager.get_stream_name(flow_id) or flow_id
|
stream_name = chat_manager.get_stream_name(flow_id) or flow_id
|
||||||
|
|
||||||
logger.debug(f"{log_prefix} 检查子心流: {stream_name},现在状态: {sub_hf.chat_state.chat_status.value}")
|
|
||||||
|
|
||||||
# 跳过非CHAT状态或已经是FOCUSED状态的子心流
|
# 跳过非CHAT状态或已经是FOCUSED状态的子心流
|
||||||
if sub_hf.chat_state.chat_status == ChatState.FOCUSED:
|
if sub_hf.chat_state.chat_status == ChatState.FOCUSED:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
from .mai_state_manager import enable_unlimited_hfc_chat
|
|
||||||
|
|
||||||
|
if sub_hf.interest_chatting.start_hfc_probability == 0:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
logger.debug(f"{stream_name},现在状态: {sub_hf.chat_state.chat_status.value},进入专注概率: {sub_hf.interest_chatting.start_hfc_probability}")
|
||||||
|
|
||||||
|
# 调试用
|
||||||
|
from .mai_state_manager import enable_unlimited_hfc_chat
|
||||||
if not enable_unlimited_hfc_chat:
|
if not enable_unlimited_hfc_chat:
|
||||||
if sub_hf.chat_state.chat_status != ChatState.CHAT:
|
if sub_hf.chat_state.chat_status != ChatState.CHAT:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# 检查是否满足提升概率
|
|
||||||
logger.debug(
|
|
||||||
f"{log_prefix} 检查子心流: {stream_name},现在概率: {sub_hf.interest_chatting.start_hfc_probability}"
|
|
||||||
)
|
|
||||||
if random.random() >= sub_hf.interest_chatting.start_hfc_probability:
|
if random.random() >= sub_hf.interest_chatting.start_hfc_probability:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# 再次检查是否达到上限
|
# 再次检查是否达到上限
|
||||||
if current_focused_count >= focused_limit:
|
if current_focused_count >= focused_limit:
|
||||||
logger.debug(f"{log_prefix} [{stream_name}] 已达专注上限")
|
logger.debug(f"{stream_name} 已达专注上限")
|
||||||
break
|
break
|
||||||
|
|
||||||
# 获取最新状态并执行提升
|
# 获取最新状态并执行提升
|
||||||
@@ -331,7 +330,7 @@ class SubHeartflowManager:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"{log_prefix} [{stream_name}] 触发 认真水群 (概率={current_subflow.interest_chatting.start_hfc_probability:.2f})"
|
f"{stream_name} 触发 认真水群 (概率={current_subflow.interest_chatting.start_hfc_probability:.2f})"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 执行状态提升
|
# 执行状态提升
|
||||||
@@ -372,12 +371,6 @@ class SubHeartflowManager:
|
|||||||
stream_name = chat_manager.get_stream_name(flow_id) or flow_id
|
stream_name = chat_manager.get_stream_name(flow_id) or flow_id
|
||||||
log_prefix = f"[{stream_name}]"
|
log_prefix = f"[{stream_name}]"
|
||||||
|
|
||||||
# --- Private chat check (redundant due to filter above, but safe) ---
|
|
||||||
# if not sub_hf_to_evaluate.is_group_chat:
|
|
||||||
# logger.debug(f"{log_prefix} 是私聊,跳过 CHAT 状态评估。")
|
|
||||||
# return
|
|
||||||
# --- End check ---
|
|
||||||
|
|
||||||
# 3. 检查 CHAT 上限
|
# 3. 检查 CHAT 上限
|
||||||
current_chat_count = self.count_subflows_by_state_nolock(ChatState.CHAT)
|
current_chat_count = self.count_subflows_by_state_nolock(ChatState.CHAT)
|
||||||
if current_chat_count >= chat_limit:
|
if current_chat_count >= chat_limit:
|
||||||
@@ -403,9 +396,9 @@ class SubHeartflowManager:
|
|||||||
first_observation = sub_hf_to_evaluate.observations[0] # 喵~第一个观察者肯定存在的说
|
first_observation = sub_hf_to_evaluate.observations[0] # 喵~第一个观察者肯定存在的说
|
||||||
await first_observation.observe()
|
await first_observation.observe()
|
||||||
current_chat_log = first_observation.talking_message_str or "当前没啥聊天内容。"
|
current_chat_log = first_observation.talking_message_str or "当前没啥聊天内容。"
|
||||||
_observation_summary = f"最近聊了这些:\n{current_chat_log}"
|
_observation_summary = f"在[{stream_name}]这个群中,你最近看群友聊了这些:\n{current_chat_log}"
|
||||||
|
|
||||||
mai_state_description = f"你当前状态: {current_mai_state.value}。"
|
_mai_state_description = f"你当前状态: {current_mai_state.value}。"
|
||||||
individuality = Individuality.get_instance()
|
individuality = Individuality.get_instance()
|
||||||
personality_prompt = individuality.get_prompt(x_person=2, level=2)
|
personality_prompt = individuality.get_prompt(x_person=2, level=2)
|
||||||
prompt_personality = f"你正在扮演名为{individuality.name}的人类,{personality_prompt}"
|
prompt_personality = f"你正在扮演名为{individuality.name}的人类,{personality_prompt}"
|
||||||
@@ -414,27 +407,26 @@ class SubHeartflowManager:
|
|||||||
chat_status_lines = []
|
chat_status_lines = []
|
||||||
if chatting_group_names:
|
if chatting_group_names:
|
||||||
chat_status_lines.append(
|
chat_status_lines.append(
|
||||||
f"正在闲聊 ({current_chat_count}/{chat_limit}): {', '.join(chatting_group_names)}"
|
f"正在这些群闲聊 ({current_chat_count}/{chat_limit}): {', '.join(chatting_group_names)}"
|
||||||
)
|
)
|
||||||
if focused_group_names:
|
if focused_group_names:
|
||||||
chat_status_lines.append(
|
chat_status_lines.append(
|
||||||
f"正在专注 ({current_focused_count}/{focused_limit}): {', '.join(focused_group_names)}"
|
f"正在这些群专注的聊天 ({current_focused_count}/{focused_limit}): {', '.join(focused_group_names)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
chat_status_prompt = "当前没有在任何群聊中。" # 默认消息喵~
|
chat_status_prompt = "当前没有在任何群聊中。" # 默认消息喵~
|
||||||
if chat_status_lines:
|
if chat_status_lines:
|
||||||
chat_status_prompt = "当前聊天情况:\n" + "\n".join(chat_status_lines) # 拼接状态信息
|
chat_status_prompt = "当前聊天情况,你已经参与了下面这几个群的聊天:\n" + "\n".join(chat_status_lines) # 拼接状态信息
|
||||||
|
|
||||||
prompt = (
|
prompt = (
|
||||||
f"{prompt_personality}\\n"
|
f"{prompt_personality}\n"
|
||||||
f"你当前没在 [{stream_name}] 群聊天。\\n"
|
f"{chat_status_prompt}\n" # <-- 喵!用了新的状态信息~
|
||||||
f"{mai_state_description}\\n"
|
f"你当前尚未加入 [{stream_name}] 群聊天。\n"
|
||||||
f"{chat_status_prompt}\\n" # <-- 喵!用了新的状态信息~
|
f"{_observation_summary}\n---\n"
|
||||||
f"{_observation_summary}\\n---\\n"
|
f"基于以上信息,你想不想开始在这个群闲聊?\n"
|
||||||
f"基于以上信息,你想不想开始在这个群闲聊?\\n"
|
f"请说明理由,并以 JSON 格式回答,包含 'decision' (布尔值) 和 'reason' (字符串)。\n"
|
||||||
f"请说明理由,并以 JSON 格式回答,包含 'decision' (布尔值) 和 'reason' (字符串)。\\n"
|
f'例如:{{"decision": true, "reason": "看起来挺热闹的,插个话"}}\n'
|
||||||
f'例如:{{"decision": true, "reason": "看起来挺热闹的,插个话"}}\\n'
|
f'例如:{{"decision": false, "reason": "已经聊了好多,休息一下"}}\n'
|
||||||
f'例如:{{"decision": false, "reason": "已经聊了好多,休息一下"}}\\n'
|
|
||||||
f"请只输出有效的 JSON 对象。"
|
f"请只输出有效的 JSON 对象。"
|
||||||
)
|
)
|
||||||
# --- 结束修改 ---
|
# --- 结束修改 ---
|
||||||
@@ -493,7 +485,6 @@ class SubHeartflowManager:
|
|||||||
checked_count = len(subflows_snapshot)
|
checked_count = len(subflows_snapshot)
|
||||||
|
|
||||||
if not subflows_snapshot:
|
if not subflows_snapshot:
|
||||||
# logger.debug(f"{log_prefix_task} 没有子心流需要检查超时。")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
for sub_hf in subflows_snapshot:
|
for sub_hf in subflows_snapshot:
|
||||||
@@ -509,25 +500,33 @@ class SubHeartflowManager:
|
|||||||
reason = ""
|
reason = ""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 使用变量名 last_bot_dong_zuo_time 替代 last_bot_activity_time
|
|
||||||
last_bot_dong_zuo_time = sub_hf.get_normal_chat_last_speak_time()
|
last_bot_dong_zuo_time = sub_hf.get_normal_chat_last_speak_time()
|
||||||
|
|
||||||
if last_bot_dong_zuo_time > 0:
|
if last_bot_dong_zuo_time > 0:
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
# 使用变量名 time_since_last_bb 替代 time_since_last_reply
|
|
||||||
time_since_last_bb = current_time - last_bot_dong_zuo_time
|
time_since_last_bb = current_time - last_bot_dong_zuo_time
|
||||||
|
minutes_since_last_bb = time_since_last_bb / 60
|
||||||
|
|
||||||
if time_since_last_bb > NORMAL_CHAT_TIMEOUT_SECONDS:
|
# 60分钟强制退出
|
||||||
|
if minutes_since_last_bb >= 60:
|
||||||
should_deactivate = True
|
should_deactivate = True
|
||||||
reason = f"超过 {NORMAL_CHAT_TIMEOUT_SECONDS / 60:.0f} 分钟没 BB"
|
reason = "超过60分钟未发言,强制退出"
|
||||||
logger.info(
|
else:
|
||||||
f"{log_prefix} 太久没有发言 ({reason}),不看了。上次活动时间: {last_bot_dong_zuo_time:.0f}"
|
# 根据时间区间确定退出概率
|
||||||
)
|
exit_probability = 0
|
||||||
# else:
|
if minutes_since_last_bb < 5:
|
||||||
# logger.debug(f"{log_prefix} Bot活动时间未超时 ({time_since_last_bb:.0f}s < {NORMAL_CHAT_TIMEOUT_SECONDS}s),保持 CHAT 状态。")
|
exit_probability = 0.01 # 1%
|
||||||
# else:
|
elif minutes_since_last_bb < 15:
|
||||||
# 如果没有记录到Bot的活动时间,暂时不因为超时而转换状态
|
exit_probability = 0.02 # 2%
|
||||||
# logger.debug(f"{log_prefix} 未找到有效的 Bot 最后活动时间记录,不执行超时检查。")
|
elif minutes_since_last_bb < 30:
|
||||||
|
exit_probability = 0.04 # 4%
|
||||||
|
else:
|
||||||
|
exit_probability = 0.08 # 8%
|
||||||
|
|
||||||
|
# 随机判断是否退出
|
||||||
|
if random.random() < exit_probability:
|
||||||
|
should_deactivate = True
|
||||||
|
reason = f"已{minutes_since_last_bb:.1f}分钟未发言,触发{exit_probability*100:.0f}%退出概率"
|
||||||
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
logger.error(
|
logger.error(
|
||||||
@@ -536,7 +535,7 @@ class SubHeartflowManager:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"{log_prefix} 检查 Bot 超时状态时出错: {e}", exc_info=True)
|
logger.error(f"{log_prefix} 检查 Bot 超时状态时出错: {e}", exc_info=True)
|
||||||
|
|
||||||
# --- 执行状态转换(如果超时) ---
|
# 执行状态转换(如果超时)
|
||||||
if should_deactivate:
|
if should_deactivate:
|
||||||
logger.debug(f"{log_prefix} 因超时 ({reason}),尝试转换为 ABSENT 状态。")
|
logger.debug(f"{log_prefix} 因超时 ({reason}),尝试转换为 ABSENT 状态。")
|
||||||
await sub_hf.change_chat_state(ChatState.ABSENT)
|
await sub_hf.change_chat_state(ChatState.ABSENT)
|
||||||
@@ -816,11 +815,6 @@ class SubHeartflowManager:
|
|||||||
if has_new:
|
if has_new:
|
||||||
is_active = True
|
is_active = True
|
||||||
logger.debug(f"{log_prefix} 检测到新消息,标记为活跃。")
|
logger.debug(f"{log_prefix} 检测到新消息,标记为活跃。")
|
||||||
# 可选:检查兴趣度是否大于0 (如果需要)
|
|
||||||
# interest_level = await sub_hf.interest_chatting.get_interest()
|
|
||||||
# if interest_level > 0:
|
|
||||||
# is_active = True
|
|
||||||
# logger.debug(f"{log_prefix} 检测到兴趣度 > 0 ({interest_level:.2f}),标记为活跃。")
|
|
||||||
else:
|
else:
|
||||||
logger.warning(f"{log_prefix} 无法获取主要观察者来检查活动状态。")
|
logger.warning(f"{log_prefix} 无法获取主要观察者来检查活动状态。")
|
||||||
|
|
||||||
@@ -850,56 +844,3 @@ class SubHeartflowManager:
|
|||||||
logger.debug(
|
logger.debug(
|
||||||
f"{log_prefix_task} 完成,共检查 {checked_count} 个私聊,{transitioned_count} 个转换为 FOCUSED。"
|
f"{log_prefix_task} 完成,共检查 {checked_count} 个私聊,{transitioned_count} 个转换为 FOCUSED。"
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- 结束新增 --- #
|
|
||||||
|
|
||||||
# --- 结束新增:处理来自 HeartFChatting 的状态转换请求 --- #
|
|
||||||
|
|
||||||
# 临时函数,用于GUI切换,有api后删除
|
|
||||||
# async def detect_command_from_gui(self):
|
|
||||||
# """检测来自GUI的命令"""
|
|
||||||
# command_file = Path("temp_command/gui_command.json")
|
|
||||||
# if not command_file.exists():
|
|
||||||
# return
|
|
||||||
|
|
||||||
# try:
|
|
||||||
# # 读取并解析命令文件
|
|
||||||
# command_data = json.loads(command_file.read_text())
|
|
||||||
# subflow_id = command_data.get("subflow_id")
|
|
||||||
# target_state = command_data.get("target_state")
|
|
||||||
|
|
||||||
# if not subflow_id or not target_state:
|
|
||||||
# logger.warning("GUI命令文件格式不正确,缺少必要字段")
|
|
||||||
# return
|
|
||||||
|
|
||||||
# # 尝试转换为ChatState枚举
|
|
||||||
# try:
|
|
||||||
# target_state_enum = ChatState[target_state.upper()]
|
|
||||||
# except KeyError:
|
|
||||||
# logger.warning(f"无效的目标状态: {target_state}")
|
|
||||||
# command_file.unlink()
|
|
||||||
# return
|
|
||||||
|
|
||||||
# # 执行状态转换
|
|
||||||
# await self.force_change_by_gui(subflow_id, target_state_enum)
|
|
||||||
|
|
||||||
# # 转换成功后删除文件
|
|
||||||
# command_file.unlink()
|
|
||||||
# logger.debug(f"已处理GUI命令并删除命令文件: {command_file}")
|
|
||||||
|
|
||||||
# except json.JSONDecodeError:
|
|
||||||
# logger.warning("GUI命令文件不是有效的JSON格式")
|
|
||||||
# except Exception as e:
|
|
||||||
# logger.error(f"处理GUI命令时发生错误: {e}", exc_info=True)
|
|
||||||
|
|
||||||
# async def force_change_by_gui(self, subflow_id: Any, target_state: ChatState):
|
|
||||||
# """强制改变指定子心流的状态"""
|
|
||||||
# async with self._lock:
|
|
||||||
# subflow = self.subheartflows.get(subflow_id)
|
|
||||||
# if not subflow:
|
|
||||||
# logger.warning(f"[强制状态转换] 尝试转换不存在的子心流 {subflow_id} 到 {target_state.value}")
|
|
||||||
# return
|
|
||||||
# await subflow.change_chat_state(target_state)
|
|
||||||
# logger.info(f"[强制状态转换] 成功将 {subflow_id} 的状态转换为 {target_state.value}")
|
|
||||||
|
|
||||||
# --- 结束新增 --- #
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ logger = get_logger("chat")
|
|||||||
|
|
||||||
|
|
||||||
class NormalChat:
|
class NormalChat:
|
||||||
def __init__(self, chat_stream: ChatStream, interest_dict: dict):
|
def __init__(self, chat_stream: ChatStream, interest_dict: dict = None):
|
||||||
"""初始化 NormalChat 实例。只进行同步操作。"""
|
"""初始化 NormalChat 实例。只进行同步操作。"""
|
||||||
|
|
||||||
# Basic info from chat_stream (sync)
|
# Basic info from chat_stream (sync)
|
||||||
|
|||||||
Reference in New Issue
Block a user