mirror of https://github.com/Mai-with-u/MaiBot.git
fix:修复私聊记忆
parent
7b3793f366
commit
98c85d8d1d
|
|
@ -238,7 +238,6 @@ class BrainChatting:
|
||||||
|
|
||||||
async with global_prompt_manager.async_message_scope(self.chat_stream.context.get_template_name()):
|
async with global_prompt_manager.async_message_scope(self.chat_stream.context.get_template_name()):
|
||||||
asyncio.create_task(self.expression_learner.trigger_learning_for_chat())
|
asyncio.create_task(self.expression_learner.trigger_learning_for_chat())
|
||||||
asyncio.create_task(global_memory_chest.build_running_content(chat_id=self.stream_id))
|
|
||||||
|
|
||||||
cycle_timers, thinking_id = self.start_cycle()
|
cycle_timers, thinking_id = self.start_cycle()
|
||||||
logger.info(f"{self.log_prefix} 开始第{self._cycle_counter}次思考")
|
logger.info(f"{self.log_prefix} 开始第{self._cycle_counter}次思考")
|
||||||
|
|
|
||||||
|
|
@ -278,22 +278,6 @@ class DefaultReplyer:
|
||||||
mood_state = await mood_manager.get_mood_by_chat_id(self.chat_stream.stream_id).get_mood()
|
mood_state = await mood_manager.get_mood_by_chat_id(self.chat_stream.stream_id).get_mood()
|
||||||
return f"你现在的心情是:{mood_state}"
|
return f"你现在的心情是:{mood_state}"
|
||||||
|
|
||||||
async def build_memory_block(self) -> str:
|
|
||||||
"""构建记忆块
|
|
||||||
"""
|
|
||||||
# if not global_config.memory.enable_memory:
|
|
||||||
# return ""
|
|
||||||
|
|
||||||
if global_memory_chest.get_chat_memories_as_string(self.chat_stream.stream_id):
|
|
||||||
return f"你有以下记忆:\n{global_memory_chest.get_chat_memories_as_string(self.chat_stream.stream_id)}"
|
|
||||||
else:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
async def build_question_block(self) -> str:
|
|
||||||
"""构建问题块"""
|
|
||||||
# 问题跟踪功能已移除,返回空字符串
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
async def build_tool_info(self, chat_history: str, sender: str, target: str, enable_tool: bool = True) -> str:
|
async def build_tool_info(self, chat_history: str, sender: str, target: str, enable_tool: bool = True) -> str:
|
||||||
"""构建工具信息块
|
"""构建工具信息块
|
||||||
|
|
@ -801,12 +785,11 @@ class DefaultReplyer:
|
||||||
show_actions=True,
|
show_actions=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 并行执行九个构建任务
|
# 并行执行七个构建任务
|
||||||
task_results = await asyncio.gather(
|
task_results = await asyncio.gather(
|
||||||
self._time_and_run_task(
|
self._time_and_run_task(
|
||||||
self.build_expression_habits(chat_talking_prompt_short, target), "expression_habits"
|
self.build_expression_habits(chat_talking_prompt_short, target), "expression_habits"
|
||||||
),
|
),
|
||||||
self._time_and_run_task(self.build_memory_block(), "memory_block"),
|
|
||||||
self._time_and_run_task(
|
self._time_and_run_task(
|
||||||
self.build_tool_info(chat_talking_prompt_short, sender, target, enable_tool=enable_tool), "tool_info"
|
self.build_tool_info(chat_talking_prompt_short, sender, target, enable_tool=enable_tool), "tool_info"
|
||||||
),
|
),
|
||||||
|
|
@ -814,7 +797,6 @@ class DefaultReplyer:
|
||||||
self._time_and_run_task(self.build_actions_prompt(available_actions, chosen_actions), "actions_info"),
|
self._time_and_run_task(self.build_actions_prompt(available_actions, chosen_actions), "actions_info"),
|
||||||
self._time_and_run_task(self.build_personality_prompt(), "personality_prompt"),
|
self._time_and_run_task(self.build_personality_prompt(), "personality_prompt"),
|
||||||
self._time_and_run_task(self.build_mood_state_prompt(), "mood_state_prompt"),
|
self._time_and_run_task(self.build_mood_state_prompt(), "mood_state_prompt"),
|
||||||
self._time_and_run_task(self.build_question_block(), "question_block"),
|
|
||||||
self._time_and_run_task(
|
self._time_and_run_task(
|
||||||
build_memory_retrieval_prompt(
|
build_memory_retrieval_prompt(
|
||||||
chat_talking_prompt_short, sender, target, self.chat_stream, self.tool_executor
|
chat_talking_prompt_short, sender, target, self.chat_stream, self.tool_executor
|
||||||
|
|
@ -827,14 +809,11 @@ class DefaultReplyer:
|
||||||
task_name_mapping = {
|
task_name_mapping = {
|
||||||
"expression_habits": "选取表达方式",
|
"expression_habits": "选取表达方式",
|
||||||
"relation_info": "感受关系",
|
"relation_info": "感受关系",
|
||||||
# "memory_block": "回忆",
|
|
||||||
"memory_block": "记忆",
|
|
||||||
"tool_info": "使用工具",
|
"tool_info": "使用工具",
|
||||||
"prompt_info": "获取知识",
|
"prompt_info": "获取知识",
|
||||||
"actions_info": "动作信息",
|
"actions_info": "动作信息",
|
||||||
"personality_prompt": "人格信息",
|
"personality_prompt": "人格信息",
|
||||||
"mood_state_prompt": "情绪状态",
|
"mood_state_prompt": "情绪状态",
|
||||||
"question_block": "问题",
|
|
||||||
"memory_retrieval": "记忆检索",
|
"memory_retrieval": "记忆检索",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -859,13 +838,10 @@ class DefaultReplyer:
|
||||||
expression_habits_block: str
|
expression_habits_block: str
|
||||||
selected_expressions: List[int]
|
selected_expressions: List[int]
|
||||||
# relation_info: str = results_dict["relation_info"]
|
# relation_info: str = results_dict["relation_info"]
|
||||||
# memory_block: str = results_dict["memory_block"]
|
|
||||||
memory_block: str = results_dict["memory_block"]
|
|
||||||
tool_info: str = results_dict["tool_info"]
|
tool_info: str = results_dict["tool_info"]
|
||||||
prompt_info: str = results_dict["prompt_info"] # 直接使用格式化后的结果
|
prompt_info: str = results_dict["prompt_info"] # 直接使用格式化后的结果
|
||||||
actions_info: str = results_dict["actions_info"]
|
actions_info: str = results_dict["actions_info"]
|
||||||
personality_prompt: str = results_dict["personality_prompt"]
|
personality_prompt: str = results_dict["personality_prompt"]
|
||||||
question_block: str = results_dict["question_block"]
|
|
||||||
memory_retrieval: str = results_dict["memory_retrieval"]
|
memory_retrieval: str = results_dict["memory_retrieval"]
|
||||||
keywords_reaction_prompt = await self.build_keywords_reaction_prompt(target)
|
keywords_reaction_prompt = await self.build_keywords_reaction_prompt(target)
|
||||||
mood_state_prompt: str = results_dict["mood_state_prompt"]
|
mood_state_prompt: str = results_dict["mood_state_prompt"]
|
||||||
|
|
@ -908,10 +884,8 @@ class DefaultReplyer:
|
||||||
"replyer_prompt",
|
"replyer_prompt",
|
||||||
expression_habits_block=expression_habits_block,
|
expression_habits_block=expression_habits_block,
|
||||||
tool_info_block=tool_info,
|
tool_info_block=tool_info,
|
||||||
memory_block=memory_block,
|
|
||||||
knowledge_prompt=prompt_info,
|
knowledge_prompt=prompt_info,
|
||||||
mood_state=mood_state_prompt,
|
mood_state=mood_state_prompt,
|
||||||
# memory_block=memory_block,
|
|
||||||
# relation_info_block=relation_info,
|
# relation_info_block=relation_info,
|
||||||
extra_info_block=extra_info_block,
|
extra_info_block=extra_info_block,
|
||||||
identity=personality_prompt,
|
identity=personality_prompt,
|
||||||
|
|
@ -923,7 +897,6 @@ class DefaultReplyer:
|
||||||
reply_style=global_config.personality.reply_style,
|
reply_style=global_config.personality.reply_style,
|
||||||
keywords_reaction_prompt=keywords_reaction_prompt,
|
keywords_reaction_prompt=keywords_reaction_prompt,
|
||||||
moderation_prompt=moderation_prompt_block,
|
moderation_prompt=moderation_prompt_block,
|
||||||
question_block=question_block,
|
|
||||||
memory_retrieval=memory_retrieval,
|
memory_retrieval=memory_retrieval,
|
||||||
chat_prompt=chat_prompt_block,
|
chat_prompt=chat_prompt_block,
|
||||||
), selected_expressions
|
), selected_expressions
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import re
|
||||||
|
|
||||||
from typing import List, Optional, Dict, Any, Tuple
|
from typing import List, Optional, Dict, Any, Tuple
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from src.memory_system.Memory_chest import global_memory_chest
|
|
||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
from src.common.data_models.database_data_model import DatabaseMessages
|
from src.common.data_models.database_data_model import DatabaseMessages
|
||||||
from src.common.data_models.info_data_model import ActionPlannerInfo
|
from src.common.data_models.info_data_model import ActionPlannerInfo
|
||||||
|
|
@ -37,10 +36,12 @@ from src.plugin_system.apis import llm_api
|
||||||
from src.chat.replyer.prompt.lpmm_prompt import init_lpmm_prompt
|
from src.chat.replyer.prompt.lpmm_prompt import init_lpmm_prompt
|
||||||
from src.chat.replyer.prompt.replyer_prompt import init_replyer_prompt
|
from src.chat.replyer.prompt.replyer_prompt import init_replyer_prompt
|
||||||
from src.chat.replyer.prompt.rewrite_prompt import init_rewrite_prompt
|
from src.chat.replyer.prompt.rewrite_prompt import init_rewrite_prompt
|
||||||
|
from src.memory_system.memory_retrieval import init_memory_retrieval_prompt, build_memory_retrieval_prompt
|
||||||
|
|
||||||
init_lpmm_prompt()
|
init_lpmm_prompt()
|
||||||
init_replyer_prompt()
|
init_replyer_prompt()
|
||||||
init_rewrite_prompt()
|
init_rewrite_prompt()
|
||||||
|
init_memory_retrieval_prompt()
|
||||||
|
|
||||||
|
|
||||||
logger = get_logger("replyer")
|
logger = get_logger("replyer")
|
||||||
|
|
@ -291,14 +292,6 @@ class PrivateReplyer:
|
||||||
return f"你现在的心情是:{mood_state}"
|
return f"你现在的心情是:{mood_state}"
|
||||||
|
|
||||||
|
|
||||||
async def build_memory_block(self) -> str:
|
|
||||||
"""构建记忆块
|
|
||||||
"""
|
|
||||||
if global_memory_chest.get_chat_memories_as_string(self.chat_stream.stream_id):
|
|
||||||
return f"你有以下记忆:\n{global_memory_chest.get_chat_memories_as_string(self.chat_stream.stream_id)}"
|
|
||||||
else:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
async def build_tool_info(self, chat_history: str, sender: str, target: str, enable_tool: bool = True) -> str:
|
async def build_tool_info(self, chat_history: str, sender: str, target: str, enable_tool: bool = True) -> str:
|
||||||
"""构建工具信息块
|
"""构建工具信息块
|
||||||
|
|
||||||
|
|
@ -712,7 +705,7 @@ class PrivateReplyer:
|
||||||
show_actions=True,
|
show_actions=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 并行执行五个构建任务
|
# 并行执行八个构建任务
|
||||||
task_results = await asyncio.gather(
|
task_results = await asyncio.gather(
|
||||||
self._time_and_run_task(
|
self._time_and_run_task(
|
||||||
self.build_expression_habits(chat_talking_prompt_short, target), "expression_habits"
|
self.build_expression_habits(chat_talking_prompt_short, target), "expression_habits"
|
||||||
|
|
@ -720,8 +713,6 @@ class PrivateReplyer:
|
||||||
self._time_and_run_task(
|
self._time_and_run_task(
|
||||||
self.build_relation_info(chat_talking_prompt_short, sender), "relation_info"
|
self.build_relation_info(chat_talking_prompt_short, sender), "relation_info"
|
||||||
),
|
),
|
||||||
self._time_and_run_task(self.build_memory_block(), "memory_block"),
|
|
||||||
# self._time_and_run_task(self.build_memory_block(message_list_before_short, target), "memory_block"),
|
|
||||||
self._time_and_run_task(
|
self._time_and_run_task(
|
||||||
self.build_tool_info(chat_talking_prompt_short, sender, target, enable_tool=enable_tool), "tool_info"
|
self.build_tool_info(chat_talking_prompt_short, sender, target, enable_tool=enable_tool), "tool_info"
|
||||||
),
|
),
|
||||||
|
|
@ -729,18 +720,24 @@ class PrivateReplyer:
|
||||||
self._time_and_run_task(self.build_actions_prompt(available_actions, chosen_actions), "actions_info"),
|
self._time_and_run_task(self.build_actions_prompt(available_actions, chosen_actions), "actions_info"),
|
||||||
self._time_and_run_task(self.build_personality_prompt(), "personality_prompt"),
|
self._time_and_run_task(self.build_personality_prompt(), "personality_prompt"),
|
||||||
self._time_and_run_task(self.build_mood_state_prompt(), "mood_state_prompt"),
|
self._time_and_run_task(self.build_mood_state_prompt(), "mood_state_prompt"),
|
||||||
|
self._time_and_run_task(
|
||||||
|
build_memory_retrieval_prompt(
|
||||||
|
chat_talking_prompt_short, sender, target, self.chat_stream, self.tool_executor
|
||||||
|
),
|
||||||
|
"memory_retrieval",
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
# 任务名称中英文映射
|
# 任务名称中英文映射
|
||||||
task_name_mapping = {
|
task_name_mapping = {
|
||||||
"expression_habits": "选取表达方式",
|
"expression_habits": "选取表达方式",
|
||||||
"relation_info": "感受关系",
|
"relation_info": "感受关系",
|
||||||
"memory_block": "回忆",
|
|
||||||
"tool_info": "使用工具",
|
"tool_info": "使用工具",
|
||||||
"prompt_info": "获取知识",
|
"prompt_info": "获取知识",
|
||||||
"actions_info": "动作信息",
|
"actions_info": "动作信息",
|
||||||
"personality_prompt": "人格信息",
|
"personality_prompt": "人格信息",
|
||||||
"mood_state_prompt": "情绪状态",
|
"mood_state_prompt": "情绪状态",
|
||||||
|
"memory_retrieval": "记忆检索",
|
||||||
}
|
}
|
||||||
|
|
||||||
# 处理结果
|
# 处理结果
|
||||||
|
|
@ -764,12 +761,12 @@ class PrivateReplyer:
|
||||||
expression_habits_block: str
|
expression_habits_block: str
|
||||||
selected_expressions: List[int]
|
selected_expressions: List[int]
|
||||||
relation_info: str = results_dict["relation_info"]
|
relation_info: str = results_dict["relation_info"]
|
||||||
memory_block: str = results_dict["memory_block"]
|
|
||||||
tool_info: str = results_dict["tool_info"]
|
tool_info: str = results_dict["tool_info"]
|
||||||
prompt_info: str = results_dict["prompt_info"] # 直接使用格式化后的结果
|
prompt_info: str = results_dict["prompt_info"] # 直接使用格式化后的结果
|
||||||
actions_info: str = results_dict["actions_info"]
|
actions_info: str = results_dict["actions_info"]
|
||||||
personality_prompt: str = results_dict["personality_prompt"]
|
personality_prompt: str = results_dict["personality_prompt"]
|
||||||
mood_state_prompt: str = results_dict["mood_state_prompt"]
|
mood_state_prompt: str = results_dict["mood_state_prompt"]
|
||||||
|
memory_retrieval: str = results_dict["memory_retrieval"]
|
||||||
keywords_reaction_prompt = await self.build_keywords_reaction_prompt(target)
|
keywords_reaction_prompt = await self.build_keywords_reaction_prompt(target)
|
||||||
|
|
||||||
if extra_info:
|
if extra_info:
|
||||||
|
|
@ -806,7 +803,6 @@ class PrivateReplyer:
|
||||||
tool_info_block=tool_info,
|
tool_info_block=tool_info,
|
||||||
knowledge_prompt=prompt_info,
|
knowledge_prompt=prompt_info,
|
||||||
mood_state=mood_state_prompt,
|
mood_state=mood_state_prompt,
|
||||||
memory_block=memory_block,
|
|
||||||
relation_info_block=relation_info,
|
relation_info_block=relation_info,
|
||||||
extra_info_block=extra_info_block,
|
extra_info_block=extra_info_block,
|
||||||
identity=personality_prompt,
|
identity=personality_prompt,
|
||||||
|
|
@ -819,6 +815,7 @@ class PrivateReplyer:
|
||||||
reply_style=global_config.personality.reply_style,
|
reply_style=global_config.personality.reply_style,
|
||||||
keywords_reaction_prompt=keywords_reaction_prompt,
|
keywords_reaction_prompt=keywords_reaction_prompt,
|
||||||
moderation_prompt=moderation_prompt_block,
|
moderation_prompt=moderation_prompt_block,
|
||||||
|
memory_retrieval=memory_retrieval,
|
||||||
chat_prompt=chat_prompt_block,
|
chat_prompt=chat_prompt_block,
|
||||||
), selected_expressions
|
), selected_expressions
|
||||||
else:
|
else:
|
||||||
|
|
@ -828,7 +825,6 @@ class PrivateReplyer:
|
||||||
tool_info_block=tool_info,
|
tool_info_block=tool_info,
|
||||||
knowledge_prompt=prompt_info,
|
knowledge_prompt=prompt_info,
|
||||||
mood_state=mood_state_prompt,
|
mood_state=mood_state_prompt,
|
||||||
memory_block=memory_block,
|
|
||||||
relation_info_block=relation_info,
|
relation_info_block=relation_info,
|
||||||
extra_info_block=extra_info_block,
|
extra_info_block=extra_info_block,
|
||||||
identity=personality_prompt,
|
identity=personality_prompt,
|
||||||
|
|
@ -840,6 +836,7 @@ class PrivateReplyer:
|
||||||
keywords_reaction_prompt=keywords_reaction_prompt,
|
keywords_reaction_prompt=keywords_reaction_prompt,
|
||||||
moderation_prompt=moderation_prompt_block,
|
moderation_prompt=moderation_prompt_block,
|
||||||
sender_name=sender,
|
sender_name=sender,
|
||||||
|
memory_retrieval=memory_retrieval,
|
||||||
chat_prompt=chat_prompt_block,
|
chat_prompt=chat_prompt_block,
|
||||||
), selected_expressions
|
), selected_expressions
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
{
|
|
||||||
"manifest_version": 1,
|
|
||||||
"name": "Memory Build组件",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "可以构建和管理记忆",
|
|
||||||
"author": {
|
|
||||||
"name": "Mai",
|
|
||||||
"url": "https://github.com/MaiM-with-u"
|
|
||||||
},
|
|
||||||
"license": "GPL-v3.0-or-later",
|
|
||||||
|
|
||||||
"host_application": {
|
|
||||||
"min_version": "0.10.4"
|
|
||||||
},
|
|
||||||
"homepage_url": "https://github.com/MaiM-with-u/maibot",
|
|
||||||
"repository_url": "https://github.com/MaiM-with-u/maibot",
|
|
||||||
"keywords": ["memory", "build", "built-in"],
|
|
||||||
"categories": ["Memory"],
|
|
||||||
|
|
||||||
"default_locale": "zh-CN",
|
|
||||||
"locales_path": "_locales",
|
|
||||||
|
|
||||||
"plugin_info": {
|
|
||||||
"is_built_in": true,
|
|
||||||
"plugin_type": "action_provider",
|
|
||||||
"components": [
|
|
||||||
{
|
|
||||||
"type": "build_memory",
|
|
||||||
"name": "build_memory",
|
|
||||||
"description": "构建记忆"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,245 +0,0 @@
|
||||||
import asyncio
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
from src.common.logger import get_logger
|
|
||||||
from src.llm_models.payload_content.tool_option import ToolParamType
|
|
||||||
from src.memory_system.Memory_chest import global_memory_chest
|
|
||||||
from src.plugin_system.base.base_tool import BaseTool
|
|
||||||
from src.plugin_system.apis.message_api import get_messages_by_time_in_chat, build_readable_messages
|
|
||||||
from src.llm_models.utils_model import LLMRequest
|
|
||||||
from src.config.config import model_config
|
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
logger = get_logger("memory")
|
|
||||||
|
|
||||||
def parse_datetime_to_timestamp(value: str) -> float:
|
|
||||||
"""
|
|
||||||
接受多种常见格式并转换为时间戳(秒)
|
|
||||||
支持示例:
|
|
||||||
- 2025-09-29
|
|
||||||
- 2025-09-29 00:00:00
|
|
||||||
- 2025/09/29 00:00
|
|
||||||
- 2025-09-29T00:00:00
|
|
||||||
"""
|
|
||||||
value = value.strip()
|
|
||||||
fmts = [
|
|
||||||
"%Y-%m-%d %H:%M:%S",
|
|
||||||
"%Y-%m-%d %H:%M",
|
|
||||||
"%Y/%m/%d %H:%M:%S",
|
|
||||||
"%Y/%m/%d %H:%M",
|
|
||||||
"%Y-%m-%d",
|
|
||||||
"%Y/%m/%d",
|
|
||||||
"%Y-%m-%dT%H:%M:%S",
|
|
||||||
"%Y-%m-%dT%H:%M",
|
|
||||||
]
|
|
||||||
last_err = None
|
|
||||||
for fmt in fmts:
|
|
||||||
try:
|
|
||||||
dt = datetime.strptime(value, fmt)
|
|
||||||
return dt.timestamp()
|
|
||||||
except Exception as e:
|
|
||||||
last_err = e
|
|
||||||
raise ValueError(f"无法解析时间: {value} ({last_err})")
|
|
||||||
|
|
||||||
def parse_time_range(time_range: str) -> tuple[float, float]:
|
|
||||||
"""
|
|
||||||
解析时间范围字符串,返回开始和结束时间戳
|
|
||||||
格式: "YYYY-MM-DD HH:MM:SS - YYYY-MM-DD HH:MM:SS"
|
|
||||||
"""
|
|
||||||
if " - " not in time_range:
|
|
||||||
raise ValueError("时间范围格式错误,应使用 ' - ' 分隔开始和结束时间")
|
|
||||||
|
|
||||||
start_str, end_str = time_range.split(" - ", 1)
|
|
||||||
start_timestamp = parse_datetime_to_timestamp(start_str.strip())
|
|
||||||
end_timestamp = parse_datetime_to_timestamp(end_str.strip())
|
|
||||||
|
|
||||||
if start_timestamp > end_timestamp:
|
|
||||||
raise ValueError("开始时间不能晚于结束时间")
|
|
||||||
|
|
||||||
return start_timestamp, end_timestamp
|
|
||||||
class GetMemoryTool(BaseTool):
|
|
||||||
"""获取用户信息"""
|
|
||||||
|
|
||||||
name = "get_memory"
|
|
||||||
description = "在记忆中搜索,获取某个问题的答案,可以指定搜索的时间范围或时间点"
|
|
||||||
parameters = [
|
|
||||||
("question", ToolParamType.STRING, "需要获取答案的问题", True, None),
|
|
||||||
("time_point", ToolParamType.STRING, "需要获取记忆的时间点,格式为YYYY-MM-DD HH:MM:SS", False, None),
|
|
||||||
("time_range", ToolParamType.STRING, "需要获取记忆的时间范围,格式为YYYY-MM-DD HH:MM:SS - YYYY-MM-DD HH:MM:SS", False, None)
|
|
||||||
]
|
|
||||||
|
|
||||||
available_for_llm = True
|
|
||||||
|
|
||||||
async def execute(self, function_args: dict[str, Any]) -> dict[str, Any]:
|
|
||||||
"""执行记忆搜索
|
|
||||||
|
|
||||||
Args:
|
|
||||||
function_args: 工具参数
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict: 工具执行结果
|
|
||||||
"""
|
|
||||||
question: str = function_args.get("question") # type: ignore
|
|
||||||
time_point: str = function_args.get("time_point") # type: ignore
|
|
||||||
time_range: str = function_args.get("time_range") # type: ignore
|
|
||||||
|
|
||||||
# 检查是否指定了时间参数
|
|
||||||
has_time_params = bool(time_point or time_range)
|
|
||||||
|
|
||||||
if has_time_params and not self.chat_id:
|
|
||||||
return {"content": f"问题:{question},无法获取聊天记录:缺少chat_id"}
|
|
||||||
|
|
||||||
# 创建并行任务
|
|
||||||
tasks = []
|
|
||||||
|
|
||||||
# 原任务:从记忆仓库获取答案
|
|
||||||
memory_task = asyncio.create_task(
|
|
||||||
global_memory_chest.get_answer_by_question(question=question)
|
|
||||||
)
|
|
||||||
tasks.append(("memory", memory_task))
|
|
||||||
|
|
||||||
# 新任务:从聊天记录获取答案(如果指定了时间参数)
|
|
||||||
chat_task = None
|
|
||||||
if has_time_params:
|
|
||||||
chat_task = asyncio.create_task(
|
|
||||||
self._get_answer_from_chat_history(question, time_point, time_range)
|
|
||||||
)
|
|
||||||
tasks.append(("chat", chat_task))
|
|
||||||
|
|
||||||
# 等待所有任务完成
|
|
||||||
results = {}
|
|
||||||
for task_name, task in tasks:
|
|
||||||
try:
|
|
||||||
results[task_name] = await task
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"任务 {task_name} 执行失败: {e}")
|
|
||||||
results[task_name] = None
|
|
||||||
|
|
||||||
# 处理结果
|
|
||||||
memory_answer = results.get("memory")
|
|
||||||
chat_answer = results.get("chat")
|
|
||||||
|
|
||||||
# 构建返回内容
|
|
||||||
content_parts = []
|
|
||||||
|
|
||||||
if memory_answer:
|
|
||||||
content_parts.append(f"对问题'{question}',你回忆的信息是:{memory_answer}")
|
|
||||||
|
|
||||||
if chat_answer:
|
|
||||||
content_parts.append(f"对问题'{question}',基于聊天记录的回答:{chat_answer}")
|
|
||||||
elif has_time_params:
|
|
||||||
if time_point:
|
|
||||||
content_parts.append(f"在 {time_point} 的时间点,你没有参与聊天")
|
|
||||||
elif time_range:
|
|
||||||
content_parts.append(f"在 {time_range} 的时间范围内,你没有参与聊天")
|
|
||||||
|
|
||||||
if content_parts:
|
|
||||||
retrieval_content = f"问题:{question}" + "\n".join(content_parts)
|
|
||||||
return {"content": retrieval_content}
|
|
||||||
else:
|
|
||||||
return {"content": ""}
|
|
||||||
|
|
||||||
|
|
||||||
async def _get_answer_from_chat_history(self, question: str, time_point: str = None, time_range: str = None) -> str:
|
|
||||||
"""从聊天记录中获取问题的答案"""
|
|
||||||
try:
|
|
||||||
# 确定时间范围
|
|
||||||
print(f"time_point: {time_point}, time_range: {time_range}")
|
|
||||||
|
|
||||||
# 检查time_range的两个时间值是否相同,如果相同则按照time_point处理
|
|
||||||
if time_range and not time_point:
|
|
||||||
try:
|
|
||||||
start_timestamp, end_timestamp = parse_time_range(time_range)
|
|
||||||
if start_timestamp == end_timestamp:
|
|
||||||
# 两个时间值相同,按照time_point处理
|
|
||||||
time_point = time_range.split(" - ")[0].strip()
|
|
||||||
time_range = None
|
|
||||||
print(f"time_range两个值相同,按照time_point处理: {time_point}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"解析time_range失败: {e}")
|
|
||||||
|
|
||||||
if time_point:
|
|
||||||
# 时间点:搜索前后25条记录
|
|
||||||
target_timestamp = parse_datetime_to_timestamp(time_point)
|
|
||||||
# 获取前后各25条记录,总共50条
|
|
||||||
messages_before = get_messages_by_time_in_chat(
|
|
||||||
chat_id=self.chat_id,
|
|
||||||
start_time=0,
|
|
||||||
end_time=target_timestamp,
|
|
||||||
limit=25,
|
|
||||||
limit_mode="latest"
|
|
||||||
)
|
|
||||||
messages_after = get_messages_by_time_in_chat(
|
|
||||||
chat_id=self.chat_id,
|
|
||||||
start_time=target_timestamp,
|
|
||||||
end_time=float('inf'),
|
|
||||||
limit=25,
|
|
||||||
limit_mode="earliest"
|
|
||||||
)
|
|
||||||
messages = messages_before + messages_after
|
|
||||||
elif time_range:
|
|
||||||
# 时间范围:搜索范围内最多50条记录
|
|
||||||
start_timestamp, end_timestamp = parse_time_range(time_range)
|
|
||||||
messages = get_messages_by_time_in_chat(
|
|
||||||
chat_id=self.chat_id,
|
|
||||||
start_time=start_timestamp,
|
|
||||||
end_time=end_timestamp,
|
|
||||||
limit=50,
|
|
||||||
limit_mode="latest"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
return "未指定时间参数"
|
|
||||||
|
|
||||||
if not messages:
|
|
||||||
return "没有找到相关聊天记录"
|
|
||||||
|
|
||||||
# 将消息转换为可读格式
|
|
||||||
chat_content = build_readable_messages(messages, timestamp_mode="relative")
|
|
||||||
|
|
||||||
if not chat_content.strip():
|
|
||||||
return "聊天记录为空"
|
|
||||||
|
|
||||||
# 使用LLM分析聊天内容并回答问题
|
|
||||||
try:
|
|
||||||
llm_request = LLMRequest(
|
|
||||||
model_set=model_config.model_task_config.utils_small,
|
|
||||||
request_type="chat_history_analysis"
|
|
||||||
)
|
|
||||||
|
|
||||||
analysis_prompt = f"""请根据以下聊天记录内容,回答用户的问题。请输出一段平文本,不要有特殊格式。
|
|
||||||
聊天记录:
|
|
||||||
{chat_content}
|
|
||||||
|
|
||||||
用户问题:{question}
|
|
||||||
|
|
||||||
请仔细分析聊天记录,提取与问题相关的信息,并给出准确的答案。如果聊天记录中没有相关信息,无法回答问题,输出"无有效信息"即可,不要输出其他内容。
|
|
||||||
|
|
||||||
答案:"""
|
|
||||||
|
|
||||||
print(f"analysis_prompt: {analysis_prompt}")
|
|
||||||
|
|
||||||
|
|
||||||
response, (reasoning, model_name, tool_calls) = await llm_request.generate_response_async(
|
|
||||||
prompt=analysis_prompt,
|
|
||||||
temperature=0.3,
|
|
||||||
max_tokens=256
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
print(f"response: {response}")
|
|
||||||
|
|
||||||
if "无有效信息" in response:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
except Exception as llm_error:
|
|
||||||
logger.error(f"LLM分析聊天记录失败: {llm_error}")
|
|
||||||
# 如果LLM分析失败,返回聊天内容的摘要
|
|
||||||
if len(chat_content) > 300:
|
|
||||||
chat_content = chat_content[:300] + "..."
|
|
||||||
return chat_content
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"从聊天记录获取答案失败: {e}")
|
|
||||||
return ""
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
from typing import List, Tuple, Type
|
|
||||||
|
|
||||||
# 导入新插件系统
|
|
||||||
from src.plugin_system import BasePlugin, ComponentInfo, register_plugin
|
|
||||||
from src.plugin_system.base.config_types import ConfigField
|
|
||||||
|
|
||||||
# 导入依赖的系统组件
|
|
||||||
from src.common.logger import get_logger
|
|
||||||
|
|
||||||
from src.plugins.built_in.memory.build_memory import GetMemoryTool
|
|
||||||
|
|
||||||
logger = get_logger("memory_build")
|
|
||||||
|
|
||||||
|
|
||||||
@register_plugin
|
|
||||||
class MemoryBuildPlugin(BasePlugin):
|
|
||||||
"""记忆构建插件
|
|
||||||
|
|
||||||
系统内置插件,提供基础的聊天交互功能:
|
|
||||||
- GetMemory: 获取记忆
|
|
||||||
|
|
||||||
注意:插件基本信息优先从_manifest.json文件中读取
|
|
||||||
"""
|
|
||||||
|
|
||||||
# 插件基本信息
|
|
||||||
plugin_name: str = "memory_build" # 内部标识符
|
|
||||||
enable_plugin: bool = True
|
|
||||||
dependencies: list[str] = [] # 插件依赖列表
|
|
||||||
python_dependencies: list[str] = [] # Python包依赖列表
|
|
||||||
config_file_name: str = "config.toml"
|
|
||||||
|
|
||||||
# 配置节描述
|
|
||||||
config_section_descriptions = {
|
|
||||||
"plugin": "插件启用配置",
|
|
||||||
"components": "核心组件启用配置",
|
|
||||||
}
|
|
||||||
|
|
||||||
# 配置Schema定义
|
|
||||||
config_schema: dict = {
|
|
||||||
"plugin": {
|
|
||||||
"enabled": ConfigField(type=bool, default=True, description="是否启用插件"),
|
|
||||||
"config_version": ConfigField(type=str, default="1.1.1", description="配置文件版本"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
def get_plugin_components(self) -> List[Tuple[ComponentInfo, Type]]:
|
|
||||||
"""返回插件包含的组件列表"""
|
|
||||||
|
|
||||||
# --- 根据配置注册组件 ---
|
|
||||||
components = []
|
|
||||||
components.append((GetMemoryTool.get_tool_info(), GetMemoryTool))
|
|
||||||
|
|
||||||
return components
|
|
||||||
Loading…
Reference in New Issue