update
This commit is contained in:
parent
c73341b950
commit
bf9b02c0b1
152
PM2_DEPLOYMENT_GUIDE.md
Normal file
152
PM2_DEPLOYMENT_GUIDE.md
Normal 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值)
|
||||||
@ -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"
|
||||||
|
|
||||||
|
|||||||
@ -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
82
diagnose_api_key.py
Normal 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
19
ecosystem.config.js
Normal 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
|
||||||
|
}]
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user