修复重复初始化问题 - 统一Redis连接管理
主要修复: 1. 创建统一Redis连接管理器 (src/core/redis_manager.py) - 单例模式管理所有Redis连接 - 懒加载连接,避免重复初始化 - 线程安全的连接管理 2. 更新所有Redis使用模块 - TokenMonitor: 使用统一Redis管理器 - AISuccessMonitor: 移除重复Redis连接代码 - SystemOptimizer: 统一Redis连接管理 - ConversationHistoryManager: 使用统一Redis管理器 3. 修复DialogueManager重复初始化 - 使用懒加载属性(@property)避免重复创建监控器 - 只有在实际使用时才创建实例 4. 优化启动性能 - 避免重复的Redis连接创建 - 消除重复的TSP助手初始化 - 减少启动时的日志输出 技术改进: - 单例模式Redis管理器 - 懒加载组件初始化 - 统一连接管理 - 线程安全设计 解决启动卡顿问题,提升系统响应速度
This commit is contained in:
@@ -10,11 +10,11 @@ from typing import Dict, List, Optional, Any, Tuple
|
||||
from datetime import datetime, timedelta
|
||||
from dataclasses import dataclass
|
||||
from collections import defaultdict
|
||||
import redis
|
||||
import time
|
||||
|
||||
from ..core.database import db_manager
|
||||
from ..core.models import Alert
|
||||
from ..core.redis_manager import redis_manager
|
||||
from ..config.config import Config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -38,8 +38,7 @@ class AISuccessMonitor:
|
||||
"""AI调用成功率监控器"""
|
||||
|
||||
def __init__(self):
|
||||
self.redis_client = None
|
||||
self._init_redis()
|
||||
# 使用统一的Redis管理器
|
||||
|
||||
# 监控阈值
|
||||
self.thresholds = {
|
||||
@@ -58,23 +57,9 @@ class AISuccessMonitor:
|
||||
"poor": {"success_rate": 0.85, "response_time": 12.0}
|
||||
}
|
||||
|
||||
def _init_redis(self):
|
||||
"""初始化Redis连接"""
|
||||
try:
|
||||
self.redis_client = redis.Redis(
|
||||
host='43.134.68.207',
|
||||
port=6379,
|
||||
password='123456',
|
||||
decode_responses=True,
|
||||
socket_connect_timeout=5,
|
||||
socket_timeout=5,
|
||||
retry_on_timeout=True
|
||||
)
|
||||
self.redis_client.ping()
|
||||
logger.info("AI成功率监控Redis连接成功")
|
||||
except Exception as e:
|
||||
logger.error(f"AI成功率监控Redis连接失败: {e}")
|
||||
self.redis_client = None
|
||||
def _get_redis_client(self):
|
||||
"""获取Redis客户端"""
|
||||
return redis_manager.get_connection()
|
||||
|
||||
def record_api_call(
|
||||
self,
|
||||
|
||||
@@ -10,10 +10,9 @@ from typing import Dict, List, Optional, Any, Tuple
|
||||
from datetime import datetime, timedelta
|
||||
from dataclasses import dataclass
|
||||
from collections import defaultdict
|
||||
import redis
|
||||
|
||||
from ..core.database import db_manager
|
||||
from ..core.models import Conversation
|
||||
from ..core.redis_manager import redis_manager
|
||||
from ..config.config import Config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -37,8 +36,7 @@ class TokenMonitor:
|
||||
"""Token消耗监控器"""
|
||||
|
||||
def __init__(self):
|
||||
self.redis_client = None
|
||||
self._init_redis()
|
||||
# 使用统一的Redis管理器
|
||||
|
||||
# Token价格配置(每1000个token的价格,单位:元)
|
||||
self.token_prices = {
|
||||
@@ -64,23 +62,9 @@ class TokenMonitor:
|
||||
"error_rate_threshold": 0.1 # 错误率阈值
|
||||
}
|
||||
|
||||
def _init_redis(self):
|
||||
"""初始化Redis连接"""
|
||||
try:
|
||||
self.redis_client = redis.Redis(
|
||||
host='43.134.68.207',
|
||||
port=6379,
|
||||
password='123456',
|
||||
decode_responses=True,
|
||||
socket_connect_timeout=5,
|
||||
socket_timeout=5,
|
||||
retry_on_timeout=True
|
||||
)
|
||||
self.redis_client.ping()
|
||||
logger.info("Token监控Redis连接成功")
|
||||
except Exception as e:
|
||||
logger.error(f"Token监控Redis连接失败: {e}")
|
||||
self.redis_client = None
|
||||
def _get_redis_client(self):
|
||||
"""获取Redis客户端"""
|
||||
return redis_manager.get_connection()
|
||||
|
||||
def record_token_usage(
|
||||
self,
|
||||
@@ -141,7 +125,9 @@ class TokenMonitor:
|
||||
|
||||
def _save_to_redis(self, usage: TokenUsage):
|
||||
"""保存到Redis"""
|
||||
if not self.redis_client:
|
||||
redis_client = self._get_redis_client()
|
||||
|
||||
if not redis_client:
|
||||
return
|
||||
|
||||
try:
|
||||
@@ -161,24 +147,24 @@ class TokenMonitor:
|
||||
}
|
||||
|
||||
# 保存到多个键
|
||||
self.redis_client.zadd(
|
||||
redis_client.zadd(
|
||||
"token_usage:daily",
|
||||
{json.dumps(usage_data, ensure_ascii=False): timestamp}
|
||||
)
|
||||
|
||||
self.redis_client.zadd(
|
||||
redis_client.zadd(
|
||||
f"token_usage:user:{usage.user_id}",
|
||||
{json.dumps(usage_data, ensure_ascii=False): timestamp}
|
||||
)
|
||||
|
||||
if usage.work_order_id:
|
||||
self.redis_client.zadd(
|
||||
redis_client.zadd(
|
||||
f"token_usage:work_order:{usage.work_order_id}",
|
||||
{json.dumps(usage_data, ensure_ascii=False): timestamp}
|
||||
)
|
||||
|
||||
# 设置过期时间(保留30天)
|
||||
self.redis_client.expire("token_usage:daily", 30 * 24 * 3600)
|
||||
redis_client.expire("token_usage:daily", 30 * 24 * 3600)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"保存Token使用到Redis失败: {e}")
|
||||
@@ -241,14 +227,16 @@ class TokenMonitor:
|
||||
def get_daily_cost(self, date: datetime.date) -> float:
|
||||
"""获取指定日期的成本"""
|
||||
try:
|
||||
if not self.redis_client:
|
||||
redis_client = self._get_redis_client()
|
||||
|
||||
if not redis_client:
|
||||
return 0.0
|
||||
|
||||
start_time = datetime.combine(date, datetime.min.time()).timestamp()
|
||||
end_time = datetime.combine(date, datetime.max.time()).timestamp()
|
||||
|
||||
# 从Redis获取当日数据
|
||||
usage_records = self.redis_client.zrangebyscore(
|
||||
usage_records = redis_client.zrangebyscore(
|
||||
"token_usage:daily",
|
||||
start_time,
|
||||
end_time,
|
||||
@@ -272,7 +260,9 @@ class TokenMonitor:
|
||||
def get_hourly_cost(self, timestamp: datetime) -> float:
|
||||
"""获取指定小时的成本"""
|
||||
try:
|
||||
if not self.redis_client:
|
||||
redis_client = self._get_redis_client()
|
||||
|
||||
if not redis_client:
|
||||
return 0.0
|
||||
|
||||
# 获取当前小时的数据
|
||||
@@ -282,7 +272,7 @@ class TokenMonitor:
|
||||
start_time = hour_start.timestamp()
|
||||
end_time = hour_end.timestamp()
|
||||
|
||||
usage_records = self.redis_client.zrangebyscore(
|
||||
usage_records = redis_client.zrangebyscore(
|
||||
"token_usage:daily",
|
||||
start_time,
|
||||
end_time,
|
||||
@@ -306,13 +296,15 @@ class TokenMonitor:
|
||||
def get_user_token_stats(self, user_id: str, days: int = 7) -> Dict[str, Any]:
|
||||
"""获取用户Token使用统计"""
|
||||
try:
|
||||
if not self.redis_client:
|
||||
redis_client = self._get_redis_client()
|
||||
|
||||
if not redis_client:
|
||||
return {}
|
||||
|
||||
end_time = datetime.now().timestamp()
|
||||
start_time = (datetime.now() - timedelta(days=days)).timestamp()
|
||||
|
||||
usage_records = self.redis_client.zrangebyscore(
|
||||
usage_records = redis_client.zrangebyscore(
|
||||
f"token_usage:user:{user_id}",
|
||||
start_time,
|
||||
end_time,
|
||||
@@ -378,13 +370,15 @@ class TokenMonitor:
|
||||
def get_system_token_stats(self, days: int = 7) -> Dict[str, Any]:
|
||||
"""获取系统Token使用统计"""
|
||||
try:
|
||||
if not self.redis_client:
|
||||
redis_client = self._get_redis_client()
|
||||
|
||||
if not redis_client:
|
||||
return {}
|
||||
|
||||
end_time = datetime.now().timestamp()
|
||||
start_time = (datetime.now() - timedelta(days=days)).timestamp()
|
||||
|
||||
usage_records = self.redis_client.zrangebyscore(
|
||||
usage_records = redis_client.zrangebyscore(
|
||||
"token_usage:daily",
|
||||
start_time,
|
||||
end_time,
|
||||
@@ -466,27 +460,29 @@ class TokenMonitor:
|
||||
def cleanup_old_data(self, days: int = 30) -> int:
|
||||
"""清理旧数据"""
|
||||
try:
|
||||
if not self.redis_client:
|
||||
redis_client = self._get_redis_client()
|
||||
|
||||
if not redis_client:
|
||||
return 0
|
||||
|
||||
cutoff_time = (datetime.now() - timedelta(days=days)).timestamp()
|
||||
|
||||
# 清理每日数据
|
||||
removed_count = self.redis_client.zremrangebyscore(
|
||||
removed_count = redis_client.zremrangebyscore(
|
||||
"token_usage:daily",
|
||||
0,
|
||||
cutoff_time
|
||||
)
|
||||
|
||||
# 清理用户数据
|
||||
user_keys = self.redis_client.keys("token_usage:user:*")
|
||||
user_keys = redis_client.keys("token_usage:user:*")
|
||||
for key in user_keys:
|
||||
self.redis_client.zremrangebyscore(key, 0, cutoff_time)
|
||||
redis_client.zremrangebyscore(key, 0, cutoff_time)
|
||||
|
||||
# 清理工单数据
|
||||
work_order_keys = self.redis_client.keys("token_usage:work_order:*")
|
||||
work_order_keys = redis_client.keys("token_usage:work_order:*")
|
||||
for key in work_order_keys:
|
||||
self.redis_client.zremrangebyscore(key, 0, cutoff_time)
|
||||
redis_client.zremrangebyscore(key, 0, cutoff_time)
|
||||
|
||||
logger.info(f"清理Token监控数据成功: 数量={removed_count}")
|
||||
return removed_count
|
||||
|
||||
@@ -22,21 +22,32 @@ class CacheManager:
|
||||
self.default_ttl = 60 # 默认1分钟过期,提高响应速度
|
||||
self.max_memory_size = 2000 # 增加内存缓存条目数
|
||||
|
||||
# Redis支持(可选)
|
||||
# Redis支持(可选)- 延迟连接
|
||||
self.redis_client = None
|
||||
if redis_url:
|
||||
self.redis_url = redis_url
|
||||
self.redis_connected = False
|
||||
|
||||
def _ensure_redis_connection(self):
|
||||
"""确保Redis连接(延迟连接)"""
|
||||
if self.redis_url and not self.redis_connected:
|
||||
try:
|
||||
import redis
|
||||
self.redis_client = redis.from_url(redis_url)
|
||||
self.redis_client = redis.from_url(self.redis_url, socket_connect_timeout=2, socket_timeout=2)
|
||||
self.redis_client.ping() # 测试连接
|
||||
self.redis_connected = True
|
||||
logger.info("Redis缓存已启用")
|
||||
except ImportError:
|
||||
logger.warning("Redis未安装,使用内存缓存")
|
||||
logger.debug("Redis未安装,使用内存缓存")
|
||||
except Exception as e:
|
||||
logger.warning(f"Redis连接失败: {e},使用内存缓存")
|
||||
logger.debug(f"Redis连接失败: {e},使用内存缓存")
|
||||
self.redis_client = None
|
||||
|
||||
def get(self, key: str) -> Optional[Any]:
|
||||
"""获取缓存值"""
|
||||
try:
|
||||
# 确保Redis连接
|
||||
self._ensure_redis_connection()
|
||||
|
||||
# 先尝试Redis
|
||||
if self.redis_client:
|
||||
try:
|
||||
@@ -66,6 +77,9 @@ class CacheManager:
|
||||
ttl = ttl or self.default_ttl
|
||||
expires_at = time.time() + ttl
|
||||
|
||||
# 确保Redis连接
|
||||
self._ensure_redis_connection()
|
||||
|
||||
# 先尝试Redis
|
||||
if self.redis_client:
|
||||
try:
|
||||
|
||||
81
src/core/redis_manager.py
Normal file
81
src/core/redis_manager.py
Normal file
@@ -0,0 +1,81 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Redis连接管理器
|
||||
统一管理所有Redis连接,避免重复连接
|
||||
"""
|
||||
|
||||
import redis
|
||||
import logging
|
||||
import threading
|
||||
from typing import Optional
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class RedisManager:
|
||||
"""Redis连接管理器(单例模式)"""
|
||||
|
||||
_instance = None
|
||||
_lock = threading.Lock()
|
||||
|
||||
def __new__(cls):
|
||||
if cls._instance is None:
|
||||
with cls._lock:
|
||||
if cls._instance is None:
|
||||
cls._instance = super().__new__(cls)
|
||||
cls._instance._initialized = False
|
||||
return cls._instance
|
||||
|
||||
def __init__(self):
|
||||
if self._initialized:
|
||||
return
|
||||
|
||||
self.redis_client = None
|
||||
self.connected = False
|
||||
self.connection_lock = threading.Lock()
|
||||
self._initialized = True
|
||||
|
||||
# Redis配置
|
||||
self.config = {
|
||||
'host': '43.134.68.207',
|
||||
'port': 6379,
|
||||
'password': '123456',
|
||||
'decode_responses': True,
|
||||
'socket_connect_timeout': 2,
|
||||
'socket_timeout': 2,
|
||||
'retry_on_timeout': True
|
||||
}
|
||||
|
||||
def get_connection(self) -> Optional[redis.Redis]:
|
||||
"""获取Redis连接(懒加载)"""
|
||||
with self.connection_lock:
|
||||
if not self.connected:
|
||||
try:
|
||||
self.redis_client = redis.Redis(**self.config)
|
||||
self.redis_client.ping()
|
||||
self.connected = True
|
||||
logger.info("Redis连接成功")
|
||||
except Exception as e:
|
||||
logger.debug(f"Redis连接失败: {e}")
|
||||
self.redis_client = None
|
||||
self.connected = False
|
||||
|
||||
return self.redis_client
|
||||
|
||||
def is_connected(self) -> bool:
|
||||
"""检查Redis是否已连接"""
|
||||
return self.connected and self.redis_client is not None
|
||||
|
||||
def close_connection(self):
|
||||
"""关闭Redis连接"""
|
||||
with self.connection_lock:
|
||||
if self.redis_client:
|
||||
try:
|
||||
self.redis_client.close()
|
||||
except Exception as e:
|
||||
logger.debug(f"关闭Redis连接失败: {e}")
|
||||
finally:
|
||||
self.redis_client = None
|
||||
self.connected = False
|
||||
|
||||
# 全局Redis管理器实例
|
||||
redis_manager = RedisManager()
|
||||
65
src/core/startup_config.py
Normal file
65
src/core/startup_config.py
Normal file
@@ -0,0 +1,65 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
启动优化配置
|
||||
控制启动时的初始化行为,避免重复初始化和阻塞
|
||||
"""
|
||||
|
||||
class StartupConfig:
|
||||
"""启动配置类"""
|
||||
|
||||
# 启动优化设置
|
||||
SKIP_SYSTEM_CHECK = True # 跳过系统检查
|
||||
DELAY_REDIS_CONNECTION = True # 延迟Redis连接
|
||||
DELAY_MONITORING_START = True # 延迟监控启动
|
||||
DELAY_AGENT_INIT = True # 延迟Agent初始化
|
||||
|
||||
# 延迟时间(秒)
|
||||
REDIS_CONNECTION_DELAY = 2 # Redis连接延迟
|
||||
MONITORING_START_DELAY = 5 # 监控启动延迟
|
||||
AGENT_INIT_DELAY = 3 # Agent初始化延迟
|
||||
|
||||
# 连接超时设置
|
||||
REDIS_CONNECT_TIMEOUT = 2 # Redis连接超时
|
||||
REDIS_SOCKET_TIMEOUT = 2 # Redis Socket超时
|
||||
DATABASE_CONNECT_TIMEOUT = 5 # 数据库连接超时
|
||||
|
||||
# 日志级别控制
|
||||
REDIS_LOG_LEVEL = "DEBUG" # Redis日志级别
|
||||
STARTUP_LOG_LEVEL = "INFO" # 启动日志级别
|
||||
|
||||
@classmethod
|
||||
def should_skip_system_check(cls):
|
||||
"""是否跳过系统检查"""
|
||||
return cls.SKIP_SYSTEM_CHECK
|
||||
|
||||
@classmethod
|
||||
def should_delay_redis_connection(cls):
|
||||
"""是否延迟Redis连接"""
|
||||
return cls.DELAY_REDIS_CONNECTION
|
||||
|
||||
@classmethod
|
||||
def should_delay_monitoring_start(cls):
|
||||
"""是否延迟监控启动"""
|
||||
return cls.DELAY_MONITORING_START
|
||||
|
||||
@classmethod
|
||||
def should_delay_agent_init(cls):
|
||||
"""是否延迟Agent初始化"""
|
||||
return cls.DELAY_AGENT_INIT
|
||||
|
||||
@classmethod
|
||||
def get_redis_timeout_config(cls):
|
||||
"""获取Redis超时配置"""
|
||||
return {
|
||||
'socket_connect_timeout': cls.REDIS_CONNECT_TIMEOUT,
|
||||
'socket_timeout': cls.REDIS_SOCKET_TIMEOUT
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def get_delay_times(cls):
|
||||
"""获取延迟时间配置"""
|
||||
return {
|
||||
'redis_connection': cls.REDIS_CONNECTION_DELAY,
|
||||
'monitoring_start': cls.MONITORING_START_DELAY,
|
||||
'agent_init': cls.AGENT_INIT_DELAY
|
||||
}
|
||||
@@ -11,10 +11,9 @@ from typing import Dict, List, Optional, Any
|
||||
from datetime import datetime, timedelta
|
||||
from collections import defaultdict, deque
|
||||
import psutil
|
||||
import redis
|
||||
|
||||
from ..config.config import Config
|
||||
from .database import db_manager
|
||||
from .redis_manager import redis_manager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -22,7 +21,7 @@ class SystemOptimizer:
|
||||
"""系统优化器"""
|
||||
|
||||
def __init__(self):
|
||||
self.redis_client = None
|
||||
# 使用统一的Redis管理器
|
||||
self._init_redis()
|
||||
|
||||
# 性能监控
|
||||
@@ -52,26 +51,12 @@ class SystemOptimizer:
|
||||
"max_concurrent_users": 50 # 最大并发用户数(调整为更合理的值)
|
||||
}
|
||||
|
||||
# 启动监控线程
|
||||
self._start_monitoring()
|
||||
# 延迟启动监控线程(避免启动时阻塞)
|
||||
threading.Timer(5.0, self._start_monitoring).start()
|
||||
|
||||
def _init_redis(self):
|
||||
"""初始化Redis连接"""
|
||||
try:
|
||||
self.redis_client = redis.Redis(
|
||||
host='43.134.68.207',
|
||||
port=6379,
|
||||
password='123456',
|
||||
decode_responses=True,
|
||||
socket_connect_timeout=5,
|
||||
socket_timeout=5,
|
||||
retry_on_timeout=True
|
||||
)
|
||||
self.redis_client.ping()
|
||||
logger.info("系统优化Redis连接成功")
|
||||
except Exception as e:
|
||||
logger.error(f"系统优化Redis连接失败: {e}")
|
||||
self.redis_client = None
|
||||
def _get_redis_client(self):
|
||||
"""获取Redis客户端"""
|
||||
return redis_manager.get_connection()
|
||||
|
||||
def _start_monitoring(self):
|
||||
"""启动监控线程"""
|
||||
@@ -140,12 +125,13 @@ class SystemOptimizer:
|
||||
self.performance_metrics.append(metrics)
|
||||
|
||||
# 保存到Redis
|
||||
if self.redis_client:
|
||||
self.redis_client.lpush(
|
||||
redis_client = self._get_redis_client()
|
||||
if redis_client:
|
||||
redis_client.lpush(
|
||||
"system_metrics",
|
||||
str(metrics)
|
||||
)
|
||||
self.redis_client.ltrim("system_metrics", 0, 999) # 保留最近1000条
|
||||
redis_client.ltrim("system_metrics", 0, 999) # 保留最近1000条
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"收集系统指标失败: {e}")
|
||||
@@ -240,7 +226,9 @@ class SystemOptimizer:
|
||||
def check_rate_limit(self, user_id: str) -> bool:
|
||||
"""检查用户请求频率限制"""
|
||||
try:
|
||||
if not self.redis_client:
|
||||
redis_client = self._get_redis_client()
|
||||
|
||||
if not redis_client:
|
||||
return True # Redis不可用时允许请求
|
||||
|
||||
now = datetime.now()
|
||||
@@ -249,32 +237,32 @@ class SystemOptimizer:
|
||||
day_key = f"rate_limit:{user_id}:{now.strftime('%Y%m%d')}"
|
||||
|
||||
# 检查每分钟限制
|
||||
minute_count = self.redis_client.get(minute_key) or 0
|
||||
minute_count = redis_client.get(minute_key) or 0
|
||||
if int(minute_count) >= self.rate_limits["per_minute"]:
|
||||
logger.warning(f"用户 {user_id} 触发每分钟频率限制")
|
||||
return False
|
||||
|
||||
# 检查每小时限制
|
||||
hour_count = self.redis_client.get(hour_key) or 0
|
||||
hour_count = redis_client.get(hour_key) or 0
|
||||
if int(hour_count) >= self.rate_limits["per_hour"]:
|
||||
logger.warning(f"用户 {user_id} 触发每小时频率限制")
|
||||
return False
|
||||
|
||||
# 检查每日限制
|
||||
day_count = self.redis_client.get(day_key) or 0
|
||||
day_count = redis_client.get(day_key) or 0
|
||||
if int(day_count) >= self.rate_limits["per_day"]:
|
||||
logger.warning(f"用户 {user_id} 触发每日频率限制")
|
||||
return False
|
||||
|
||||
# 增加计数
|
||||
self.redis_client.incr(minute_key)
|
||||
self.redis_client.incr(hour_key)
|
||||
self.redis_client.incr(day_key)
|
||||
redis_client.incr(minute_key)
|
||||
redis_client.incr(hour_key)
|
||||
redis_client.incr(day_key)
|
||||
|
||||
# 设置过期时间
|
||||
self.redis_client.expire(minute_key, 60)
|
||||
self.redis_client.expire(hour_key, 3600)
|
||||
self.redis_client.expire(day_key, 86400)
|
||||
redis_client.expire(minute_key, 60)
|
||||
redis_client.expire(hour_key, 3600)
|
||||
redis_client.expire(day_key, 86400)
|
||||
|
||||
return True
|
||||
|
||||
@@ -324,7 +312,9 @@ class SystemOptimizer:
|
||||
def check_cost_limit(self, estimated_cost: float) -> bool:
|
||||
"""检查成本限制"""
|
||||
try:
|
||||
if not self.redis_client:
|
||||
redis_client = self._get_redis_client()
|
||||
|
||||
if not redis_client:
|
||||
return True # Redis不可用时允许请求
|
||||
|
||||
now = datetime.now()
|
||||
@@ -337,24 +327,24 @@ class SystemOptimizer:
|
||||
return False
|
||||
|
||||
# 检查每小时成本
|
||||
hour_cost = float(self.redis_client.get(hour_key) or 0)
|
||||
hour_cost = float(redis_client.get(hour_key) or 0)
|
||||
if hour_cost + estimated_cost > self.cost_limits["hourly"]:
|
||||
logger.warning(f"每小时成本超限: {hour_cost + estimated_cost:.4f} > {self.cost_limits['hourly']}")
|
||||
return False
|
||||
|
||||
# 检查每日成本
|
||||
day_cost = float(self.redis_client.get(day_key) or 0)
|
||||
day_cost = float(redis_client.get(day_key) or 0)
|
||||
if day_cost + estimated_cost > self.cost_limits["daily"]:
|
||||
logger.warning(f"每日成本超限: {day_cost + estimated_cost:.4f} > {self.cost_limits['daily']}")
|
||||
return False
|
||||
|
||||
# 增加成本计数
|
||||
self.redis_client.incrbyfloat(hour_key, estimated_cost)
|
||||
self.redis_client.incrbyfloat(day_key, estimated_cost)
|
||||
redis_client.incrbyfloat(hour_key, estimated_cost)
|
||||
redis_client.incrbyfloat(day_key, estimated_cost)
|
||||
|
||||
# 设置过期时间
|
||||
self.redis_client.expire(hour_key, 3600)
|
||||
self.redis_client.expire(day_key, 86400)
|
||||
redis_client.expire(hour_key, 3600)
|
||||
redis_client.expire(day_key, 86400)
|
||||
|
||||
return True
|
||||
|
||||
@@ -455,27 +445,29 @@ class SystemOptimizer:
|
||||
def cleanup_old_metrics(self, days: int = 7) -> int:
|
||||
"""清理旧指标数据"""
|
||||
try:
|
||||
if not self.redis_client:
|
||||
redis_client = self._get_redis_client()
|
||||
|
||||
if not redis_client:
|
||||
return 0
|
||||
|
||||
cutoff_time = (datetime.now() - timedelta(days=days)).timestamp()
|
||||
|
||||
# 清理系统指标
|
||||
removed_count = self.redis_client.zremrangebyscore(
|
||||
removed_count = redis_client.zremrangebyscore(
|
||||
"system_metrics",
|
||||
0,
|
||||
cutoff_time
|
||||
)
|
||||
|
||||
# 清理频率限制数据
|
||||
rate_limit_keys = self.redis_client.keys("rate_limit:*")
|
||||
rate_limit_keys = redis_client.keys("rate_limit:*")
|
||||
for key in rate_limit_keys:
|
||||
self.redis_client.delete(key)
|
||||
redis_client.delete(key)
|
||||
|
||||
# 清理成本限制数据
|
||||
cost_limit_keys = self.redis_client.keys("cost_limit:*")
|
||||
cost_limit_keys = redis_client.keys("cost_limit:*")
|
||||
for key in cost_limit_keys:
|
||||
self.redis_client.delete(key)
|
||||
redis_client.delete(key)
|
||||
|
||||
logger.info(f"清理系统优化数据成功: 数量={removed_count}")
|
||||
return removed_count
|
||||
|
||||
@@ -8,11 +8,11 @@ import json
|
||||
import logging
|
||||
from typing import Dict, List, Optional, Any, Tuple
|
||||
from datetime import datetime, timedelta
|
||||
import redis
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ..core.database import db_manager
|
||||
from ..core.models import Conversation
|
||||
from ..core.redis_manager import redis_manager
|
||||
from ..config.config import Config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -21,29 +21,12 @@ class ConversationHistoryManager:
|
||||
"""对话历史管理器"""
|
||||
|
||||
def __init__(self):
|
||||
self.redis_client = None
|
||||
self._init_redis()
|
||||
self.max_history_length = 20 # 最大历史记录数
|
||||
self.cache_ttl = 3600 * 24 # 缓存24小时
|
||||
|
||||
def _init_redis(self):
|
||||
"""初始化Redis连接"""
|
||||
try:
|
||||
self.redis_client = redis.Redis(
|
||||
host='43.134.68.207',
|
||||
port=6379,
|
||||
password='123456',
|
||||
decode_responses=True,
|
||||
socket_connect_timeout=5,
|
||||
socket_timeout=5,
|
||||
retry_on_timeout=True
|
||||
)
|
||||
# 测试连接
|
||||
self.redis_client.ping()
|
||||
logger.info("Redis连接成功")
|
||||
except Exception as e:
|
||||
logger.error(f"Redis连接失败: {e}")
|
||||
self.redis_client = None
|
||||
def _get_redis_client(self):
|
||||
"""获取Redis客户端"""
|
||||
return redis_manager.get_connection()
|
||||
|
||||
def _get_cache_key(self, user_id: str, work_order_id: Optional[int] = None) -> str:
|
||||
"""生成缓存键"""
|
||||
@@ -109,7 +92,8 @@ class ConversationHistoryManager:
|
||||
response_time: Optional[float] = None
|
||||
):
|
||||
"""保存对话到Redis缓存"""
|
||||
if not self.redis_client:
|
||||
redis_client = self._get_redis_client()
|
||||
if not redis_client:
|
||||
return
|
||||
|
||||
try:
|
||||
@@ -126,13 +110,13 @@ class ConversationHistoryManager:
|
||||
}
|
||||
|
||||
# 添加到Redis列表
|
||||
self.redis_client.lpush(cache_key, json.dumps(conversation_record, ensure_ascii=False))
|
||||
redis_client.lpush(cache_key, json.dumps(conversation_record, ensure_ascii=False))
|
||||
|
||||
# 限制列表长度
|
||||
self.redis_client.ltrim(cache_key, 0, self.max_history_length - 1)
|
||||
redis_client.ltrim(cache_key, 0, self.max_history_length - 1)
|
||||
|
||||
# 设置过期时间
|
||||
self.redis_client.expire(cache_key, self.cache_ttl)
|
||||
redis_client.expire(cache_key, self.cache_ttl)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"保存到Redis缓存失败: {e}")
|
||||
@@ -147,7 +131,8 @@ class ConversationHistoryManager:
|
||||
"""获取对话历史(优先从Redis获取)"""
|
||||
try:
|
||||
# 先尝试从Redis获取
|
||||
if self.redis_client:
|
||||
redis_client = self._get_redis_client()
|
||||
if redis_client:
|
||||
cached_history = self._get_from_cache(user_id, work_order_id, limit, offset)
|
||||
if cached_history:
|
||||
return cached_history
|
||||
@@ -167,7 +152,8 @@ class ConversationHistoryManager:
|
||||
offset: int
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""从Redis缓存获取对话历史"""
|
||||
if not self.redis_client:
|
||||
redis_client = self._get_redis_client()
|
||||
if not redis_client:
|
||||
return []
|
||||
|
||||
try:
|
||||
@@ -177,7 +163,7 @@ class ConversationHistoryManager:
|
||||
start = offset
|
||||
end = offset + limit - 1
|
||||
|
||||
cached_data = self.redis_client.lrange(cache_key, start, end)
|
||||
cached_data = redis_client.lrange(cache_key, start, end)
|
||||
|
||||
history = []
|
||||
for data in cached_data:
|
||||
|
||||
@@ -23,11 +23,36 @@ class DialogueManager:
|
||||
self.knowledge_manager = KnowledgeManager()
|
||||
self.vehicle_manager = VehicleDataManager()
|
||||
self.history_manager = ConversationHistoryManager()
|
||||
self.token_monitor = TokenMonitor()
|
||||
self.ai_success_monitor = AISuccessMonitor()
|
||||
self.system_optimizer = SystemOptimizer()
|
||||
# 延迟初始化监控器,避免重复创建
|
||||
self._token_monitor = None
|
||||
self._ai_success_monitor = None
|
||||
self._system_optimizer = None
|
||||
self.conversation_history = {} # 存储对话历史
|
||||
|
||||
@property
|
||||
def token_monitor(self):
|
||||
"""获取Token监控器(懒加载)"""
|
||||
if self._token_monitor is None:
|
||||
from ..analytics.token_monitor import TokenMonitor
|
||||
self._token_monitor = TokenMonitor()
|
||||
return self._token_monitor
|
||||
|
||||
@property
|
||||
def ai_success_monitor(self):
|
||||
"""获取AI成功监控器(懒加载)"""
|
||||
if self._ai_success_monitor is None:
|
||||
from ..analytics.ai_success_monitor import AISuccessMonitor
|
||||
self._ai_success_monitor = AISuccessMonitor()
|
||||
return self._ai_success_monitor
|
||||
|
||||
@property
|
||||
def system_optimizer(self):
|
||||
"""获取系统优化器(懒加载)"""
|
||||
if self._system_optimizer is None:
|
||||
from ..core.system_optimizer import SystemOptimizer
|
||||
self._system_optimizer = SystemOptimizer()
|
||||
return self._system_optimizer
|
||||
|
||||
def process_user_message(
|
||||
self,
|
||||
user_message: str,
|
||||
|
||||
@@ -16,13 +16,14 @@ from flask_cors import CORS
|
||||
# 添加项目根目录到Python路径
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from src.main import TSPAssistant
|
||||
from src.agent_assistant import TSPAgentAssistant
|
||||
from src.dialogue.realtime_chat import RealtimeChatManager
|
||||
from src.vehicle.vehicle_data_manager import VehicleDataManager
|
||||
# 延迟导入,避免启动时重复初始化
|
||||
# from src.main import TSPAssistant
|
||||
# from src.agent_assistant import TSPAgentAssistant
|
||||
# from src.dialogue.realtime_chat import RealtimeChatManager
|
||||
# from src.vehicle.vehicle_data_manager import VehicleDataManager
|
||||
from src.core.database import db_manager
|
||||
from src.core.models import Conversation, Alert, WorkOrder
|
||||
from src.core.query_optimizer import query_optimizer
|
||||
# from src.core.query_optimizer import query_optimizer
|
||||
|
||||
# 导入蓝图
|
||||
from src.web.blueprints.alerts import alerts_bp
|
||||
@@ -67,6 +68,7 @@ def get_assistant():
|
||||
"""获取TSP助手实例(懒加载)"""
|
||||
global assistant
|
||||
if assistant is None:
|
||||
from src.main import TSPAssistant
|
||||
assistant = TSPAssistant()
|
||||
return assistant
|
||||
|
||||
@@ -74,6 +76,7 @@ def get_agent_assistant():
|
||||
"""获取Agent助手实例(懒加载)"""
|
||||
global agent_assistant
|
||||
if agent_assistant is None:
|
||||
from src.agent_assistant import TSPAgentAssistant
|
||||
agent_assistant = TSPAgentAssistant()
|
||||
return agent_assistant
|
||||
|
||||
@@ -81,6 +84,7 @@ def get_chat_manager():
|
||||
"""获取聊天管理器实例(懒加载)"""
|
||||
global chat_manager
|
||||
if chat_manager is None:
|
||||
from src.dialogue.realtime_chat import RealtimeChatManager
|
||||
chat_manager = RealtimeChatManager()
|
||||
return chat_manager
|
||||
|
||||
@@ -88,6 +92,7 @@ def get_vehicle_manager():
|
||||
"""获取车辆数据管理器实例(懒加载)"""
|
||||
global vehicle_manager
|
||||
if vehicle_manager is None:
|
||||
from src.vehicle.vehicle_data_manager import VehicleDataManager
|
||||
vehicle_manager = VehicleDataManager()
|
||||
return vehicle_manager
|
||||
|
||||
|
||||
@@ -53,26 +53,8 @@ def main():
|
||||
|
||||
logger.info("正在启动TSP智能助手综合管理平台...")
|
||||
|
||||
# 快速系统检查(不创建完整实例)
|
||||
try:
|
||||
from src.core.database import db_manager
|
||||
from src.core.llm_client import QwenClient
|
||||
|
||||
# 快速测试数据库连接
|
||||
db_ok = db_manager.test_connection()
|
||||
|
||||
# 快速测试LLM连接
|
||||
llm_client = QwenClient()
|
||||
llm_ok = llm_client.test_connection()
|
||||
|
||||
logger.info(f"系统检查结果: 数据库={db_ok}, LLM={llm_ok}")
|
||||
|
||||
if not (db_ok and llm_ok):
|
||||
logger.warning("系统检查发现问题,但继续启动...")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"系统检查失败: {e}")
|
||||
print(f"警告: 系统检查失败 - {e}")
|
||||
# 跳过系统检查,直接启动(避免重复初始化)
|
||||
logger.info("跳过系统检查,直接启动服务...")
|
||||
|
||||
# 导入并启动Flask应用
|
||||
from src.web.app import app
|
||||
|
||||
18
快速启动_优化版.bat
Normal file
18
快速启动_优化版.bat
Normal file
@@ -0,0 +1,18 @@
|
||||
@echo off
|
||||
chcp 65001 >nul
|
||||
echo ========================================
|
||||
echo TSP智能助手 - 快速启动(优化版)
|
||||
echo ========================================
|
||||
echo.
|
||||
|
||||
echo 正在启动服务...
|
||||
echo 优化内容:
|
||||
echo - 跳过系统检查,快速启动
|
||||
echo - 延迟Redis连接,避免阻塞
|
||||
echo - 延迟监控启动,减少初始化时间
|
||||
echo - 懒加载组件,按需初始化
|
||||
echo.
|
||||
|
||||
python start_dashboard.py
|
||||
|
||||
pause
|
||||
Reference in New Issue
Block a user