23 KiB
23 KiB
心流系统 (Heart Flow System)
一条消息是怎么到最终回复的?简明易懂的介绍
1 接受消息,由HeartHC_processor处理消息,存储消息
1.1 process_message()函数,接受消息
1.2 创建消息对应的聊天流(chat_stream)和子心流(sub_heartflow)
1.3 进行常规消息处理
1.4 存储消息 store_message()
1.5 计算兴趣度Interest
1.6 将消息连同兴趣度,存储到内存中的interest_dict(SubHeartflow的属性)
2 根据 sub_heartflow 的聊天状态,决定后续处理流程
2a ABSENT状态:不做任何处理
2b CHAT状态:送入NormalChat 实例
2c FOCUS状态:送入HeartFChatting 实例
b NormalChat工作方式
b.1 启动后台任务 _reply_interested_message,持续运行。
b.2 该任务轮询 InterestChatting 提供的 interest_dict
b.3 对每条消息,结合兴趣度、是否被提及(@)、意愿管理器(WillingManager)计算回复概率。(这部分要改,目前还是用willing计算的,之后要和Interest合并)
b.4 若概率通过:
b.4.1 创建"思考中"消息 (MessageThinking)。
b.4.2 调用 NormalChatGenerator 生成文本回复。
b.4.3 通过 message_manager 发送回复 (MessageSending)。
b.4.4 可能根据配置和文本内容,额外发送一个匹配的表情包。
b.4.5 更新关系值和全局情绪。
b.5 处理完成后,从 interest_dict 中移除该消息。
c HeartFChatting工作方式
c.1 启动主循环 _hfc_loop
c.2 每个循环称为一个周期 (Cycle),执行 think_plan_execute 流程。
c.3 Think (思考) 阶段:
c.3.1 观察 (Observe): 通过 ChattingObservation,使用 observe() 获取最新的聊天消息。
c.3.2 思考 (Think): 调用 SubMind 的 do_thinking_before_reply 方法。
c.3.2.1 SubMind 结合观察到的内容、个性、情绪、上周期动作等信息,生成当前的内心想法 (current_mind)。
c.3.2.2 在此过程中 SubMind 的LLM可能请求调用工具 (ToolUser) 来获取额外信息或执行操作,结果存储在 structured_info 中。
c.4 Plan (规划/决策) 阶段:
c.4.1 结合观察到的消息文本、`SubMind` 生成的 `current_mind` 和 `structured_info`、以及 `ActionManager` 提供的可用动作,决定本次周期的行动 (`text_reply`/`emoji_reply`/`no_reply`) 和理由。
c.4.2 重新规划检查 (Re-plan Check): 如果在 c.3.1 到 c.4.1 期间检测到新消息,可能(有概率)触发重新执行 c.4.1 决策步骤。
c.5 Execute (执行/回复) 阶段:
c.5.1 如果决策是 text_reply:
c.5.1.1 获取锚点消息。
c.5.1.2 通过 HeartFCSender 注册"思考中"状态。
c.5.1.3 调用 HeartFCGenerator (gpt_instance) 生成回复文本。
c.5.1.4 通过 HeartFCSender 发送回复
c.5.1.5 如果规划时指定了表情查询 (emoji_query),随后发送表情。
c.5.2 如果决策是 emoji_reply:
c.5.2.1 获取锚点消息。
c.5.2.2 通过 HeartFCSender 直接发送匹配查询 (emoji_query) 的表情。
c.5.3 如果决策是 no_reply:
c.5.3.1 进入等待状态,直到检测到新消息或超时。
c.5.3.2 同时,增加内部连续不回复计数器。如果该计数器达到预设阈值(例如 5 次),则调用初始化时由 `SubHeartflowManager` 提供的回调函数。此回调函数会通知 `SubHeartflowManager` 请求将对应的 `SubHeartflow` 状态转换为 `ABSENT`。如果执行了其他动作(如 `text_reply` 或 `emoji_reply`),则此计数器会被重置。
c.6 循环结束后,记录周期信息 (CycleInfo),并根据情况进行短暂休眠,防止CPU空转。
1. 一条消息是怎么到最终回复的?复杂细致的介绍
1.1. 主心流 (Heartflow)
- 文件:
heartflow.py - 职责:
- 作为整个系统的主控制器。
- 持有并管理
SubHeartflowManager,用于管理所有子心流。 - 持有并管理自身状态
self.current_state: MaiStateInfo,该状态控制系统的整体行为模式。 - 统筹管理系统后台任务(如消息存储、资源分配等)。
- 注意: 主心流自身不进行周期性的全局思考更新。
1.2. 子心流 (SubHeartflow)
- 文件:
sub_heartflow.py - 职责:
- 处理具体的交互场景,例如:群聊、私聊、与虚拟主播(vtb)互动、桌面宠物交互等。
- 维护特定场景下的思维状态和聊天流状态 (
ChatState)。 - 通过关联的
Observation实例接收和处理信息。 - 拥有独立的思考 (
SubMind) 和回复判断能力。
- 观察者: 每个子心流可以拥有一个或多个
Observation实例(目前每个子心流仅使用一个ChattingObservation)。 - 内部结构:
- 聊天流状态 (
ChatState): 标记当前子心流的参与模式 (ABSENT,CHAT,FOCUSED),决定是否观察、回复以及使用何种回复模式。 - 聊天实例 (
NormalChatInstance/HeartFlowChatInstance): 根据ChatState激活对应的实例来处理聊天逻辑。同一时间只有一个实例处于活动状态。
- 聊天流状态 (
1.3. 观察系统 (Observation)
- 文件:
observation.py - 职责:
- 定义信息输入的来源和格式。
- 为子心流提供其所处环境的信息。
- 当前实现:
- 目前仅有
ChattingObservation一种观察类型。 ChattingObservation负责从数据库拉取指定聊天的最新消息,并将其格式化为可读内容,供SubHeartflow使用。
- 目前仅有
1.4. 子心流管理器 (SubHeartflowManager)
- 文件:
subheartflow_manager.py - 职责:
- 作为
Heartflow的成员变量存在。 - 在初始化时接收并持有
Heartflow的MaiStateInfo实例。 - 负责所有
SubHeartflow实例的生命周期管理,包括:- 创建和获取 (
get_or_create_subheartflow)。 - 停止和清理 (
sleep_subheartflow,cleanup_inactive_subheartflows)。 - 根据
Heartflow的状态 (self.mai_state_info) 和限制条件,激活、停用或调整子心流的状态(例如enforce_subheartflow_limits,randomly_deactivate_subflows,evaluate_interest_and_promote)。 - 新增: 通过调用
evaluate_and_transition_subflows_by_llm方法,使用 LLM (配置与Heartflow主 LLM 相同) 评估处于ABSENT或CHAT状态的子心流,根据观察到的活动摘要和Heartflow的当前状态,判断是否应在ABSENT和CHAT之间进行转换 (同样受限于CHAT状态的数量上限)。
- 创建和获取 (
- 清理机制: 通过后台任务 (
BackgroundTaskManager) 定期调用cleanup_inactive_subheartflows方法,此方法会识别并删除那些处于ABSENT状态超过一小时 (INACTIVE_THRESHOLD_SECONDS) 的子心流实例。
- 作为
1.5. 消息处理与回复流程 (Message Processing vs. Replying Flow)
- 关注点分离: 系统严格区分了接收和处理传入消息的流程与决定和生成回复的流程。
- 消息处理 (Processing):
- 由一个独立的处理器(例如
HeartFCProcessor)负责接收原始消息数据。 - 职责包括:消息解析 (
MessageRecv)、过滤(屏蔽词、正则表达式)、基于记忆系统的初步兴趣计算 (HippocampusManager)、消息存储 (MessageStorage) 以及用户关系更新 (RelationshipManager)。 - 处理后的消息信息(如计算出的兴趣度)会传递给对应的
SubHeartflow。
- 由一个独立的处理器(例如
- 回复决策与生成 (Replying):
- 由
SubHeartflow及其当前激活的聊天实例 (NormalChatInstance或HeartFlowChatInstance) 负责。 - 基于其内部状态 (
ChatState、SubMind的思考结果)、观察到的信息 (Observation提供的内容) 以及InterestChatting的状态来决定是否回复、何时回复以及如何回复。
- 由
- 消息处理 (Processing):
- 消息缓冲 (Message Caching):
message_buffer模块会对某些传入消息进行临时缓存,尤其是在处理连续的多部分消息(如多张图片)时。- 这个缓冲机制发生在
HeartFCProcessor处理流程中,确保消息的完整性,然后才进行后续的存储和兴趣计算。 - 缓存的消息最终仍会流向对应的
ChatStream(与SubHeartflow关联),但核心的消息处理与回复决策仍然是分离的步骤。
2. 核心控制与状态管理 (Core Control and State Management)
2.1. Heart Flow 整体控制
- 控制者: 主心流 (
Heartflow) - 核心职责:
- 通过其成员
SubHeartflowManager创建和管理子心流(在创建SubHeartflowManager时会传入自身的MaiStateInfo)。 - 通过其成员
self.current_state: MaiStateInfo控制整体行为模式。 - 管理系统级后台任务。
- 注意: 不再提供直接获取所有子心流 ID (
get_all_subheartflows_streams_ids) 的公共方法。
- 通过其成员
2.2. Heart Flow 状态 (MaiStateInfo)
- 定义与管理:
Heartflow持有MaiStateInfo的实例 (self.current_state) 来管理其状态。状态的枚举定义在my_state_manager.py中的MaiState。 - 状态及含义:
MaiState.OFFLINE(不在线): 不观察任何群消息,不进行主动交互,仅存储消息。当主状态变为OFFLINE时,SubHeartflowManager会将所有子心流的状态设置为ChatState.ABSENT。MaiState.PEEKING(看一眼手机): 有限度地参与聊天(由MaiStateInfo定义具体的普通/专注群数量限制)。MaiState.NORMAL_CHAT(正常看手机): 正常参与聊天,允许SubHeartflow进入CHAT或FOCUSED状态(数量受限)。
MaiState.FOCUSED_CHAT(专心看手机): 更积极地参与聊天,通常允许更多或更高优先级的FOCUSED状态子心流。
- 当前转换逻辑: 目前,
MaiState之间的转换由MaiStateManager管理,主要基于状态持续时间和随机概率。这是一种临时的实现方式,未来计划进行改进。 - 作用:
Heartflow的状态直接影响SubHeartflowManager如何管理子心流(如激活数量、允许的状态等)。
2.3. 聊天流状态 (ChatState) 与转换
- 管理对象: 每个
SubHeartflow实例内部维护其ChatStateInfo,包含当前的ChatState。 - 状态及含义:
ChatState.ABSENT(不参与/没在看): 初始或停用状态。子心流不观察新信息,不进行思考,也不回复。ChatState.CHAT(随便看看/水群): 普通聊天模式。激活NormalChatInstance。
ChatState.FOCUSED(专注/认真水群): 专注聊天模式。激活HeartFlowChatInstance。
- 选择: 子心流可以根据外部指令(来自
SubHeartflowManager)或内部逻辑(未来的扩展)选择进入ABSENT状态(不回复不观察),或进入CHAT/FOCUSED中的一种回复模式。 - 状态转换机制 (由
SubHeartflowManager驱动):- 激活
CHAT: 当Heartflow状态从OFFLINE变为允许聊天的状态时,SubHeartflowManager会根据限制(通过self.mai_state_info获取),选择部分ABSENT状态的子心流,检查当前 CHAT 状态数量是否达到上限,如果未达上限,则调用其change_chat_state方法将其转换为CHAT。此外,evaluate_and_transition_subflows_by_llm方法也会根据 LLM 的判断,在未达上限时将ABSENT状态的子心流激活为CHAT。 - 激活
FOCUSED:SubHeartflowManager会定期评估处于CHAT状态的子心流的兴趣度 (InterestChatting.start_hfc_probability),若满足条件且检查当前 FOCUSED 状态数量未达上限(通过self.mai_state_info获取限制),则调用change_chat_state将其提升为FOCUSED。 - 停用/回退:
SubHeartflowManager可能因Heartflow状态变化、达到数量限制、长时间不活跃、随机概率 (randomly_deactivate_subflows)、LLM 评估 (evaluate_and_transition_subflows_by_llm判断CHAT状态子心流应休眠) 或收到来自HeartFChatting的连续不回复回调信号 (request_absent_transition) 等原因,调用change_chat_state将子心流状态设置为ABSENT或从FOCUSED回退到CHAT。当子心流进入ABSENT状态后,如果持续一小时不活跃,才会被后台清理任务删除。 - 注意:
change_chat_state方法本身只负责执行状态转换和管理内部聊天实例(NormalChatInstance/HeartFlowChatInstance),不再进行限额检查。限额检查的责任完全由调用方(即SubHeartflowManager中的相关方法,这些方法会使用内部存储的mai_state_info来获取限制)承担。
- 激活
3. 聊天实例详解 (Chat Instances Explained)
3.1. NormalChatInstance
- 激活条件: 对应
SubHeartflow的ChatState为CHAT。 - 工作流程:
- 当
SubHeartflow进入CHAT状态时,NormalChatInstance会被激活。 - 实例启动后,会创建一个后台任务 (
_reply_interested_message)。 - 该任务持续监控由
InterestChatting传入的、具有一定兴趣度的消息列表 (interest_dict)。 - 对列表中的每条消息,结合是否被提及 (
@)、消息本身的兴趣度以及当前的回复意愿 (WillingManager),计算出一个回复概率。 - 根据计算出的概率随机决定是否对该消息进行回复。
- 如果决定回复,则调用
NormalChatGenerator生成回复内容,并可能附带表情包。
- 当
- 行为特点:
- 回复相对常规、简单。
- 不投入过多计算资源。
- 侧重于维持基本的交流氛围。
- 示例:对问候语、日常分享等进行简单回应。
3.2. HeartFlowChatInstance (继承自原 PFC 逻辑)
- 激活条件: 对应
SubHeartflow的ChatState为FOCUSED。 - 工作流程:
- 基于更复杂的规则(原 PFC 模式)进行深度处理。
- 对群内话题进行深入分析。
- 可能主动发起相关话题或引导交流。
- 行为特点:
- 回复更积极、深入。
- 投入更多资源参与聊天。
- 回复内容可能更详细、有针对性。
- 对话题参与度高,能带动交流。
- 示例:对复杂或有争议话题阐述观点,并与人互动。
4. 工作流程示例 (Example Workflow)
- 启动:
Heartflow启动,初始化MaiStateInfo(例如OFFLINE) 和SubHeartflowManager。 - 状态变化: 用户操作或内部逻辑使
Heartflow的current_state变为NORMAL_CHAT。 - 管理器响应:
SubHeartflowManager检测到状态变化,根据NORMAL_CHAT的限制,调用get_or_create_subheartflow获取或创建子心流,并通过change_chat_state将部分子心流状态从ABSENT激活为CHAT。 - 子心流激活: 被激活的
SubHeartflow启动其NormalChatInstance。 - 信息接收: 该
SubHeartflow的ChattingObservation开始从数据库拉取新消息。 - 普通回复:
NormalChatInstance处理观察到的信息,执行普通回复逻辑。 - 兴趣评估:
SubHeartflowManager定期评估该子心流的InterestChatting状态。 - 提升状态: 若兴趣度达标且
Heartflow状态允许,SubHeartflowManager调用该子心流的change_chat_state将其状态提升为FOCUSED。 - 子心流切换:
SubHeartflow内部停止NormalChatInstance,启动HeartFlowChatInstance。 - 专注回复:
HeartFlowChatInstance开始根据其逻辑进行更深入的交互。 - 状态回落/停用: 若
Heartflow状态变为OFFLINE,SubHeartflowManager会调用所有活跃子心流的change_chat_state(ChatState.ABSENT),使其进入ABSENT状态(它们不会立即被删除,只有在ABSENT状态持续1小时后才会被清理)。
5. 使用与配置 (Usage and Configuration)
5.1. 使用说明 (Code Examples)
- (内部)创建/获取子心流 (由
SubHeartflowManager调用, 示例):# subheartflow_manager.py (get_or_create_subheartflow 内部) # 注意:mai_states 现在是 self.mai_state_info new_subflow = SubHeartflow(subheartflow_id, self.mai_state_info) await new_subflow.initialize() observation = ChattingObservation(chat_id=subheartflow_id) new_subflow.add_observation(observation) - (内部)添加观察者 (由
SubHeartflowManager或SubHeartflow内部调用):# sub_heartflow.py self.observations.append(observation)
5.2. 配置参数 (Key Parameters)
sub_heart_flow_stop_time: (已废弃,现在由INACTIVE_THRESHOLD_SECONDSinsubheartflow_manager.py控制) 子心流在ABSENT状态持续多久后被后台任务清理,默认为 3600 秒 (1 小时)。sub_heart_flow_freeze_time: 子心流冻结时间 (当前文档未明确体现,可能需要审阅代码确认)。heart_flow_update_interval: 主心流更新其状态或执行管理操作的频率 (需要审阅Heartflow代码确认)。
5.3. 之后可以做的 (Future Work)
-
智能化 MaiState 状态转换:
- 当前
MaiState(整体状态,如OFFLINE,NORMAL_CHAT等) 的转换逻辑 (MaiStateManager) 较为简单,主要依赖时间和随机性。 - 未来的计划是让主心流 (
Heartflow) 负责决策自身的MaiState。 - 该决策将综合考虑以下信息:
- 各个子心流 (
SubHeartflow) 的活动状态和信息摘要。 - 主心流自身的状态和历史信息。
- (可能) 结合预设的日程安排 (Schedule) 信息。
- 各个子心流 (
- 目标是让 Mai 的整体状态变化更符合逻辑和上下文。 (计划在 064 实现)
- 当前
-
参数化与动态调整聊天行为:
- 将
NormalChatInstance和HeartFlowChatInstance中的关键行为参数(例如:回复概率、思考频率、兴趣度阈值、状态转换条件等)提取出来,使其更易于配置。 - 允许每个
SubHeartflow(即每个聊天场景) 拥有其独立的参数配置,实现"千群千面"。 - 开发机制,使得这些参数能够被动态调整:
- 基于外部反馈:例如,根据用户评价("话太多"或"太冷淡")调整回复频率。
- 基于环境分析:例如,根据群消息的活跃度自动调整参与度。
- 基于学习:通过分析历史交互数据,优化特定群聊下的行为模式。
- 目标是让 Mai 在不同群聊中展现出更适应环境、更个性化的交互风格。
- 将
-
动态 Prompt 生成与人格塑造:
- 当前 Prompt (提示词) 相对静态。计划实现动态或半结构化的 Prompt 生成。
- Prompt 内容可根据以下因素调整:
- 人格特质: 通过参数化配置(如友善度、严谨性等),影响 Prompt 的措辞、语气和思考倾向,塑造更稳定和独特的人格。
- 当前情绪: 将实时情绪状态融入 Prompt,使回复更符合当下心境。
- 目标:提升
HeartFlowChatInstance(HFC) 回复的多样性、一致性和真实感。 - 前置:需要重构 Prompt 构建逻辑,可能引入
PromptBuilder并提供标准接口 (认为是必须步骤)。
-
扩展观察系统 (Observation System):
- 目前主要依赖
ChattingObservation获取消息。 - 计划引入更多
Observation类型,为SubHeartflow提供更丰富的上下文:- Mai 的全局状态 (
MaiStateInfo)。 SubHeartflow自身的聊天状态 (ChatStateInfo) 和参数配置。- Mai 的系统配置、连接平台信息。
- 其他相关聊天或系统的聚合信息。
- Mai 的全局状态 (
- 目标:让
SubHeartflow基于更全面的信息进行决策。
- 目前主要依赖
-
增强工具调用能力 (Enhanced Tool Usage):
- 扩展
HeartFlowChatInstance(HFC) 可用的工具集。 - 考虑引入"元工具"或分层工具机制,允许 HFC 在需要时(如深度思考)访问更强大的工具,例如:
- 修改自身或其他
SubHeartflow的聊天参数。 - 请求改变 Mai 的全局状态 (
MaiState)。 - 管理日程或执行更复杂的分析任务。
- 修改自身或其他
- 目标:提升 HFC 的自主决策和行动能力,即使会增加一定的延迟。
- 扩展
-
基于历史学习的行为模式应用:
- 学习: 分析过往聊天记录,提取和学习具体的行为模式(如特定梗的用法、情境化回应风格等)。可能需要专门的分析模块。
- 存储与匹配: 需要有效的方法存储学习到的行为模式,并开发强大的 匹配 机制,在运行时根据当前情境检索最合适的模式。(匹配的准确性是关键)
- 应用与评估: 将匹配到的行为模式融入 HFC 的决策和回复生成(例如,将其整合进 Prompt)。之后需评估该行为模式应用的实际效果。
- 人格塑造: 通过学习到的实际行为来动态塑造人格,作为静态人设描述的补充或替代,使其更生动自然。
-
标准化人设生成 (Standardized Persona Generation):
- 目标: 解决手动配置
人设文件缺乏标准、难以全面描述个性的问题,并生成更丰富、可操作的人格资源。 - 方法: 利用大型语言模型 (LLM) 辅助生成标准化的、结构化的人格资源包。
- 生成内容: 不仅生成描述性文本(替代现有
individual配置),还可以同时生成与该人格配套的:- 相关工具 (Tools): 该人格倾向于使用的工具或能力。
- 初始记忆/知识库 (Memories/Knowledge): 定义其背景和知识基础。
- 核心行为模式 (Core Behavior Patterns): 预置一些典型的行为方式,可作为行为学习的起点。
- 实现途径:
- 通过与 LLM 的交互式对话来定义和细化人格及其配套资源。
- 让 LLM 分析提供的文本材料(如小说、背景故事)来提取人格特质和相关信息。
- 优势: 替代易出错且标准不一的手动配置,生成更丰富、一致、包含配套资源且易于系统理解和应用的人格包。
- 目标: 解决手动配置
-
优化表情包处理与理解 (Enhanced Emoji Handling and Understanding):
- 面临挑战:
- 历史记录表示: 如何在聊天历史中有效表示表情包,供 LLM 理解。
- 语义理解: 如何让 LLM 准确把握表情包的含义、情感和语境。
- 场景判断与选择: 如何让 LLM 判断何时适合使用表情包,并选择最贴切的一个。
- 目标: 提升 Mai 理解和运用表情包的能力,使交互更自然生动。
- 说明: 可能需要较多时间进行数据处理和模型调优,但对改善体验潜力巨大。
- 面临挑战: