feat:将relation获取变为工具

pull/1249/head
SengokuCola 2025-09-17 21:17:52 +08:00
parent ddf4fb1bce
commit a932ca695a
13 changed files with 103 additions and 44 deletions

View File

@ -44,7 +44,7 @@
## 🔥 更新和安装
**最新版本: v0.10.2** ([更新日志](changelogs/changelog.md))
**最新版本: v0.10.3** ([更新日志](changelogs/changelog.md))
可前往 [Release](https://github.com/MaiM-with-u/MaiBot/releases/) 页面下载最新版本
可前往 [启动器发布页面](https://github.com/MaiM-with-u/mailauncher/releases/)下载最新启动器

View File

@ -28,6 +28,7 @@ class CompareNumbersTool(BaseTool):
("num1", ToolParamType.FLOAT, "第一个数字", True, None),
("num2", ToolParamType.FLOAT, "第二个数字", True, None),
]
available_for_llm = True
async def execute(self, function_args: dict[str, Any]) -> dict[str, Any]:
"""执行比较两个数的大小

View File

@ -106,8 +106,8 @@ class HeartFCMessageReceiver:
message.message_info.platform, # type: ignore
replace_bot_name=True,
)
if not processed_plain_text:
print(message)
# if not processed_plain_text:
# print(message)
logger.info(f"[{mes_name}]{userinfo.user_nickname}:{processed_plain_text}") # type: ignore

View File

@ -344,6 +344,7 @@ class ActionPlanner:
plan_style=global_config.personality.plan_style,
)
return prompt, message_id_list
except Exception as e:
logger.error(f"构建 Planner 提示词时出错: {e}")
@ -450,8 +451,8 @@ class ActionPlanner:
# 调用LLM
llm_content, (reasoning_content, _, _) = await self.planner_llm.generate_response_async(prompt=prompt)
# logger.info(f"{self.log_prefix}规划器原始提示词: {prompt}")
# logger.info(f"{self.log_prefix}规划器原始响应: {llm_content}")
logger.info(f"{self.log_prefix}规划器原始提示词: {prompt}")
logger.info(f"{self.log_prefix}规划器原始响应: {llm_content}")
if global_config.debug.show_prompt:
logger.info(f"{self.log_prefix}规划器原始提示词: {prompt}")

View File

@ -702,9 +702,9 @@ class DefaultReplyer:
self._time_and_run_task(
self.build_expression_habits(chat_talking_prompt_short, target), "expression_habits"
),
self._time_and_run_task(
self.build_relation_info(chat_talking_prompt_short, sender, person_list_short), "relation_info"
),
# self._time_and_run_task(
# self.build_relation_info(chat_talking_prompt_short, sender, person_list_short), "relation_info"
# ),
# self._time_and_run_task(self.build_memory_block(message_list_before_short, target), "memory_block"),
self._time_and_run_task(
self.build_tool_info(chat_talking_prompt_short, sender, target, enable_tool=enable_tool), "tool_info"
@ -745,7 +745,7 @@ class DefaultReplyer:
expression_habits_block, selected_expressions = results_dict["expression_habits"]
expression_habits_block: str
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"]
prompt_info: str = results_dict["prompt_info"] # 直接使用格式化后的结果
@ -786,7 +786,7 @@ class DefaultReplyer:
tool_info_block=tool_info,
knowledge_prompt=prompt_info,
# memory_block=memory_block,
relation_info_block=relation_info,
# relation_info_block=relation_info,
extra_info_block=extra_info_block,
identity=personality_prompt,
action_descriptions=actions_info,
@ -806,7 +806,7 @@ class DefaultReplyer:
tool_info_block=tool_info,
knowledge_prompt=prompt_info,
# memory_block=memory_block,
relation_info_block=relation_info,
# relation_info_block=relation_info,
extra_info_block=extra_info_block,
identity=personality_prompt,
action_descriptions=actions_info,
@ -856,9 +856,9 @@ class DefaultReplyer:
)
# 并行执行2个构建任务
(expression_habits_block, _), relation_info, personality_prompt = await asyncio.gather(
(expression_habits_block, _), personality_prompt = await asyncio.gather(
self.build_expression_habits(chat_talking_prompt_half, target),
self.build_relation_info(chat_talking_prompt_half, sender, []),
# self.build_relation_info(chat_talking_prompt_half, sender, []),
self.build_personality_prompt(),
)
@ -909,7 +909,7 @@ class DefaultReplyer:
return await global_prompt_manager.format_prompt(
template_name,
expression_habits_block=expression_habits_block,
relation_info_block=relation_info,
# relation_info_block=relation_info,
chat_target=chat_target_1,
time_block=time_block,
chat_info=chat_talking_prompt_half,

View File

@ -216,25 +216,25 @@ class PrivateReplyer:
traceback.print_exc()
return False, llm_response
async def build_relation_info(self, chat_content: str, sender: str):
if not global_config.relationship.enable_relationship:
return ""
# async def build_relation_info(self, chat_content: str, sender: str):
# if not global_config.relationship.enable_relationship:
# return ""
if not sender:
return ""
# if not sender:
# return ""
if sender == global_config.bot.nickname:
return ""
# if sender == global_config.bot.nickname:
# return ""
# 获取用户ID
person = Person(person_name=sender)
if not is_person_known(person_name=sender):
logger.warning(f"未找到用户 {sender} 的ID跳过信息提取")
return f"你完全不认识{sender}不理解ta的相关信息。"
# # 获取用户ID
# person = Person(person_name=sender)
# if not is_person_known(person_name=sender):
# logger.warning(f"未找到用户 {sender} 的ID跳过信息提取")
# return f"你完全不认识{sender}不理解ta的相关信息。"
sender_relation = await person.build_relationship(chat_content)
# sender_relation = await person.build_relationship(chat_content)
return f"{sender_relation}"
# return f"{sender_relation}"
async def build_expression_habits(self, chat_history: str, target: str) -> Tuple[str, List[int]]:
# sourcery skip: for-append-to-extend
@ -724,9 +724,9 @@ class PrivateReplyer:
)
# 并行执行2个构建任务
(expression_habits_block, _), relation_info, personality_prompt = await asyncio.gather(
(expression_habits_block, _), personality_prompt = await asyncio.gather(
self.build_expression_habits(chat_talking_prompt_half, target),
self.build_relation_info(chat_talking_prompt_half, sender),
# self.build_relation_info(chat_talking_prompt_half, sender),
self.build_personality_prompt(),
)
@ -777,7 +777,7 @@ class PrivateReplyer:
return await global_prompt_manager.format_prompt(
template_name,
expression_habits_block=expression_habits_block,
relation_info_block=relation_info,
# relation_info_block=relation_info,
chat_target=chat_target_1,
time_block=time_block,
chat_info=chat_talking_prompt_half,

View File

@ -12,7 +12,7 @@ def init_replyer_prompt():
Prompt(
"""{knowledge_prompt}{relation_info_block}{tool_info_block}{extra_info_block}
"""{knowledge_prompt}{tool_info_block}{extra_info_block}
{expression_habits_block}
你正在qq群里聊天下面是群里正在聊的内容:
@ -33,7 +33,7 @@ def init_replyer_prompt():
Prompt(
"""{knowledge_prompt}{relation_info_block}{tool_info_block}{extra_info_block}
"""{knowledge_prompt}{tool_info_block}{extra_info_block}
{expression_habits_block}
你正在qq群里聊天下面是群里正在聊的内容:
@ -54,7 +54,7 @@ def init_replyer_prompt():
Prompt(
"""{knowledge_prompt}{relation_info_block}{tool_info_block}{extra_info_block}
"""{knowledge_prompt}{tool_info_block}{extra_info_block}
{expression_habits_block}
你正在和{sender_name}聊天这是你们之前聊的内容:
@ -73,7 +73,7 @@ def init_replyer_prompt():
Prompt(
"""{knowledge_prompt}{relation_info_block}{tool_info_block}{extra_info_block}
"""{knowledge_prompt}{tool_info_block}{extra_info_block}
{expression_habits_block}
你正在和{sender_name}聊天这是你们之前聊的内容:

View File

@ -13,8 +13,6 @@ def init_rewrite_prompt():
Prompt(
"""
{expression_habits_block}
{relation_info_block}
{chat_target}
{time_block}
{chat_info}

View File

@ -420,7 +420,7 @@ class Person:
except Exception as e:
logger.error(f"同步用户 {self.person_id} 信息到数据库时出错: {e}")
async def build_relationship(self,chat_content:str = ""):
async def build_relationship(self,chat_content:str = "",info_type = ""):
if not self.is_known:
return ""
# 构建points文本
@ -446,8 +446,8 @@ class Person:
如果没有相关的分类请输出<none>"""
response, _ = await relation_selection_model.generate_response_async(prompt)
print(prompt)
print(response)
# print(prompt)
# print(response)
category_list = extract_categories_from_response(response)
if "none" not in category_list:
for category in category_list:
@ -456,7 +456,26 @@ class Person:
random_memory_str = "\n".join([get_memory_content_from_memory(memory) for memory in random_memory])
points_text = f"有关 {category} 的内容:{random_memory_str}"
break
elif info_type:
prompt = f"""你需要获取用户{self.person_name}的 **{info_type}** 信息。
现有信息类别列表
{category_list}
**要求**请你根据**{info_type}**从以下分类中选择一个与**{info_type}**相关的分类并用<>包裹输出不要输出其他内容不要输出引号或[]严格用<>包裹
例如:
<分类1><分类2><分类3>......
如果没有相关的分类请输出<none>"""
response, _ = await relation_selection_model.generate_response_async(prompt)
print(prompt)
print(response)
category_list = extract_categories_from_response(response)
if "none" not in category_list:
for category in category_list:
random_memory = self.get_random_memory_by_category(category, 3)
if random_memory:
random_memory_str = "\n".join([get_memory_content_from_memory(memory) for memory in random_memory])
points_text = f"有关 {category} 的内容:{random_memory_str}"
break
else:
for category in category_list:

View File

@ -92,6 +92,8 @@ class ToolExecutor:
# 获取可用工具
tools = self._get_tool_definitions()
# print(f"tools: {tools}")
# 获取当前时间
time_now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

View File

@ -140,7 +140,7 @@ class EmojiAction(BaseAction):
# 存储动作信息
await self.store_action_info(
action_build_into_prompt=True,
action_prompt_display=f"发送了表情包,原因:{reason}",
action_prompt_display=f"发送了表情包,原因:{reason}",
action_done=True,
)
return True, f"成功发送表情包:{emoji_description}"

View File

@ -1,8 +1,10 @@
from typing import List, Tuple, Type
from typing import List, Tuple, Type, Any
# 导入新插件系统
from src.plugin_system import BasePlugin, register_plugin, ComponentInfo
from src.plugin_system.base.config_types import ConfigField
from src.person_info.person_info import Person
from src.plugin_system.base.base_tool import BaseTool, ToolParamType
# 导入依赖的系统组件
from src.common.logger import get_logger
@ -12,6 +14,42 @@ from src.plugins.built_in.relation.relation import BuildRelationAction
logger = get_logger("relation_actions")
class GetPersonInfoTool(BaseTool):
"""获取用户信息"""
name = "get_person_info"
description = "获取某个人的信息,包括印象,特征点,与用户的关系等等"
parameters = [
("person_name", ToolParamType.STRING, "需要获取信息的人的名称", True, None),
("info_type", ToolParamType.STRING, "需要获取信息的类型", True, None),
]
available_for_llm = True
async def execute(self, function_args: dict[str, Any]) -> dict[str, Any]:
"""执行比较两个数的大小
Args:
function_args: 工具参数
Returns:
dict: 工具执行结果
"""
person_name: str = function_args.get("person_name") # type: ignore
info_type: str = function_args.get("info_type") # type: ignore
person = Person(person_name=person_name)
if not person:
return {"content": f"用户 {person_name} 不存在"}
if not person.is_known:
return {"content": f"不认识用户 {person_name}"}
relation_str = await person.build_relationship(info_type=info_type)
return {"content": relation_str}
@register_plugin
class RelationActionsPlugin(BasePlugin):
"""关系动作插件
@ -54,5 +92,6 @@ class RelationActionsPlugin(BasePlugin):
# --- 根据配置注册组件 ---
components = []
components.append((BuildRelationAction.get_action_info(), BuildRelationAction))
components.append((GetPersonInfoTool.get_tool_info(), GetPersonInfoTool))
return components

View File

@ -78,7 +78,7 @@ max_context_size = 20 # 上下文长度
enable_relationship = true # 是否启用关系系统
[tool]
enable_tool = false # 是否启用回复工具
enable_tool = true # 是否启用回复工具
[mood]
enable_mood = true # 是否启用情绪系统
@ -86,7 +86,6 @@ mood_update_threshold = 1 # 情绪更新阈值,越高,更新越慢
[emoji]
emoji_chance = 0.6 # 麦麦激活表情包动作的概率
max_reg_num = 100 # 表情包最大注册数量
do_replace = true # 开启则在达到最大数量时删除(替换)表情包,关闭则达到最大数量时不会继续收集表情包
check_interval = 10 # 检查表情包(注册,破损,删除)的时间间隔(分钟)