This commit is contained in:
aaron 2026-02-03 10:27:04 +08:00
parent c73341b950
commit bf9b02c0b1
5 changed files with 283 additions and 2 deletions

152
PM2_DEPLOYMENT_GUIDE.md Normal file
View File

@ -0,0 +1,152 @@
# PM2部署问题排查指南
## 问题描述
使用PM2部署时出现错误
```
LLM调用失败: Exception: ('invalid api_key', ValueError('not enough values to unpack (expected 2, got 1)'))
```
## 原因分析
智谱AI的API Key格式要求包含`.`分隔符(例如:`xxxxx.yyyyyyy`),如果格式不正确或环境变量未正确加载,会导致此错误。
## 解决方案
### 方案1使用PM2配置文件推荐
1. 使用项目根目录的 `ecosystem.config.js` 配置文件:
```bash
cd /path/to/Stock_Agent
pm2 start ecosystem.config.js
```
2. 如果需要修改路径,编辑 `ecosystem.config.js`
```javascript
module.exports = {
apps: [{
name: 'stock-agent',
script: 'backend/app/main.py',
interpreter: 'python3',
cwd: '/your/project/path/Stock_Agent', // 修改为你的实际路径
env: {
ENV_FILE: '/your/project/path/Stock_Agent/.env' // 修改为你的实际路径
}
}]
};
```
### 方案2直接指定环境变量
```bash
cd /path/to/Stock_Agent
pm2 start backend/app/main.py \
--name stock-agent \
--interpreter python3 \
--env ENV_FILE=/path/to/Stock_Agent/.env
```
### 方案3在PM2中设置环境变量
```bash
pm2 start backend/app/main.py --name stock-agent --interpreter python3
pm2 env stock-agent ENV_FILE /path/to/Stock_Agent/.env
pm2 restart stock-agent
```
## 诊断步骤
### 1. 运行诊断脚本
```bash
cd /path/to/Stock_Agent
python3 diagnose_api_key.py
```
这个脚本会检查:
- .env文件是否存在
- API Key是否正确加载
- API Key格式是否正确
- 智谱AI客户端是否能初始化
### 2. 检查.env文件
确保 `.env` 文件存在且格式正确:
```bash
cat .env
```
应该看到类似内容:
```
ZHIPUAI_API_KEY=xxxxx.yyyyyyy
TUSHARE_TOKEN=your_token_here
```
### 3. 验证API Key格式
智谱AI的API Key应该
- 包含 `.` 分隔符
- 格式类似:`415e176f8b964f98a6b4e44b24171145.AVe4qY6RSbxBolhI`
- 长度通常在40-60个字符
### 4. 检查PM2日志
```bash
pm2 logs stock-agent
```
查看启动日志中的配置加载信息:
- `[Config] 找到.env文件: /path/to/.env` - 表示找到了配置文件
- `正在初始化智谱AI客户端` - 表示开始初始化
- `智谱AI LLM服务初始化成功` - 表示初始化成功
## 常见问题
### Q1: API Key格式错误
**症状**: 错误信息包含 `not enough values to unpack`
**解决**:
1. 检查API Key是否包含 `.` 分隔符
2. 确认从智谱AI官网复制的完整Key
3. 检查是否有多余的空格或换行符
### Q2: 环境变量未加载
**症状**: 日志显示 `智谱AI API Key未配置`
**解决**:
1. 使用 `ecosystem.config.js` 配置文件
2. 确保 `cwd``ENV_FILE` 路径正确
3. 重启PM2进程
### Q3: .env文件路径问题
**症状**: 日志显示 `警告:未找到.env文件`
**解决**:
1. 确认.env文件在项目根目录
2. 使用绝对路径指定ENV_FILE
3. 检查文件权限
## 验证修复
修复后,运行以下命令验证:
```bash
# 1. 重启PM2进程
pm2 restart stock-agent
# 2. 查看日志
pm2 logs stock-agent --lines 50
# 3. 应该看到成功信息
# [Config] 找到.env文件: ...
# 正在初始化智谱AI客户端API Key前10位: 415e176f8b...
# 智谱AI LLM服务初始化成功
```
## 联系支持
如果问题仍未解决,请提供以下信息:
1. 诊断脚本输出
2. PM2日志隐藏敏感信息
3. .env文件格式隐藏实际Key值

View File

