From 4fb56e5b879d6f42ee27a255299c8bab020ad2da Mon Sep 17 00:00:00 2001 From: tt-P607 <68868379+tt-P607@users.noreply.github.com> Date: Wed, 29 Oct 2025 18:58:28 +0800 Subject: [PATCH] =?UTF-8?q?feat(chatter):=20=E5=BC=95=E5=85=A5=E5=86=B3?= =?UTF-8?q?=E7=AD=96=E5=8E=86=E5=8F=B2=E4=BB=A5=E5=A2=9E=E5=BC=BA=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E8=BF=9E=E7=BB=AD=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为提升语言模型在连续对话中的表现,本次更新引入了决策历史功能。该功能旨在为模型提供一个短期记忆,记录其最近的思考过程与采取的行动。 主要变更包括: - 新增 `DecisionRecord` 数据模型,用于存储“思考-动作”对。 - 在 `StreamContext` 中添加 `decision_history` 字段,以维护每个聊天流的决策历史。 - 在 `plan_filter` 中实现决策记录的逻辑,并在构建提示词时将其注入,供模型参考。 - 添加 `enable_decision_history` 和 `decision_history_length` 配置项,允许用户启用此功能并调整历史记录的长度。 通过回顾近期的决策,模型可以更好地避免重复行为,并生成更具连贯性和创造性的响应。 --- .../data_models/message_manager_data_model.py | 11 ++- src/config/official_configs.py | 4 + .../affinity_flow_chatter/plan_filter.py | 80 +++++++++++++++++++ .../affinity_flow_chatter/planner_prompts.py | 3 + template/bot_config_template.toml | 3 +- 5 files changed, 99 insertions(+), 2 deletions(-) diff --git a/src/common/data_models/message_manager_data_model.py b/src/common/data_models/message_manager_data_model.py index 81e8a7764..eb29b3302 100644 --- a/src/common/data_models/message_manager_data_model.py +++ b/src/common/data_models/message_manager_data_model.py @@ -7,7 +7,7 @@ import asyncio import time from dataclasses import dataclass, field from enum import Enum -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING, List, Optional from src.common.logger import get_logger from src.plugin_system.base.component_types import ChatMode, ChatType @@ -28,6 +28,14 @@ class MessageStatus(Enum): PROCESSING = "processing" # 处理中 +@dataclass +class DecisionRecord(BaseDataModel): + """决策记录""" + + thought: str + action: str + + @dataclass class StreamContext(BaseDataModel): """聊天流上下文信息""" @@ -56,6 +64,7 @@ class StreamContext(BaseDataModel): triggering_user_id: str | None = None # 触发当前聊天流的用户ID is_replying: bool = False # 是否正在生成回复 processing_message_id: str | None = None # 当前正在规划/处理的目标消息ID,用于防止重复回复 + decision_history: List["DecisionRecord"] = field(default_factory=list) # 决策历史 def add_action_to_message(self, message_id: str, action: str): """ diff --git a/src/config/official_configs.py b/src/config/official_configs.py index 038405094..4cbfcd921 100644 --- a/src/config/official_configs.py +++ b/src/config/official_configs.py @@ -143,6 +143,10 @@ class ChatConfig(ValidatedConfigBase): dynamic_distribution_max_interval: float = Field(default=30.0, ge=5.0, le=300.0, description="最大分发间隔(秒)") dynamic_distribution_jitter_factor: float = Field(default=0.2, ge=0.0, le=0.5, description="分发间隔随机扰动因子") max_concurrent_distributions: int = Field(default=10, ge=1, le=100, description="最大并发处理的消息流数量") + enable_decision_history: bool = Field(default=True, description="是否启用决策历史功能") + decision_history_length: int = Field( + default=3, ge=1, le=10, description="决策历史记录的长度,用于增强语言模型的上下文连续性" + ) class MessageReceiveConfig(ValidatedConfigBase): diff --git a/src/plugins/built_in/affinity_flow_chatter/plan_filter.py b/src/plugins/built_in/affinity_flow_chatter/plan_filter.py index bc8cf0895..d1a281d79 100644 --- a/src/plugins/built_in/affinity_flow_chatter/plan_filter.py +++ b/src/plugins/built_in/affinity_flow_chatter/plan_filter.py @@ -104,6 +104,23 @@ class ChatterPlanFilter: # 预解析 action_type 来进行判断 thinking = item.get("thinking", "未提供思考过程") actions_obj = item.get("actions", {}) + + # 记录决策历史 + if hasattr(global_config.chat, "enable_decision_history") and global_config.chat.enable_decision_history: + action_types_to_log = [] + actions_to_process_for_log = [] + if isinstance(actions_obj, dict): + actions_to_process_for_log.append(actions_obj) + elif isinstance(actions_obj, list): + actions_to_process_for_log.extend(actions_obj) + + for single_action in actions_to_process_for_log: + if isinstance(single_action, dict): + action_types_to_log.append(single_action.get("action_type", "no_action")) + + if thinking != "未提供思考过程" and action_types_to_log: + await self._add_decision_to_history(plan, thinking, ", ".join(action_types_to_log)) + # 处理actions字段可能是字典或列表的情况 if isinstance(actions_obj, dict): @@ -141,6 +158,65 @@ class ChatterPlanFilter: return plan + async def _add_decision_to_history(self, plan: Plan, thought: str, action: str): + """添加决策记录到历史中""" + try: + from src.chat.message_receive.chat_stream import get_chat_manager + from src.common.data_models.message_manager_data_model import DecisionRecord + + chat_manager = get_chat_manager() + chat_stream = await chat_manager.get_stream(plan.chat_id) + if not chat_stream: + return + + if not thought or not action: + logger.debug("尝试添加空的决策历史,已跳过") + return + + context = chat_stream.context_manager.context + new_record = DecisionRecord(thought=thought, action=action) + + # 添加新记录 + context.decision_history.append(new_record) + + # 获取历史长度限制 + max_history_length = getattr(global_config.chat, "decision_history_length", 3) + + # 如果历史记录超过长度,则移除最旧的记录 + if len(context.decision_history) > max_history_length: + context.decision_history.pop(0) + + logger.debug(f"已添加决策历史,当前长度: {len(context.decision_history)}") + + except Exception as e: + logger.warning(f"记录决策历史失败: {e}") + + async def _build_decision_history_block(self, plan: Plan) -> str: + """构建决策历史块""" + if not hasattr(global_config.chat, "enable_decision_history") or not global_config.chat.enable_decision_history: + return "" + try: + from src.chat.message_receive.chat_stream import get_chat_manager + + chat_manager = get_chat_manager() + chat_stream = await chat_manager.get_stream(plan.chat_id) + if not chat_stream: + return "" + + context = chat_stream.context_manager.context + if not context.decision_history: + return "" + + history_records = [] + for i, record in enumerate(context.decision_history): + history_records.append(f"- 思考: {record.thought}\n - 动作: {record.action}") + + history_str = "\n".join(history_records) + return f"{history_str}" + except Exception as e: + logger.warning(f"构建决策历史块失败: {e}") + return "" + async def _build_prompt(self, plan: Plan) -> tuple[str, list]: """ 根据 Plan 对象构建提示词。 @@ -166,6 +242,9 @@ class ChatterPlanFilter: chat_mood = mood_manager.get_mood_by_chat_id(plan.chat_id) mood_block = f"你现在的心情是:{chat_mood.mood_state}" + # 构建决策历史 + decision_history_block = await self._build_decision_history_block(plan) + # 构建已读/未读历史消息 read_history_block, unread_history_block, message_id_list = await self._build_read_unread_history_blocks( plan @@ -239,6 +318,7 @@ class ChatterPlanFilter: mood_block=mood_block, time_block=time_block, chat_context_description=chat_context_description, + decision_history_block=decision_history_block, read_history_block=read_history_block, unread_history_block=unread_history_block, actions_before_now_block=actions_before_now_block, diff --git a/src/plugins/built_in/affinity_flow_chatter/planner_prompts.py b/src/plugins/built_in/affinity_flow_chatter/planner_prompts.py index 6f2bcc6f3..0e760fc15 100644 --- a/src/plugins/built_in/affinity_flow_chatter/planner_prompts.py +++ b/src/plugins/built_in/affinity_flow_chatter/planner_prompts.py @@ -30,6 +30,9 @@ def init_prompts(): {actions_before_now_block} +## 🤔 最近的决策历史 (回顾你之前的思考与动作,可以帮助你避免重复,并做出更有趣的连贯回应) +{decision_history_block} + ## 📜 已读历史(仅供理解,不可作为动作对象) {read_history_block} diff --git a/template/bot_config_template.toml b/template/bot_config_template.toml index ddfdada13..e824467d2 100644 --- a/template/bot_config_template.toml +++ b/template/bot_config_template.toml @@ -142,7 +142,8 @@ dynamic_distribution_min_interval = 1.0 # 最小分发间隔(秒) dynamic_distribution_max_interval = 30.0 # 最大分发间隔(秒) dynamic_distribution_jitter_factor = 0.2 # 分发间隔随机扰动因子 max_concurrent_distributions = 10 # 最大并发处理的消息流数量,可以根据API性能和服务器负载调整 - +enable_decision_history = true # 是否启用决策历史功能 +decision_history_length = 3 # 决策历史记录的长度,用于增强语言模型的上下文连续性 [message_receive]