Files
recommend/config/api_keys.py

319 lines
10 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
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密钥管理测试完成")