feat: 统一API密钥管理 - 将所有API密钥集中到config/api_keys.py进行统一管理,提供更安全便捷的密钥管理方式
This commit is contained in:
238
API_KEY_SETUP_GUIDE.md
Normal file
238
API_KEY_SETUP_GUIDE.md
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
# API密钥配置指南
|
||||||
|
|
||||||
|
## 📋 概述
|
||||||
|
|
||||||
|
本项目已将所有API密钥统一管理到 `config/api_keys.py` 文件中,提供更安全、更便捷的密钥管理方式。
|
||||||
|
|
||||||
|
## 🔧 配置步骤
|
||||||
|
|
||||||
|
### 1. 创建环境变量文件
|
||||||
|
|
||||||
|
在项目根目录创建 `.env` 文件:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 复制模板文件
|
||||||
|
cp .env.template .env
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 配置API密钥
|
||||||
|
|
||||||
|
编辑 `.env` 文件,填入您的API密钥:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# 千问大模型API密钥 (必需)
|
||||||
|
QWEN_API_KEY=sk-your-actual-qwen-api-key-here
|
||||||
|
|
||||||
|
# OpenAI API密钥 (可选)
|
||||||
|
OPENAI_API_KEY=sk-your-actual-openai-api-key-here
|
||||||
|
|
||||||
|
# Anthropic API密钥 (可选)
|
||||||
|
ANTHROPIC_API_KEY=sk-ant-your-actual-anthropic-api-key-here
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 验证配置
|
||||||
|
|
||||||
|
运行以下命令验证API密钥配置:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -c "from config.api_keys import get_api_status_report; print(get_api_status_report())"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🏗️ 架构说明
|
||||||
|
|
||||||
|
### 统一API密钥管理
|
||||||
|
|
||||||
|
- **文件位置**: `config/api_keys.py`
|
||||||
|
- **管理类**: `APIKeyManager`
|
||||||
|
- **全局实例**: 通过 `get_api_key_manager()` 获取
|
||||||
|
|
||||||
|
### 支持的API提供商
|
||||||
|
|
||||||
|
| 提供商 | 环境变量 | 必需性 | 用途 |
|
||||||
|
|--------|----------|--------|------|
|
||||||
|
| 千问 | `QWEN_API_KEY` | ✅ 必需 | 主要AI分析服务 |
|
||||||
|
| OpenAI | `OPENAI_API_KEY` | ⚪ 可选 | 备用AI服务 |
|
||||||
|
| Anthropic | `ANTHROPIC_API_KEY` | ⚪ 可选 | 备用AI服务 |
|
||||||
|
| Google | `GOOGLE_API_KEY` | ⚪ 可选 | 扩展服务 |
|
||||||
|
| 百度 | `BAIDU_API_KEY` | ⚪ 可选 | 扩展服务 |
|
||||||
|
| 腾讯 | `TENCENT_API_KEY` | ⚪ 可选 | 扩展服务 |
|
||||||
|
|
||||||
|
## 🔒 安全特性
|
||||||
|
|
||||||
|
### 1. 密钥验证
|
||||||
|
- 自动验证API密钥格式
|
||||||
|
- 检查密钥是否为空或无效
|
||||||
|
- 提供详细的验证报告
|
||||||
|
|
||||||
|
### 2. 环境隔离
|
||||||
|
- 所有密钥存储在环境变量中
|
||||||
|
- `.env` 文件被 `.gitignore` 忽略
|
||||||
|
- 不会意外提交到版本控制
|
||||||
|
|
||||||
|
### 3. 运行时管理
|
||||||
|
- 支持运行时动态设置密钥
|
||||||
|
- 提供密钥状态监控
|
||||||
|
- 支持多提供商切换
|
||||||
|
|
||||||
|
## 📚 使用方法
|
||||||
|
|
||||||
|
### 基本用法
|
||||||
|
|
||||||
|
```python
|
||||||
|
from config.api_keys import get_qwen_key, get_openai_key
|
||||||
|
|
||||||
|
# 获取千问API密钥
|
||||||
|
qwen_key = get_qwen_key()
|
||||||
|
if qwen_key:
|
||||||
|
print("千问API密钥已配置")
|
||||||
|
else:
|
||||||
|
print("千问API密钥未配置")
|
||||||
|
|
||||||
|
# 获取OpenAI API密钥
|
||||||
|
openai_key = get_openai_key()
|
||||||
|
```
|
||||||
|
|
||||||
|
### 高级用法
|
||||||
|
|
||||||
|
```python
|
||||||
|
from config.api_keys import get_api_key_manager
|
||||||
|
|
||||||
|
# 获取管理器实例
|
||||||
|
manager = get_api_key_manager()
|
||||||
|
|
||||||
|
# 检查提供商可用性
|
||||||
|
if manager.is_available('qwen'):
|
||||||
|
print("千问服务可用")
|
||||||
|
|
||||||
|
# 获取所有可用提供商
|
||||||
|
available = manager.get_available_providers()
|
||||||
|
print(f"可用提供商: {available}")
|
||||||
|
|
||||||
|
# 获取状态报告
|
||||||
|
status = manager.get_status_report()
|
||||||
|
print(f"配置状态: {status}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 动态设置密钥
|
||||||
|
|
||||||
|
```python
|
||||||
|
from config.api_keys import get_api_key_manager
|
||||||
|
|
||||||
|
manager = get_api_key_manager()
|
||||||
|
|
||||||
|
# 运行时设置API密钥
|
||||||
|
manager.set_key('qwen', 'sk-your-new-api-key')
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ 开发工具
|
||||||
|
|
||||||
|
### 创建环境变量模板
|
||||||
|
|
||||||
|
```python
|
||||||
|
from config.api_keys import create_env_template
|
||||||
|
|
||||||
|
# 创建 .env 文件模板
|
||||||
|
create_env_template()
|
||||||
|
```
|
||||||
|
|
||||||
|
### 获取配置建议
|
||||||
|
|
||||||
|
```python
|
||||||
|
from config.api_keys import get_api_status_report
|
||||||
|
|
||||||
|
status = get_api_status_report()
|
||||||
|
for recommendation in status['recommendations']:
|
||||||
|
print(f"💡 {recommendation}")
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 故障排除
|
||||||
|
|
||||||
|
### 常见问题
|
||||||
|
|
||||||
|
1. **API密钥未配置**
|
||||||
|
```
|
||||||
|
ValueError: 千问API密钥未配置,请在.env文件中设置QWEN_API_KEY
|
||||||
|
```
|
||||||
|
**解决方案**: 检查 `.env` 文件是否存在且包含正确的API密钥
|
||||||
|
|
||||||
|
2. **密钥格式错误**
|
||||||
|
```
|
||||||
|
⚠️ 千问API密钥格式可能不正确
|
||||||
|
```
|
||||||
|
**解决方案**: 确保API密钥以 `sk-` 开头(千问)或 `sk-ant-` 开头(Anthropic)
|
||||||
|
|
||||||
|
3. **环境变量未加载**
|
||||||
|
```
|
||||||
|
⚠️ 千问API密钥未配置
|
||||||
|
```
|
||||||
|
**解决方案**: 确保 `.env` 文件在项目根目录,且格式正确
|
||||||
|
|
||||||
|
### 调试命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 检查环境变量
|
||||||
|
python -c "import os; print('QWEN_API_KEY:', os.getenv('QWEN_API_KEY', 'Not set'))"
|
||||||
|
|
||||||
|
# 测试API密钥管理
|
||||||
|
python config/api_keys.py
|
||||||
|
|
||||||
|
# 验证配置
|
||||||
|
python -c "from config.api_keys import get_api_status_report; import json; print(json.dumps(get_api_status_report(), indent=2, ensure_ascii=False))"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📈 最佳实践
|
||||||
|
|
||||||
|
1. **密钥安全**
|
||||||
|
- 永远不要将API密钥硬编码在代码中
|
||||||
|
- 使用环境变量或配置文件
|
||||||
|
- 定期轮换API密钥
|
||||||
|
|
||||||
|
2. **错误处理**
|
||||||
|
- 始终检查API密钥是否可用
|
||||||
|
- 提供友好的错误提示
|
||||||
|
- 实现降级策略
|
||||||
|
|
||||||
|
3. **配置管理**
|
||||||
|
- 使用统一的配置管理
|
||||||
|
- 提供配置验证
|
||||||
|
- 支持多环境配置
|
||||||
|
|
||||||
|
## 🔄 迁移指南
|
||||||
|
|
||||||
|
如果您之前在其他文件中硬编码了API密钥,请按以下步骤迁移:
|
||||||
|
|
||||||
|
1. **移除硬编码密钥**
|
||||||
|
```python
|
||||||
|
# 旧方式 ❌
|
||||||
|
api_key = "sk-hardcoded-key"
|
||||||
|
|
||||||
|
# 新方式 ✅
|
||||||
|
from config.api_keys import get_qwen_key
|
||||||
|
api_key = get_qwen_key()
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **更新导入语句**
|
||||||
|
```python
|
||||||
|
# 添加统一导入
|
||||||
|
from config.api_keys import get_qwen_key, get_openai_key, get_anthropic_key
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **添加错误处理**
|
||||||
|
```python
|
||||||
|
api_key = get_qwen_key()
|
||||||
|
if not api_key:
|
||||||
|
raise ValueError("千问API密钥未配置")
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📞 支持
|
||||||
|
|
||||||
|
如果您在配置API密钥时遇到问题,请:
|
||||||
|
|
||||||
|
1. 检查本指南的故障排除部分
|
||||||
|
2. 运行调试命令验证配置
|
||||||
|
3. 查看项目日志获取详细错误信息
|
||||||
|
4. 提交Issue描述具体问题
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**注意**: 请妥善保管您的API密钥,不要分享给他人或提交到公开仓库。
|
||||||
52
README.md
52
README.md
@@ -121,8 +121,8 @@ diet_recommendation_app/
|
|||||||
### 2. 安装依赖
|
### 2. 安装依赖
|
||||||
```bash
|
```bash
|
||||||
# 克隆项目
|
# 克隆项目
|
||||||
git clone <repository-url>
|
git clone https://github.com/random-jason/diet_recommendation.git
|
||||||
cd diet_recommendation_app
|
cd diet_recommendation
|
||||||
|
|
||||||
# 安装基础依赖
|
# 安装基础依赖
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
@@ -131,7 +131,22 @@ pip install -r requirements.txt
|
|||||||
pip install pytesseract opencv-python paddleocr easyocr
|
pip install pytesseract opencv-python paddleocr easyocr
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. OCR引擎配置(可选)
|
### 3. 配置API密钥
|
||||||
|
```bash
|
||||||
|
# 方法1: 使用自动生成的模板
|
||||||
|
python -c "from config.api_keys import create_env_template; create_env_template()"
|
||||||
|
|
||||||
|
# 方法2: 手动创建.env文件
|
||||||
|
echo "QWEN_API_KEY=your_qwen_api_key_here" > .env
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 验证配置
|
||||||
|
```bash
|
||||||
|
# 检查API密钥配置状态
|
||||||
|
python -c "from config.api_keys import get_api_status_report; print(get_api_status_report())"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. OCR引擎配置(可选)
|
||||||
|
|
||||||
#### Tesseract安装
|
#### Tesseract安装
|
||||||
- **Windows**: 下载 [Tesseract安装包](https://github.com/UB-Mannheim/tesseract/wiki)
|
- **Windows**: 下载 [Tesseract安装包](https://github.com/UB-Mannheim/tesseract/wiki)
|
||||||
@@ -166,6 +181,37 @@ python main.py
|
|||||||
5. 查看和编辑识别结果
|
5. 查看和编辑识别结果
|
||||||
6. 确认保存到餐食记录
|
6. 确认保存到餐食记录
|
||||||
|
|
||||||
|
## 🔐 API密钥管理
|
||||||
|
|
||||||
|
### 统一密钥管理
|
||||||
|
项目采用统一的API密钥管理系统,所有API密钥都通过 `config/api_keys.py` 进行管理:
|
||||||
|
|
||||||
|
- **千问API密钥** (必需): 用于主要AI分析服务
|
||||||
|
- **OpenAI API密钥** (可选): 备用AI服务
|
||||||
|
- **Anthropic API密钥** (可选): 备用AI服务
|
||||||
|
- **其他API密钥** (可选): Google、百度、腾讯等
|
||||||
|
|
||||||
|
### 配置方法
|
||||||
|
```python
|
||||||
|
from config.api_keys import get_qwen_key, get_api_status_report
|
||||||
|
|
||||||
|
# 获取API密钥
|
||||||
|
qwen_key = get_qwen_key()
|
||||||
|
|
||||||
|
# 检查配置状态
|
||||||
|
status = get_api_status_report()
|
||||||
|
print(f"可用提供商: {status['available_list']}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 安全特性
|
||||||
|
- ✅ 环境变量隔离
|
||||||
|
- ✅ 密钥格式验证
|
||||||
|
- ✅ 运行时状态监控
|
||||||
|
- ✅ 多提供商支持
|
||||||
|
- ✅ 自动配置建议
|
||||||
|
|
||||||
|
详细配置指南请参考:[API_KEY_SETUP_GUIDE.md](API_KEY_SETUP_GUIDE.md)
|
||||||
|
|
||||||
## 🔄 工作流程
|
## 🔄 工作流程
|
||||||
|
|
||||||
### 1. 智能数据采集(5天)
|
### 1. 智能数据采集(5天)
|
||||||
|
|||||||
318
config/api_keys.py
Normal file
318
config/api_keys.py
Normal 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密钥管理测试完成")
|
||||||
@@ -161,13 +161,16 @@ class UnifiedConfig:
|
|||||||
if os.getenv('DATABASE_PATH'):
|
if os.getenv('DATABASE_PATH'):
|
||||||
self.database.database_path = os.getenv('DATABASE_PATH')
|
self.database.database_path = os.getenv('DATABASE_PATH')
|
||||||
|
|
||||||
# API配置
|
# API配置 - 使用统一API密钥管理
|
||||||
self.api.qwen_api_key = os.getenv('QWEN_API_KEY')
|
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_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.qwen_model = os.getenv('QWEN_MODEL', self.api.qwen_model)
|
||||||
|
|
||||||
self.api.openai_api_key = os.getenv('OPENAI_API_KEY')
|
self.api.openai_api_key = api_manager.get_openai_key()
|
||||||
self.api.anthropic_api_key = os.getenv('ANTHROPIC_API_KEY')
|
self.api.anthropic_api_key = api_manager.get_anthropic_key()
|
||||||
|
|
||||||
# 应用配置
|
# 应用配置
|
||||||
if os.getenv('DEBUG'):
|
if os.getenv('DEBUG'):
|
||||||
|
|||||||
@@ -479,8 +479,20 @@ class AIAnalyzer(BaseEngine):
|
|||||||
import openai
|
import openai
|
||||||
import anthropic
|
import anthropic
|
||||||
|
|
||||||
self.openai_client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
|
from config.api_keys import get_openai_key, get_anthropic_key
|
||||||
self.anthropic_client = anthropic.Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
|
|
||||||
|
openai_key = get_openai_key()
|
||||||
|
anthropic_key = get_anthropic_key()
|
||||||
|
|
||||||
|
if openai_key:
|
||||||
|
self.openai_client = openai.OpenAI(api_key=openai_key)
|
||||||
|
else:
|
||||||
|
self.logger.warning("OpenAI API密钥未配置")
|
||||||
|
|
||||||
|
if anthropic_key:
|
||||||
|
self.anthropic_client = anthropic.Anthropic(api_key=anthropic_key)
|
||||||
|
else:
|
||||||
|
self.logger.warning("Anthropic API密钥未配置")
|
||||||
|
|
||||||
self._initialized = True
|
self._initialized = True
|
||||||
self.logger.info("AI分析器初始化成功")
|
self.logger.info("AI分析器初始化成功")
|
||||||
|
|||||||
@@ -519,10 +519,15 @@ class QwenLLMClient:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# 千问配置 - 从环境变量获取
|
# 千问配置 - 使用统一API密钥管理
|
||||||
def get_qwen_config() -> LLMConfig:
|
def get_qwen_config() -> LLMConfig:
|
||||||
"""获取千问配置"""
|
"""获取千问配置"""
|
||||||
api_key = os.getenv('QWEN_API_KEY', 'sk-c0dbefa1718d46eaa897199135066f00')
|
from config.api_keys import get_qwen_key
|
||||||
|
|
||||||
|
api_key = get_qwen_key()
|
||||||
|
if not api_key:
|
||||||
|
raise ValueError("千问API密钥未配置,请在.env文件中设置QWEN_API_KEY")
|
||||||
|
|
||||||
base_url = os.getenv('QWEN_BASE_URL', 'https://dashscope.aliyuncs.com/compatible-mode/v1')
|
base_url = os.getenv('QWEN_BASE_URL', 'https://dashscope.aliyuncs.com/compatible-mode/v1')
|
||||||
model = os.getenv('QWEN_MODEL', 'qwen-plus-latest')
|
model = os.getenv('QWEN_MODEL', 'qwen-plus-latest')
|
||||||
|
|
||||||
|
|||||||
16
main.py
16
main.py
@@ -48,19 +48,9 @@ class DietRecommendationApp:
|
|||||||
"""加载配置"""
|
"""加载配置"""
|
||||||
config = BaseConfig()
|
config = BaseConfig()
|
||||||
|
|
||||||
# 从环境变量加载API密钥
|
# 使用统一API密钥管理
|
||||||
config.qwen_api_key = os.getenv('QWEN_API_KEY')
|
from config.api_keys import get_qwen_key
|
||||||
|
config.qwen_api_key = get_qwen_key()
|
||||||
# 从.env文件加载配置
|
|
||||||
env_file = Path('.env')
|
|
||||||
if env_file.exists():
|
|
||||||
try:
|
|
||||||
from dotenv import load_dotenv
|
|
||||||
load_dotenv()
|
|
||||||
config.qwen_api_key = os.getenv('QWEN_API_KEY')
|
|
||||||
except Exception:
|
|
||||||
# 如果.env文件有编码问题,跳过加载
|
|
||||||
pass
|
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user