feat(chatter): 引入决策历史以增强上下文连续性
为提升语言模型在连续对话中的表现,本次更新引入了决策历史功能。该功能旨在为模型提供一个短期记忆,记录其最近的思考过程与采取的行动。 主要变更包括: - 新增 `DecisionRecord` 数据模型,用于存储“思考-动作”对。 - 在 `StreamContext` 中添加 `decision_history` 字段,以维护每个聊天流的决策历史。 - 在 `plan_filter` 中实现决策记录的逻辑,并在构建提示词时将其注入,供模型参考。 - 添加 `enable_decision_history` 和 `decision_history_length` 配置项,允许用户启用此功能并调整历史记录的长度。 通过回顾近期的决策,模型可以更好地避免重复行为,并生成更具连贯性和创造性的响应。
This commit is contained in:
@@ -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):
|
||||
"""
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -30,6 +30,9 @@ def init_prompts():
|
||||
|
||||
{actions_before_now_block}
|
||||
|
||||
## 🤔 最近的决策历史 (回顾你之前的思考与动作,可以帮助你避免重复,并做出更有趣的连贯回应)
|
||||
{decision_history_block}
|
||||
|
||||
## 📜 已读历史(仅供理解,不可作为动作对象)
|
||||
{read_history_block}
|
||||
|
||||
|
||||
@@ -137,7 +137,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]
|
||||
|
||||
Reference in New Issue
Block a user