319 lines
10 KiB
Python
319 lines
10 KiB
Python
"""
|
||
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密钥管理测试完成")
|