|  | @@ -0,0 +1,388 @@
 | 
											
												
													
														|  | 
 |  | +#! /usr/bin/env python
 | 
											
												
													
														|  | 
 |  | +# -*- coding: utf-8 -*-
 | 
											
												
													
														|  | 
 |  | +# vim:fenc=utf-8
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +from enum import Enum, auto
 | 
											
												
													
														|  | 
 |  | +from typing import Dict, List, Optional, Tuple, Any
 | 
											
												
													
														|  | 
 |  | +from datetime import datetime
 | 
											
												
													
														|  | 
 |  | +import time
 | 
											
												
													
														|  | 
 |  | +import logging
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +from message import MessageType
 | 
											
												
													
														|  | 
 |  | +# from vector_memory_manager import VectorMemoryManager
 | 
											
												
													
														|  | 
 |  | +from structured_memory_manager import StructuredMemoryManager
 | 
											
												
													
														|  | 
 |  | +from user_manager import UserManager
 | 
											
												
													
														|  | 
 |  | +from prompt_templates import *
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +# 配置日志
 | 
											
												
													
														|  | 
 |  | +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(funcName)s[%(lineno)d] - %(levelname)s - %(message)s')
 | 
											
												
													
														|  | 
 |  | +logger = logging.getLogger(__name__)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +class DummyVectorMemoryManager:
 | 
											
												
													
														|  | 
 |  | +    def __init__(self, user_id):
 | 
											
												
													
														|  | 
 |  | +        pass
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def add_to_memory(self, conversation):
 | 
											
												
													
														|  | 
 |  | +        pass
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def retrieve_relevant_memories(self, query, k=3):
 | 
											
												
													
														|  | 
 |  | +        return []
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +class DialogueState(Enum):
 | 
											
												
													
														|  | 
 |  | +    GREETING = auto()              # 问候状态
 | 
											
												
													
														|  | 
 |  | +    CHITCHAT = auto()              # 闲聊状态
 | 
											
												
													
														|  | 
 |  | +    CLARIFICATION = auto()         # 澄清状态
 | 
											
												
													
														|  | 
 |  | +    FAREWELL = auto()              # 告别状态
 | 
											
												
													
														|  | 
 |  | +    HUMAN_INTERVENTION = auto()    # 人工介入状态
 | 
											
												
													
														|  | 
 |  | +    MESSAGE_AGGREGATING = auto()   # 等待消息状态
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +class TimeContext(Enum):
 | 
											
												
													
														|  | 
 |  | +    EARLY_MORNING = "清晨"     # 清晨 (5:00-7:59)
 | 
											
												
													
														|  | 
 |  | +    MORNING = "上午"           # 上午 (8:00-11:59)
 | 
											
												
													
														|  | 
 |  | +    NOON = "中午"              # 中午 (12:00-13:59)
 | 
											
												
													
														|  | 
 |  | +    AFTERNOON = "下午"         # 下午 (14:00-17:59)
 | 
											
												
													
														|  | 
 |  | +    EVENING = "晚上"           # 晚上 (18:00-21:59)
 | 
											
												
													
														|  | 
 |  | +    NIGHT = "深夜"             # 夜晚 (22:00-4:59)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def __init__(self, description):
 | 
											
												
													
														|  | 
 |  | +        self.description = description
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +class DialogueManager:
 | 
											
												
													
														|  | 
 |  | +    def __init__(self, user_id: str, user_manager: UserManager):
 | 
											
												
													
														|  | 
 |  | +        self.user_id = user_id
 | 
											
												
													
														|  | 
 |  | +        self.user_manager = user_manager
 | 
											
												
													
														|  | 
 |  | +        self.current_state = DialogueState.GREETING
 | 
											
												
													
														|  | 
 |  | +        self.previous_state = None
 | 
											
												
													
														|  | 
 |  | +        self.dialogue_history = []
 | 
											
												
													
														|  | 
 |  | +        self.user_profile = self.user_manager.get_user_profile(user_id)
 | 
											
												
													
														|  | 
 |  | +        self.last_interaction_time = 0
 | 
											
												
													
														|  | 
 |  | +        self.consecutive_clarifications = 0
 | 
											
												
													
														|  | 
 |  | +        self.complex_request_counter = 0
 | 
											
												
													
														|  | 
 |  | +        self.human_intervention_triggered = False
 | 
											
												
													
														|  | 
 |  | +        self.vector_memory = DummyVectorMemoryManager(user_id)
 | 
											
												
													
														|  | 
 |  | +        self.message_aggregation_sec = 5
 | 
											
												
													
														|  | 
 |  | +        self.unprocessed_messages = []
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def get_current_time_context(self) -> TimeContext:
 | 
											
												
													
														|  | 
 |  | +        """获取当前时间上下文"""
 | 
											
												
													
														|  | 
 |  | +        current_hour = datetime.now().hour
 | 
											
												
													
														|  | 
 |  | +        if 5 <= current_hour < 8:
 | 
											
												
													
														|  | 
 |  | +            return TimeContext.EARLY_MORNING
 | 
											
												
													
														|  | 
 |  | +        elif 8 <= current_hour < 12:
 | 
											
												
													
														|  | 
 |  | +            return TimeContext.MORNING
 | 
											
												
													
														|  | 
 |  | +        elif 12 <= current_hour < 14:
 | 
											
												
													
														|  | 
 |  | +            return TimeContext.NOON
 | 
											
												
													
														|  | 
 |  | +        elif 14 <= current_hour < 18:
 | 
											
												
													
														|  | 
 |  | +            return TimeContext.AFTERNOON
 | 
											
												
													
														|  | 
 |  | +        elif 18 <= current_hour < 22:
 | 
											
												
													
														|  | 
 |  | +            return TimeContext.EVENING
 | 
											
												
													
														|  | 
 |  | +        else:
 | 
											
												
													
														|  | 
 |  | +            return TimeContext.NIGHT
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def update_state(self, message: Dict) -> Tuple[DialogueState, str]:
 | 
											
												
													
														|  | 
 |  | +        """根据用户消息更新对话状态,并返回下一条需处理的用户消息"""
 | 
											
												
													
														|  | 
 |  | +        message_text = message.get('text', None)
 | 
											
												
													
														|  | 
 |  | +        message_ts = message['timestamp']
 | 
											
												
													
														|  | 
 |  | +        # 如果当前已经是人工介入状态,保持该状态
 | 
											
												
													
														|  | 
 |  | +        if self.current_state == DialogueState.HUMAN_INTERVENTION:
 | 
											
												
													
														|  | 
 |  | +            # 记录对话历史,但不改变状态
 | 
											
												
													
														|  | 
 |  | +            self.dialogue_history.append({
 | 
											
												
													
														|  | 
 |  | +                "role": "user",
 | 
											
												
													
														|  | 
 |  | +                "content": message_text,
 | 
											
												
													
														|  | 
 |  | +                "timestamp": int(time.time() * 1000),
 | 
											
												
													
														|  | 
 |  | +                "state": self.current_state.name
 | 
											
												
													
														|  | 
 |  | +            })
 | 
											
												
													
														|  | 
 |  | +            return self.current_state, message_text
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 检查是否处于消息聚合状态
 | 
											
												
													
														|  | 
 |  | +        if self.current_state == DialogueState.MESSAGE_AGGREGATING:
 | 
											
												
													
														|  | 
 |  | +            # 收到的是特殊定时触发的空消息,且在聚合中,且已经超时,恢复之前状态,继续处理
 | 
											
												
													
														|  | 
 |  | +            if message['type'] == MessageType.AGGREGATION_TRIGGER \
 | 
											
												
													
														|  | 
 |  | +                    and message_ts - self.last_interaction_time > self.message_aggregation_sec * 1000:
 | 
											
												
													
														|  | 
 |  | +                logging.debug("user_id: {}, last interaction time: {}".format(
 | 
											
												
													
														|  | 
 |  | +                    self.user_id, datetime.fromtimestamp(self.last_interaction_time / 1000)))
 | 
											
												
													
														|  | 
 |  | +                self.current_state = self.previous_state
 | 
											
												
													
														|  | 
 |  | +            else:
 | 
											
												
													
														|  | 
 |  | +                # 非空消息,更新最后交互时间,保持消息聚合状态
 | 
											
												
													
														|  | 
 |  | +                if message_text:
 | 
											
												
													
														|  | 
 |  | +                    self.unprocessed_messages.append(message_text)
 | 
											
												
													
														|  | 
 |  | +                    self.last_interaction_time = message_ts
 | 
											
												
													
														|  | 
 |  | +                return self.current_state, message_text
 | 
											
												
													
														|  | 
 |  | +        elif message['type'] != MessageType.AGGREGATION_TRIGGER and self.message_aggregation_sec > 0:
 | 
											
												
													
														|  | 
 |  | +            # 收到有内容的用户消息,切换到消息聚合状态
 | 
											
												
													
														|  | 
 |  | +            self.previous_state = self.current_state
 | 
											
												
													
														|  | 
 |  | +            self.current_state = DialogueState.MESSAGE_AGGREGATING
 | 
											
												
													
														|  | 
 |  | +            self.unprocessed_messages.append(message_text)
 | 
											
												
													
														|  | 
 |  | +            # 更新最后交互时间
 | 
											
												
													
														|  | 
 |  | +            if message_text:
 | 
											
												
													
														|  | 
 |  | +                self.last_interaction_time = message_ts
 | 
											
												
													
														|  | 
 |  | +            return self.current_state, message_text
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 保存前一个状态
 | 
											
												
													
														|  | 
 |  | +        self.previous_state = self.current_state
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 检查是否长时间未交互(超过3小时)
 | 
											
												
													
														|  | 
 |  | +        if self._get_hours_since_last_interaction() > 3:
 | 
											
												
													
														|  | 
 |  | +            self.current_state = DialogueState.GREETING
 | 
											
												
													
														|  | 
 |  | +            self.dialogue_history = []  # 重置对话历史
 | 
											
												
													
														|  | 
 |  | +            self.consecutive_clarifications = 0  # 重置澄清计数
 | 
											
												
													
														|  | 
 |  | +            self.complex_request_counter = 0  # 重置复杂请求计数
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 获得未处理的聚合消息,并清空未处理队列
 | 
											
												
													
														|  | 
 |  | +        if message_text:
 | 
											
												
													
														|  | 
 |  | +            self.unprocessed_messages.append(message_text)
 | 
											
												
													
														|  | 
 |  | +        if self.unprocessed_messages:
 | 
											
												
													
														|  | 
 |  | +            message_text = '\n'.join(self.unprocessed_messages)
 | 
											
												
													
														|  | 
 |  | +            self.unprocessed_messages.clear()
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 根据消息内容和当前状态确定新状态
 | 
											
												
													
														|  | 
 |  | +        new_state = self._determine_state_from_message(message_text)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 处理连续澄清的情况
 | 
											
												
													
														|  | 
 |  | +        if new_state == DialogueState.CLARIFICATION:
 | 
											
												
													
														|  | 
 |  | +            self.consecutive_clarifications += 1
 | 
											
												
													
														|  | 
 |  | +            if self.consecutive_clarifications >= 2:
 | 
											
												
													
														|  | 
 |  | +                new_state = DialogueState.HUMAN_INTERVENTION
 | 
											
												
													
														|  | 
 |  | +                # self._trigger_human_intervention("连续多次澄清请求")
 | 
											
												
													
														|  | 
 |  | +        else:
 | 
											
												
													
														|  | 
 |  | +            self.consecutive_clarifications = 0
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 更新状态
 | 
											
												
													
														|  | 
 |  | +        self.current_state = new_state
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 更新最后交互时间
 | 
											
												
													
														|  | 
 |  | +        if message_text:
 | 
											
												
													
														|  | 
 |  | +            self.last_interaction_time = message_ts
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 记录对话历史
 | 
											
												
													
														|  | 
 |  | +        if message_text:
 | 
											
												
													
														|  | 
 |  | +            self.dialogue_history.append({
 | 
											
												
													
														|  | 
 |  | +                "role": "user",
 | 
											
												
													
														|  | 
 |  | +                "content": message_text,
 | 
											
												
													
														|  | 
 |  | +                "timestamp": int(time.time() * 1000),
 | 
											
												
													
														|  | 
 |  | +                "state": self.current_state.name
 | 
											
												
													
														|  | 
 |  | +            })
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        return self.current_state, message_text
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def _determine_state_from_message(self, message: str) -> DialogueState:
 | 
											
												
													
														|  | 
 |  | +        """根据消息内容确定对话状态"""
 | 
											
												
													
														|  | 
 |  | +        if not message:
 | 
											
												
													
														|  | 
 |  | +            return self.current_state
 | 
											
												
													
														|  | 
 |  | +        # 简单的规则-关键词匹配
 | 
											
												
													
														|  | 
 |  | +        message_lower = message.lower()
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 判断是否是复杂请求
 | 
											
												
													
														|  | 
 |  | +        complex_request_keywords = ["帮我", "怎么办", "我需要", "麻烦你", "请帮助", "急", "紧急"]
 | 
											
												
													
														|  | 
 |  | +        if any(keyword in message_lower for keyword in complex_request_keywords):
 | 
											
												
													
														|  | 
 |  | +            self.complex_request_counter += 1
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            # 如果检测到困难请求且计数达到阈值,触发人工介入
 | 
											
												
													
														|  | 
 |  | +            if self.complex_request_counter >= 1:
 | 
											
												
													
														|  | 
 |  | +                # self._trigger_human_intervention("检测到复杂请求")
 | 
											
												
													
														|  | 
 |  | +                return DialogueState.HUMAN_INTERVENTION
 | 
											
												
													
														|  | 
 |  | +        else:
 | 
											
												
													
														|  | 
 |  | +            # 如果不是复杂请求,重置计数器
 | 
											
												
													
														|  | 
 |  | +            self.complex_request_counter = 0
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 问候检测
 | 
											
												
													
														|  | 
 |  | +        greeting_keywords = ["你好", "早上好", "中午好", "晚上好", "嗨", "在吗"]
 | 
											
												
													
														|  | 
 |  | +        if any(keyword in message_lower for keyword in greeting_keywords):
 | 
											
												
													
														|  | 
 |  | +            return DialogueState.GREETING
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 告别检测
 | 
											
												
													
														|  | 
 |  | +        farewell_keywords = ["再见", "拜拜", "晚安", "明天见", "回头见"]
 | 
											
												
													
														|  | 
 |  | +        if any(keyword in message_lower for keyword in farewell_keywords):
 | 
											
												
													
														|  | 
 |  | +            return DialogueState.FAREWELL
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 澄清请求
 | 
											
												
													
														|  | 
 |  | +        clarification_keywords = ["没明白", "不明白", "没听懂", "不懂", "什么意思", "再说一遍"]
 | 
											
												
													
														|  | 
 |  | +        if any(keyword in message_lower for keyword in clarification_keywords):
 | 
											
												
													
														|  | 
 |  | +            return DialogueState.CLARIFICATION
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 默认为闲聊状态
 | 
											
												
													
														|  | 
 |  | +        return DialogueState.CHITCHAT
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def _trigger_human_intervention(self, reason: str) -> None:
 | 
											
												
													
														|  | 
 |  | +        """触发人工介入"""
 | 
											
												
													
														|  | 
 |  | +        if not self.human_intervention_triggered:
 | 
											
												
													
														|  | 
 |  | +            self.human_intervention_triggered = True
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            # 记录人工介入事件
 | 
											
												
													
														|  | 
 |  | +            event = {
 | 
											
												
													
														|  | 
 |  | +                "timestamp": int(time.time() * 1000),
 | 
											
												
													
														|  | 
 |  | +                "reason": reason,
 | 
											
												
													
														|  | 
 |  | +                "dialogue_context": self.dialogue_history[-5:] if len(self.dialogue_history) >= 5 else self.dialogue_history
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            # 更新用户资料中的人工介入历史
 | 
											
												
													
														|  | 
 |  | +            if "human_intervention_history" not in self.user_profile:
 | 
											
												
													
														|  | 
 |  | +                self.user_profile["human_intervention_history"] = []
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            self.user_profile["human_intervention_history"].append(event)
 | 
											
												
													
														|  | 
 |  | +            self.user_manager.save_user_profile(self.user_profile)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            # 发送告警
 | 
											
												
													
														|  | 
 |  | +            self._send_human_intervention_alert(reason)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def _send_human_intervention_alert(self, reason: str) -> None:
 | 
											
												
													
														|  | 
 |  | +        alert_message = f"""
 | 
											
												
													
														|  | 
 |  | +        人工介入告警
 | 
											
												
													
														|  | 
 |  | +        用户ID: {self.user_id}
 | 
											
												
													
														|  | 
 |  | +        用户昵称: {self.user_profile.get("nickname", "未知")}
 | 
											
												
													
														|  | 
 |  | +        时间: {int(time.time() * 1000)}
 | 
											
												
													
														|  | 
 |  | +        原因: {reason}
 | 
											
												
													
														|  | 
 |  | +        最近对话:
 | 
											
												
													
														|  | 
 |  | +        """
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 添加最近的对话记录
 | 
											
												
													
														|  | 
 |  | +        recent_dialogues = self.dialogue_history[-5:] if len(self.dialogue_history) >= 5 else self.dialogue_history
 | 
											
												
													
														|  | 
 |  | +        for dialogue in recent_dialogues:
 | 
											
												
													
														|  | 
 |  | +            alert_message += f"\n{dialogue['role']}: {dialogue['content']}"
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # TODO(zhoutian): 实现发送告警的具体逻辑
 | 
											
												
													
														|  | 
 |  | +        logger.warning(alert_message)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def resume_from_human_intervention(self) -> None:
 | 
											
												
													
														|  | 
 |  | +        """从人工介入状态恢复"""
 | 
											
												
													
														|  | 
 |  | +        if self.current_state == DialogueState.HUMAN_INTERVENTION:
 | 
											
												
													
														|  | 
 |  | +            self.current_state = DialogueState.GREETING
 | 
											
												
													
														|  | 
 |  | +            self.human_intervention_triggered = False
 | 
											
												
													
														|  | 
 |  | +            self.consecutive_clarifications = 0
 | 
											
												
													
														|  | 
 |  | +            self.complex_request_counter = 0
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            # 记录恢复事件
 | 
											
												
													
														|  | 
 |  | +            self.dialogue_history.append({
 | 
											
												
													
														|  | 
 |  | +                "role": "system",
 | 
											
												
													
														|  | 
 |  | +                "content": "已从人工介入状态恢复到自动对话",
 | 
											
												
													
														|  | 
 |  | +                "timestamp": int(time.time() * 1000),
 | 
											
												
													
														|  | 
 |  | +                "state": self.current_state.name
 | 
											
												
													
														|  | 
 |  | +            })
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def generate_response(self, llm_response: str) -> Optional[str]:
 | 
											
												
													
														|  | 
 |  | +        """根据当前状态处理LLM响应,如果处于人工介入状态则返回None"""
 | 
											
												
													
														|  | 
 |  | +        # 如果处于人工介入状态,不生成回复
 | 
											
												
													
														|  | 
 |  | +        if self.current_state == DialogueState.HUMAN_INTERVENTION:
 | 
											
												
													
														|  | 
 |  | +            return None
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 记录响应到对话历史
 | 
											
												
													
														|  | 
 |  | +        current_ts = int(time.time() * 1000)
 | 
											
												
													
														|  | 
 |  | +        self.dialogue_history.append({
 | 
											
												
													
														|  | 
 |  | +            "role": "assistant",
 | 
											
												
													
														|  | 
 |  | +            "content": llm_response,
 | 
											
												
													
														|  | 
 |  | +            "timestamp": current_ts,
 | 
											
												
													
														|  | 
 |  | +            "state": self.current_state.name
 | 
											
												
													
														|  | 
 |  | +        })
 | 
											
												
													
														|  | 
 |  | +        self.last_interaction_time = current_ts
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        return llm_response
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def _get_hours_since_last_interaction(self):
 | 
											
												
													
														|  | 
 |  | +        time_diff = (time.time() * 1000) - self.last_interaction_time
 | 
											
												
													
														|  | 
 |  | +        hours_passed = time_diff / 1000 / 3600
 | 
											
												
													
														|  | 
 |  | +        return hours_passed
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def should_initiate_conversation(self) -> bool:
 | 
											
												
													
														|  | 
 |  | +        """判断是否应该主动发起对话"""
 | 
											
												
													
														|  | 
 |  | +        # 如果处于人工介入状态,不应主动发起对话
 | 
											
												
													
														|  | 
 |  | +        if self.current_state == DialogueState.HUMAN_INTERVENTION:
 | 
											
												
													
														|  | 
 |  | +            return False
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        hours_passed = self._get_hours_since_last_interaction()
 | 
											
												
													
														|  | 
 |  | +        # 获取当前时间上下文
 | 
											
												
													
														|  | 
 |  | +        time_context = self.get_current_time_context()
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 根据用户交互频率偏好设置不同的阈值
 | 
											
												
													
														|  | 
 |  | +        interaction_frequency = self.user_profile.get("interaction_frequency", "medium")
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 设置不同偏好的交互时间阈值(小时)
 | 
											
												
													
														|  | 
 |  | +        thresholds = {
 | 
											
												
													
														|  | 
 |  | +            "low": 24,  # 低频率:一天一次
 | 
											
												
													
														|  | 
 |  | +            "medium": 12,  # 中频率:半天一次
 | 
											
												
													
														|  | 
 |  | +            "high": 6  # 高频率:大约6小时一次
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        threshold = thresholds.get(interaction_frequency, 12)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 如果足够时间已经过去
 | 
											
												
													
														|  | 
 |  | +        if hours_passed >= threshold:
 | 
											
												
													
														|  | 
 |  | +            # 根据时间上下文决定主动交互的状态
 | 
											
												
													
														|  | 
 |  | +            if time_context in [TimeContext.EARLY_MORNING, TimeContext.MORNING,
 | 
											
												
													
														|  | 
 |  | +                                TimeContext.NOON, TimeContext.AFTERNOON,
 | 
											
												
													
														|  | 
 |  | +                                TimeContext.EVENING]:
 | 
											
												
													
														|  | 
 |  | +                return True
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        return False
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def is_in_human_intervention(self) -> bool:
 | 
											
												
													
														|  | 
 |  | +        """检查是否处于人工介入状态"""
 | 
											
												
													
														|  | 
 |  | +        return self.current_state == DialogueState.HUMAN_INTERVENTION
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def get_prompt_context(self, user_message) -> Dict:
 | 
											
												
													
														|  | 
 |  | +        # 获取当前时间上下文
 | 
											
												
													
														|  | 
 |  | +        time_context = self.get_current_time_context()
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        context = {
 | 
											
												
													
														|  | 
 |  | +            "user_profile": self.user_profile,
 | 
											
												
													
														|  | 
 |  | +            "current_state": self.current_state.name,
 | 
											
												
													
														|  | 
 |  | +            "previous_state": self.previous_state.name if self.previous_state else None,
 | 
											
												
													
														|  | 
 |  | +            "current_time_period": time_context.description,
 | 
											
												
													
														|  | 
 |  | +            "dialogue_history": self.dialogue_history[-10:],
 | 
											
												
													
														|  | 
 |  | +            "user_message": user_message,
 | 
											
												
													
														|  | 
 |  | +            "last_interaction_interval": self._get_hours_since_last_interaction(),
 | 
											
												
													
														|  | 
 |  | +            "if_first_interaction": False,
 | 
											
												
													
														|  | 
 |  | +            "if_active_greeting": True if user_message else False
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 获取长期记忆
 | 
											
												
													
														|  | 
 |  | +        relevant_memories = self.vector_memory.retrieve_relevant_memories(user_message)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        context["long_term_memory"] = {
 | 
											
												
													
														|  | 
 |  | +            "relevant_conversations": relevant_memories
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        return context
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def _select_prompt(self, state):
 | 
											
												
													
														|  | 
 |  | +        state_to_prompt_map = {
 | 
											
												
													
														|  | 
 |  | +            DialogueState.GREETING: GENERAL_GREETING_PROMPT,
 | 
											
												
													
														|  | 
 |  | +            DialogueState.CHITCHAT: GENERAL_GREETING_PROMPT,
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +        return state_to_prompt_map[state]
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def _create_system_message(self):
 | 
											
												
													
														|  | 
 |  | +        prompt_context = self.get_prompt_context(None)
 | 
											
												
													
														|  | 
 |  | +        prompt_template = self._select_prompt(self.current_state)
 | 
											
												
													
														|  | 
 |  | +        prompt = prompt_template.format(**prompt_context['user_profile'], **prompt_context)
 | 
											
												
													
														|  | 
 |  | +        return {'role': 'system', 'content': prompt}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def make_llm_messages(self, user_message: Optional[str] = None) -> List[Dict[str, str]]:
 | 
											
												
													
														|  | 
 |  | +        """
 | 
											
												
													
														|  | 
 |  | +        参数:
 | 
											
												
													
														|  | 
 |  | +            dialogue_manager: 对话管理器实例
 | 
											
												
													
														|  | 
 |  | +            user_message: 当前用户消息,如果是主动交互则为None
 | 
											
												
													
														|  | 
 |  | +        返回:
 | 
											
												
													
														|  | 
 |  | +            消息列表
 | 
											
												
													
														|  | 
 |  | +        """
 | 
											
												
													
														|  | 
 |  | +        messages = []
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 添加系统消息
 | 
											
												
													
														|  | 
 |  | +        system_message = self._create_system_message()
 | 
											
												
													
														|  | 
 |  | +        messages.append(system_message)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        # 添加历史对话
 | 
											
												
													
														|  | 
 |  | +        dialogue_history = self.dialogue_history[-10:] \
 | 
											
												
													
														|  | 
 |  | +            if len(self.dialogue_history) > 10 \
 | 
											
												
													
														|  | 
 |  | +            else self.dialogue_history
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        for entry in dialogue_history:
 | 
											
												
													
														|  | 
 |  | +            role = entry['role']
 | 
											
												
													
														|  | 
 |  | +            messages.append({
 | 
											
												
													
														|  | 
 |  | +                "role": role,
 | 
											
												
													
														|  | 
 |  | +                "content": entry["content"]
 | 
											
												
													
														|  | 
 |  | +            })
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        return messages
 | 
											
												
													
														|  | 
 |  | +
 |