feat: 新增飞书长连接模式,无需公网域名
## 🚀 重大更新 ### 飞书集成升级 - ✅ 迁移到飞书官方 SDK 的事件订阅 2.0(长连接模式) - ✅ 无需公网域名和 webhook 配置 - ✅ 支持内网部署 - ✅ 自动重连机制 ### 核心功能优化 - ✅ 优化群聊隔离机制(每个用户在每个群独立会话) - ✅ 增强日志输出(emoji 标记便于快速识别) - ✅ 完善错误处理和异常恢复 - ✅ 添加 SSL 证书问题解决方案 ### 新增文件 - `src/integrations/feishu_longconn_service.py` - 飞书长连接服务 - `start_feishu_bot.py` - 启动脚本 - `test_feishu_connection.py` - 连接诊断工具 - `docs/FEISHU_LONGCONN.md` - 详细使用文档 - `README.md` - 项目说明文档 ### 技术改进 - 添加 lark-oapi==1.3.5 官方 SDK - 升级 certifi 包以支持 SSL 验证 - 优化配置加载逻辑 - 改进会话管理机制 ### 文档更新 - 新增飞书长连接模式完整文档 - 更新快速开始指南 - 添加常见问题解答(SSL、权限、部署等) - 完善架构说明和技术栈介绍 ## 📝 使用方式 启动飞书长连接服务(无需公网域名): ```bash python3 start_feishu_bot.py ``` 详见:docs/FEISHU_LONGCONN.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
113
init_database.py
113
init_database.py
@@ -38,6 +38,21 @@ class DatabaseInitializer:
|
||||
# 迁移历史记录
|
||||
self.migration_history = []
|
||||
|
||||
def _mask_db_url(self, url: str) -> str:
|
||||
"""隐藏数据库连接字符串中的敏感信息"""
|
||||
try:
|
||||
# 隐藏密码部分
|
||||
if '@' in url and ':' in url:
|
||||
parts = url.split('@')
|
||||
if len(parts) == 2:
|
||||
auth_part = parts[0]
|
||||
if ':' in auth_part:
|
||||
protocol_user = auth_part.rsplit(':', 1)[0]
|
||||
return f"{protocol_user}:***@{parts[1]}"
|
||||
return url
|
||||
except:
|
||||
return url
|
||||
|
||||
def _get_database_version(self) -> str:
|
||||
"""获取数据库版本信息"""
|
||||
try:
|
||||
@@ -61,14 +76,14 @@ class DatabaseInitializer:
|
||||
print("TSP智能助手数据库初始化系统")
|
||||
print("=" * 80)
|
||||
print(f"数据库类型: {self.db_version}")
|
||||
print(f"连接地址: {self.db_url}")
|
||||
print(f"连接地址: {self._mask_db_url(self.db_url)}")
|
||||
print(f"初始化时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
print("=" * 80)
|
||||
|
||||
try:
|
||||
# 设置日志
|
||||
config = get_config()
|
||||
setup_logging(config.server.log_level, "logs/tsp_assistant.log")
|
||||
setup_logging(config.server.log_level, "logs/tsp_assistant.log")
|
||||
|
||||
# 测试数据库连接
|
||||
if not self._test_connection():
|
||||
@@ -95,6 +110,9 @@ class DatabaseInitializer:
|
||||
if not self._verify_database_integrity():
|
||||
return False
|
||||
|
||||
# 初始化 Redis 缓存(如果启用)
|
||||
self._initialize_redis_cache()
|
||||
|
||||
# 生成初始化报告
|
||||
self._generate_init_report()
|
||||
|
||||
@@ -521,7 +539,16 @@ class DatabaseInitializer:
|
||||
# 插入初始知识库数据
|
||||
initial_data = self._get_initial_knowledge_data()
|
||||
for data in initial_data:
|
||||
entry = KnowledgeEntry(**data)
|
||||
# 只使用模型定义中存在的字段
|
||||
entry = KnowledgeEntry(
|
||||
question=data['question'],
|
||||
answer=data['answer'],
|
||||
category=data['category'],
|
||||
confidence_score=data.get('confidence_score', 0.7),
|
||||
is_verified=data.get('is_verified', True),
|
||||
verified_by=data.get('verified_by', 'system'),
|
||||
verified_at=data.get('verified_at', datetime.now())
|
||||
)
|
||||
session.add(entry)
|
||||
|
||||
session.commit()
|
||||
@@ -548,9 +575,7 @@ class DatabaseInitializer:
|
||||
"confidence_score": 0.9,
|
||||
"is_verified": True,
|
||||
"verified_by": "system",
|
||||
"verified_at": datetime.now(),
|
||||
"search_frequency": 0,
|
||||
"relevance_score": 0.9
|
||||
"verified_at": datetime.now()
|
||||
},
|
||||
{
|
||||
"question": "账户被锁定了怎么办?",
|
||||
@@ -559,9 +584,7 @@ class DatabaseInitializer:
|
||||
"confidence_score": 0.8,
|
||||
"is_verified": True,
|
||||
"verified_by": "system",
|
||||
"verified_at": datetime.now(),
|
||||
"search_frequency": 0,
|
||||
"relevance_score": 0.8
|
||||
"verified_at": datetime.now()
|
||||
},
|
||||
{
|
||||
"question": "如何修改个人信息?",
|
||||
@@ -570,9 +593,7 @@ class DatabaseInitializer:
|
||||
"confidence_score": 0.7,
|
||||
"is_verified": True,
|
||||
"verified_by": "system",
|
||||
"verified_at": datetime.now(),
|
||||
"search_frequency": 0,
|
||||
"relevance_score": 0.7
|
||||
"verified_at": datetime.now()
|
||||
},
|
||||
{
|
||||
"question": "支付失败怎么办?",
|
||||
@@ -581,9 +602,7 @@ class DatabaseInitializer:
|
||||
"confidence_score": 0.8,
|
||||
"is_verified": True,
|
||||
"verified_by": "system",
|
||||
"verified_at": datetime.now(),
|
||||
"search_frequency": 0,
|
||||
"relevance_score": 0.8
|
||||
"verified_at": datetime.now()
|
||||
},
|
||||
{
|
||||
"question": "如何申请退款?",
|
||||
@@ -592,9 +611,7 @@ class DatabaseInitializer:
|
||||
"confidence_score": 0.7,
|
||||
"is_verified": True,
|
||||
"verified_by": "system",
|
||||
"verified_at": datetime.now(),
|
||||
"search_frequency": 0,
|
||||
"relevance_score": 0.7
|
||||
"verified_at": datetime.now()
|
||||
},
|
||||
{
|
||||
"question": "系统无法访问怎么办?",
|
||||
@@ -603,9 +620,7 @@ class DatabaseInitializer:
|
||||
"confidence_score": 0.8,
|
||||
"is_verified": True,
|
||||
"verified_by": "system",
|
||||
"verified_at": datetime.now(),
|
||||
"search_frequency": 0,
|
||||
"relevance_score": 0.8
|
||||
"verified_at": datetime.now()
|
||||
},
|
||||
{
|
||||
"question": "如何联系客服?",
|
||||
@@ -614,9 +629,7 @@ class DatabaseInitializer:
|
||||
"confidence_score": 0.9,
|
||||
"is_verified": True,
|
||||
"verified_by": "system",
|
||||
"verified_at": datetime.now(),
|
||||
"search_frequency": 0,
|
||||
"relevance_score": 0.9
|
||||
"verified_at": datetime.now()
|
||||
},
|
||||
{
|
||||
"question": "如何远程启动车辆?",
|
||||
@@ -625,9 +638,7 @@ class DatabaseInitializer:
|
||||
"confidence_score": 0.9,
|
||||
"is_verified": True,
|
||||
"verified_by": "system",
|
||||
"verified_at": datetime.now(),
|
||||
"search_frequency": 0,
|
||||
"relevance_score": 0.9
|
||||
"verified_at": datetime.now()
|
||||
},
|
||||
{
|
||||
"question": "APP显示车辆信息错误怎么办?",
|
||||
@@ -636,9 +647,7 @@ class DatabaseInitializer:
|
||||
"confidence_score": 0.8,
|
||||
"is_verified": True,
|
||||
"verified_by": "system",
|
||||
"verified_at": datetime.now(),
|
||||
"search_frequency": 0,
|
||||
"relevance_score": 0.8
|
||||
"verified_at": datetime.now()
|
||||
},
|
||||
{
|
||||
"question": "车辆无法远程启动的原因?",
|
||||
@@ -647,9 +656,7 @@ class DatabaseInitializer:
|
||||
"confidence_score": 0.9,
|
||||
"is_verified": True,
|
||||
"verified_by": "system",
|
||||
"verified_at": datetime.now(),
|
||||
"search_frequency": 0,
|
||||
"relevance_score": 0.9
|
||||
"verified_at": datetime.now()
|
||||
}
|
||||
]
|
||||
|
||||
@@ -688,10 +695,14 @@ class DatabaseInitializer:
|
||||
entry.is_verified = True
|
||||
entry.verified_by = "system_init"
|
||||
entry.verified_at = datetime.now()
|
||||
if not hasattr(entry, 'search_frequency'):
|
||||
entry.search_frequency = 0
|
||||
if not hasattr(entry, 'relevance_score'):
|
||||
entry.relevance_score = 0.7
|
||||
# 尝试设置优化字段(如果存在)
|
||||
try:
|
||||
if hasattr(entry, 'search_frequency') and entry.search_frequency is None:
|
||||
entry.search_frequency = 0
|
||||
if hasattr(entry, 'relevance_score') and entry.relevance_score is None:
|
||||
entry.relevance_score = 0.7
|
||||
except:
|
||||
pass # 如果字段不存在,忽略
|
||||
|
||||
session.commit()
|
||||
print(f" 成功验证 {len(unverified_entries)} 条知识库条目")
|
||||
@@ -795,6 +806,34 @@ class DatabaseInitializer:
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
def _initialize_redis_cache(self):
|
||||
"""初始化 Redis 缓存"""
|
||||
print("\n检查 Redis 缓存配置...")
|
||||
|
||||
try:
|
||||
from src.core.cache_manager import cache_manager
|
||||
|
||||
health = cache_manager.health_check()
|
||||
|
||||
if health["status"] == "healthy":
|
||||
print(" ✓ Redis 缓存连接成功")
|
||||
stats = cache_manager.get_stats()
|
||||
print(f" - 当前连接数: {stats.get('connected_clients', 0)}")
|
||||
print(f" - 内存使用: {stats.get('used_memory_human', '0B')}")
|
||||
print(f" - 总键数: {stats.get('total_keys', 0)}")
|
||||
elif health["status"] == "disabled":
|
||||
print(" ⚠ Redis 缓存未启用(可选功能)")
|
||||
else:
|
||||
print(f" ⚠ Redis 缓存连接失败: {health.get('message', '未知错误')}")
|
||||
print(" 提示: Redis 是可选功能,不影响系统正常运行")
|
||||
|
||||
except ImportError:
|
||||
print(" ⚠ Redis 库未安装,缓存功能将被禁用")
|
||||
print(" 提示: 运行 'pip install redis hiredis' 安装 Redis 支持")
|
||||
except Exception as e:
|
||||
print(f" ⚠ Redis 初始化失败: {e}")
|
||||
print(" 提示: Redis 是可选功能,不影响系统正常运行")
|
||||
|
||||
def check_database_status(self) -> Dict[str, Any]:
|
||||
"""检查数据库状态"""
|
||||
print("\n" + "=" * 80)
|
||||
|
||||
Reference in New Issue
Block a user