feat:精简处理器上下文
This commit is contained in:
@@ -660,6 +660,7 @@ class HeartFChatting:
|
||||
}
|
||||
|
||||
with Timer("执行动作", cycle_timers):
|
||||
|
||||
action_type, action_data, reasoning = (
|
||||
plan_result.get("action_result", {}).get("action_type", "error"),
|
||||
plan_result.get("action_result", {}).get("action_data", {}),
|
||||
@@ -674,7 +675,7 @@ class HeartFChatting:
|
||||
action_str = action_type
|
||||
|
||||
logger.debug(f"{self.log_prefix} 麦麦想要:'{action_str}'")
|
||||
|
||||
|
||||
success, reply_text, command = await self._handle_action(
|
||||
action_type, reasoning, action_data, cycle_timers, thinking_id
|
||||
)
|
||||
|
||||
@@ -20,7 +20,7 @@ class HFCVersionManager:
|
||||
"""HFC版本号管理器"""
|
||||
|
||||
# 默认版本号
|
||||
DEFAULT_VERSION = "v1.0.0"
|
||||
DEFAULT_VERSION = "v2.0.2"
|
||||
|
||||
# 当前运行时版本号
|
||||
_current_version: Optional[str] = None
|
||||
|
||||
@@ -16,6 +16,8 @@ class ObsInfo(InfoBase):
|
||||
Data Fields:
|
||||
talking_message (str): 说话消息内容
|
||||
talking_message_str_truncate (str): 截断后的说话消息内容
|
||||
talking_message_str_short (str): 简短版本的说话消息内容(使用最新一半消息)
|
||||
talking_message_str_truncate_short (str): 截断简短版本的说话消息内容(使用最新一半消息)
|
||||
chat_type (str): 聊天类型,可以是 "private"(私聊)、"group"(群聊)或 "other"(其他)
|
||||
"""
|
||||
|
||||
@@ -37,6 +39,22 @@ class ObsInfo(InfoBase):
|
||||
"""
|
||||
self.data["talking_message_str_truncate"] = message
|
||||
|
||||
def set_talking_message_str_short(self, message: str) -> None:
|
||||
"""设置简短版本的说话消息
|
||||
|
||||
Args:
|
||||
message (str): 简短版本的说话消息内容
|
||||
"""
|
||||
self.data["talking_message_str_short"] = message
|
||||
|
||||
def set_talking_message_str_truncate_short(self, message: str) -> None:
|
||||
"""设置截断简短版本的说话消息
|
||||
|
||||
Args:
|
||||
message (str): 截断简短版本的说话消息内容
|
||||
"""
|
||||
self.data["talking_message_str_truncate_short"] = message
|
||||
|
||||
def set_previous_chat_info(self, message: str) -> None:
|
||||
"""设置之前聊天信息
|
||||
|
||||
@@ -62,6 +80,22 @@ class ObsInfo(InfoBase):
|
||||
chat_target (str): 聊天目标,可以是 "private"(私聊)、"group"(群聊)或 "other"(其他)
|
||||
"""
|
||||
self.data["chat_target"] = chat_target
|
||||
|
||||
def set_chat_id(self, chat_id: str) -> None:
|
||||
"""设置聊天ID
|
||||
|
||||
Args:
|
||||
chat_id (str): 聊天ID
|
||||
"""
|
||||
self.data["chat_id"] = chat_id
|
||||
|
||||
def get_chat_id(self) -> Optional[str]:
|
||||
"""获取聊天ID
|
||||
|
||||
Returns:
|
||||
Optional[str]: 聊天ID,如果未设置则返回 None
|
||||
"""
|
||||
return self.get_info("chat_id")
|
||||
|
||||
def get_talking_message(self) -> Optional[str]:
|
||||
"""获取说话消息
|
||||
@@ -79,6 +113,22 @@ class ObsInfo(InfoBase):
|
||||
"""
|
||||
return self.get_info("talking_message_str_truncate")
|
||||
|
||||
def get_talking_message_str_short(self) -> Optional[str]:
|
||||
"""获取简短版本的说话消息
|
||||
|
||||
Returns:
|
||||
Optional[str]: 简短版本的说话消息内容,如果未设置则返回 None
|
||||
"""
|
||||
return self.get_info("talking_message_str_short")
|
||||
|
||||
def get_talking_message_str_truncate_short(self) -> Optional[str]:
|
||||
"""获取截断简短版本的说话消息
|
||||
|
||||
Returns:
|
||||
Optional[str]: 截断简短版本的说话消息内容,如果未设置则返回 None
|
||||
"""
|
||||
return self.get_info("talking_message_str_truncate_short")
|
||||
|
||||
def get_chat_type(self) -> str:
|
||||
"""获取聊天类型
|
||||
|
||||
|
||||
@@ -62,6 +62,10 @@ class ChattingInfoProcessor(BaseProcessor):
|
||||
# 改为异步任务,不阻塞主流程
|
||||
# asyncio.create_task(self.chat_compress(obs))
|
||||
|
||||
# 设置聊天ID
|
||||
if hasattr(obs, "chat_id"):
|
||||
obs_info.set_chat_id(obs.chat_id)
|
||||
|
||||
# 设置说话消息
|
||||
if hasattr(obs, "talking_message_str"):
|
||||
# print(f"设置说话消息:obs.talking_message_str: {obs.talking_message_str}")
|
||||
@@ -72,6 +76,14 @@ class ChattingInfoProcessor(BaseProcessor):
|
||||
# print(f"设置截断后的说话消息:obs.talking_message_str_truncate: {obs.talking_message_str_truncate}")
|
||||
obs_info.set_talking_message_str_truncate(obs.talking_message_str_truncate)
|
||||
|
||||
# 设置简短版本的说话消息
|
||||
if hasattr(obs, "talking_message_str_short"):
|
||||
obs_info.set_talking_message_str_short(obs.talking_message_str_short)
|
||||
|
||||
# 设置截断简短版本的说话消息
|
||||
if hasattr(obs, "talking_message_str_truncate_short"):
|
||||
obs_info.set_talking_message_str_truncate_short(obs.talking_message_str_truncate_short)
|
||||
|
||||
if hasattr(obs, "mid_memory_info"):
|
||||
# print(f"设置之前聊天信息:obs.mid_memory_info: {obs.mid_memory_info}")
|
||||
obs_info.set_previous_chat_info(obs.mid_memory_info)
|
||||
@@ -82,7 +94,8 @@ class ChattingInfoProcessor(BaseProcessor):
|
||||
chat_type = "group"
|
||||
else:
|
||||
chat_type = "private"
|
||||
obs_info.set_chat_target(obs.chat_target_info.get("person_name", "某人"))
|
||||
if hasattr(obs, "chat_target_info") and obs.chat_target_info:
|
||||
obs_info.set_chat_target(obs.chat_target_info.get("person_name", "某人"))
|
||||
obs_info.set_chat_type(chat_type)
|
||||
|
||||
# logger.debug(f"聊天信息处理器处理后的信息: {obs_info}")
|
||||
|
||||
@@ -149,7 +149,8 @@ class ExpressionSelectorProcessor(BaseProcessor):
|
||||
if observations:
|
||||
for observation in observations:
|
||||
if isinstance(observation, ChattingObservation):
|
||||
chat_info = observation.get_observe_info()
|
||||
# chat_info = observation.get_observe_info()
|
||||
chat_info = observation.talking_message_str_truncate_short
|
||||
break
|
||||
|
||||
if not chat_info:
|
||||
|
||||
@@ -144,7 +144,7 @@ def init_prompt():
|
||||
fetch_info_prompt = """
|
||||
|
||||
{name_block}
|
||||
以下是你对{person_name}的了解,请你从中提取用户的有关"{info_type}"的信息,如果用户没有相关信息,请输出none:
|
||||
以下是你在之前与{person_name}的交流中,产生的对{person_name}的了解,请你从中提取用户的有关"{info_type}"的信息,如果用户没有相关信息,请输出none:
|
||||
{person_impression_block}
|
||||
{points_text_block}
|
||||
请严格按照以下json输出格式,不要输出多余内容:
|
||||
@@ -547,8 +547,7 @@ class PersonImpressionpProcessor(BaseProcessor):
|
||||
for observation in observations:
|
||||
if isinstance(observation, ChattingObservation):
|
||||
chat_observe_info = observation.get_observe_info()
|
||||
chat_observe_info = chat_observe_info[-300:]
|
||||
|
||||
# latest_message_time = observation.last_observe_time
|
||||
# 从聊天观察中提取用户信息并更新消息段
|
||||
# 获取最新的非bot消息来更新消息段
|
||||
latest_messages = get_raw_msg_by_timestamp_with_chat(
|
||||
|
||||
@@ -112,7 +112,8 @@ class ToolProcessor(BaseProcessor):
|
||||
|
||||
is_group_chat = observation.is_group_chat
|
||||
|
||||
chat_observe_info = observation.get_observe_info()
|
||||
# chat_observe_info = observation.get_observe_info()
|
||||
chat_observe_info = observation.talking_message_str_truncate_short
|
||||
# person_list = observation.person_list
|
||||
|
||||
# 获取时间信息
|
||||
|
||||
@@ -94,7 +94,7 @@ class MemoryActivator:
|
||||
obs_info_text = ""
|
||||
for observation in observations:
|
||||
if isinstance(observation, ChattingObservation):
|
||||
obs_info_text += observation.get_observe_info()
|
||||
obs_info_text += observation.talking_message_str_truncate_short
|
||||
elif isinstance(observation, StructureObservation):
|
||||
working_info = observation.get_observe_info()
|
||||
for working_info_item in working_info:
|
||||
|
||||
@@ -63,6 +63,8 @@ class ChattingObservation(Observation):
|
||||
self.talking_message = []
|
||||
self.talking_message_str = ""
|
||||
self.talking_message_str_truncate = ""
|
||||
self.talking_message_str_short = ""
|
||||
self.talking_message_str_truncate_short = ""
|
||||
self.name = global_config.bot.nickname
|
||||
self.nick_name = global_config.bot.alias_names
|
||||
self.max_now_obs_len = global_config.focus_chat.observation_context_size
|
||||
@@ -88,6 +90,8 @@ class ChattingObservation(Observation):
|
||||
"chat_target_info": self.chat_target_info,
|
||||
"talking_message_str": self.talking_message_str,
|
||||
"talking_message_str_truncate": self.talking_message_str_truncate,
|
||||
"talking_message_str_short": self.talking_message_str_short,
|
||||
"talking_message_str_truncate_short": self.talking_message_str_truncate_short,
|
||||
"name": self.name,
|
||||
"nick_name": self.nick_name,
|
||||
"last_observe_time": self.last_observe_time,
|
||||
@@ -228,6 +232,24 @@ class ChattingObservation(Observation):
|
||||
truncate=True,
|
||||
show_actions=True,
|
||||
)
|
||||
|
||||
# 构建简短版本 - 使用最新一半的消息
|
||||
half_count = len(self.talking_message) // 2
|
||||
recent_messages = self.talking_message[-half_count:] if half_count > 0 else self.talking_message
|
||||
|
||||
self.talking_message_str_short = build_readable_messages(
|
||||
messages=recent_messages,
|
||||
timestamp_mode="lite",
|
||||
read_mark=last_obs_time_mark,
|
||||
show_actions=True,
|
||||
)
|
||||
self.talking_message_str_truncate_short = build_readable_messages(
|
||||
messages=recent_messages,
|
||||
timestamp_mode="normal_no_YMD",
|
||||
read_mark=last_obs_time_mark,
|
||||
truncate=True,
|
||||
show_actions=True,
|
||||
)
|
||||
|
||||
self.person_list = await get_person_id_list(self.talking_message)
|
||||
|
||||
|
||||
@@ -54,6 +54,8 @@ class ReplyAction(BaseAction):
|
||||
logger.info(f"{self.log_prefix} 决定回复: {self.reasoning}")
|
||||
|
||||
start_time = self.action_data.get("loop_start_time", time.time())
|
||||
|
||||
|
||||
|
||||
try:
|
||||
success, reply_set = await generator_api.generate_reply(
|
||||
@@ -64,6 +66,7 @@ class ReplyAction(BaseAction):
|
||||
is_group=self.is_group,
|
||||
)
|
||||
|
||||
|
||||
# 检查从start_time以来的新消息数量
|
||||
# 获取动作触发时间或使用默认值
|
||||
current_time = time.time()
|
||||
@@ -79,15 +82,20 @@ class ReplyAction(BaseAction):
|
||||
|
||||
# 构建回复文本
|
||||
reply_text = ""
|
||||
first_reply = False
|
||||
first_replyed = False
|
||||
for reply_seg in reply_set:
|
||||
data = reply_seg[1]
|
||||
if not first_reply and need_reply:
|
||||
await self.send_text(content=data, reply_to=self.action_data.get("reply_to", ""))
|
||||
if not first_replyed:
|
||||
if need_reply:
|
||||
await self.send_text(content=data, reply_to=self.action_data.get("reply_to", ""),typing=False)
|
||||
first_replyed = True
|
||||
else:
|
||||
await self.send_text(content=data,typing=False)
|
||||
first_replyed = True
|
||||
else:
|
||||
await self.send_text(content=data)
|
||||
first_reply = True
|
||||
await self.send_text(content=data,typing=True)
|
||||
reply_text += data
|
||||
|
||||
|
||||
# 存储动作记录
|
||||
await self.store_action_info(
|
||||
@@ -119,16 +127,17 @@ class NoReplyAction(BaseAction):
|
||||
action_name = "no_reply"
|
||||
action_description = "暂时不回复消息"
|
||||
|
||||
# 默认超时时间,将由插件在注册时设置
|
||||
waiting_timeout = 1200
|
||||
|
||||
# 连续no_reply计数器
|
||||
_consecutive_count = 0
|
||||
|
||||
# random_activation_probability = 0.2
|
||||
|
||||
# 分级等待时间
|
||||
_waiting_stages = [10, 60, 600] # 第1、2、3次的等待时间
|
||||
|
||||
# 概率判定时间点
|
||||
_probability_check_time = 15 # 15秒时进行概率判定
|
||||
|
||||
# 概率判定通过的概率(通过则结束动作)
|
||||
_end_probability = 0.5 # 50%概率结束
|
||||
|
||||
# 最大等待超时时间
|
||||
_max_timeout = 1200 # 1200秒
|
||||
|
||||
# 动作参数定义
|
||||
action_parameters = {"reason": "不回复的原因"}
|
||||
@@ -140,33 +149,42 @@ class NoReplyAction(BaseAction):
|
||||
associated_types = []
|
||||
|
||||
async def execute(self) -> Tuple[bool, str]:
|
||||
"""执行不回复动作,等待新消息或超时"""
|
||||
"""执行不回复动作,在15秒时进行概率判定,决定是否继续等待"""
|
||||
import random
|
||||
|
||||
try:
|
||||
# 增加连续计数
|
||||
NoReplyAction._consecutive_count += 1
|
||||
count = NoReplyAction._consecutive_count
|
||||
|
||||
reason = self.action_data.get("reason", "")
|
||||
|
||||
logger.info(f"{self.log_prefix} 选择不回复(第{count}次),开始等待新消息,原因: {reason}")
|
||||
|
||||
# 计算本次等待时间
|
||||
if count <= len(self._waiting_stages):
|
||||
# 前3次使用预设时间
|
||||
stage_time = self._waiting_stages[count - 1]
|
||||
# 如果WAITING_TIME_THRESHOLD更小,则使用它
|
||||
timeout = min(stage_time, self.waiting_timeout)
|
||||
# 先等待到概率判定时间点(15秒)
|
||||
logger.info(f"{self.log_prefix} 等待{self._probability_check_time}秒后进行概率判定...")
|
||||
|
||||
# 等待15秒或有新消息
|
||||
result = await self.wait_for_new_message(self._probability_check_time)
|
||||
|
||||
# 如果在15秒内有新消息,直接返回
|
||||
if result[0]: # 有新消息
|
||||
logger.info(f"{self.log_prefix} 在{self._probability_check_time}秒内收到新消息,结束等待")
|
||||
return result
|
||||
|
||||
# 15秒后进行概率判定
|
||||
if random.random() < self._end_probability:
|
||||
# 概率判定通过,结束动作
|
||||
logger.info(f"{self.log_prefix} 概率判定通过({self._end_probability * 100}%),结束不回复动作")
|
||||
return True, "概率判定通过,结束等待"
|
||||
else:
|
||||
# 第4次及以后使用WAITING_TIME_THRESHOLD
|
||||
timeout = self.waiting_timeout
|
||||
|
||||
logger.info(
|
||||
f"{self.log_prefix} 选择不回复(第{count}次连续),等待新消息中... (超时: {timeout}秒),原因: {reason}"
|
||||
)
|
||||
|
||||
# 等待新消息或达到时间上限
|
||||
result = await self.wait_for_new_message(timeout)
|
||||
|
||||
# 如果有新消息或者超时,都不重置计数器,因为可能还会继续no_reply
|
||||
return result
|
||||
# 概率判定不通过,继续等待直到最大超时时间
|
||||
remaining_time = self._max_timeout - self._probability_check_time
|
||||
logger.info(f"{self.log_prefix} 概率判定不通过,继续等待{remaining_time}秒直到超时或有新消息...")
|
||||
|
||||
# 继续等待剩余时间
|
||||
result = await self.wait_for_new_message(remaining_time)
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"{self.log_prefix} 不回复动作执行失败: {e}")
|
||||
@@ -245,41 +263,6 @@ class EmojiAction(BaseAction):
|
||||
return False, f"表情发送失败: {str(e)}"
|
||||
|
||||
|
||||
class ChangeToFocusChatAction(BaseAction):
|
||||
"""切换到专注聊天动作 - 从普通模式切换到专注模式"""
|
||||
|
||||
focus_activation_type = ActionActivationType.NEVER
|
||||
normal_activation_type = ActionActivationType.NEVER
|
||||
mode_enable = ChatMode.NORMAL
|
||||
parallel_action = False
|
||||
|
||||
# 动作基本信息
|
||||
action_name = "change_to_focus_chat"
|
||||
action_description = "切换到专注聊天,从普通模式切换到专注模式"
|
||||
|
||||
# 动作参数定义
|
||||
action_parameters = {}
|
||||
|
||||
apex = 111
|
||||
# 动作使用场景
|
||||
action_require = [
|
||||
"你想要进入专注聊天模式",
|
||||
"聊天上下文中自己的回复条数较多(超过3-4条)",
|
||||
"对话进行得非常热烈活跃",
|
||||
"用户表现出深入交流的意图",
|
||||
"话题需要更专注和深入的讨论",
|
||||
]
|
||||
|
||||
async def execute(self) -> Tuple[bool, str]:
|
||||
"""执行切换到专注聊天动作"""
|
||||
logger.info(f"{self.log_prefix} 决定切换到专注聊天: {self.reasoning}")
|
||||
|
||||
# 重置NoReplyAction的连续计数器
|
||||
NoReplyAction.reset_consecutive_count()
|
||||
|
||||
# 这里只做决策标记,具体切换逻辑由上层管理器处理
|
||||
return True, "决定切换到专注聊天模式"
|
||||
|
||||
|
||||
class ExitFocusChatAction(BaseAction):
|
||||
"""退出专注聊天动作 - 从专注模式切换到普通模式"""
|
||||
@@ -371,7 +354,7 @@ class CoreActionsPlugin(BasePlugin):
|
||||
config_schema = {
|
||||
"plugin": {
|
||||
"enabled": ConfigField(type=bool, default=True, description="是否启用插件"),
|
||||
"config_version": ConfigField(type=str, default="0.0.2", description="配置文件版本"),
|
||||
"config_version": ConfigField(type=str, default="0.0.3", description="配置文件版本"),
|
||||
},
|
||||
"components": {
|
||||
"enable_reply": ConfigField(type=bool, default=True, description="是否启用'回复'动作"),
|
||||
@@ -381,12 +364,11 @@ class CoreActionsPlugin(BasePlugin):
|
||||
"enable_exit_focus": ConfigField(type=bool, default=True, description="是否启用'退出专注模式'动作"),
|
||||
},
|
||||
"no_reply": {
|
||||
"waiting_timeout": ConfigField(
|
||||
type=int, default=1200, description="连续不回复时,最长的等待超时时间(秒)"
|
||||
"probability_check_time": ConfigField(type=int, default=15, description="进行概率判定的时间点(秒)"),
|
||||
"end_probability": ConfigField(
|
||||
type=float, default=0.5, description="在判定时间点结束等待的概率(0.0到1.0)", example=0.5
|
||||
),
|
||||
"stage_1_wait": ConfigField(type=int, default=10, description="第1次连续不回复的等待时间(秒)"),
|
||||
"stage_2_wait": ConfigField(type=int, default=60, description="第2次连续不回复的等待时间(秒)"),
|
||||
"stage_3_wait": ConfigField(type=int, default=600, description="第3次连续不回复的等待时间(秒)"),
|
||||
"max_timeout": ConfigField(type=int, default=1200, description="最大等待超时时间(秒)"),
|
||||
"random_probability": ConfigField(
|
||||
type=float, default=0.8, description="Focus模式下,随机选择不回复的概率(0.0到1.0)", example=0.8
|
||||
),
|
||||
@@ -408,13 +390,14 @@ class CoreActionsPlugin(BasePlugin):
|
||||
no_reply_probability = self.get_config("no_reply.random_probability", 0.8)
|
||||
NoReplyAction.random_activation_probability = no_reply_probability
|
||||
|
||||
no_reply_timeout = self.get_config("no_reply.waiting_timeout", 1200)
|
||||
NoReplyAction.waiting_timeout = no_reply_timeout
|
||||
probability_check_time = self.get_config("no_reply.probability_check_time", 15)
|
||||
NoReplyAction._probability_check_time = probability_check_time
|
||||
|
||||
stage1 = self.get_config("no_reply.stage_1_wait", 10)
|
||||
stage2 = self.get_config("no_reply.stage_2_wait", 60)
|
||||
stage3 = self.get_config("no_reply.stage_3_wait", 600)
|
||||
NoReplyAction._waiting_stages = [stage1, stage2, stage3]
|
||||
end_probability = self.get_config("no_reply.end_probability", 0.5)
|
||||
NoReplyAction._end_probability = end_probability
|
||||
|
||||
max_timeout = self.get_config("no_reply.max_timeout", 1200)
|
||||
NoReplyAction._max_timeout = max_timeout
|
||||
|
||||
# --- 根据配置注册组件 ---
|
||||
components = []
|
||||
@@ -426,8 +409,7 @@ class CoreActionsPlugin(BasePlugin):
|
||||
components.append((EmojiAction.get_action_info(), EmojiAction))
|
||||
if self.get_config("components.enable_exit_focus", True):
|
||||
components.append((ExitFocusChatAction.get_action_info(), ExitFocusChatAction))
|
||||
if self.get_config("components.enable_change_to_focus", True):
|
||||
components.append((ChangeToFocusChatAction.get_action_info(), ChangeToFocusChatAction))
|
||||
|
||||
# components.append((DeepReplyAction.get_action_info(), DeepReplyAction))
|
||||
|
||||
return components
|
||||
|
||||
Reference in New Issue
Block a user