Skip to content

Latest commit

 

History

History
137 lines (105 loc) · 4.57 KB

File metadata and controls

137 lines (105 loc) · 4.57 KB

API Key Round-Robin Proxy

当多个 API key 各有额度限制时,通过本地代理均匀轮询消耗,对 tchkiller 完全透明。

架构

┌─────────────┐                    ┌──────────────┐                    ┌────────────┐
│  tchkiller  │  providers.json    │  key_proxy   │  round-robin       │  上游 API  │
│             │  base_url:8090     │  (本地代理)   │  sk-1→sk-2→sk-3   │            │
│  单个 key   │ ─────────────────► │              │ ─────────────────► │  GLM/其他  │
│  单个进程   │  SSE streaming     │  端口 8090   │  透传 SSE          │            │
└─────────────┘                    └──────────────┘                    └────────────┘
                                          │
                                   ┌──────┴──────┐
                                   │ 额度耗尽?   │
                                   │ 402/429     │
                                   │ → 冷却 60s  │
                                   │ → 跳到下个   │
                                   │ → 自动重试   │
                                   └─────────────┘

为什么不在 tchkiller 内部轮询 key?

  • 上下文丢失:tchkiller 通过 subprocess 运行 agent,API key 以环境变量传入,换 key = 重启进程 = 丢失对话上下文
  • Proxy 方案:对 tchkiller 完全透明,只看到一个 endpoint + 一个 key,进程不重启,上下文不丢

快速使用

1. 准备 keys

方式 A:命令行直接传

python3 key_proxy.py \
  --keys "sk-glm-aaa,sk-glm-bbb,sk-glm-ccc" \
  --upstream https://open.bigmodel.cn/api/anthropic

方式 B:keys 文件

# 创建 keys.txt(每行一个 key,# 开头为注释)
cat > keys.txt << 'EOF'
# GLM API keys
sk-glm-aaa
sk-glm-bbb
sk-glm-ccc
EOF

python3 key_proxy.py --keys-file keys.txt --upstream https://open.bigmodel.cn/api/anthropic

2. 配置 providers.json

将使用 proxy 的 provider 的 base_url 指向 localhost:8090api_key 设为 proxy token:

{
  "providers": [
    {
      "name": "glm-proxy",
      "base_url": "http://localhost:8090",
      "api_key": "proxy-local-token",
      "models": {
        "sonnet": "glm-5.1",
        "haiku": "glm-5.1",
        "opus": "glm-5.1",
        "judge": "glm-5.1"
      }
    }
  ]
}

3. 正常运行 tchkiller

python3 main.py TARGET -m cve_cloud --browser

无需任何代码修改。

命令行参数

参数 默认值 说明
--keys - 逗号分隔的 API keys
--keys-file - API keys 文件路径(每行一个)
--upstream (必填) 上游 API base URL
--port 8090 监听端口
--host 127.0.0.1 监听地址
--token proxy-local-token Proxy 鉴权 token
--cooldown 60 key 额度耗尽冷却秒数

日志格式

  [   1] POST /v1/messages → key-1 (200)       # 正常请求
  [   2] POST /v1/messages → key-2 (200)       # 轮到 key-2
  [   3] POST /v1/messages → key-3 (200)       # 轮到 key-3
  ⚠️  key-1 额度耗尽,冷却 60s(剩余 2/3 可用)    # key-1 触发 429
  [   4] POST /v1/messages → key-2 (retry, 200) # 自动重试

轮询策略

  • Atomic Round-Robin:每次请求使用下一个 key(1→2→3→1→2→3...)
  • 额度耗尽自动跳过:检测到 402/429 → 该 key 冷却 N 秒 → 立即用下一个 key 重试当前请求
  • 冷却自动恢复:冷却时间到后 key 自动回到轮询池
  • 全部耗尽:所有 key 都在冷却 → 选等待时间最短的 key(不会阻塞)

与 tchkiller failover 的配合

两个机制互不冲突

请求级(key_proxy 处理):
  单次请求 429 → proxy 内部换 key 重试 → tchkiller 无感知

轮次级(ProviderManager 处理):
  proxy 全部 key 耗尽 → 返回 429 给 tchkiller → failover 到其他 provider(如 minimax)

停用

  1. 关闭 proxy 进程
  2. providers.jsonbase_url 改回上游直连地址
  3. 完事

安全

  • 仅监听 127.0.0.1,外部无法访问
  • 使用 token 鉴权,防止本机其他进程滥用
  • keys 通过命令行或文件传入,不写入代码
  • keys.txt 已在 .gitignore 中,不会被提交