@ -17,19 +17,30 @@ def find_env_file():
# 尝试当前目录 # 尝试当前目录
env_path = current_dir / ".env" env_path = current_dir / ".env"
if env_path.exists(): if env_path.exists():
print(f"[Config] 找到.env文件: {env_path}")
return str(env_path) return str(env_path)
# 尝试父目录(项目根目录) # 尝试父目录(项目根目录)
env_path = current_dir.parent / ".env" env_path = current_dir.parent / ".env"
if env_path.exists(): if env_path.exists():
print(f"[Config] 找到.env文件: {env_path}")
return str(env_path) return str(env_path)
# 尝试backend的父目录 # 尝试backend的父目录
if current_dir.name == "backend": if current_dir.name == "backend":
env_path = current_dir.parent / ".env" env_path = current_dir.parent / ".env"
if env_path.exists(): if env_path.exists():
print(f"[Config] 找到.env文件: {env_path}")
return str(env_path) return str(env_path)
# 尝试从环境变量指定的路径
if os.getenv('ENV_FILE'):
env_path = Path(os.getenv('ENV_FILE'))
if env_path.exists():
print(f"[Config] 从ENV_FILE环境变量找到.env文件: {env_path}")
return str(env_path)
print(f"[Config] 警告:未找到.env文件当前目录: {current_dir}")
# 默认返回当前目录的.env # 默认返回当前目录的.env
return ".env" return ".env"

View File

@ -30,11 +30,28 @@ class LLMService:
self.client = None self.client = None
return return
# 验证API Key格式
api_key = settings.zhipuai_api_key.strip()
if not api_key or len(api_key) < 10:
logger.error(f"智谱AI API Key格式无效长度: {len(api_key)}")
self.client = None
return
# 检查API Key是否包含必要的分隔符
if '.' not in api_key:
logger.error("智谱AI API Key格式无效缺少'.'分隔符")
logger.error(f"当前API Key前10个字符: {api_key[:10]}...")
self.client = None
return
try: try:
self.client = ZhipuAI(api_key=settings.zhipuai_api_key) logger.info(f"正在初始化智谱AI客户端API Key前10位: {api_key[:10]}...")
self.client = ZhipuAI(api_key=api_key)
logger.info("智谱AI LLM服务初始化成功") logger.info("智谱AI LLM服务初始化成功")
except Exception as e: except Exception as e:
logger.error(f"智谱AI初始化失败: {e}") logger.error(f"智谱AI初始化失败: {type(e).__name__}: {e}")
import traceback
logger.error(f"详细错误: {traceback.format_exc()}")
self.client = None self.client = None
def chat( def chat(

82
diagnose_api_key.py Normal file
View File

@ -0,0 +1,82 @@
#!/usr/bin/env python3
"""
诊断脚本检查智谱AI API Key配置
"""
import os
import sys
from pathlib import Path
# 添加项目路径
sys.path.insert(0, str(Path(__file__).parent / 'backend'))
from app.config import get_settings
def main():
print("=" * 60)
print("智谱AI API Key 诊断")
print("=" * 60)
# 检查当前工作目录
print(f"\n当前工作目录: {Path.cwd()}")
# 检查.env文件
env_files = [
Path.cwd() / ".env",
Path.cwd().parent / ".env",
Path(__file__).parent / ".env"
]
print("\n检查.env文件:")
for env_file in env_files:
if env_file.exists():
print(f" ✓ 找到: {env_file}")
else:
print(f" ✗ 不存在: {env_file}")
# 加载配置
print("\n加载配置...")
try:
settings = get_settings()
print(" ✓ 配置加载成功")
except Exception as e:
print(f" ✗ 配置加载失败: {e}")
return
# 检查API Key
print("\nAPI Key 检查:")
api_key = settings.zhipuai_api_key
if not api_key:
print(" ✗ API Key 为空")
return
print(f" ✓ API Key 已设置")
print(f" - 长度: {len(api_key)}")
print(f" - 前10位: {api_key[:10]}...")
print(f" - 后10位: ...{api_key[-10:]}")
# 检查格式
if '.' in api_key:
parts = api_key.split('.')
print(f" ✓ 包含'.'分隔符,分为{len(parts)}部分")
for i, part in enumerate(parts):
print(f" 部分{i+1}: {len(part)}字符")
else:
print(" ✗ 缺少'.'分隔符智谱AI Key应该包含'.'")
# 尝试初始化客户端
print("\n尝试初始化智谱AI客户端...")
try:
from zhipuai import ZhipuAI
client = ZhipuAI(api_key=api_key)
print(" ✓ 客户端初始化成功")
except Exception as e:
print(f" ✗ 客户端初始化失败: {type(e).__name__}: {e}")
import traceback
print("\n详细错误:")
print(traceback.format_exc())
print("\n" + "=" * 60)
if __name__ == "__main__":
main()

19
ecosystem.config.js Normal file
View File

@ -0,0 +1,19 @@
module.exports = {
apps: [{
name: 'stock-agent',
script: 'backend/app/main.py',
interpreter: 'python3',
cwd: '/Users/aaron/source_code/Stock_Agent',
env: {
ENV_FILE: '/Users/aaron/source_code/Stock_Agent/.env'
},
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '1G',
error_file: './logs/err.log',
out_file: './logs/out.log',
log_file: './logs/combined.log',
time: true
}]
};