feat:修复了action变更,修改了默认配置,提升版本号
This commit is contained in:
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
## [0.7.0] -2025-6-1
|
## [0.7.0] -2025-6-1
|
||||||
- 重构数据库,弃用MongoDB,采用轻量sqlite,无需额外安装
|
- 重构数据库,弃用MongoDB,采用轻量sqlite,无需额外安装
|
||||||
- 重构HFC,可扩展的聊天模式
|
- 重构HFC,可扩展的聊天模式,支持独立的表达模式
|
||||||
|
- HFC,丰富HFC的决策信息,更好的把握聊天内容
|
||||||
- HFC初步支持插件v0.1(测试版)
|
- HFC初步支持插件v0.1(测试版)
|
||||||
- 重构表情包模块
|
- 重构表情包模块
|
||||||
- 移除日程系统
|
- 移除日程系统
|
||||||
@@ -26,19 +27,12 @@
|
|||||||
- 插件:禁言动作
|
- 插件:禁言动作
|
||||||
- 表达器:装饰语言风格
|
- 表达器:装饰语言风格
|
||||||
- 可通过插件添加和自定义HFC部件(目前只支持action定义)
|
- 可通过插件添加和自定义HFC部件(目前只支持action定义)
|
||||||
|
- 为专注模式添加关系线索
|
||||||
**插件系统**
|
- 在专注模式下,麦麦可以决定自行发送语音消息(需要搭配tts适配器)
|
||||||
- 添加示例插件
|
- 优化reply,减少复读
|
||||||
- 示例插件:禁言插件
|
|
||||||
- 示例插件:豆包绘图插件
|
|
||||||
|
|
||||||
**人格**
|
|
||||||
- 简化了人格身份的配置
|
|
||||||
|
|
||||||
**语音**
|
|
||||||
- 麦麦可以决定自行发送语音消息(需要搭配tts适配器)
|
|
||||||
|
|
||||||
**新增表达方式学习**
|
**新增表达方式学习**
|
||||||
|
- 在专注模式下,麦麦可以有独特的表达方式
|
||||||
- 自主学习群聊中的表达方式,更贴近群友
|
- 自主学习群聊中的表达方式,更贴近群友
|
||||||
- 可自定义的学习频率和开关
|
- 可自定义的学习频率和开关
|
||||||
- 根据人设生成额外的表达方式
|
- 根据人设生成额外的表达方式
|
||||||
@@ -48,6 +42,14 @@
|
|||||||
- 大幅精简聊天状态切换规则,减少复杂度
|
- 大幅精简聊天状态切换规则,减少复杂度
|
||||||
- 移除聊天限额数量
|
- 移除聊天限额数量
|
||||||
|
|
||||||
|
**插件系统**
|
||||||
|
- 添加示例插件
|
||||||
|
- 示例插件:禁言插件
|
||||||
|
- 示例插件:豆包绘图插件
|
||||||
|
|
||||||
|
**人格**
|
||||||
|
- 简化了人格身份的配置
|
||||||
|
|
||||||
**数据库重构**
|
**数据库重构**
|
||||||
- 移除了默认使用MongoDB,采用轻量sqlite
|
- 移除了默认使用MongoDB,采用轻量sqlite
|
||||||
- 无需额外安装数据库
|
- 无需额外安装数据库
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ class MaiEmoji:
|
|||||||
emotion_str = ",".join(self.emotion) if self.emotion else ""
|
emotion_str = ",".join(self.emotion) if self.emotion else ""
|
||||||
|
|
||||||
Emoji.create(
|
Emoji.create(
|
||||||
hash=self.hash,
|
emoji_hash=self.hash,
|
||||||
full_path=self.full_path,
|
full_path=self.full_path,
|
||||||
format=self.format,
|
format=self.format,
|
||||||
description=self.description,
|
description=self.description,
|
||||||
@@ -367,7 +367,9 @@ class EmojiManager:
|
|||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self._initialized = None
|
if self._initialized:
|
||||||
|
return # 如果已经初始化过,直接返回
|
||||||
|
|
||||||
self._scan_task = None
|
self._scan_task = None
|
||||||
|
|
||||||
self.vlm = LLMRequest(model=global_config.model.vlm, temperature=0.3, max_tokens=1000, request_type="emoji")
|
self.vlm = LLMRequest(model=global_config.model.vlm, temperature=0.3, max_tokens=1000, request_type="emoji")
|
||||||
@@ -389,6 +391,7 @@ class EmojiManager:
|
|||||||
raise RuntimeError("数据库连接失败")
|
raise RuntimeError("数据库连接失败")
|
||||||
_ensure_emoji_dir()
|
_ensure_emoji_dir()
|
||||||
Emoji.create_table(safe=True) # Ensures table exists
|
Emoji.create_table(safe=True) # Ensures table exists
|
||||||
|
self._initialized = True
|
||||||
|
|
||||||
def _ensure_db(self) -> None:
|
def _ensure_db(self) -> None:
|
||||||
"""确保数据库已初始化"""
|
"""确保数据库已初始化"""
|
||||||
@@ -467,7 +470,7 @@ class EmojiManager:
|
|||||||
selected_emoji, similarity, matched_emotion = random.choice(top_emojis)
|
selected_emoji, similarity, matched_emotion = random.choice(top_emojis)
|
||||||
|
|
||||||
# 更新使用次数
|
# 更新使用次数
|
||||||
self.record_usage(selected_emoji.emoji_hash)
|
self.record_usage(selected_emoji.hash)
|
||||||
|
|
||||||
_time_end = time.time()
|
_time_end = time.time()
|
||||||
|
|
||||||
@@ -796,7 +799,7 @@ class EmojiManager:
|
|||||||
|
|
||||||
# 删除选定的表情包
|
# 删除选定的表情包
|
||||||
logger.info(f"[决策] 删除表情包: {emoji_to_delete.description}")
|
logger.info(f"[决策] 删除表情包: {emoji_to_delete.description}")
|
||||||
delete_success = await self.delete_emoji(emoji_to_delete.emoji_hash)
|
delete_success = await self.delete_emoji(emoji_to_delete.hash)
|
||||||
|
|
||||||
if delete_success:
|
if delete_success:
|
||||||
# 修复:等待异步注册完成
|
# 修复:等待异步注册完成
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from src.common.logger_manager import get_logger
|
|||||||
from src.llm_models.utils_model import LLMRequest
|
from src.llm_models.utils_model import LLMRequest
|
||||||
from src.config.config import global_config
|
from src.config.config import global_config
|
||||||
from src.chat.utils.chat_message_builder import get_raw_msg_by_timestamp_random, build_anonymous_messages
|
from src.chat.utils.chat_message_builder import get_raw_msg_by_timestamp_random, build_anonymous_messages
|
||||||
from src.chat.focus_chat.heartflow_prompt_builder import Prompt, global_prompt_manager
|
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
|||||||
@@ -56,44 +56,56 @@ class ActionProcessor(BaseProcessor):
|
|||||||
all_actions = None
|
all_actions = None
|
||||||
hfc_obs = None
|
hfc_obs = None
|
||||||
chat_obs = None
|
chat_obs = None
|
||||||
|
|
||||||
|
# 收集所有观察对象
|
||||||
for obs in observations:
|
for obs in observations:
|
||||||
if isinstance(obs, HFCloopObservation):
|
if isinstance(obs, HFCloopObservation):
|
||||||
hfc_obs = obs
|
hfc_obs = obs
|
||||||
if isinstance(obs, ChattingObservation):
|
if isinstance(obs, ChattingObservation):
|
||||||
chat_obs = obs
|
chat_obs = obs
|
||||||
|
|
||||||
|
# 合并所有动作变更
|
||||||
|
merged_action_changes = {"add": [], "remove": []}
|
||||||
|
reasons = []
|
||||||
|
|
||||||
|
# 处理HFCloopObservation
|
||||||
if hfc_obs:
|
if hfc_obs:
|
||||||
obs = hfc_obs
|
obs = hfc_obs
|
||||||
# 创建动作信息
|
|
||||||
all_actions = obs.all_actions
|
all_actions = obs.all_actions
|
||||||
action_changes = await self.analyze_loop_actions(obs)
|
action_changes = await self.analyze_loop_actions(obs)
|
||||||
if action_changes["add"] or action_changes["remove"]:
|
if action_changes["add"] or action_changes["remove"]:
|
||||||
action_info.set_action_changes(action_changes)
|
# 合并动作变更
|
||||||
# 设置变更原因
|
merged_action_changes["add"].extend(action_changes["add"])
|
||||||
reasons = []
|
merged_action_changes["remove"].extend(action_changes["remove"])
|
||||||
|
|
||||||
|
# 收集变更原因
|
||||||
if action_changes["add"]:
|
if action_changes["add"]:
|
||||||
reasons.append(f"添加动作{action_changes['add']}因为检测到大量无回复")
|
reasons.append(f"添加动作{action_changes['add']}因为检测到大量无回复")
|
||||||
if action_changes["remove"]:
|
if action_changes["remove"]:
|
||||||
reasons.append(f"移除动作{action_changes['remove']}因为检测到连续回复")
|
reasons.append(f"移除动作{action_changes['remove']}因为检测到连续回复")
|
||||||
action_info.set_reason(" | ".join(reasons))
|
|
||||||
|
# 处理ChattingObservation
|
||||||
if chat_obs and all_actions is not None:
|
if chat_obs and all_actions is not None:
|
||||||
obs = chat_obs
|
obs = chat_obs
|
||||||
action_changes = {"add": [], "remove": []}
|
|
||||||
# 检查动作的关联类型
|
# 检查动作的关联类型
|
||||||
chat_context = chat_manager.get_stream(obs.chat_id).context
|
chat_context = chat_manager.get_stream(obs.chat_id).context
|
||||||
|
type_mismatched_actions = []
|
||||||
|
|
||||||
for action_name in all_actions.keys():
|
for action_name in all_actions.keys():
|
||||||
data = all_actions[action_name]
|
data = all_actions[action_name]
|
||||||
if data.get("associated_types"):
|
if data.get("associated_types"):
|
||||||
if not chat_context.check_types(data["associated_types"]):
|
if not chat_context.check_types(data["associated_types"]):
|
||||||
action_changes["remove"].append(action_name)
|
type_mismatched_actions.append(action_name)
|
||||||
logger.debug(f"{self.log_prefix} 动作 {action_name} 关联类型不匹配,移除该动作")
|
logger.debug(f"{self.log_prefix} 动作 {action_name} 关联类型不匹配,移除该动作")
|
||||||
if len(action_changes["remove"]) > 0:
|
|
||||||
action_info.set_action_changes(action_changes)
|
if type_mismatched_actions:
|
||||||
# 设置变更原因
|
# 合并到移除列表中
|
||||||
reasons = []
|
merged_action_changes["remove"].extend(type_mismatched_actions)
|
||||||
if action_info.get_reason():
|
reasons.append(f"移除动作{type_mismatched_actions}因为关联类型不匹配")
|
||||||
reasons.append(action_info.get_reason())
|
|
||||||
if action_changes["remove"]:
|
# 如果有任何动作变更,设置到action_info中
|
||||||
reasons.append(f"移除动作{action_changes['remove']}因为关联类型不匹配")
|
if merged_action_changes["add"] or merged_action_changes["remove"]:
|
||||||
|
action_info.set_action_changes(merged_action_changes)
|
||||||
action_info.set_reason(" | ".join(reasons))
|
action_info.set_reason(" | ".join(reasons))
|
||||||
|
|
||||||
processed_infos.append(action_info)
|
processed_infos.append(action_info)
|
||||||
@@ -129,6 +141,7 @@ class ActionProcessor(BaseProcessor):
|
|||||||
|
|
||||||
# 检查no_reply比例
|
# 检查no_reply比例
|
||||||
if len(recent_cycles) >= 5 and (no_reply_count / len(recent_cycles)) >= 0.8:
|
if len(recent_cycles) >= 5 and (no_reply_count / len(recent_cycles)) >= 0.8:
|
||||||
|
if global_config.chat.chat_mode == "auto":
|
||||||
result["add"].append("exit_focus_chat")
|
result["add"].append("exit_focus_chat")
|
||||||
|
|
||||||
# 获取最近三次的reply状态
|
# 获取最近三次的reply状态
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ from src.chat.heart_flow.observation.hfcloop_observation import HFCloopObservati
|
|||||||
from typing import Dict
|
from typing import Dict
|
||||||
from src.chat.focus_chat.info.info_base import InfoBase
|
from src.chat.focus_chat.info.info_base import InfoBase
|
||||||
from src.chat.focus_chat.info.self_info import SelfInfo
|
from src.chat.focus_chat.info.self_info import SelfInfo
|
||||||
|
from src.chat.utils.utils import get_recent_group_speaker
|
||||||
|
|
||||||
logger = get_logger("processor")
|
logger = get_logger("processor")
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ logger = get_logger("processor")
|
|||||||
def init_prompt():
|
def init_prompt():
|
||||||
indentify_prompt = """
|
indentify_prompt = """
|
||||||
{name_block}
|
{name_block}
|
||||||
你是一个AI,但是你伪装成了一个人类,你的人格是,{prompt_personality}。
|
你是一个AI,但是你伪装成了一个人类,你的人格是,{prompt_personality}
|
||||||
{indentify_block}
|
{indentify_block}
|
||||||
|
|
||||||
{relation_prompt}
|
{relation_prompt}
|
||||||
@@ -101,12 +102,27 @@ class SelfProcessor(BaseProcessor):
|
|||||||
tuple: (current_mind, past_mind, prompt) 当前想法、过去的想法列表和使用的prompt
|
tuple: (current_mind, past_mind, prompt) 当前想法、过去的想法列表和使用的prompt
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
for observation in observations:
|
||||||
|
if isinstance(observation, ChattingObservation):
|
||||||
|
is_group_chat = observation.is_group_chat
|
||||||
|
chat_target_info = observation.chat_target_info
|
||||||
|
chat_target_name = "对方" # 私聊默认名称
|
||||||
|
person_list = observation.person_list
|
||||||
|
|
||||||
memory_str = ""
|
memory_str = ""
|
||||||
if running_memorys:
|
if running_memorys:
|
||||||
memory_str = "以下是当前在聊天中,你回忆起的记忆:\n"
|
memory_str = "以下是当前在聊天中,你回忆起的记忆:\n"
|
||||||
for running_memory in running_memorys:
|
for running_memory in running_memorys:
|
||||||
memory_str += f"{running_memory['topic']}: {running_memory['content']}\n"
|
memory_str += f"{running_memory['topic']}: {running_memory['content']}\n"
|
||||||
|
|
||||||
|
|
||||||
|
relation_prompt = ""
|
||||||
|
for person in person_list:
|
||||||
|
if len(person) >= 3 and person[0] and person[1]:
|
||||||
|
relation_prompt += await relationship_manager.build_relationship_info(person,is_id=True)
|
||||||
|
|
||||||
|
|
||||||
if observations is None:
|
if observations is None:
|
||||||
observations = []
|
observations = []
|
||||||
for observation in observations:
|
for observation in observations:
|
||||||
@@ -135,9 +151,17 @@ class SelfProcessor(BaseProcessor):
|
|||||||
personality_block = individuality.get_personality_prompt(x_person=2, level=2)
|
personality_block = individuality.get_personality_prompt(x_person=2, level=2)
|
||||||
identity_block = individuality.get_identity_prompt(x_person=2, level=2)
|
identity_block = individuality.get_identity_prompt(x_person=2, level=2)
|
||||||
|
|
||||||
relation_prompt = ""
|
if is_group_chat:
|
||||||
|
relation_prompt_init = "在这个群聊中,你:\n"
|
||||||
|
else:
|
||||||
|
relation_prompt_init = ""
|
||||||
for person in person_list:
|
for person in person_list:
|
||||||
relation_prompt += await relationship_manager.build_relationship_info(person, is_id=True)
|
relation_prompt += await relationship_manager.build_relationship_info(person, is_id=True)
|
||||||
|
if relation_prompt:
|
||||||
|
relation_prompt = relation_prompt_init + relation_prompt
|
||||||
|
else:
|
||||||
|
relation_prompt = relation_prompt_init + "没有特别在意的人\n"
|
||||||
|
|
||||||
|
|
||||||
prompt = (await global_prompt_manager.get_prompt_async("indentify_prompt")).format(
|
prompt = (await global_prompt_manager.get_prompt_async("indentify_prompt")).format(
|
||||||
name_block=name_block,
|
name_block=name_block,
|
||||||
@@ -149,6 +173,8 @@ class SelfProcessor(BaseProcessor):
|
|||||||
chat_observe_info=chat_observe_info,
|
chat_observe_info=chat_observe_info,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# print(prompt)
|
||||||
|
|
||||||
content = ""
|
content = ""
|
||||||
try:
|
try:
|
||||||
content, _ = await self.llm_model.generate_response_async(prompt=prompt)
|
content, _ = await self.llm_model.generate_response_async(prompt=prompt)
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ def init_prompt():
|
|||||||
{mind_info_block}
|
{mind_info_block}
|
||||||
{cycle_info_block}
|
{cycle_info_block}
|
||||||
|
|
||||||
|
{action_available_block}
|
||||||
|
|
||||||
请综合分析聊天内容和你看到的新消息,参考聊天规划,选择合适的action:
|
请综合分析聊天内容和你看到的新消息,参考聊天规划,选择合适的action:
|
||||||
|
|
||||||
{action_options_text}
|
{action_options_text}
|
||||||
@@ -43,6 +45,8 @@ def init_prompt():
|
|||||||
你必须从上面列出的可用action中选择一个,并说明原因。
|
你必须从上面列出的可用action中选择一个,并说明原因。
|
||||||
你的决策必须以严格的 JSON 格式输出,且仅包含 JSON 内容,不要有任何其他文字或解释。
|
你的决策必须以严格的 JSON 格式输出,且仅包含 JSON 内容,不要有任何其他文字或解释。
|
||||||
|
|
||||||
|
{moderation_prompt}
|
||||||
|
|
||||||
请你以下面格式输出你选择的action:
|
请你以下面格式输出你选择的action:
|
||||||
{{
|
{{
|
||||||
"action": "action_name",
|
"action": "action_name",
|
||||||
@@ -104,6 +108,7 @@ class ActionPlanner:
|
|||||||
add_actions = info.get_add_actions()
|
add_actions = info.get_add_actions()
|
||||||
remove_actions = info.get_remove_actions()
|
remove_actions = info.get_remove_actions()
|
||||||
reason = info.get_reason()
|
reason = info.get_reason()
|
||||||
|
print(f"{self.log_prefix} 动作变更: {add_actions} {remove_actions} {reason}")
|
||||||
|
|
||||||
# 处理动作的增加
|
# 处理动作的增加
|
||||||
for action_name in add_actions:
|
for action_name in add_actions:
|
||||||
@@ -121,6 +126,14 @@ class ActionPlanner:
|
|||||||
action = "no_reply"
|
action = "no_reply"
|
||||||
reasoning = f"之前选择的动作{action}已被移除,原因: {reason}"
|
reasoning = f"之前选择的动作{action}已被移除,原因: {reason}"
|
||||||
|
|
||||||
|
using_actions = self.action_manager.get_using_actions()
|
||||||
|
action_available_block = ""
|
||||||
|
for action_name, action_info in using_actions.items():
|
||||||
|
action_description = action_info["description"]
|
||||||
|
action_available_block += f"\n你在聊天中可以使用{action_name},这个动作的描述是{action_description}\n"
|
||||||
|
action_available_block += "注意,除了上述动作选项之外,你在群聊里不能做其他任何事情,这是你能力的边界\n"
|
||||||
|
|
||||||
|
|
||||||
# 继续处理其他信息
|
# 继续处理其他信息
|
||||||
for info in all_plan_info:
|
for info in all_plan_info:
|
||||||
if isinstance(info, ObsInfo):
|
if isinstance(info, ObsInfo):
|
||||||
@@ -142,11 +155,11 @@ class ActionPlanner:
|
|||||||
# 获取当前可用的动作
|
# 获取当前可用的动作
|
||||||
current_available_actions = self.action_manager.get_using_actions()
|
current_available_actions = self.action_manager.get_using_actions()
|
||||||
|
|
||||||
# 如果没有可用动作,直接返回no_reply
|
# 如果没有可用动作或只有no_reply动作,直接返回no_reply
|
||||||
if not current_available_actions:
|
if not current_available_actions or (len(current_available_actions) == 1 and "no_reply" in current_available_actions):
|
||||||
logger.warning(f"{self.log_prefix}没有可用的动作,将使用no_reply")
|
|
||||||
action = "no_reply"
|
action = "no_reply"
|
||||||
reasoning = "没有可用的动作"
|
reasoning = "没有可用的动作" if not current_available_actions else "只有no_reply动作可用,跳过规划"
|
||||||
|
logger.info(f"{self.log_prefix}{reasoning}")
|
||||||
return {
|
return {
|
||||||
"action_result": {"action_type": action, "action_data": action_data, "reasoning": reasoning},
|
"action_result": {"action_type": action, "action_data": action_data, "reasoning": reasoning},
|
||||||
"current_mind": current_mind,
|
"current_mind": current_mind,
|
||||||
@@ -164,6 +177,7 @@ class ActionPlanner:
|
|||||||
current_available_actions=current_available_actions, # <-- Pass determined actions
|
current_available_actions=current_available_actions, # <-- Pass determined actions
|
||||||
cycle_info=cycle_info, # <-- Pass cycle info
|
cycle_info=cycle_info, # <-- Pass cycle info
|
||||||
extra_info=extra_info,
|
extra_info=extra_info,
|
||||||
|
action_available_block=action_available_block,
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- 调用 LLM (普通文本生成) ---
|
# --- 调用 LLM (普通文本生成) ---
|
||||||
@@ -249,6 +263,7 @@ class ActionPlanner:
|
|||||||
chat_target_info: Optional[dict], # Now passed as argument
|
chat_target_info: Optional[dict], # Now passed as argument
|
||||||
observed_messages_str: str,
|
observed_messages_str: str,
|
||||||
current_mind: Optional[str],
|
current_mind: Optional[str],
|
||||||
|
action_available_block: str,
|
||||||
current_available_actions: Dict[str, ActionInfo],
|
current_available_actions: Dict[str, ActionInfo],
|
||||||
cycle_info: Optional[str],
|
cycle_info: Optional[str],
|
||||||
extra_info: list[str],
|
extra_info: list[str],
|
||||||
@@ -306,7 +321,13 @@ class ActionPlanner:
|
|||||||
action_options_block += using_action_prompt
|
action_options_block += using_action_prompt
|
||||||
|
|
||||||
extra_info_block = "\n".join(extra_info)
|
extra_info_block = "\n".join(extra_info)
|
||||||
|
if extra_info:
|
||||||
extra_info_block = f"以下是一些额外的信息,现在请你阅读以下内容,进行决策\n{extra_info_block}\n以上是一些额外的信息,现在请你阅读以下内容,进行决策"
|
extra_info_block = f"以下是一些额外的信息,现在请你阅读以下内容,进行决策\n{extra_info_block}\n以上是一些额外的信息,现在请你阅读以下内容,进行决策"
|
||||||
|
else:
|
||||||
|
extra_info_block = ""
|
||||||
|
|
||||||
|
|
||||||
|
moderation_prompt_block = "请不要输出违法违规内容,不要输出色情,暴力,政治相关内容,如有敏感内容,请规避。"
|
||||||
|
|
||||||
planner_prompt_template = await global_prompt_manager.get_prompt_async("planner_prompt")
|
planner_prompt_template = await global_prompt_manager.get_prompt_async("planner_prompt")
|
||||||
prompt = planner_prompt_template.format(
|
prompt = planner_prompt_template.format(
|
||||||
@@ -318,7 +339,9 @@ class ActionPlanner:
|
|||||||
mind_info_block=mind_info_block,
|
mind_info_block=mind_info_block,
|
||||||
cycle_info_block=cycle_info,
|
cycle_info_block=cycle_info,
|
||||||
action_options_text=action_options_block,
|
action_options_text=action_options_block,
|
||||||
|
action_available_block=action_available_block,
|
||||||
extra_info_block=extra_info_block,
|
extra_info_block=extra_info_block,
|
||||||
|
moderation_prompt=moderation_prompt_block,
|
||||||
)
|
)
|
||||||
return prompt
|
return prompt
|
||||||
|
|
||||||
|
|||||||
@@ -84,10 +84,4 @@ class HFCloopObservation:
|
|||||||
else:
|
else:
|
||||||
cycle_info_block += "\n你还没看过消息\n"
|
cycle_info_block += "\n你还没看过消息\n"
|
||||||
|
|
||||||
using_actions = self.action_manager.get_using_actions()
|
|
||||||
for action_name, action_info in using_actions.items():
|
|
||||||
action_description = action_info["description"]
|
|
||||||
cycle_info_block += f"\n你在聊天中可以使用{action_name},这个动作的描述是{action_description}\n"
|
|
||||||
cycle_info_block += "注意,除了上述动作选项之外,你在群聊里不能做其他任何事情,这是你能力的边界\n"
|
|
||||||
|
|
||||||
self.observe_info = cycle_info_block
|
self.observe_info = cycle_info_block
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import random
|
|||||||
from src.llm_models.utils_model import LLMRequest
|
from src.llm_models.utils_model import LLMRequest
|
||||||
from src.config.config import global_config
|
from src.config.config import global_config
|
||||||
from src.chat.message_receive.message import MessageThinking
|
from src.chat.message_receive.message import MessageThinking
|
||||||
from src.chat.focus_chat.heartflow_prompt_builder import prompt_builder
|
from src.chat.normal_chat.normal_prompt import prompt_builder
|
||||||
from src.chat.utils.utils import process_llm_response
|
from src.chat.utils.utils import process_llm_response
|
||||||
from src.chat.utils.timer_calculator import Timer
|
from src.chat.utils.timer_calculator import Timer
|
||||||
from src.common.logger_manager import get_logger
|
from src.common.logger_manager import get_logger
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ logger = get_logger("prompt")
|
|||||||
|
|
||||||
|
|
||||||
def init_prompt():
|
def init_prompt():
|
||||||
Prompt(
|
# Prompt(
|
||||||
"""
|
# """
|
||||||
你有以下信息可供参考:
|
# 你有以下信息可供参考:
|
||||||
{structured_info}
|
# {structured_info}
|
||||||
以上的消息是你获取到的消息,或许可以帮助你更好地回复。
|
# 以上的消息是你获取到的消息,或许可以帮助你更好地回复。
|
||||||
""",
|
# """,
|
||||||
"info_from_tools",
|
# "info_from_tools",
|
||||||
)
|
# )
|
||||||
|
|
||||||
Prompt("你正在qq群里聊天,下面是群里在聊的内容:", "chat_target_group1")
|
Prompt("你正在qq群里聊天,下面是群里在聊的内容:", "chat_target_group1")
|
||||||
Prompt("你正在和{sender_name}聊天,这是你们之前聊的内容:", "chat_target_private1")
|
Prompt("你正在和{sender_name}聊天,这是你们之前聊的内容:", "chat_target_private1")
|
||||||
@@ -94,9 +94,9 @@ class PromptBuilder:
|
|||||||
in_mind_reply=None,
|
in_mind_reply=None,
|
||||||
target_message=None,
|
target_message=None,
|
||||||
) -> Optional[str]:
|
) -> Optional[str]:
|
||||||
if build_mode == "normal":
|
|
||||||
return await self._build_prompt_normal(chat_stream, message_txt or "", sender_name)
|
return await self._build_prompt_normal(chat_stream, message_txt or "", sender_name)
|
||||||
return None
|
|
||||||
|
|
||||||
async def _build_prompt_normal(self, chat_stream, message_txt: str, sender_name: str = "某人") -> str:
|
async def _build_prompt_normal(self, chat_stream, message_txt: str, sender_name: str = "某人") -> str:
|
||||||
prompt_personality = individuality.get_prompt(x_person=2, level=2)
|
prompt_personality = individuality.get_prompt(x_person=2, level=2)
|
||||||
@@ -107,7 +107,7 @@ class PromptBuilder:
|
|||||||
who_chat_in_group = get_recent_group_speaker(
|
who_chat_in_group = get_recent_group_speaker(
|
||||||
chat_stream.stream_id,
|
chat_stream.stream_id,
|
||||||
(chat_stream.user_info.platform, chat_stream.user_info.user_id) if chat_stream.user_info else None,
|
(chat_stream.user_info.platform, chat_stream.user_info.user_id) if chat_stream.user_info else None,
|
||||||
limit=global_config.focus_chat.observation_context_size,
|
limit=global_config.normal_chat.max_context_size,
|
||||||
)
|
)
|
||||||
elif chat_stream.user_info:
|
elif chat_stream.user_info:
|
||||||
who_chat_in_group.append(
|
who_chat_in_group.append(
|
||||||
@@ -118,8 +118,8 @@ class PromptBuilder:
|
|||||||
for person in who_chat_in_group:
|
for person in who_chat_in_group:
|
||||||
if len(person) >= 3 and person[0] and person[1]:
|
if len(person) >= 3 and person[0] and person[1]:
|
||||||
relation_prompt += await relationship_manager.build_relationship_info(person)
|
relation_prompt += await relationship_manager.build_relationship_info(person)
|
||||||
else:
|
|
||||||
logger.warning(f"Invalid person tuple encountered for relationship prompt: {person}")
|
|
||||||
mood_prompt = mood_manager.get_mood_prompt()
|
mood_prompt = mood_manager.get_mood_prompt()
|
||||||
reply_styles1 = [
|
reply_styles1 = [
|
||||||
("然后给出日常且口语化的回复,平淡一些", 0.4),
|
("然后给出日常且口语化的回复,平淡一些", 0.4),
|
||||||
@@ -194,6 +194,8 @@ class PromptBuilder:
|
|||||||
if random.random() < 0.04:
|
if random.random() < 0.04:
|
||||||
prompt_ger += "你喜欢用流行梗"
|
prompt_ger += "你喜欢用流行梗"
|
||||||
|
|
||||||
|
moderation_prompt_block = "请不要输出违法违规内容,不要输出色情,暴力,政治相关内容,如有敏感内容,请规避。"
|
||||||
|
|
||||||
# 知识构建
|
# 知识构建
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
prompt_info = await self.get_prompt_info(message_txt, threshold=0.38)
|
prompt_info = await self.get_prompt_info(message_txt, threshold=0.38)
|
||||||
@@ -231,7 +233,7 @@ class PromptBuilder:
|
|||||||
keywords_reaction_prompt=keywords_reaction_prompt,
|
keywords_reaction_prompt=keywords_reaction_prompt,
|
||||||
prompt_ger=prompt_ger,
|
prompt_ger=prompt_ger,
|
||||||
# moderation_prompt=await global_prompt_manager.get_prompt_async("moderation_prompt"),
|
# moderation_prompt=await global_prompt_manager.get_prompt_async("moderation_prompt"),
|
||||||
moderation_prompt="",
|
moderation_prompt=moderation_prompt_block,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
template_name = "reasoning_prompt_private_main"
|
template_name = "reasoning_prompt_private_main"
|
||||||
@@ -254,7 +256,7 @@ class PromptBuilder:
|
|||||||
keywords_reaction_prompt=keywords_reaction_prompt,
|
keywords_reaction_prompt=keywords_reaction_prompt,
|
||||||
prompt_ger=prompt_ger,
|
prompt_ger=prompt_ger,
|
||||||
# moderation_prompt=await global_prompt_manager.get_prompt_async("moderation_prompt"),
|
# moderation_prompt=await global_prompt_manager.get_prompt_async("moderation_prompt"),
|
||||||
moderation_prompt="",
|
moderation_prompt=moderation_prompt_block,
|
||||||
)
|
)
|
||||||
# --- End choosing template ---
|
# --- End choosing template ---
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ class ImageManager:
|
|||||||
current_timestamp = time.time()
|
current_timestamp = time.time()
|
||||||
defaults = {"description": description, "timestamp": current_timestamp}
|
defaults = {"description": description, "timestamp": current_timestamp}
|
||||||
desc_obj, created = ImageDescriptions.get_or_create(
|
desc_obj, created = ImageDescriptions.get_or_create(
|
||||||
hash=image_hash, type=description_type, defaults=defaults
|
image_description_hash=image_hash, type=description_type, defaults=defaults
|
||||||
)
|
)
|
||||||
if not created: # 如果记录已存在,则更新
|
if not created: # 如果记录已存在,则更新
|
||||||
desc_obj.description = description
|
desc_obj.description = description
|
||||||
@@ -150,7 +150,7 @@ class ImageManager:
|
|||||||
img_obj.save()
|
img_obj.save()
|
||||||
except Images.DoesNotExist:
|
except Images.DoesNotExist:
|
||||||
Images.create(
|
Images.create(
|
||||||
hash=image_hash,
|
emoji_hash=image_hash,
|
||||||
path=file_path,
|
path=file_path,
|
||||||
type="emoji",
|
type="emoji",
|
||||||
description=description,
|
description=description,
|
||||||
@@ -223,7 +223,7 @@ class ImageManager:
|
|||||||
img_obj.save()
|
img_obj.save()
|
||||||
except Images.DoesNotExist:
|
except Images.DoesNotExist:
|
||||||
Images.create(
|
Images.create(
|
||||||
hash=image_hash,
|
emoji_hash=image_hash,
|
||||||
path=file_path,
|
path=file_path,
|
||||||
type="image",
|
type="image",
|
||||||
description=description,
|
description=description,
|
||||||
|
|||||||
@@ -663,11 +663,11 @@ PROCESSOR_STYLE_CONFIG = {
|
|||||||
|
|
||||||
PLANNER_STYLE_CONFIG = {
|
PLANNER_STYLE_CONFIG = {
|
||||||
"advanced": {
|
"advanced": {
|
||||||
"console_format": "<level>{time:HH:mm:ss}</level> | <fg #4DCDFF>规划器</fg #4DCDFF> | <fg #4DCDFF>{message}</fg #4DCDFF>",
|
"console_format": "<level>{time:HH:mm:ss}</level> | <fg #069AFF>规划器</fg #069AFF> | <fg #069AFF>{message}</fg #069AFF>",
|
||||||
"file_format": "{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {extra[module]: <15} | 规划器 | {message}",
|
"file_format": "{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {extra[module]: <15} | 规划器 | {message}",
|
||||||
},
|
},
|
||||||
"simple": {
|
"simple": {
|
||||||
"console_format": "<level>{time:HH:mm:ss}</level> | <fg #4DCDFF>规划器</fg #4DCDFF> | <fg #4DCDFF>{message}</fg #4DCDFF>",
|
"console_format": "<level>{time:HH:mm:ss}</level> | <fg #069AFF>规划器</fg #069AFF> | <fg #069AFF>{message}</fg #069AFF>",
|
||||||
"file_format": "{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {extra[module]: <15} | 规划器 | {message}",
|
"file_format": "{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {extra[module]: <15} | 规划器 | {message}",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ TEMPLATE_DIR = "template"
|
|||||||
|
|
||||||
# 考虑到,实际上配置文件中的mai_version是不会自动更新的,所以采用硬编码
|
# 考虑到,实际上配置文件中的mai_version是不会自动更新的,所以采用硬编码
|
||||||
# 对该字段的更新,请严格参照语义化版本规范:https://semver.org/lang/zh-CN/
|
# 对该字段的更新,请严格参照语义化版本规范:https://semver.org/lang/zh-CN/
|
||||||
MMC_VERSION = "0.7.0-snapshot.1"
|
MMC_VERSION = "0.7.0-snapshot.2"
|
||||||
|
|
||||||
|
|
||||||
def update_config():
|
def update_config():
|
||||||
|
|||||||
@@ -181,6 +181,9 @@ class EmojiConfig(ConfigBase):
|
|||||||
save_pic: bool = False
|
save_pic: bool = False
|
||||||
"""是否保存图片"""
|
"""是否保存图片"""
|
||||||
|
|
||||||
|
save_emoji: bool = False
|
||||||
|
"""是否保存表情包"""
|
||||||
|
|
||||||
cache_emoji: bool = True
|
cache_emoji: bool = True
|
||||||
"""是否缓存表情包"""
|
"""是否缓存表情包"""
|
||||||
|
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ class PersonalityExpression:
|
|||||||
logger.error(f"删除旧的表达文件 {self.expressions_file_path} 失败: {e}")
|
logger.error(f"删除旧的表达文件 {self.expressions_file_path} 失败: {e}")
|
||||||
|
|
||||||
if count >= self.max_calculations:
|
if count >= self.max_calculations:
|
||||||
logger.info(f"对于风格 '{current_style_text}' 已达到最大计算次数 ({self.max_calculations})。跳过提取。")
|
logger.debug(f"对于风格 '{current_style_text}' 已达到最大计算次数 ({self.max_calculations})。跳过提取。")
|
||||||
# 即使跳过,也更新元数据以反映当前风格已被识别且计数已满
|
# 即使跳过,也更新元数据以反映当前风格已被识别且计数已满
|
||||||
self._write_meta_data({"last_style_text": current_style_text, "count": count})
|
self._write_meta_data({"last_style_text": current_style_text, "count": count})
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -435,7 +435,7 @@ class LLMRequest:
|
|||||||
logger.error(
|
logger.error(
|
||||||
f"模型 {self.model_name} 错误码: {response.status} - {error_code_mapping.get(response.status)}"
|
f"模型 {self.model_name} 错误码: {response.status} - {error_code_mapping.get(response.status)}"
|
||||||
)
|
)
|
||||||
raise RuntimeError("服务器负载过高,模型恢复失败QAQ")
|
raise RuntimeError("服务器负载过高,模型回复失败QAQ")
|
||||||
else:
|
else:
|
||||||
logger.warning(f"模型 {self.model_name} 请求限制(429),等待{wait_time}秒后重试...")
|
logger.warning(f"模型 {self.model_name} 请求限制(429),等待{wait_time}秒后重试...")
|
||||||
raise RuntimeError("请求限制(429)")
|
raise RuntimeError("请求限制(429)")
|
||||||
@@ -459,6 +459,7 @@ class LLMRequest:
|
|||||||
logger.error(
|
logger.error(
|
||||||
f"模型 {self.model_name} 错误码: {response.status} - {error_code_mapping.get(response.status)}"
|
f"模型 {self.model_name} 错误码: {response.status} - {error_code_mapping.get(response.status)}"
|
||||||
)
|
)
|
||||||
|
print(response)
|
||||||
# 尝试获取并记录服务器返回的详细错误信息
|
# 尝试获取并记录服务器返回的详细错误信息
|
||||||
try:
|
try:
|
||||||
error_json = await response.json()
|
error_json = await response.json()
|
||||||
|
|||||||
@@ -96,11 +96,6 @@ class MainSystem:
|
|||||||
personality_core=global_config.personality.personality_core,
|
personality_core=global_config.personality.personality_core,
|
||||||
personality_sides=global_config.personality.personality_sides,
|
personality_sides=global_config.personality.personality_sides,
|
||||||
identity_detail=global_config.identity.identity_detail,
|
identity_detail=global_config.identity.identity_detail,
|
||||||
height=global_config.identity.height,
|
|
||||||
weight=global_config.identity.weight,
|
|
||||||
age=global_config.identity.age,
|
|
||||||
gender=global_config.identity.gender,
|
|
||||||
appearance=global_config.identity.appearance,
|
|
||||||
)
|
)
|
||||||
logger.success("个体特征初始化成功")
|
logger.success("个体特征初始化成功")
|
||||||
|
|
||||||
|
|||||||
@@ -297,6 +297,8 @@ class RelationshipManager:
|
|||||||
relationship_value = await person_info_manager.get_value(person_id, "relationship_value")
|
relationship_value = await person_info_manager.get_value(person_id, "relationship_value")
|
||||||
level_num = self.calculate_level_num(relationship_value)
|
level_num = self.calculate_level_num(relationship_value)
|
||||||
|
|
||||||
|
relation_value_prompt = ""
|
||||||
|
|
||||||
if level_num == 0 or level_num == 5:
|
if level_num == 0 or level_num == 5:
|
||||||
relationship_level = ["厌恶", "冷漠以对", "认识", "友好对待", "喜欢", "暧昧"]
|
relationship_level = ["厌恶", "冷漠以对", "认识", "友好对待", "喜欢", "暧昧"]
|
||||||
relation_prompt2_list = [
|
relation_prompt2_list = [
|
||||||
@@ -307,9 +309,9 @@ class RelationshipManager:
|
|||||||
"积极回复",
|
"积极回复",
|
||||||
"友善和包容的回复",
|
"友善和包容的回复",
|
||||||
]
|
]
|
||||||
return f"你{relationship_level[level_num]}{person_name},打算{relation_prompt2_list[level_num]}。\n"
|
relation_value_prompt = f"你{relationship_level[level_num]}{person_name},打算{relation_prompt2_list[level_num]}。"
|
||||||
elif level_num == 2:
|
elif level_num == 2:
|
||||||
return ""
|
relation_value_prompt = ""
|
||||||
else:
|
else:
|
||||||
if random.random() < 0.6:
|
if random.random() < 0.6:
|
||||||
relationship_level = ["厌恶", "冷漠以对", "认识", "友好对待", "喜欢", "暧昧"]
|
relationship_level = ["厌恶", "冷漠以对", "认识", "友好对待", "喜欢", "暧昧"]
|
||||||
@@ -321,9 +323,18 @@ class RelationshipManager:
|
|||||||
"积极回复",
|
"积极回复",
|
||||||
"友善和包容的回复",
|
"友善和包容的回复",
|
||||||
]
|
]
|
||||||
return f"你{relationship_level[level_num]}{person_name},打算{relation_prompt2_list[level_num]}。\n"
|
relation_value_prompt = f"你{relationship_level[level_num]}{person_name},打算{relation_prompt2_list[level_num]}。"
|
||||||
else:
|
else:
|
||||||
return ""
|
relation_value_prompt = ""
|
||||||
|
|
||||||
|
if relation_value_prompt:
|
||||||
|
nickname_str = await person_info_manager.get_value(person_id, "nickname")
|
||||||
|
platform = await person_info_manager.get_value(person_id, "platform")
|
||||||
|
relation_prompt = f"{relation_value_prompt},ta在{platform}上的昵称是{nickname_str}。\n"
|
||||||
|
else:
|
||||||
|
relation_prompt = ""
|
||||||
|
|
||||||
|
return relation_prompt
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def calculate_level_num(relationship_value) -> int:
|
def calculate_level_num(relationship_value) -> int:
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ class PicAction(PluginAction):
|
|||||||
|
|
||||||
if encode_success:
|
if encode_success:
|
||||||
base64_image_string = encode_result
|
base64_image_string = encode_result
|
||||||
send_success = await self.send_message(type="emoji", data=base64_image_string)
|
send_success = await self.send_message(type="image", data=base64_image_string)
|
||||||
if send_success:
|
if send_success:
|
||||||
await self.send_message_by_expressor("图片表情已发送!")
|
await self.send_message_by_expressor("图片表情已发送!")
|
||||||
return True, "图片表情已发送"
|
return True, "图片表情已发送"
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ learning_interval = 300 # 学习间隔 单位秒
|
|||||||
max_reg_num = 40 # 表情包最大注册数量
|
max_reg_num = 40 # 表情包最大注册数量
|
||||||
do_replace = true # 开启则在达到最大数量时删除(替换)表情包,关闭则达到最大数量时不会继续收集表情包
|
do_replace = true # 开启则在达到最大数量时删除(替换)表情包,关闭则达到最大数量时不会继续收集表情包
|
||||||
check_interval = 120 # 检查表情包(注册,破损,删除)的时间间隔(分钟)
|
check_interval = 120 # 检查表情包(注册,破损,删除)的时间间隔(分钟)
|
||||||
save_pic = false # 是否保存图片
|
save_pic = true # 是否保存图片
|
||||||
cache_emoji = true # 是否缓存表情包
|
cache_emoji = true # 是否缓存表情包
|
||||||
steal_emoji = true # 是否偷取表情包,让麦麦可以发送她保存的这些表情包
|
steal_emoji = true # 是否偷取表情包,让麦麦可以发送她保存的这些表情包
|
||||||
content_filtration = false # 是否启用表情包过滤,只有符合该要求的表情包才会被保存
|
content_filtration = false # 是否启用表情包过滤,只有符合该要求的表情包才会被保存
|
||||||
|
|||||||
Reference in New Issue
Block a user