feat:优化工具调用的得到的信息调用和缓存
This commit is contained in:
@@ -9,7 +9,7 @@ class CompareNumbersTool(BaseTool):
|
|||||||
"""比较两个数大小的工具"""
|
"""比较两个数大小的工具"""
|
||||||
|
|
||||||
name = "compare_numbers"
|
name = "compare_numbers"
|
||||||
description = "比较两个数的大小,返回较大的数"
|
description = "使用工具 比较两个数的大小,返回较大的数"
|
||||||
parameters = {
|
parameters = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -39,10 +39,10 @@ class CompareNumbersTool(BaseTool):
|
|||||||
else:
|
else:
|
||||||
result = f"{num1} 等于 {num2}"
|
result = f"{num1} 等于 {num2}"
|
||||||
|
|
||||||
return {"name": self.name, "content": result}
|
return {"type": "comparison_result", "id": f"{num1}_vs_{num2}", "content": result}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"比较数字失败: {str(e)}")
|
logger.error(f"比较数字失败: {str(e)}")
|
||||||
return {"name": self.name, "content": f"比较数字失败: {str(e)}"}
|
return {"type": "info", "id": f"{num1}_vs_{num2}", "content": f"比较数字失败,炸了: {str(e)}"}
|
||||||
|
|
||||||
|
|
||||||
# 注册工具
|
# 注册工具
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class SearchKnowledgeTool(BaseTool):
|
|||||||
"""从知识库中搜索相关信息的工具"""
|
"""从知识库中搜索相关信息的工具"""
|
||||||
|
|
||||||
name = "search_knowledge"
|
name = "search_knowledge"
|
||||||
description = "从知识库中搜索相关信息"
|
description = "使用工具从知识库中搜索相关信息"
|
||||||
parameters = {
|
parameters = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -42,11 +42,11 @@ class SearchKnowledgeTool(BaseTool):
|
|||||||
content = f"你知道这些知识: {knowledge_info}"
|
content = f"你知道这些知识: {knowledge_info}"
|
||||||
else:
|
else:
|
||||||
content = f"你不太了解有关{query}的知识"
|
content = f"你不太了解有关{query}的知识"
|
||||||
return {"name": "search_knowledge", "content": content}
|
return {"type": "knowledge", "id": query, "content": content}
|
||||||
return {"name": "search_knowledge", "content": f"无法获取关于'{query}'的嵌入向量"}
|
return {"type": "info", "id": query, "content": f"无法获取关于'{query}'的嵌入向量,你知识库炸了"}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"知识库搜索工具执行失败: {str(e)}")
|
logger.error(f"知识库搜索工具执行失败: {str(e)}")
|
||||||
return {"name": "search_knowledge", "content": f"知识库搜索失败: {str(e)}"}
|
return {"type": "info", "id": query, "content": f"知识库搜索失败,炸了: {str(e)}"}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_info_from_db(
|
def get_info_from_db(
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class GetMemoryTool(BaseTool):
|
|||||||
"""从记忆系统中获取相关记忆的工具"""
|
"""从记忆系统中获取相关记忆的工具"""
|
||||||
|
|
||||||
name = "get_memory"
|
name = "get_memory"
|
||||||
description = "从记忆系统中获取相关记忆"
|
description = "使用工具从记忆系统中获取相关记忆"
|
||||||
parameters = {
|
parameters = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -53,10 +53,11 @@ class GetMemoryTool(BaseTool):
|
|||||||
else:
|
else:
|
||||||
content = f"{topic}的记忆,你记不太清"
|
content = f"{topic}的记忆,你记不太清"
|
||||||
|
|
||||||
return {"name": "get_memory", "content": content}
|
return {"type": "memory", "id": topic_list, "content": content}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"记忆获取工具执行失败: {str(e)}")
|
logger.error(f"记忆获取工具执行失败: {str(e)}")
|
||||||
return {"name": "get_memory", "content": f"记忆获取失败: {str(e)}"}
|
# 在失败时也保持格式一致,但id可能不适用或设为None/Error
|
||||||
|
return {"type": "memory_error", "id": topic_list, "content": f"记忆获取失败: {str(e)}"}
|
||||||
|
|
||||||
|
|
||||||
# 注册工具
|
# 注册工具
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from src.do_tool.tool_can_use.base_tool import BaseTool
|
|||||||
from src.common.logger_manager import get_logger
|
from src.common.logger_manager import get_logger
|
||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
import time
|
||||||
|
|
||||||
logger = get_logger("get_time_date")
|
logger = get_logger("get_time_date")
|
||||||
|
|
||||||
@@ -32,6 +33,7 @@ class GetCurrentDateTimeTool(BaseTool):
|
|||||||
current_weekday = datetime.now().strftime("%A")
|
current_weekday = datetime.now().strftime("%A")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"name": "get_current_date_time",
|
"type": "time_info",
|
||||||
|
"id": f"time_info_{time.time()}",
|
||||||
"content": f"当前时间: {current_time}, 日期: {current_date}, 年份: {current_year}, 星期: {current_weekday}",
|
"content": f"当前时间: {current_time}, 日期: {current_date}, 年份: {current_year}, 星期: {current_weekday}",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,11 +46,14 @@ class SearchKnowledgeFromLPMMTool(BaseTool):
|
|||||||
content = f"你知道这些知识: {knowledge_info}"
|
content = f"你知道这些知识: {knowledge_info}"
|
||||||
else:
|
else:
|
||||||
content = f"你不太了解有关{query}的知识"
|
content = f"你不太了解有关{query}的知识"
|
||||||
return {"name": "search_knowledge", "content": content}
|
return {"type": "lpmm_knowledge", "id": query, "content": content}
|
||||||
return {"name": "search_knowledge", "content": f"无法获取关于'{query}'的嵌入向量"}
|
# 如果获取嵌入失败
|
||||||
|
return {"type": "info", "id": query, "content": f"无法获取关于'{query}'的嵌入向量,你lpmm知识库炸了"}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"知识库搜索工具执行失败: {str(e)}")
|
logger.error(f"知识库搜索工具执行失败: {str(e)}")
|
||||||
return {"name": "search_knowledge", "content": f"知识库搜索失败: {str(e)}"}
|
# 在其他异常情况下,确保 id 仍然是 query (如果它被定义了)
|
||||||
|
query_id = query if 'query' in locals() else 'unknown_query'
|
||||||
|
return {"type": "info", "id": query_id, "content": f"lpmm知识库搜索失败,炸了: {str(e)}"}
|
||||||
|
|
||||||
# def get_info_from_db(
|
# def get_info_from_db(
|
||||||
# self, query_embedding: list, limit: int = 1, threshold: float = 0.5, return_raw: bool = False
|
# self, query_embedding: list, limit: int = 1, threshold: float = 0.5, return_raw: bool = False
|
||||||
@@ -133,6 +136,25 @@ class SearchKnowledgeFromLPMMTool(BaseTool):
|
|||||||
# # 返回所有找到的内容,用换行分隔
|
# # 返回所有找到的内容,用换行分隔
|
||||||
# return "\n".join(str(result["content"]) for result in results)
|
# return "\n".join(str(result["content"]) for result in results)
|
||||||
|
|
||||||
|
def _format_results(self, results: list) -> str:
|
||||||
|
"""格式化结果"""
|
||||||
|
if not results:
|
||||||
|
return "未找到相关知识。"
|
||||||
|
|
||||||
|
formatted_string = "我找到了一些相关知识:\n"
|
||||||
|
for i, result in enumerate(results):
|
||||||
|
chunk_id = result.get("chunk_id")
|
||||||
|
text = result.get("text", "")
|
||||||
|
source = result.get("source", "未知来源")
|
||||||
|
source_type = result.get("source_type", "未知类型")
|
||||||
|
similarity = result.get("similarity", 0.0)
|
||||||
|
|
||||||
|
formatted_string += f"{i + 1}. (相似度: {similarity:.2f}) 类型: {source_type}, 来源: {source} \n内容片段: {text}\n\n"
|
||||||
|
# 暂时去掉chunk_id
|
||||||
|
# formatted_string += f"{i + 1}. (相似度: {similarity:.2f}) 类型: {source_type}, 来源: {source}, Chunk ID: {chunk_id} \n内容片段: {text}\n\n"
|
||||||
|
|
||||||
|
return formatted_string
|
||||||
|
|
||||||
|
|
||||||
# 注册工具
|
# 注册工具
|
||||||
# register_tool(SearchKnowledgeTool)
|
# register_tool(SearchKnowledgeTool)
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
from src.do_tool.tool_can_use.base_tool import BaseTool, register_tool
|
from src.do_tool.tool_can_use.base_tool import BaseTool, register_tool
|
||||||
from src.plugins.person_info.person_info import person_info_manager
|
from src.plugins.person_info.person_info import person_info_manager
|
||||||
from src.common.logger_manager import get_logger
|
from src.common.logger_manager import get_logger
|
||||||
|
from src.plugins.person_info.relationship_manager import relationship_manager
|
||||||
import json
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
logger = get_logger("rename_person_tool")
|
logger = get_logger("rename_person_tool")
|
||||||
|
|
||||||
@@ -82,10 +84,10 @@ class RenamePersonTool(BaseTool):
|
|||||||
new_name = result["nickname"]
|
new_name = result["nickname"]
|
||||||
reason = result.get("reason", "未提供理由")
|
reason = result.get("reason", "未提供理由")
|
||||||
logger.info(f"成功为用户 {person_id} 取了新昵称: {new_name}")
|
logger.info(f"成功为用户 {person_id} 取了新昵称: {new_name}")
|
||||||
return {
|
|
||||||
"name": self.name,
|
content = f"已成功将用户 {person_name_to_find} 的备注名更新为 {new_name}"
|
||||||
"content": f"好的,我已经给 '{person_name_to_find}' 取了新昵称:'{new_name}'。因为:{reason}"
|
logger.info(content)
|
||||||
}
|
return {"type": "info", "id": f"rename_success_{time.time()}", "content": content}
|
||||||
else:
|
else:
|
||||||
logger.warning(f"为用户 {person_id} 调用 qv_person_name 后未能成功获取新昵称。")
|
logger.warning(f"为用户 {person_id} 调用 qv_person_name 后未能成功获取新昵称。")
|
||||||
# 尝试从内存中获取可能已经更新的名字
|
# 尝试从内存中获取可能已经更新的名字
|
||||||
@@ -102,11 +104,9 @@ class RenamePersonTool(BaseTool):
|
|||||||
}
|
}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"执行 rename_person 工具时出错: {e}", exc_info=True)
|
error_msg = f"重命名失败: {str(e)}"
|
||||||
return {
|
logger.error(error_msg, exc_info=True)
|
||||||
"name": self.name,
|
return {"type": "info_error", "id": f"rename_error_{time.time()}", "content": error_msg}
|
||||||
"content": f"执行重命名操作时遇到内部错误: {e}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 注册工具
|
# 注册工具
|
||||||
register_tool(RenamePersonTool)
|
register_tool(RenamePersonTool)
|
||||||
@@ -79,9 +79,8 @@ class ChattingObservation(Observation):
|
|||||||
async def initialize(self):
|
async def initialize(self):
|
||||||
# --- Use utility function to determine chat type and fetch info ---
|
# --- Use utility function to determine chat type and fetch info ---
|
||||||
self.is_group_chat, self.chat_target_info = await get_chat_type_and_target_info(self.chat_id)
|
self.is_group_chat, self.chat_target_info = await get_chat_type_and_target_info(self.chat_id)
|
||||||
logger.debug(
|
# logger.debug(f"is_group_chat: {self.is_group_chat}")
|
||||||
f"ChattingObservation {self.chat_id} initialized: is_group={self.is_group_chat}, target_info={self.chat_target_info}"
|
# logger.debug(f"chat_target_info: {self.chat_target_info}")
|
||||||
)
|
|
||||||
# --- End using utility function ---
|
# --- End using utility function ---
|
||||||
|
|
||||||
# Fetch initial messages (existing logic)
|
# Fetch initial messages (existing logic)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from .observation import Observation
|
from .observation import Observation, ChattingObservation
|
||||||
from src.plugins.models.utils_model import LLMRequest
|
from src.plugins.models.utils_model import LLMRequest
|
||||||
from src.config.config import global_config
|
from src.config.config import global_config
|
||||||
import time
|
import time
|
||||||
@@ -114,7 +114,7 @@ def calculate_replacement_probability(similarity: float) -> float:
|
|||||||
|
|
||||||
|
|
||||||
class SubMind:
|
class SubMind:
|
||||||
def __init__(self, subheartflow_id: str, chat_state: ChatStateInfo, observations: Observation):
|
def __init__(self, subheartflow_id: str, chat_state: ChatStateInfo, observations: ChattingObservation):
|
||||||
self.last_active_time = None
|
self.last_active_time = None
|
||||||
self.subheartflow_id = subheartflow_id
|
self.subheartflow_id = subheartflow_id
|
||||||
|
|
||||||
@@ -130,10 +130,41 @@ class SubMind:
|
|||||||
|
|
||||||
self.current_mind = ""
|
self.current_mind = ""
|
||||||
self.past_mind = []
|
self.past_mind = []
|
||||||
self.structured_info = {}
|
self.structured_info = []
|
||||||
|
self.structured_info_str = ""
|
||||||
|
|
||||||
name = chat_manager.get_stream_name(self.subheartflow_id)
|
name = chat_manager.get_stream_name(self.subheartflow_id)
|
||||||
self.log_prefix = f"[{name}] "
|
self.log_prefix = f"[{name}] "
|
||||||
|
self._update_structured_info_str()
|
||||||
|
|
||||||
|
def _update_structured_info_str(self):
|
||||||
|
"""根据 structured_info 更新 structured_info_str"""
|
||||||
|
if not self.structured_info:
|
||||||
|
self.structured_info_str = ""
|
||||||
|
return
|
||||||
|
|
||||||
|
lines = ["【信息】"]
|
||||||
|
for item in self.structured_info:
|
||||||
|
# 简化展示,突出内容和类型,包含TTL供调试
|
||||||
|
type_str = item.get('type', '未知类型')
|
||||||
|
content_str = item.get('content', '')
|
||||||
|
ttl = item.get('ttl', '?')
|
||||||
|
|
||||||
|
if type_str == "info":
|
||||||
|
lines.append(f"刚刚: {content_str}")
|
||||||
|
elif type_str == "memory":
|
||||||
|
lines.append(f"{content_str}")
|
||||||
|
elif type_str == "comparison_result":
|
||||||
|
lines.append(f"数字大小比较结果: {content_str}")
|
||||||
|
elif type_str == "time_info":
|
||||||
|
lines.append(f"{content_str}")
|
||||||
|
elif type_str == "lpmm_knowledge":
|
||||||
|
lines.append(f"你知道:{content_str}")
|
||||||
|
else:
|
||||||
|
lines.append(f"{type_str}的信息: {content_str}")
|
||||||
|
|
||||||
|
self.structured_info_str = "\n".join(lines)
|
||||||
|
logger.debug(f"{self.log_prefix} 更新 structured_info_str: \n{self.structured_info_str}")
|
||||||
|
|
||||||
async def do_thinking_before_reply(self, history_cycle: list[CycleInfo] = None):
|
async def do_thinking_before_reply(self, history_cycle: list[CycleInfo] = None):
|
||||||
"""
|
"""
|
||||||
@@ -145,19 +176,36 @@ class SubMind:
|
|||||||
# 更新活跃时间
|
# 更新活跃时间
|
||||||
self.last_active_time = time.time()
|
self.last_active_time = time.time()
|
||||||
|
|
||||||
|
# ---------- 0. 更新和清理 structured_info ----------
|
||||||
|
if self.structured_info:
|
||||||
|
logger.debug(f"{self.log_prefix} 更新前的 structured_info: {safe_json_dumps(self.structured_info, ensure_ascii=False)}")
|
||||||
|
updated_info = []
|
||||||
|
for item in self.structured_info:
|
||||||
|
item['ttl'] -= 1
|
||||||
|
if item['ttl'] > 0:
|
||||||
|
updated_info.append(item)
|
||||||
|
else:
|
||||||
|
logger.debug(f"{self.log_prefix} 移除过期的 structured_info 项: {item['id']}")
|
||||||
|
self.structured_info = updated_info
|
||||||
|
logger.debug(f"{self.log_prefix} 更新后的 structured_info: {safe_json_dumps(self.structured_info, ensure_ascii=False)}")
|
||||||
|
self._update_structured_info_str()
|
||||||
|
logger.debug(f"{self.log_prefix} 当前完整的 structured_info: {safe_json_dumps(self.structured_info, ensure_ascii=False)}")
|
||||||
|
|
||||||
# ---------- 1. 准备基础数据 ----------
|
# ---------- 1. 准备基础数据 ----------
|
||||||
# 获取现有想法和情绪状态
|
# 获取现有想法和情绪状态
|
||||||
previous_mind = self.current_mind if self.current_mind else ""
|
previous_mind = self.current_mind if self.current_mind else ""
|
||||||
mood_info = self.chat_state.mood
|
mood_info = self.chat_state.mood
|
||||||
|
|
||||||
# 获取观察对象
|
# 获取观察对象
|
||||||
observation = self.observations[0] if self.observations else None
|
observation: ChattingObservation = self.observations[0] if self.observations else None
|
||||||
if not observation or not hasattr(observation, "is_group_chat"): # Ensure it's ChattingObservation or similar
|
if not observation or not hasattr(observation, "is_group_chat"): # Ensure it's ChattingObservation or similar
|
||||||
logger.error(f"{self.log_prefix} 无法获取有效的观察对象或缺少聊天类型信息")
|
logger.error(f"{self.log_prefix} 无法获取有效的观察对象或缺少聊天类型信息")
|
||||||
self.update_current_mind("(观察出错了...)")
|
self.update_current_mind("(观察出错了...)")
|
||||||
return self.current_mind, self.past_mind
|
return self.current_mind, self.past_mind
|
||||||
|
|
||||||
is_group_chat = observation.is_group_chat
|
is_group_chat = observation.is_group_chat
|
||||||
|
# logger.debug(f"is_group_chat: {is_group_chat}")
|
||||||
|
|
||||||
chat_target_info = observation.chat_target_info
|
chat_target_info = observation.chat_target_info
|
||||||
chat_target_name = "对方" # Default for private
|
chat_target_name = "对方" # Default for private
|
||||||
if not is_group_chat and chat_target_info:
|
if not is_group_chat and chat_target_info:
|
||||||
@@ -277,10 +325,11 @@ class SubMind:
|
|||||||
|
|
||||||
# ---------- 4. 构建最终提示词 ----------
|
# ---------- 4. 构建最终提示词 ----------
|
||||||
# --- Choose template based on chat type ---
|
# --- Choose template based on chat type ---
|
||||||
|
logger.debug(f"is_group_chat: {is_group_chat}")
|
||||||
if is_group_chat:
|
if is_group_chat:
|
||||||
template_name = "sub_heartflow_prompt_before"
|
template_name = "sub_heartflow_prompt_before"
|
||||||
prompt = (await global_prompt_manager.get_prompt_async(template_name)).format(
|
prompt = (await global_prompt_manager.get_prompt_async(template_name)).format(
|
||||||
extra_info="",
|
extra_info=self.structured_info_str,
|
||||||
prompt_personality=prompt_personality,
|
prompt_personality=prompt_personality,
|
||||||
relation_prompt=relation_prompt,
|
relation_prompt=relation_prompt,
|
||||||
bot_name=individuality.name,
|
bot_name=individuality.name,
|
||||||
@@ -295,7 +344,7 @@ class SubMind:
|
|||||||
else: # Private chat
|
else: # Private chat
|
||||||
template_name = "sub_heartflow_prompt_private_before"
|
template_name = "sub_heartflow_prompt_private_before"
|
||||||
prompt = (await global_prompt_manager.get_prompt_async(template_name)).format(
|
prompt = (await global_prompt_manager.get_prompt_async(template_name)).format(
|
||||||
extra_info="",
|
extra_info=self.structured_info_str,
|
||||||
prompt_personality=prompt_personality,
|
prompt_personality=prompt_personality,
|
||||||
relation_prompt=relation_prompt, # Might need adjustment for private context
|
relation_prompt=relation_prompt, # Might need adjustment for private context
|
||||||
bot_name=individuality.name,
|
bot_name=individuality.name,
|
||||||
@@ -447,7 +496,7 @@ class SubMind:
|
|||||||
tool_instance: 工具使用器实例
|
tool_instance: 工具使用器实例
|
||||||
"""
|
"""
|
||||||
tool_results = []
|
tool_results = []
|
||||||
structured_info = {} # 动态生成键
|
new_structured_items = [] # 收集新产生的结构化信息
|
||||||
|
|
||||||
# 执行所有工具调用
|
# 执行所有工具调用
|
||||||
for tool_call in tool_calls:
|
for tool_call in tool_calls:
|
||||||
@@ -455,23 +504,34 @@ class SubMind:
|
|||||||
result = await tool_instance._execute_tool_call(tool_call)
|
result = await tool_instance._execute_tool_call(tool_call)
|
||||||
if result:
|
if result:
|
||||||
tool_results.append(result)
|
tool_results.append(result)
|
||||||
|
# 创建新的结构化信息项
|
||||||
|
new_item = {
|
||||||
|
"type": result.get("type", "unknown_type"), # 使用 'type' 键
|
||||||
|
"id": result.get("id", f"fallback_id_{time.time()}"), # 使用 'id' 键
|
||||||
|
"content": result.get("content", ""), # 'content' 键保持不变
|
||||||
|
"ttl": 3
|
||||||
|
}
|
||||||
|
new_structured_items.append(new_item)
|
||||||
|
|
||||||
# 使用工具名称作为键
|
|
||||||
tool_name = result["name"]
|
|
||||||
if tool_name not in structured_info:
|
|
||||||
structured_info[tool_name] = []
|
|
||||||
|
|
||||||
structured_info[tool_name].append({"name": result["name"], "content": result["content"]})
|
|
||||||
except Exception as tool_e:
|
except Exception as tool_e:
|
||||||
logger.error(f"[{self.subheartflow_id}] 工具执行失败: {tool_e}")
|
logger.error(f"[{self.subheartflow_id}] 工具执行失败: {tool_e}")
|
||||||
|
logger.error(traceback.format_exc()) # 添加 traceback 记录
|
||||||
|
|
||||||
# 如果有工具结果,记录并更新结构化信息
|
# 如果有新的工具结果,记录并更新结构化信息
|
||||||
if structured_info:
|
if new_structured_items:
|
||||||
logger.debug(f"工具调用收集到结构化信息: {safe_json_dumps(structured_info, ensure_ascii=False)}")
|
self.structured_info.extend(new_structured_items) # 添加到现有列表
|
||||||
self.structured_info = structured_info
|
logger.debug(f"工具调用收集到新的结构化信息: {safe_json_dumps(new_structured_items, ensure_ascii=False)}")
|
||||||
|
# logger.debug(f"当前完整的 structured_info: {safe_json_dumps(self.structured_info, ensure_ascii=False)}") # 可以取消注释以查看完整列表
|
||||||
|
self._update_structured_info_str() # 添加新信息后,更新字符串表示
|
||||||
|
|
||||||
def update_current_mind(self, response):
|
def update_current_mind(self, response):
|
||||||
self.past_mind.append(self.current_mind)
|
if self.current_mind: # 只有当 current_mind 非空时才添加到 past_mind
|
||||||
|
self.past_mind.append(self.current_mind)
|
||||||
|
# 可以考虑限制 past_mind 的大小,例如:
|
||||||
|
# max_past_mind_size = 10
|
||||||
|
# if len(self.past_mind) > max_past_mind_size:
|
||||||
|
# self.past_mind.pop(0) # 移除最旧的
|
||||||
|
|
||||||
self.current_mind = response
|
self.current_mind = response
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -127,6 +127,8 @@ class SubHeartflowManager:
|
|||||||
|
|
||||||
# 添加聊天观察者
|
# 添加聊天观察者
|
||||||
observation = ChattingObservation(chat_id=subheartflow_id)
|
observation = ChattingObservation(chat_id=subheartflow_id)
|
||||||
|
await observation.initialize()
|
||||||
|
|
||||||
new_subflow.add_observation(observation)
|
new_subflow.add_observation(observation)
|
||||||
|
|
||||||
# 注册子心流
|
# 注册子心流
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ async def get_chat_type_and_target_info(chat_id: str) -> Tuple[bool, Optional[Di
|
|||||||
Tuple[bool, Optional[Dict]]:
|
Tuple[bool, Optional[Dict]]:
|
||||||
- bool: 是否为群聊 (True 是群聊, False 是私聊或未知)
|
- bool: 是否为群聊 (True 是群聊, False 是私聊或未知)
|
||||||
- Optional[Dict]: 如果是私聊,包含对方信息的字典;否则为 None。
|
- Optional[Dict]: 如果是私聊,包含对方信息的字典;否则为 None。
|
||||||
字典包含: platform, user_id, user_nickname, person_id, person_name
|
字典包含: platform, user_id, user_nickname, person_id, person_name
|
||||||
"""
|
"""
|
||||||
is_group_chat = False # Default to private/unknown
|
is_group_chat = False # Default to private/unknown
|
||||||
chat_target_info = None
|
chat_target_info = None
|
||||||
|
|||||||
@@ -31,19 +31,21 @@ class Message(MessageBase):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
message_id: str,
|
message_id: str,
|
||||||
timestamp: float,
|
|
||||||
chat_stream: ChatStream,
|
chat_stream: ChatStream,
|
||||||
user_info: UserInfo,
|
user_info: UserInfo,
|
||||||
message_segment: Optional[Seg] = None,
|
message_segment: Optional[Seg] = None,
|
||||||
|
timestamp: Optional[float] = None,
|
||||||
reply: Optional["MessageRecv"] = None,
|
reply: Optional["MessageRecv"] = None,
|
||||||
detailed_plain_text: str = "",
|
detailed_plain_text: str = "",
|
||||||
processed_plain_text: str = "",
|
processed_plain_text: str = "",
|
||||||
):
|
):
|
||||||
|
# 使用传入的时间戳或当前时间
|
||||||
|
current_timestamp = timestamp if timestamp is not None else round(time.time(), 3)
|
||||||
# 构造基础消息信息
|
# 构造基础消息信息
|
||||||
message_info = BaseMessageInfo(
|
message_info = BaseMessageInfo(
|
||||||
platform=chat_stream.platform,
|
platform=chat_stream.platform,
|
||||||
message_id=message_id,
|
message_id=message_id,
|
||||||
time=timestamp,
|
time=current_timestamp,
|
||||||
group_info=chat_stream.group_info,
|
group_info=chat_stream.group_info,
|
||||||
user_info=user_info,
|
user_info=user_info,
|
||||||
)
|
)
|
||||||
@@ -164,11 +166,12 @@ class MessageProcessBase(Message):
|
|||||||
message_segment: Optional[Seg] = None,
|
message_segment: Optional[Seg] = None,
|
||||||
reply: Optional["MessageRecv"] = None,
|
reply: Optional["MessageRecv"] = None,
|
||||||
thinking_start_time: float = 0,
|
thinking_start_time: float = 0,
|
||||||
|
timestamp: Optional[float] = None,
|
||||||
):
|
):
|
||||||
# 调用父类初始化
|
# 调用父类初始化,传递时间戳
|
||||||
super().__init__(
|
super().__init__(
|
||||||
message_id=message_id,
|
message_id=message_id,
|
||||||
timestamp=round(time.time(), 3), # 保留3位小数
|
timestamp=timestamp,
|
||||||
chat_stream=chat_stream,
|
chat_stream=chat_stream,
|
||||||
user_info=bot_user_info,
|
user_info=bot_user_info,
|
||||||
message_segment=message_segment,
|
message_segment=message_segment,
|
||||||
@@ -238,8 +241,9 @@ class MessageThinking(MessageProcessBase):
|
|||||||
bot_user_info: UserInfo,
|
bot_user_info: UserInfo,
|
||||||
reply: Optional["MessageRecv"] = None,
|
reply: Optional["MessageRecv"] = None,
|
||||||
thinking_start_time: float = 0,
|
thinking_start_time: float = 0,
|
||||||
|
timestamp: Optional[float] = None,
|
||||||
):
|
):
|
||||||
# 调用父类初始化
|
# 调用父类初始化,传递时间戳
|
||||||
super().__init__(
|
super().__init__(
|
||||||
message_id=message_id,
|
message_id=message_id,
|
||||||
chat_stream=chat_stream,
|
chat_stream=chat_stream,
|
||||||
@@ -247,6 +251,7 @@ class MessageThinking(MessageProcessBase):
|
|||||||
message_segment=None, # 思考状态不需要消息段
|
message_segment=None, # 思考状态不需要消息段
|
||||||
reply=reply,
|
reply=reply,
|
||||||
thinking_start_time=thinking_start_time,
|
thinking_start_time=thinking_start_time,
|
||||||
|
timestamp=timestamp,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 思考状态特有属性
|
# 思考状态特有属性
|
||||||
|
|||||||
@@ -107,53 +107,6 @@ async def get_embedding(text, request_type="embedding"):
|
|||||||
return embedding
|
return embedding
|
||||||
|
|
||||||
|
|
||||||
async def get_recent_group_messages(chat_id: str, limit: int = 12) -> list:
|
|
||||||
"""从数据库获取群组最近的消息记录
|
|
||||||
|
|
||||||
Args:
|
|
||||||
chat_id: 群组ID
|
|
||||||
limit: 获取消息数量,默认12条
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list: Message对象列表,按时间正序排列
|
|
||||||
"""
|
|
||||||
|
|
||||||
# 从数据库获取最近消息
|
|
||||||
recent_messages = list(
|
|
||||||
db.messages.find(
|
|
||||||
{"chat_id": chat_id},
|
|
||||||
)
|
|
||||||
.sort("time", -1)
|
|
||||||
.limit(limit)
|
|
||||||
)
|
|
||||||
|
|
||||||
if not recent_messages:
|
|
||||||
return []
|
|
||||||
|
|
||||||
# 转换为 Message对象列表
|
|
||||||
message_objects = []
|
|
||||||
for msg_data in recent_messages:
|
|
||||||
try:
|
|
||||||
chat_info = msg_data.get("chat_info", {})
|
|
||||||
chat_stream = ChatStream.from_dict(chat_info)
|
|
||||||
user_info = msg_data.get("user_info", {})
|
|
||||||
user_info = UserInfo.from_dict(user_info)
|
|
||||||
msg = Message(
|
|
||||||
message_id=msg_data["message_id"],
|
|
||||||
chat_stream=chat_stream,
|
|
||||||
timestamp=msg_data["time"],
|
|
||||||
user_info=user_info,
|
|
||||||
processed_plain_text=msg_data.get("processed_text", ""),
|
|
||||||
detailed_plain_text=msg_data.get("detailed_plain_text", ""),
|
|
||||||
)
|
|
||||||
message_objects.append(msg)
|
|
||||||
except KeyError:
|
|
||||||
logger.warning("数据库中存在无效的消息")
|
|
||||||
continue
|
|
||||||
|
|
||||||
# 按时间正序排列
|
|
||||||
message_objects.reverse()
|
|
||||||
return message_objects
|
|
||||||
|
|
||||||
|
|
||||||
def get_recent_group_detailed_plain_text(chat_stream_id: str, limit: int = 12, combine=False):
|
def get_recent_group_detailed_plain_text(chat_stream_id: str, limit: int = 12, combine=False):
|
||||||
|
|||||||
@@ -264,9 +264,6 @@ class HeartFChatting:
|
|||||||
logger.error(f"[HFC:{self.stream_id}] 获取ChatStream时出错 in _initialize: {e}")
|
logger.error(f"[HFC:{self.stream_id}] 获取ChatStream时出错 in _initialize: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
logger.debug(
|
|
||||||
f"{self.log_prefix} HeartFChatting initialized: is_group={self.is_group_chat}, target_info={self.chat_target_info}"
|
|
||||||
)
|
|
||||||
# --- End using utility function ---
|
# --- End using utility function ---
|
||||||
|
|
||||||
self._initialized = True
|
self._initialized = True
|
||||||
@@ -861,7 +858,7 @@ class HeartFChatting:
|
|||||||
cycle_history=self._cycle_history, # <-- Pass HFC state
|
cycle_history=self._cycle_history, # <-- Pass HFC state
|
||||||
observed_messages_str=observed_messages_str, # <-- Pass local variable
|
observed_messages_str=observed_messages_str, # <-- Pass local variable
|
||||||
current_mind=current_mind, # <-- Pass argument
|
current_mind=current_mind, # <-- Pass argument
|
||||||
structured_info=self.sub_mind.structured_info, # <-- Pass SubMind info
|
structured_info=self.sub_mind.structured_info_str, # <-- Pass SubMind info
|
||||||
current_available_actions=current_available_actions, # <-- Pass determined actions
|
current_available_actions=current_available_actions, # <-- Pass determined actions
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1301,7 +1298,7 @@ class HeartFChatting:
|
|||||||
# Focus specific args:
|
# Focus specific args:
|
||||||
reason=reason,
|
reason=reason,
|
||||||
current_mind_info=self.sub_mind.current_mind,
|
current_mind_info=self.sub_mind.current_mind,
|
||||||
structured_info=self.sub_mind.structured_info,
|
structured_info=self.sub_mind.structured_info_str,
|
||||||
sender_name=sender_name_for_prompt, # Pass determined name
|
sender_name=sender_name_for_prompt, # Pass determined name
|
||||||
# Normal specific args (not used in focus mode):
|
# Normal specific args (not used in focus mode):
|
||||||
# message_txt="",
|
# message_txt="",
|
||||||
|
|||||||
@@ -63,15 +63,12 @@ class NormalChat:
|
|||||||
self.is_group_chat, self.chat_target_info = await get_chat_type_and_target_info(self.stream_id)
|
self.is_group_chat, self.chat_target_info = await get_chat_type_and_target_info(self.stream_id)
|
||||||
# Update stream_name again after potential async call in util func
|
# Update stream_name again after potential async call in util func
|
||||||
self.stream_name = chat_manager.get_stream_name(self.stream_id) or self.stream_id
|
self.stream_name = chat_manager.get_stream_name(self.stream_id) or self.stream_id
|
||||||
logger.debug(
|
|
||||||
f"[{self.stream_name}] NormalChat initialized: is_group={self.is_group_chat}, target_info={self.chat_target_info}"
|
|
||||||
)
|
|
||||||
# --- End using utility function ---
|
# --- End using utility function ---
|
||||||
self._initialized = True
|
self._initialized = True
|
||||||
logger.info(f"[{self.stream_name}] NormalChat 实例 initialize 完成 (异步部分)。")
|
logger.info(f"[{self.stream_name}] NormalChat 实例 initialize 完成 (异步部分)。")
|
||||||
|
|
||||||
# 改为实例方法
|
# 改为实例方法
|
||||||
async def _create_thinking_message(self, message: MessageRecv) -> str:
|
async def _create_thinking_message(self, message: MessageRecv, timestamp: Optional[float] = None) -> str:
|
||||||
"""创建思考消息"""
|
"""创建思考消息"""
|
||||||
messageinfo = message.message_info
|
messageinfo = message.message_info
|
||||||
|
|
||||||
@@ -85,15 +82,15 @@ class NormalChat:
|
|||||||
thinking_id = "mt" + str(thinking_time_point)
|
thinking_id = "mt" + str(thinking_time_point)
|
||||||
thinking_message = MessageThinking(
|
thinking_message = MessageThinking(
|
||||||
message_id=thinking_id,
|
message_id=thinking_id,
|
||||||
chat_stream=self.chat_stream, # 使用 self.chat_stream
|
chat_stream=self.chat_stream,
|
||||||
bot_user_info=bot_user_info,
|
bot_user_info=bot_user_info,
|
||||||
reply=message,
|
reply=message,
|
||||||
thinking_start_time=thinking_time_point,
|
thinking_start_time=thinking_time_point,
|
||||||
|
timestamp=timestamp if timestamp is not None else None
|
||||||
)
|
)
|
||||||
|
|
||||||
await message_manager.add_message(thinking_message)
|
await message_manager.add_message(thinking_message)
|
||||||
return thinking_id
|
return thinking_id
|
||||||
|
|
||||||
# 改为实例方法
|
# 改为实例方法
|
||||||
async def _add_messages_to_manager(
|
async def _add_messages_to_manager(
|
||||||
self, message: MessageRecv, response_set: List[str], thinking_id
|
self, message: MessageRecv, response_set: List[str], thinking_id
|
||||||
@@ -209,7 +206,7 @@ class NormalChat:
|
|||||||
try:
|
try:
|
||||||
# 处理消息
|
# 处理消息
|
||||||
await self.normal_response(
|
await self.normal_response(
|
||||||
message=message, is_mentioned=is_mentioned, interested_rate=interest_value
|
message=message, is_mentioned=is_mentioned, interested_rate=interest_value, rewind_response = False
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"[{self.stream_name}] 处理兴趣消息{msg_id}时出错: {e}\n{traceback.format_exc()}")
|
logger.error(f"[{self.stream_name}] 处理兴趣消息{msg_id}时出错: {e}\n{traceback.format_exc()}")
|
||||||
@@ -217,7 +214,7 @@ class NormalChat:
|
|||||||
self.interest_dict.pop(msg_id, None)
|
self.interest_dict.pop(msg_id, None)
|
||||||
|
|
||||||
# 改为实例方法, 移除 chat 参数
|
# 改为实例方法, 移除 chat 参数
|
||||||
async def normal_response(self, message: MessageRecv, is_mentioned: bool, interested_rate: float) -> None:
|
async def normal_response(self, message: MessageRecv, is_mentioned: bool, interested_rate: float, rewind_response: bool = False) -> None:
|
||||||
# 检查收到的消息是否属于当前实例处理的 chat stream
|
# 检查收到的消息是否属于当前实例处理的 chat stream
|
||||||
if message.chat_stream.stream_id != self.stream_id:
|
if message.chat_stream.stream_id != self.stream_id:
|
||||||
logger.error(
|
logger.error(
|
||||||
@@ -264,7 +261,10 @@ class NormalChat:
|
|||||||
await willing_manager.before_generate_reply_handle(message.message_info.message_id)
|
await willing_manager.before_generate_reply_handle(message.message_info.message_id)
|
||||||
|
|
||||||
with Timer("创建思考消息", timing_results):
|
with Timer("创建思考消息", timing_results):
|
||||||
thinking_id = await self._create_thinking_message(message)
|
if rewind_response:
|
||||||
|
thinking_id = await self._create_thinking_message(message, message.message_info.time)
|
||||||
|
else:
|
||||||
|
thinking_id = await self._create_thinking_message(message)
|
||||||
|
|
||||||
logger.debug(f"[{self.stream_name}] 创建捕捉器,thinking_id:{thinking_id}")
|
logger.debug(f"[{self.stream_name}] 创建捕捉器,thinking_id:{thinking_id}")
|
||||||
|
|
||||||
@@ -393,7 +393,7 @@ class NormalChat:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
logger.info(f"[{self.stream_name}] 处理初始高兴趣消息 {msg_id} (兴趣值: {interest_value:.2f})")
|
logger.info(f"[{self.stream_name}] 处理初始高兴趣消息 {msg_id} (兴趣值: {interest_value:.2f})")
|
||||||
await self.normal_response(message=message, is_mentioned=is_mentioned, interested_rate=interest_value)
|
await self.normal_response(message=message, is_mentioned=is_mentioned, interested_rate=interest_value, rewind_response = True)
|
||||||
processed_count += 1
|
processed_count += 1
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"[{self.stream_name}] 处理初始兴趣消息 {msg_id} 时出错: {e}\\n{traceback.format_exc()}")
|
logger.error(f"[{self.stream_name}] 处理初始兴趣消息 {msg_id} 时出错: {e}\\n{traceback.format_exc()}")
|
||||||
|
|||||||
Reference in New Issue
Block a user