Fix router failover and add Discord bot
- Remove duplicate claude_api provider to fix automatic failover - Enhance error detection with HTTP status codes and more indicators - Add comprehensive README documentation with manual switching - Implement Discord bot with Claude Code CLI integration - Support /terminal and /claude commands with AI-powered responses 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
438
router/README.md
438
router/README.md
@@ -1,238 +1,314 @@
|
||||
# Claude Router
|
||||
# Claude API Router
|
||||
|
||||
一个智能的Claude API路由器,支持Claude Pro和Claude API之间的自动故障转移。当Claude Pro达到使用限制时,自动切换到Claude API,确保服务的连续性。
|
||||
智能的Claude API路由器,提供自动故障转移和负载均衡功能。当主要API服务遇到限制或错误时,自动切换到备用提供商。
|
||||
|
||||
## 功能特性
|
||||
## 🚀 功能特性
|
||||
|
||||
- **自动故障转移**: 检测到速率限制或使用限制时自动切换provider
|
||||
- **定时健康检查**: 每小时前5分钟自动检测Claude Pro限额恢复
|
||||
- **智能恢复**: 自动切换回Claude Pro,优先使用高级功能
|
||||
- **手动切换**: 支持手动切换到指定provider
|
||||
- **兼容Claude Code CLI**: 完全兼容Anthropic API格式
|
||||
- **Docker化部署**: 一键部署,开箱即用
|
||||
- **自动故障转移**: 检测到速率限制或错误时自动切换API提供商
|
||||
- **多提供商支持**: 支持Claude Pro、DeepSeek、Kimi
|
||||
- **手动切换**: 支持手动强制切换到指定提供商
|
||||
- **健康检查**: 自动监控和恢复主要提供商
|
||||
- **完全兼容**: 与Anthropic Claude API完全兼容
|
||||
- **流式响应**: 支持流式和非流式响应
|
||||
|
||||
## 快速开始
|
||||
## 📋 支持的提供商
|
||||
|
||||
### 1. 使用Docker Compose部署
|
||||
按优先级排序:
|
||||
|
||||
1. **Claude Pro** - 最高优先级,首选提供商
|
||||
2. **DeepSeek** - OpenAI兼容的备用提供商
|
||||
3. **Kimi** - OpenAI兼容的备用提供商
|
||||
|
||||
## 🛠️ 安装和配置
|
||||
|
||||
### 1. 环境要求
|
||||
|
||||
```bash
|
||||
# 克隆或进入项目目录
|
||||
cd /home/will/docker/router
|
||||
cd router
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
# 构建并启动服务
|
||||
### 2. 配置API密钥
|
||||
|
||||
在 `/home/will/docker/tokens.txt` 文件中添加以下令牌:
|
||||
|
||||
```txt
|
||||
claude_api_key=your_claude_api_key_here
|
||||
deepseek_api_key=your_deepseek_api_key_here
|
||||
kimi_api_key=your_kimi_api_key_here
|
||||
```
|
||||
|
||||
或者设置环境变量:
|
||||
|
||||
```bash
|
||||
export CLAUDE_API_KEY="your_claude_api_key"
|
||||
export DEEPSEEK_API_KEY="your_deepseek_api_key"
|
||||
export KIMI_API_KEY="your_kimi_api_key"
|
||||
```
|
||||
|
||||
### 3. 启动服务
|
||||
|
||||
```bash
|
||||
# 开发模式
|
||||
python app.py
|
||||
|
||||
# 生产模式 (使用Docker Compose)
|
||||
docker-compose up -d
|
||||
|
||||
# 查看服务状态
|
||||
docker-compose ps
|
||||
```
|
||||
|
||||
### 2. 验证服务运行
|
||||
服务将在 `http://localhost:8000` 启动。
|
||||
|
||||
```bash
|
||||
# 健康检查
|
||||
curl http://localhost:8000/health
|
||||
## 🔧 手动切换提供商
|
||||
|
||||
# 查看当前状态
|
||||
curl http://localhost:8000/v1/status
|
||||
```
|
||||
### API端点
|
||||
|
||||
### 3. 配置Claude Code CLI
|
||||
```http
|
||||
POST /v1/switch-provider
|
||||
Content-Type: application/json
|
||||
|
||||
设置环境变量将Claude Code CLI指向路由器:
|
||||
|
||||
```bash
|
||||
# 设置API endpoint为路由器地址
|
||||
export ANTHROPIC_API_URL="http://localhost:8000"
|
||||
|
||||
# 添加到bashrc使其永久生效
|
||||
echo 'export ANTHROPIC_API_URL="http://localhost:8000"' >> ~/.bashrc
|
||||
|
||||
# 测试配置
|
||||
echo "Hello Claude Router" | claude --print
|
||||
```
|
||||
|
||||
**注意**: 无需修改ANTHROPIC_API_KEY,路由器会自动处理API密钥。
|
||||
|
||||
## API端点
|
||||
|
||||
### 主要端点
|
||||
|
||||
- `POST /v1/messages` - Claude API消息创建(兼容Anthropic API)
|
||||
- `GET /health` - 健康检查
|
||||
- `GET /v1/status` - 获取路由器状态
|
||||
- `POST /v1/switch-provider` - 手动切换provider
|
||||
- `POST /v1/health-check` - 手动触发Claude Pro健康检查
|
||||
|
||||
### 健康检查响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"current_provider": "claude_pro",
|
||||
"failover_count": 0,
|
||||
"last_failover": null,
|
||||
"last_health_check": "2025-07-14T19:00:00.000Z",
|
||||
"health_check_failures": 0,
|
||||
"providers": {
|
||||
"claude_pro": {"active": true},
|
||||
"claude_api": {"active": true}
|
||||
}
|
||||
"provider": "provider_name"
|
||||
}
|
||||
```
|
||||
|
||||
## 配置说明
|
||||
### 可用的提供商名称
|
||||
|
||||
### 环境变量
|
||||
- `claude_pro` - Claude Pro提供商 (默认)
|
||||
- `deepseek` - DeepSeek提供商
|
||||
- `kimi` - Kimi提供商
|
||||
|
||||
- `CLAUDE_API_KEY`: Claude API密钥
|
||||
- `ROUTER_HOST`: 服务监听地址(默认: 0.0.0.0)
|
||||
- `ROUTER_PORT`: 服务监听端口(默认: 8000)
|
||||
- `MAX_RETRIES`: 最大重试次数(默认: 3)
|
||||
- `RETRY_DELAY`: 重试延迟(默认: 1.0秒)
|
||||
### 使用示例
|
||||
|
||||
### 健康检查配置
|
||||
|
||||
- `health_check_enabled`: 是否启用定时健康检查(默认: true)
|
||||
- `health_check_cron`: 检查时间表达式(默认: "0-4 * * * *" - 每小时前5分钟)
|
||||
- `health_check_message`: 测试消息内容(默认: "ping")
|
||||
- `health_check_model`: 使用的模型(默认: claude-3-haiku-20240307)
|
||||
|
||||
### Token文件
|
||||
|
||||
路由器会自动从 `/home/will/docker/tokens.txt` 读取API密钥,无需手动配置环境变量。
|
||||
|
||||
## 故障转移机制
|
||||
|
||||
当检测到以下错误时,路由器会自动切换到下一个可用的provider:
|
||||
|
||||
- 429 (Too Many Requests)
|
||||
- 速率限制错误
|
||||
- 使用限制达到
|
||||
- "usage limit reached"相关错误
|
||||
|
||||
**优先级顺序**: Claude Pro → Claude API
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 基本API调用
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/v1/messages \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer your_api_key" \
|
||||
-d '{
|
||||
"model": "claude-3-sonnet-20240229",
|
||||
"max_tokens": 1024,
|
||||
"messages": [
|
||||
{"role": "user", "content": "Hello, Claude!"}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
### 手动切换provider
|
||||
#### curl命令
|
||||
|
||||
```bash
|
||||
# 切换到DeepSeek
|
||||
curl -X POST http://localhost:8000/v1/switch-provider \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '"claude_api"'
|
||||
-d '{"provider": "deepseek"}'
|
||||
|
||||
# 切换到Kimi
|
||||
curl -X POST http://localhost:8000/v1/switch-provider \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"provider": "kimi"}'
|
||||
|
||||
# 切换回Claude Pro
|
||||
curl -X POST http://localhost:8000/v1/switch-provider \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"provider": "claude_pro"}'
|
||||
```
|
||||
|
||||
### 手动健康检查
|
||||
#### Python脚本
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
def switch_provider(provider_name):
|
||||
"""切换API提供商"""
|
||||
url = "http://localhost:8000/v1/switch-provider"
|
||||
data = {"provider": provider_name}
|
||||
|
||||
response = requests.post(url, json=data)
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
print(f"成功切换到: {result['current_provider']}")
|
||||
return True
|
||||
else:
|
||||
print(f"切换失败: {response.text}")
|
||||
return False
|
||||
|
||||
# 使用示例
|
||||
switch_provider("deepseek")
|
||||
switch_provider("kimi")
|
||||
switch_provider("claude_pro")
|
||||
```
|
||||
|
||||
### 查看当前状态
|
||||
|
||||
```bash
|
||||
# 立即检测Claude Pro是否可用
|
||||
curl -X POST http://localhost:8000/v1/health-check
|
||||
# 查看当前使用的提供商
|
||||
curl http://localhost:8000/v1/health
|
||||
|
||||
# 查看详细状态
|
||||
curl http://localhost:8000/v1/status
|
||||
# 响应示例
|
||||
{
|
||||
"status": "healthy",
|
||||
"current_provider": "claude_pro",
|
||||
"providers": {
|
||||
"claude_pro": "available",
|
||||
"deepseek": "unknown",
|
||||
"kimi": "unknown"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 开发和调试
|
||||
## 🔄 自动故障转移
|
||||
|
||||
### 本地开发
|
||||
路由器会自动检测以下错误并进行故障转移:
|
||||
|
||||
```bash
|
||||
# 创建虚拟环境
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
- 速率限制 (Rate limit exceeded)
|
||||
- 使用配额超额 (Usage limit exceeded)
|
||||
- HTTP 429错误
|
||||
- 每日/月度限制达到
|
||||
- 网络连接错误
|
||||
|
||||
# 安装依赖
|
||||
pip install -r requirements.txt
|
||||
### 故障转移流程
|
||||
|
||||
# 运行应用
|
||||
python app.py
|
||||
1. 检测到故障转移触发条件
|
||||
2. 自动切换到下一个优先级提供商
|
||||
3. 重试请求
|
||||
4. 记录切换日志
|
||||
5. 定期尝试恢复到主要提供商
|
||||
|
||||
## 🩺 健康检查和自动恢复
|
||||
|
||||
- **自动检查频率**: 每小时的前5分钟
|
||||
- **检查内容**: 向Claude Pro发送测试请求
|
||||
- **自动恢复**: 如果Claude Pro恢复可用,自动切换回去
|
||||
|
||||
## 🔌 API兼容性
|
||||
|
||||
路由器完全兼容Anthropic Claude API,支持:
|
||||
|
||||
- 所有Claude模型 (claude-3-sonnet, claude-3-opus等)
|
||||
- 流式和非流式响应
|
||||
- 系统消息和用户消息
|
||||
- 所有API参数 (max_tokens, temperature等)
|
||||
|
||||
### 使用示例
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
# 标准Claude API调用
|
||||
url = "http://localhost:8000/v1/messages"
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"x-api-key": "your_claude_api_key"
|
||||
}
|
||||
data = {
|
||||
"model": "claude-3-sonnet-20240229",
|
||||
"max_tokens": 1000,
|
||||
"messages": [
|
||||
{"role": "user", "content": "Hello, Claude!"}
|
||||
]
|
||||
}
|
||||
|
||||
response = requests.post(url, headers=headers, json=data)
|
||||
print(response.json())
|
||||
```
|
||||
|
||||
### 查看日志
|
||||
|
||||
```bash
|
||||
# Docker容器日志
|
||||
docker-compose logs -f claude-router
|
||||
|
||||
# 实时日志
|
||||
docker logs -f claude-router
|
||||
```
|
||||
|
||||
## 故障排除
|
||||
## 🐛 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **服务无法启动**
|
||||
- 检查tokens.txt文件是否存在且格式正确
|
||||
- 确认端口8000未被占用
|
||||
#### 1. 自动切换不工作
|
||||
|
||||
2. **API调用失败**
|
||||
- 验证API密钥是否有效
|
||||
- 检查网络连接到api.anthropic.com
|
||||
**问题**: 遇到限制时不自动切换
|
||||
|
||||
3. **自动切换不工作**
|
||||
- 查看日志确认错误检测逻辑
|
||||
- 确认backup provider配置正确
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 手动切换到备用提供商
|
||||
curl -X POST http://localhost:8000/v1/switch-provider \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"provider": "deepseek"}'
|
||||
```
|
||||
|
||||
### 监控
|
||||
#### 2. API密钥错误
|
||||
|
||||
- 健康检查: `http://localhost:8000/health`
|
||||
- 状态监控: `http://localhost:8000/v1/status`
|
||||
- Docker健康检查: `docker inspect claude-router`
|
||||
**问题**: 提示API密钥无效
|
||||
|
||||
## 技术架构
|
||||
**解决方案**:
|
||||
1. 检查 `tokens.txt` 文件中的密钥格式
|
||||
2. 确保密钥没有多余的空格或换行
|
||||
3. 验证密钥是否有效
|
||||
|
||||
- **框架**: FastAPI + Uvicorn
|
||||
- **HTTP客户端**: httpx
|
||||
- **AI库**: anthropic
|
||||
- **容器化**: Docker + Docker Compose
|
||||
- **配置管理**: pydantic + python-dotenv
|
||||
#### 3. 服务无法启动
|
||||
|
||||
## 版本信息
|
||||
**问题**: 路由器启动失败
|
||||
|
||||
- 版本: 1.0.0 (MVP)
|
||||
- Python: 3.11+
|
||||
- 支持: Claude-3 系列模型
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 检查日志
|
||||
docker-compose logs router
|
||||
|
||||
## 更新日志
|
||||
# 手动启动调试
|
||||
cd router
|
||||
python app.py
|
||||
```
|
||||
|
||||
### v1.1.0 (2025-07-14)
|
||||
- ✅ 添加定时健康检查功能
|
||||
- ✅ 每小时前5分钟自动检测Claude Pro限额恢复
|
||||
- ✅ 智能自动切换回Claude Pro
|
||||
- ✅ 新增手动健康检查API
|
||||
- ✅ 完善日志记录和状态监控
|
||||
### 调试模式
|
||||
|
||||
### v1.0.0 (2025-07-14)
|
||||
- ✅ 基础路由器功能
|
||||
- ✅ Claude Pro到Claude API自动故障转移
|
||||
- ✅ Docker容器化部署
|
||||
- ✅ Claude Code CLI兼容性
|
||||
启用详细日志:
|
||||
|
||||
## 后续开发计划
|
||||
```python
|
||||
import logging
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
```
|
||||
|
||||
- [ ] 添加DeepSeek API支持
|
||||
- [ ] 添加ChatGPT API支持
|
||||
- [ ] 实现请求统计和监控面板
|
||||
- [ ] 添加请求缓存功能
|
||||
- [ ] 支持负载均衡
|
||||
- [ ] 集成Kimi v2 API
|
||||
## 📊 监控和日志
|
||||
|
||||
## 许可证
|
||||
### 日志级别
|
||||
|
||||
MIT License
|
||||
- `INFO`: 正常操作日志
|
||||
- `WARNING`: 提供商切换警告
|
||||
- `ERROR`: 错误和故障转移事件
|
||||
|
||||
### 关键日志信息
|
||||
|
||||
- 提供商切换事件
|
||||
- API请求失败
|
||||
- 健康检查结果
|
||||
- 自动恢复操作
|
||||
|
||||
## ⚙️ 高级配置
|
||||
|
||||
### 自定义故障转移条件
|
||||
|
||||
编辑 `app.py` 中的 `should_failover` 方法:
|
||||
|
||||
```python
|
||||
def should_failover(self, error_message: str) -> bool:
|
||||
# 添加自定义错误检测条件
|
||||
custom_indicators = [
|
||||
"your_custom_error",
|
||||
"specific_provider_error"
|
||||
]
|
||||
return any(indicator in error_message.lower()
|
||||
for indicator in custom_indicators)
|
||||
```
|
||||
|
||||
### 调整健康检查频率
|
||||
|
||||
修改 `app.py` 中的定时任务:
|
||||
|
||||
```python
|
||||
# 每30分钟检查一次
|
||||
@scheduler.cron("*/30 * * * *")
|
||||
async def health_check_claude_pro():
|
||||
# ... 健康检查逻辑
|
||||
```
|
||||
|
||||
## 🤝 SillyTavern集成
|
||||
|
||||
在SillyTavern中使用此路由器:
|
||||
|
||||
1. **API URL**: `http://localhost:8000/v1/messages`
|
||||
2. **API Key**: 使用你的Claude API密钥
|
||||
3. **模型**: 选择任何Claude模型
|
||||
|
||||
路由器会自动处理故障转移,对SillyTavern完全透明。
|
||||
|
||||
## 📄 许可证
|
||||
|
||||
MIT License
|
||||
|
||||
## 🆘 获取帮助
|
||||
|
||||
如果遇到问题:
|
||||
|
||||
1. 检查日志文件
|
||||
2. 验证API密钥配置
|
||||
3. 尝试手动切换提供商
|
||||
4. 查看健康检查状态
|
||||
|
||||
需要进一步帮助请查看代码注释或联系开发者。
|
||||
@@ -26,11 +26,11 @@ class ClaudeRouter:
|
||||
self.last_health_check = None
|
||||
self.health_check_failures = 0
|
||||
self.scheduler = None
|
||||
# 按优先级顺序排列:Claude Pro > DeepSeek > Kimi > Claude API
|
||||
# 按优先级顺序排列:Claude Pro > DeepSeek > Kimi (removed claude_api)
|
||||
from collections import OrderedDict
|
||||
self.providers = OrderedDict([
|
||||
("claude_pro", {
|
||||
"api_key": config.claude_pro_api_key,
|
||||
"api_key": config.claude_api_key, # Use claude_api_key for claude_pro
|
||||
"base_url": config.claude_pro_base_url,
|
||||
"type": "anthropic",
|
||||
"active": True
|
||||
@@ -46,12 +46,6 @@ class ClaudeRouter:
|
||||
"base_url": config.kimi_base_url,
|
||||
"type": "openai",
|
||||
"active": True
|
||||
}),
|
||||
("claude_api", {
|
||||
"api_key": config.claude_api_key,
|
||||
"base_url": config.claude_api_base_url,
|
||||
"type": "anthropic",
|
||||
"active": True
|
||||
})
|
||||
])
|
||||
|
||||
@@ -220,19 +214,21 @@ class ClaudeRouter:
|
||||
|
||||
return response
|
||||
|
||||
async def health_check_claude_pro(self):
|
||||
"""Check if Claude Pro is available again"""
|
||||
# Only check if we're not currently using Claude Pro
|
||||
if self.current_provider == "claude_pro":
|
||||
logger.debug("Skipping health check - already using Claude Pro")
|
||||
async def health_check_primary_provider(self):
|
||||
"""Check if primary provider (claude_pro) is available again"""
|
||||
primary_provider = "claude_pro"
|
||||
|
||||
# Only check if we're not currently using the primary provider
|
||||
if self.current_provider == primary_provider:
|
||||
logger.debug(f"Skipping health check - already using {primary_provider}")
|
||||
return
|
||||
|
||||
logger.info("Running Claude Pro health check...")
|
||||
logger.info(f"Running {primary_provider} health check...")
|
||||
self.last_health_check = datetime.now()
|
||||
|
||||
try:
|
||||
client = Anthropic(
|
||||
api_key=config.claude_pro_api_key,
|
||||
api_key=config.claude_api_key, # Use claude_api_key for claude_pro
|
||||
base_url=config.claude_pro_base_url
|
||||
)
|
||||
|
||||
@@ -253,21 +249,21 @@ class ClaudeRouter:
|
||||
prompt=f"Human: {config.health_check_message}\n\nAssistant:"
|
||||
)
|
||||
|
||||
# If successful, switch back to Claude Pro
|
||||
# If successful, switch back to primary provider
|
||||
old_provider = self.current_provider
|
||||
self.current_provider = "claude_pro"
|
||||
self.current_provider = primary_provider
|
||||
self.health_check_failures = 0
|
||||
|
||||
logger.info(f"Claude Pro health check successful! Switched from {old_provider} to claude_pro")
|
||||
logger.info(f"{primary_provider} health check successful! Switched from {old_provider} to {primary_provider}")
|
||||
|
||||
except Exception as e:
|
||||
self.health_check_failures += 1
|
||||
error_str = str(e).lower()
|
||||
|
||||
if any(indicator in error_str for indicator in ["rate_limit", "usage limit", "quota exceeded", "429", "too many requests", "limit reached"]):
|
||||
logger.info(f"Claude Pro still rate limited: {str(e)}")
|
||||
logger.info(f"{primary_provider} still rate limited: {str(e)}")
|
||||
else:
|
||||
logger.warning(f"Claude Pro health check failed (attempt {self.health_check_failures}): {str(e)}")
|
||||
logger.warning(f"{primary_provider} health check failed (attempt {self.health_check_failures}): {str(e)}")
|
||||
|
||||
def start_scheduler(self):
|
||||
"""Start the health check scheduler"""
|
||||
|
||||
@@ -18,7 +18,7 @@ class Config(BaseModel):
|
||||
retry_delay: float = 1.0
|
||||
|
||||
# API endpoints
|
||||
claude_pro_base_url: str = "https://api.anthropic.com"
|
||||
claude_pro_base_url: str = "https://api.anthropic.com" # Claude Pro might use different endpoint in future
|
||||
claude_api_base_url: str = "https://api.anthropic.com"
|
||||
deepseek_base_url: str = "https://api.deepseek.com"
|
||||
kimi_base_url: str = "https://api.moonshot.ai"
|
||||
@@ -57,8 +57,8 @@ class Config(BaseModel):
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
# For MVP, we'll use the same API key for both pro and regular
|
||||
# In practice, Claude Pro might use a different endpoint or key
|
||||
# Claude Pro uses the same API key as regular Claude API
|
||||
# but may use different endpoint or have different rate limits
|
||||
self.claude_pro_api_key = self.claude_api_key
|
||||
|
||||
# Global config instance
|
||||
|
||||
Reference in New Issue
Block a user