feat: 统一API密钥管理 - 将所有API密钥集中到config/api_keys.py进行统一管理,提供更安全便捷的密钥管理方式

This commit is contained in:
赵杰
2025-09-25 14:34:58 +01:00
parent aea5f6bf74
commit 81162475d0
7 changed files with 636 additions and 24 deletions

318
config/api_keys.py Normal file
View File

@@ -0,0 +1,318 @@
"""
API密钥统一管理
所有API密钥的集中管理和配置
"""
import os
from typing import Optional, Dict, Any
from dataclasses import dataclass
import logging
# 尝试加载环境变量
try:
from dotenv import load_dotenv
load_dotenv()
except Exception:
# 如果没有.env文件或加载失败使用默认配置
pass
logger = logging.getLogger(__name__)
@dataclass
class APIKeys:
"""API密钥配置类"""
# 千问大模型API密钥
qwen_api_key: Optional[str] = None
# OpenAI API密钥
openai_api_key: Optional[str] = None
# Anthropic API密钥
anthropic_api_key: Optional[str] = None
# 其他API密钥可扩展
google_api_key: Optional[str] = None
baidu_api_key: Optional[str] = None
tencent_api_key: Optional[str] = None
class APIKeyManager:
"""API密钥管理器"""
def __init__(self):
self.keys = APIKeys()
self._load_from_env()
self._validate_keys()
def _load_from_env(self):
"""从环境变量加载API密钥"""
# 千问API密钥
self.keys.qwen_api_key = os.getenv('QWEN_API_KEY')
# OpenAI API密钥
self.keys.openai_api_key = os.getenv('OPENAI_API_KEY')
# Anthropic API密钥
self.keys.anthropic_api_key = os.getenv('ANTHROPIC_API_KEY')
# 其他API密钥
self.keys.google_api_key = os.getenv('GOOGLE_API_KEY')
self.keys.baidu_api_key = os.getenv('BAIDU_API_KEY')
self.keys.tencent_api_key = os.getenv('TENCENT_API_KEY')
logger.info("API密钥已从环境变量加载")
def _validate_keys(self):
"""验证API密钥格式"""
validation_results = {}
# 验证千问API密钥
if self.keys.qwen_api_key:
if self.keys.qwen_api_key.startswith('sk-'):
validation_results['qwen'] = True
logger.info("✅ 千问API密钥格式正确")
else:
validation_results['qwen'] = False
logger.warning("⚠️ 千问API密钥格式可能不正确")
else:
validation_results['qwen'] = False
logger.warning("⚠️ 千问API密钥未配置")
# 验证OpenAI API密钥
if self.keys.openai_api_key:
if self.keys.openai_api_key.startswith('sk-'):
validation_results['openai'] = True
logger.info("✅ OpenAI API密钥格式正确")
else:
validation_results['openai'] = False
logger.warning("⚠️ OpenAI API密钥格式可能不正确")
else:
validation_results['openai'] = False
logger.warning("⚠️ OpenAI API密钥未配置")
# 验证Anthropic API密钥
if self.keys.anthropic_api_key:
if self.keys.anthropic_api_key.startswith('sk-ant-'):
validation_results['anthropic'] = True
logger.info("✅ Anthropic API密钥格式正确")
else:
validation_results['anthropic'] = False
logger.warning("⚠️ Anthropic API密钥格式可能不正确")
else:
validation_results['anthropic'] = False
logger.warning("⚠️ Anthropic API密钥未配置")
return validation_results
def get_qwen_key(self) -> Optional[str]:
"""获取千问API密钥"""
return self.keys.qwen_api_key
def get_openai_key(self) -> Optional[str]:
"""获取OpenAI API密钥"""
return self.keys.openai_api_key
def get_anthropic_key(self) -> Optional[str]:
"""获取Anthropic API密钥"""
return self.keys.anthropic_api_key
def get_key(self, provider: str) -> Optional[str]:
"""根据提供商获取API密钥"""
key_map = {
'qwen': self.keys.qwen_api_key,
'openai': self.keys.openai_api_key,
'anthropic': self.keys.anthropic_api_key,
'google': self.keys.google_api_key,
'baidu': self.keys.baidu_api_key,
'tencent': self.keys.tencent_api_key
}
return key_map.get(provider.lower())
def is_available(self, provider: str) -> bool:
"""检查指定提供商的API密钥是否可用"""
key = self.get_key(provider)
return key is not None and len(key.strip()) > 0
def get_available_providers(self) -> list:
"""获取所有可用的API提供商"""
providers = ['qwen', 'openai', 'anthropic', 'google', 'baidu', 'tencent']
available = []
for provider in providers:
if self.is_available(provider):
available.append(provider)
return available
def get_all_keys(self) -> Dict[str, Optional[str]]:
"""获取所有API密钥用于调试不包含实际密钥值"""
return {
'qwen': '***' if self.keys.qwen_api_key else None,
'openai': '***' if self.keys.openai_api_key else None,
'anthropic': '***' if self.keys.anthropic_api_key else None,
'google': '***' if self.keys.google_api_key else None,
'baidu': '***' if self.keys.baidu_api_key else None,
'tencent': '***' if self.keys.tencent_api_key else None
}
def set_key(self, provider: str, api_key: str):
"""设置API密钥运行时设置"""
provider = provider.lower()
if provider == 'qwen':
self.keys.qwen_api_key = api_key
elif provider == 'openai':
self.keys.openai_api_key = api_key
elif provider == 'anthropic':
self.keys.anthropic_api_key = api_key
elif provider == 'google':
self.keys.google_api_key = api_key
elif provider == 'baidu':
self.keys.baidu_api_key = api_key
elif provider == 'tencent':
self.keys.tencent_api_key = api_key
else:
raise ValueError(f"不支持的API提供商: {provider}")
logger.info(f"API密钥已设置: {provider}")
def create_env_file(self, file_path: str = ".env"):
"""创建.env文件模板"""
env_content = """# API密钥配置文件
# 请将下面的your-api-key-here替换为实际的API密钥
# 千问大模型API密钥
QWEN_API_KEY=your-qwen-api-key-here
# OpenAI API密钥可选
OPENAI_API_KEY=your-openai-api-key-here
# Anthropic API密钥可选
ANTHROPIC_API_KEY=your-anthropic-api-key-here
# Google API密钥可选
GOOGLE_API_KEY=your-google-api-key-here
# 百度API密钥可选
BAIDU_API_KEY=your-baidu-api-key-here
# 腾讯API密钥可选
TENCENT_API_KEY=your-tencent-api-key-here
# 其他配置
DEBUG=true
LOG_LEVEL=INFO
"""
with open(file_path, 'w', encoding='utf-8') as f:
f.write(env_content)
logger.info(f"环境变量文件已创建: {file_path}")
def get_status_report(self) -> Dict[str, Any]:
"""获取API密钥状态报告"""
available_providers = self.get_available_providers()
return {
"total_providers": 6,
"available_providers": len(available_providers),
"available_list": available_providers,
"unavailable_providers": [p for p in ['qwen', 'openai', 'anthropic', 'google', 'baidu', 'tencent']
if p not in available_providers],
"recommendations": self._get_recommendations()
}
def _get_recommendations(self) -> list:
"""获取配置建议"""
recommendations = []
if not self.is_available('qwen'):
recommendations.append("建议配置千问API密钥以获得最佳的中文AI分析体验")
if not self.is_available('openai'):
recommendations.append("可选配置OpenAI API密钥作为备用AI服务")
if not self.is_available('anthropic'):
recommendations.append("可选配置Anthropic API密钥作为备用AI服务")
return recommendations
# 全局API密钥管理器实例
_api_key_manager: Optional[APIKeyManager] = None
def get_api_key_manager() -> APIKeyManager:
"""获取全局API密钥管理器实例"""
global _api_key_manager
if _api_key_manager is None:
_api_key_manager = APIKeyManager()
return _api_key_manager
# 便捷函数
def get_qwen_key() -> Optional[str]:
"""获取千问API密钥"""
return get_api_key_manager().get_qwen_key()
def get_openai_key() -> Optional[str]:
"""获取OpenAI API密钥"""
return get_api_key_manager().get_openai_key()
def get_anthropic_key() -> Optional[str]:
"""获取Anthropic API密钥"""
return get_api_key_manager().get_anthropic_key()
def get_api_key(provider: str) -> Optional[str]:
"""根据提供商获取API密钥"""
return get_api_key_manager().get_key(provider)
def is_api_available(provider: str) -> bool:
"""检查指定提供商的API是否可用"""
return get_api_key_manager().is_available(provider)
def get_available_providers() -> list:
"""获取所有可用的API提供商"""
return get_api_key_manager().get_available_providers()
def create_env_template(file_path: str = ".env"):
"""创建环境变量文件模板"""
return get_api_key_manager().create_env_file(file_path)
def get_api_status_report() -> Dict[str, Any]:
"""获取API状态报告"""
return get_api_key_manager().get_status_report()
if __name__ == "__main__":
# 测试API密钥管理
print("=== API密钥管理测试 ===")
manager = get_api_key_manager()
# 显示状态报告
status = manager.get_status_report()
print(f"✅ 总提供商数量: {status['total_providers']}")
print(f"✅ 可用提供商数量: {status['available_providers']}")
print(f"✅ 可用提供商: {status['available_list']}")
print(f"✅ 不可用提供商: {status['unavailable_providers']}")
# 显示建议
if status['recommendations']:
print("\n💡 配置建议:")
for rec in status['recommendations']:
print(f" - {rec}")
# 创建环境变量文件模板
manager.create_env_file()
print("\n✅ API密钥管理测试完成")

View File

@@ -161,13 +161,16 @@ class UnifiedConfig:
if os.getenv('DATABASE_PATH'):
self.database.database_path = os.getenv('DATABASE_PATH')
# API配置
self.api.qwen_api_key = os.getenv('QWEN_API_KEY')
# API配置 - 使用统一API密钥管理
from config.api_keys import get_api_key_manager
api_manager = get_api_key_manager()
self.api.qwen_api_key = api_manager.get_qwen_key()
self.api.qwen_base_url = os.getenv('QWEN_BASE_URL', self.api.qwen_base_url)
self.api.qwen_model = os.getenv('QWEN_MODEL', self.api.qwen_model)
self.api.openai_api_key = os.getenv('OPENAI_API_KEY')
self.api.anthropic_api_key = os.getenv('ANTHROPIC_API_KEY')
self.api.openai_api_key = api_manager.get_openai_key()
self.api.anthropic_api_key = api_manager.get_anthropic_key()
# 应用配置
if os.getenv('DEBUG'):