Spaces:
Sleeping
Sleeping
Upload 3 files
Browse files- README.md +803 -6
- app.py +253 -0
- requirements.txt +15 -0
README.md
CHANGED
|
@@ -1,10 +1,807 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
-
sdk:
|
|
|
|
| 7 |
pinned: false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: GCLI2API
|
| 3 |
+
emoji: 🚀
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: purple
|
| 6 |
+
sdk: gradio
|
| 7 |
+
app_file: app.py
|
| 8 |
pinned: false
|
| 9 |
+
license: other
|
| 10 |
+
short_description: Gemini API proxy with OpenAI compatibility
|
| 11 |
+
tags:
|
| 12 |
+
- gemini
|
| 13 |
+
- openai
|
| 14 |
+
- api-proxy
|
| 15 |
+
- fastapi
|
| 16 |
+
- google-ai
|
| 17 |
---
|
| 18 |
|
| 19 |
+
# GeminiCLI to API
|
| 20 |
+
|
| 21 |
+
**将 GeminiCLI 转换为 OpenAI 和 GEMINI API 接口**
|
| 22 |
+
|
| 23 |
+
[English](docs/README_EN.md) | 中文
|
| 24 |
+
|
| 25 |
+
## 🚀 快速部署
|
| 26 |
+
|
| 27 |
+
[](https://zeabur.com/templates/2QLQC2?referralCode=su-kaka)
|
| 28 |
+
---
|
| 29 |
+
|
| 30 |
+
## ⚠️ 许可证声明
|
| 31 |
+
|
| 32 |
+
**本项目采用 Cooperative Non-Commercial License (CNC-1.0)**
|
| 33 |
+
|
| 34 |
+
这是一个反商业化的严格开源协议,详情请查看 [LICENSE](LICENSE) 文件。
|
| 35 |
+
|
| 36 |
+
### ✅ 允许的用途:
|
| 37 |
+
- 个人学习、研究、教育用途
|
| 38 |
+
- 非营利组织使用
|
| 39 |
+
- 开源项目集成(需遵循相同协议)
|
| 40 |
+
- 学术研究和论文发表
|
| 41 |
+
|
| 42 |
+
### ❌ 禁止的用途:
|
| 43 |
+
- 任何形式的商业使用
|
| 44 |
+
- 年收入超过100万美元的企业使用
|
| 45 |
+
- 风投支持或公开交易的公司使用
|
| 46 |
+
- 提供付费服务或产品
|
| 47 |
+
- 商业竞争用途
|
| 48 |
+
|
| 49 |
+
---
|
| 50 |
+
|
| 51 |
+
## 控制面板演示网址:https://gcli2api-9xbf.onrender.com 密码:pwd
|
| 52 |
+
|
| 53 |
+
## 核心功能
|
| 54 |
+
|
| 55 |
+
### 🔄 API 端点和格式支持
|
| 56 |
+
|
| 57 |
+
**多端点双格式支持**
|
| 58 |
+
- **OpenAI 兼容端点**:`/v1/chat/completions` 和 `/v1/models`
|
| 59 |
+
- 支持标准 OpenAI 格式(messages 结构)
|
| 60 |
+
- 支持 Gemini 原生格式(contents 结构)
|
| 61 |
+
- 自动格式检测和转换,无需手动切换
|
| 62 |
+
- 支持多模态输入(文本 + 图像)
|
| 63 |
+
- **Gemini 原生端点**:`/v1/models/{model}:generateContent` 和 `streamGenerateContent`
|
| 64 |
+
- 支持完整的 Gemini 原生 API 规范
|
| 65 |
+
- 多种认证方式:Bearer Token、x-goog-api-key 头部、URL 参数 key
|
| 66 |
+
|
| 67 |
+
### 🔐 认证和安全管理
|
| 68 |
+
|
| 69 |
+
**灵活的密码管理**
|
| 70 |
+
- **分离密码支持**:API 密码(聊天端点)和控制面板密码可独立设置
|
| 71 |
+
- **多种认证方式**:支持 Authorization Bearer、x-goog-api-key 头部、URL 参数等
|
| 72 |
+
- **JWT Token 认证**:控制面板支持 JWT 令牌认证
|
| 73 |
+
- **用户邮箱获取**:自动获取和显示 Google 账户邮箱地址
|
| 74 |
+
|
| 75 |
+
### 📊 智能凭证管理系统
|
| 76 |
+
|
| 77 |
+
**高级凭证管理**
|
| 78 |
+
- 多个 Google OAuth 凭证自动轮换
|
| 79 |
+
- 通过冗余认证增强稳定性
|
| 80 |
+
- 负载均衡与并发请求支持
|
| 81 |
+
- 自动故障检测和凭证禁用
|
| 82 |
+
- 凭证使用统计和配额管理
|
| 83 |
+
- 支持手动启用/禁用凭证文件
|
| 84 |
+
- 批量凭证文件操作(启用、禁用、删除)
|
| 85 |
+
|
| 86 |
+
**凭证状态监控**
|
| 87 |
+
- 实时凭证健康检查
|
| 88 |
+
- 错误码追踪(429、403、500 等)
|
| 89 |
+
- 自动封禁机制(可配置)
|
| 90 |
+
- 凭证轮换策略(基于调用次数)
|
| 91 |
+
- 使用统计和配额监控
|
| 92 |
+
|
| 93 |
+
### 🌊 流式传输和响应处理
|
| 94 |
+
|
| 95 |
+
**多种流式支持**
|
| 96 |
+
- 真正的实时流式响应
|
| 97 |
+
- 假流式模式(用于兼容性)
|
| 98 |
+
- 流式抗截断功能(防止回答被截断)
|
| 99 |
+
- 异步任务管理和超时处理
|
| 100 |
+
|
| 101 |
+
**响应优化**
|
| 102 |
+
- 思维链(Thinking)内容分离
|
| 103 |
+
- 推理过程(reasoning_content)处理
|
| 104 |
+
- 多轮对话上下文管理
|
| 105 |
+
- 兼容性模式(将 system 消息转换为 user 消息)
|
| 106 |
+
|
| 107 |
+
### 🎛️ Web 管理控制台
|
| 108 |
+
|
| 109 |
+
**全功能 Web 界面**
|
| 110 |
+
- OAuth 认证流程管理
|
| 111 |
+
- 凭证文件上传、下载、管理
|
| 112 |
+
- 实时日志查看(WebSocket)
|
| 113 |
+
- 系统配置管理
|
| 114 |
+
- 使用统计和监控面板
|
| 115 |
+
- 移动端适配界面
|
| 116 |
+
|
| 117 |
+
**批量操作支持**
|
| 118 |
+
- ZIP 文件批量上传凭证
|
| 119 |
+
- 批量启用/禁用/删除凭证
|
| 120 |
+
- 批量获取用户邮箱
|
| 121 |
+
- 批量配置管理
|
| 122 |
+
|
| 123 |
+
### 📈 使用统计和监控
|
| 124 |
+
|
| 125 |
+
**详细使用统计**
|
| 126 |
+
- 按凭证文件统计调用次数
|
| 127 |
+
- Gemini 2.5 Pro 模型专项统计
|
| 128 |
+
- 每日配额管理(UTC+7 重置)
|
| 129 |
+
- 聚合统计和分析
|
| 130 |
+
- 自定义每日限制配置
|
| 131 |
+
|
| 132 |
+
**实时监控**
|
| 133 |
+
- WebSocket 实时日志流
|
| 134 |
+
- 系统状态监控
|
| 135 |
+
- 凭证健康状态
|
| 136 |
+
- API 调用成功率统计
|
| 137 |
+
|
| 138 |
+
### 🔧 高级配置和自定义
|
| 139 |
+
|
| 140 |
+
**网络和代理配置**
|
| 141 |
+
- HTTP/HTTPS 代理支持
|
| 142 |
+
- 代理端点配置(OAuth、Google APIs、元数据服务)
|
| 143 |
+
- 超时和重试配置
|
| 144 |
+
- 网络错误处理和恢复
|
| 145 |
+
|
| 146 |
+
**性能和稳定性配置**
|
| 147 |
+
- 429 错误自动重试(可配置间隔和次数)
|
| 148 |
+
- 抗截断最大重试次数
|
| 149 |
+
- 凭证轮换策略
|
| 150 |
+
- 并发请求管理
|
| 151 |
+
|
| 152 |
+
**日志和调试**
|
| 153 |
+
- 多级日志系统(DEBUG、INFO、WARNING、ERROR)
|
| 154 |
+
- 日志文件管理
|
| 155 |
+
- 实时日志流
|
| 156 |
+
- 日志下载和清空
|
| 157 |
+
|
| 158 |
+
### 🔄 环境变量和配置管理
|
| 159 |
+
|
| 160 |
+
**灵活的配置方式**
|
| 161 |
+
- TOML 配置文件支持
|
| 162 |
+
- 环境变量配置
|
| 163 |
+
- 热配置更新(部分配置项)
|
| 164 |
+
- 配置锁定(环境变量优先级)
|
| 165 |
+
|
| 166 |
+
**环境变量凭证支持**
|
| 167 |
+
- `GCLI_CREDS_*` 格式环境变量导入
|
| 168 |
+
- 自动加载环境变量凭证
|
| 169 |
+
- Base64 编码凭证支持
|
| 170 |
+
- Docker 容器友好
|
| 171 |
+
|
| 172 |
+
## 支持的模型
|
| 173 |
+
|
| 174 |
+
所有模型均具备 1M 上下文窗口容量。每个凭证文件提供 1000 次请求额度。
|
| 175 |
+
|
| 176 |
+
### �� 基础模型
|
| 177 |
+
- `gemini-2.5-pro`
|
| 178 |
+
- `gemini-2.5-pro-preview-06-05`
|
| 179 |
+
- `gemini-2.5-pro-preview-05-06`
|
| 180 |
+
|
| 181 |
+
### 🧠 思维模型(Thinking Models)
|
| 182 |
+
- `gemini-2.5-pro-maxthinking`:最大思考预算模式
|
| 183 |
+
- `gemini-2.5-pro-nothinking`:无思考模式
|
| 184 |
+
- 支持自定义思考预算配置
|
| 185 |
+
- 自动分离思维内容和最终回答
|
| 186 |
+
|
| 187 |
+
### 🔍 搜索增强模型
|
| 188 |
+
- `gemini-2.5-pro-search`:集成搜索功能的模型
|
| 189 |
+
|
| 190 |
+
### 🌊 特殊功能变体
|
| 191 |
+
- **假流式模式**:在任何模型名称后添加 `-假流式` 后缀
|
| 192 |
+
- 例:`gemini-2.5-pro-假流式`
|
| 193 |
+
- 用于需要流式响应但服务端不支持真流式的场景
|
| 194 |
+
- **流式抗截断模式**:在模型名称前添加 `流式抗截断/` 前缀
|
| 195 |
+
- 例:`流式抗截断/gemini-2.5-pro`
|
| 196 |
+
- 自动检测响应截断并重试,确保完整回答
|
| 197 |
+
|
| 198 |
+
### 🔧 模型功能自动检测
|
| 199 |
+
- 系统自动识别模型名称中的功能标识
|
| 200 |
+
- 透明地处理功能模式转换
|
| 201 |
+
- 支持功能组合使用
|
| 202 |
+
|
| 203 |
+
---
|
| 204 |
+
|
| 205 |
+
## 安装指南
|
| 206 |
+
|
| 207 |
+
### Termux 环境
|
| 208 |
+
|
| 209 |
+
**初始安装**
|
| 210 |
+
```bash
|
| 211 |
+
curl -o termux-install.sh "https://raw.githubusercontent.com/su-kaka/gcli2api/refs/heads/master/termux-install.sh" && chmod +x termux-install.sh && ./termux-install.sh
|
| 212 |
+
```
|
| 213 |
+
|
| 214 |
+
**重启服务**
|
| 215 |
+
```bash
|
| 216 |
+
cd gcli2api
|
| 217 |
+
bash termux-start.sh
|
| 218 |
+
```
|
| 219 |
+
|
| 220 |
+
### Windows 环境
|
| 221 |
+
|
| 222 |
+
**初始安装**
|
| 223 |
+
```powershell
|
| 224 |
+
iex (iwr "https://raw.githubusercontent.com/su-kaka/gcli2api/refs/heads/master/install.ps1" -UseBasicParsing).Content
|
| 225 |
+
```
|
| 226 |
+
|
| 227 |
+
**重启服务**
|
| 228 |
+
双击执行 `start.bat`
|
| 229 |
+
|
| 230 |
+
### Linux 环境
|
| 231 |
+
|
| 232 |
+
**初始安装**
|
| 233 |
+
```bash
|
| 234 |
+
curl -o install.sh "https://raw.githubusercontent.com/su-kaka/gcli2api/refs/heads/master/install.sh" && chmod +x install.sh && ./install.sh
|
| 235 |
+
```
|
| 236 |
+
|
| 237 |
+
**重启服务**
|
| 238 |
+
```bash
|
| 239 |
+
cd gcli2api
|
| 240 |
+
bash start.sh
|
| 241 |
+
```
|
| 242 |
+
|
| 243 |
+
### Docker 环境
|
| 244 |
+
|
| 245 |
+
**Docker 运行命令**
|
| 246 |
+
```bash
|
| 247 |
+
# 使用通用密码
|
| 248 |
+
docker run -d --name gcli2api --network host -e PASSWORD=pwd -e PORT=7861 -v $(pwd)/data/creds:/app/creds ghcr.io/su-kaka/gcli2api:latest
|
| 249 |
+
|
| 250 |
+
# 使用分离密码
|
| 251 |
+
docker run -d --name gcli2api --network host -e API_PASSWORD=api_pwd -e PANEL_PASSWORD=panel_pwd -e PORT=7861 -v $(pwd)/data/creds:/app/creds ghcr.io/su-kaka/gcli2api:latest
|
| 252 |
+
```
|
| 253 |
+
|
| 254 |
+
**Docker Compose 运行命令**
|
| 255 |
+
1. 将以下内容保存为 `docker-compose.yml` 文件:
|
| 256 |
+
```yaml
|
| 257 |
+
version: '3.8'
|
| 258 |
+
|
| 259 |
+
services:
|
| 260 |
+
gcli2api:
|
| 261 |
+
image: ghcr.io/su-kaka/gcli2api:latest
|
| 262 |
+
container_name: gcli2api
|
| 263 |
+
restart: unless-stopped
|
| 264 |
+
network_mode: host
|
| 265 |
+
environment:
|
| 266 |
+
# 使用通用密码(推荐用于简单部署)
|
| 267 |
+
- PASSWORD=pwd
|
| 268 |
+
- PORT=7861
|
| 269 |
+
# 或使用分离密码(推荐用于生产环境)
|
| 270 |
+
# - API_PASSWORD=your_api_password
|
| 271 |
+
# - PANEL_PASSWORD=your_panel_password
|
| 272 |
+
volumes:
|
| 273 |
+
- ./data/creds:/app/creds
|
| 274 |
+
healthcheck:
|
| 275 |
+
test: ["CMD-SHELL", "python -c \"import sys, urllib.request, os; port = os.environ.get('PORT', '7861'); req = urllib.request.Request(f'http://localhost:{port}/v1/models', headers={'Authorization': 'Bearer ' + os.environ.get('PASSWORD', 'pwd')}); sys.exit(0 if urllib.request.urlopen(req, timeout=5).getcode() == 200 else 1)\""]
|
| 276 |
+
interval: 30s
|
| 277 |
+
timeout: 10s
|
| 278 |
+
retries: 3
|
| 279 |
+
start_period: 40s
|
| 280 |
+
```
|
| 281 |
+
2. 启动服务:
|
| 282 |
+
```bash
|
| 283 |
+
docker-compose up -d
|
| 284 |
+
```
|
| 285 |
+
|
| 286 |
+
---
|
| 287 |
+
|
| 288 |
+
## ⚠️ 注意事项
|
| 289 |
+
|
| 290 |
+
- 当前 OAuth 验证流程**仅支持本地主机(localhost)访问**,即须通过 `http://127.0.0.1:7861/auth` 完成认证(默认端口 7861,可通过 PORT 环境变量修改)。
|
| 291 |
+
- **如需在云服务器或其他远程环境部署,请先在本地运行服务并完成 OAuth 验证,获得生成的 json 凭证文件(位于 `./geminicli/creds` 目录)后,再在auth面板将该文件上传即可。**
|
| 292 |
+
- **请严格遵守使用限制,仅用于个人学习和非商业用途**
|
| 293 |
+
|
| 294 |
+
---
|
| 295 |
+
|
| 296 |
+
## 配置说明
|
| 297 |
+
|
| 298 |
+
1. 访问 `http://127.0.0.1:7861/auth` (默认端口,可通过 PORT 环境变量修改)
|
| 299 |
+
2. 完成 OAuth 认证流程(默认密码:`pwd`,可通过环境变量修改)
|
| 300 |
+
3. 配置客户端:
|
| 301 |
+
|
| 302 |
+
**OpenAI 兼容客户端:**
|
| 303 |
+
- **端点地址**:`http://127.0.0.1:7861/v1`
|
| 304 |
+
- **API 密钥**:`pwd`(默认值,可通过 API_PASSWORD 或 PASSWORD 环境变量修改)
|
| 305 |
+
|
| 306 |
+
**Gemini 原生客户端:**
|
| 307 |
+
- **端点地址**:`http://127.0.0.1:7861`
|
| 308 |
+
- **认证方式**:
|
| 309 |
+
- `Authorization: Bearer your_api_password`
|
| 310 |
+
- `x-goog-api-key: your_api_password`
|
| 311 |
+
- URL 参数:`?key=your_api_password`
|
| 312 |
+
|
| 313 |
+
## 💾 分布式存储模式
|
| 314 |
+
|
| 315 |
+
### 🌟 存储后端优先级
|
| 316 |
+
|
| 317 |
+
gcli2api 支持多种存储后端,按优先级自动选择:**Redis > Postgres > MongoDB > 本地文件**
|
| 318 |
+
|
| 319 |
+
### ⚡ Redis 分布式存储模式
|
| 320 |
+
|
| 321 |
+
### ⚙️ 启用 Redis 模式
|
| 322 |
+
|
| 323 |
+
**步骤 1: 配置 Redis 连接**
|
| 324 |
+
```bash
|
| 325 |
+
# 本地 Redis
|
| 326 |
+
export REDIS_URI="redis://localhost:6379"
|
| 327 |
+
|
| 328 |
+
# 带密码的 Redis
|
| 329 |
+
export REDIS_URI="redis://:password@localhost:6379"
|
| 330 |
+
|
| 331 |
+
# SSL 连接(推荐生产环境)
|
| 332 |
+
export REDIS_URI="rediss://default:password@host:6380"
|
| 333 |
+
|
| 334 |
+
# Upstash Redis(免费云服务)
|
| 335 |
+
export REDIS_URI="rediss://default:token@your-host.upstash.io:6379"
|
| 336 |
+
|
| 337 |
+
# 可选:自定义数据库索引(默认: 0)
|
| 338 |
+
export REDIS_DATABASE="1"
|
| 339 |
+
```
|
| 340 |
+
|
| 341 |
+
**步骤 2: 启动应用**
|
| 342 |
+
```bash
|
| 343 |
+
# 应用会自动检测 Redis 配置并优先使用 Redis 存储
|
| 344 |
+
python web.py
|
| 345 |
+
```
|
| 346 |
+
|
| 347 |
+
### 🐘 Postgres 分布式存储模式
|
| 348 |
+
|
| 349 |
+
如果未配置 Redis,或者你希望使用关系型数据库作为主要存储方案,gcli2api 也支持 Postgres(位于 Redis 之后,优先于 MongoDB)。
|
| 350 |
+
|
| 351 |
+
⚙️ 启用 Postgres 模式
|
| 352 |
+
|
| 353 |
+
步骤 1: 配置 Postgres 连接
|
| 354 |
+
```bash
|
| 355 |
+
# 使用标准 DSN(示例)
|
| 356 |
+
export POSTGRES_DSN="postgresql://user:password@localhost:5432/gcli2api"
|
| 357 |
+
|
| 358 |
+
# 也可以使用 socket 或其他 DSN 格式,取决于你的部署方式
|
| 359 |
+
```
|
| 360 |
+
|
| 361 |
+
步骤 2: 启动应用
|
| 362 |
+
```bash
|
| 363 |
+
# 应用会自动检测 POSTGRES_DSN 并在 Redis 未启用时优先使用 Postgres 存储
|
| 364 |
+
python web.py
|
| 365 |
+
```
|
| 366 |
+
|
| 367 |
+
### 🍃 MongoDB 分布式存储模式
|
| 368 |
+
|
| 369 |
+
### 🌟 备选存储方案
|
| 370 |
+
|
| 371 |
+
如果未配置 Redis,gcli2api 将尝试使用 **MongoDB 存储模式**,
|
| 372 |
+
|
| 373 |
+
### ⚙️ 启用 MongoDB 模式
|
| 374 |
+
|
| 375 |
+
**步骤 1: 配置 MongoDB 连接**
|
| 376 |
+
```bash
|
| 377 |
+
# 本地 MongoDB
|
| 378 |
+
export MONGODB_URI="mongodb://localhost:27017"
|
| 379 |
+
|
| 380 |
+
# MongoDB Atlas 云服务
|
| 381 |
+
export MONGODB_URI="mongodb+srv://username:password@cluster.mongodb.net"
|
| 382 |
+
|
| 383 |
+
# 带认证的 MongoDB
|
| 384 |
+
export MONGODB_URI="mongodb://admin:password@localhost:27017/admin"
|
| 385 |
+
|
| 386 |
+
# 可选:自定义数据库名称(默认: gcli2api)
|
| 387 |
+
export MONGODB_DATABASE="my_gcli_db"
|
| 388 |
+
```
|
| 389 |
+
|
| 390 |
+
**步骤 2: 启动应用**
|
| 391 |
+
```bash
|
| 392 |
+
# 应用会自动检测 MongoDB 配置并使用 MongoDB 存储
|
| 393 |
+
python web.py
|
| 394 |
+
```
|
| 395 |
+
|
| 396 |
+
**Docker 环境使用 MongoDB**
|
| 397 |
+
```bash
|
| 398 |
+
# 单机 MongoDB 部署
|
| 399 |
+
docker run -d --name gcli2api \
|
| 400 |
+
-e MONGODB_URI="mongodb://mongodb:27017" \
|
| 401 |
+
-e API_PASSWORD=your_password \
|
| 402 |
+
--network your_network \
|
| 403 |
+
ghcr.io/su-kaka/gcli2api:latest
|
| 404 |
+
|
| 405 |
+
# 使用 MongoDB Atlas
|
| 406 |
+
docker run -d --name gcli2api \
|
| 407 |
+
-e MONGODB_URI="mongodb+srv://user:pass@cluster.mongodb.net/gcli2api" \
|
| 408 |
+
-e API_PASSWORD=your_password \
|
| 409 |
+
-p 7861:7861 \
|
| 410 |
+
ghcr.io/su-kaka/gcli2api:latest
|
| 411 |
+
```
|
| 412 |
+
|
| 413 |
+
**Docker Compose 示例**
|
| 414 |
+
```yaml
|
| 415 |
+
version: '3.8'
|
| 416 |
+
|
| 417 |
+
services:
|
| 418 |
+
mongodb:
|
| 419 |
+
image: mongo:7
|
| 420 |
+
container_name: gcli2api-mongodb
|
| 421 |
+
restart: unless-stopped
|
| 422 |
+
environment:
|
| 423 |
+
MONGO_INITDB_ROOT_USERNAME: admin
|
| 424 |
+
MONGO_INITDB_ROOT_PASSWORD: password123
|
| 425 |
+
volumes:
|
| 426 |
+
- mongodb_data:/data/db
|
| 427 |
+
ports:
|
| 428 |
+
- "27017:27017"
|
| 429 |
+
|
| 430 |
+
gcli2api:
|
| 431 |
+
image: ghcr.io/su-kaka/gcli2api:latest
|
| 432 |
+
container_name: gcli2api
|
| 433 |
+
restart: unless-stopped
|
| 434 |
+
depends_on:
|
| 435 |
+
- mongodb
|
| 436 |
+
environment:
|
| 437 |
+
- MONGODB_URI=mongodb://admin:password123@mongodb:27017/admin
|
| 438 |
+
- MONGODB_DATABASE=gcli2api
|
| 439 |
+
- API_PASSWORD=your_api_password
|
| 440 |
+
- PORT=7861
|
| 441 |
+
ports:
|
| 442 |
+
- "7861:7861"
|
| 443 |
+
|
| 444 |
+
volumes:
|
| 445 |
+
mongodb_data:
|
| 446 |
+
```
|
| 447 |
+
|
| 448 |
+
|
| 449 |
+
### 🔧 高级配置
|
| 450 |
+
|
| 451 |
+
**MongoDB 连接优化**
|
| 452 |
+
```bash
|
| 453 |
+
# 连接池和超时配置
|
| 454 |
+
export MONGODB_URI="mongodb://localhost:27017?maxPoolSize=10&serverSelectionTimeoutMS=5000"
|
| 455 |
+
|
| 456 |
+
# 副本集配置
|
| 457 |
+
export MONGODB_URI="mongodb://host1:27017,host2:27017,host3:27017/gcli2api?replicaSet=myReplicaSet"
|
| 458 |
+
|
| 459 |
+
# 读写分离配置
|
| 460 |
+
export MONGODB_URI="mongodb://localhost:27017/gcli2api?readPreference=secondaryPreferred"
|
| 461 |
+
```
|
| 462 |
+
|
| 463 |
+
## 🏗️ 技术架构
|
| 464 |
+
|
| 465 |
+
### 核心模块说明
|
| 466 |
+
|
| 467 |
+
**认证和凭证管理** (`src/auth.py`, `src/credential_manager.py`)
|
| 468 |
+
- OAuth 2.0 认证流程管理
|
| 469 |
+
- 多凭证文件状态管理和轮换
|
| 470 |
+
- 自动故障检测和恢复
|
| 471 |
+
- JWT 令牌生成和验证
|
| 472 |
+
|
| 473 |
+
**API 路由和转换** (`src/openai_router.py`, `src/gemini_router.py`, `src/openai_transfer.py`)
|
| 474 |
+
- OpenAI 和 Gemini 格式双向转换
|
| 475 |
+
- 多模态输入处理(文本+图像)
|
| 476 |
+
- 思维链内容分离和处理
|
| 477 |
+
- 流式响应管理
|
| 478 |
+
|
| 479 |
+
**网络和代理** (`src/httpx_client.py`, `src/google_chat_api.py`)
|
| 480 |
+
- 统一 HTTP 客户端管理
|
| 481 |
+
- 代理配置和热更新支持
|
| 482 |
+
- 超时和重试策略
|
| 483 |
+
- 异步请求池管理
|
| 484 |
+
|
| 485 |
+
**状态管理** (`src/state_manager.py`, `src/usage_stats.py`)
|
| 486 |
+
- 原子化状态操作
|
| 487 |
+
- 使用统计和配额管理
|
| 488 |
+
- 文件锁和并发安全
|
| 489 |
+
- 数据持久化(TOML 格式)
|
| 490 |
+
|
| 491 |
+
**任务管理** (`src/task_manager.py`)
|
| 492 |
+
- 全局异步任务生命周期管理
|
| 493 |
+
- 资源清理和内存管理
|
| 494 |
+
- 优雅关闭和异常处理
|
| 495 |
+
|
| 496 |
+
**Web 控制台** (`src/web_routes.py`)
|
| 497 |
+
- RESTful API 端点
|
| 498 |
+
- WebSocket 实时通信
|
| 499 |
+
- 移动端适配检测
|
| 500 |
+
- 批量操作支持
|
| 501 |
+
|
| 502 |
+
### 高级特性实现
|
| 503 |
+
|
| 504 |
+
**流式抗截断机制** (`src/anti_truncation.py`)
|
| 505 |
+
- 检测响应截断模式
|
| 506 |
+
- 自动重试和状态恢复
|
| 507 |
+
- 上下文连接管理
|
| 508 |
+
|
| 509 |
+
**格式检测和转换** (`src/format_detector.py`)
|
| 510 |
+
- 自动检测请求格式(OpenAI vs Gemini)
|
| 511 |
+
- 无缝格式转换
|
| 512 |
+
- 参数映射和验证
|
| 513 |
+
|
| 514 |
+
**用户代理模拟** (`src/utils.py`)
|
| 515 |
+
- GeminiCLI 格式用户代理生成
|
| 516 |
+
- 平台检测和客户端元数据
|
| 517 |
+
- API 兼容性保证
|
| 518 |
+
|
| 519 |
+
### 环境变量配置
|
| 520 |
+
|
| 521 |
+
**基础配置**
|
| 522 |
+
- `PORT`: 服务端口(默认:7861)
|
| 523 |
+
- `HOST`: 服务器监听地址(默认:0.0.0.0)
|
| 524 |
+
|
| 525 |
+
**密码配置**
|
| 526 |
+
- `API_PASSWORD`: 聊天 API 访问密码(默认:继承 PASSWORD 或 pwd)
|
| 527 |
+
- `PANEL_PASSWORD`: 控制面板访问密码(默认:继承 PASSWORD 或 pwd)
|
| 528 |
+
- `PASSWORD`: 通用密码,设置后覆盖上述两个(默认:pwd)
|
| 529 |
+
|
| 530 |
+
**性能和稳定性配置**
|
| 531 |
+
- `CALLS_PER_ROTATION`: 每个凭证轮换前的调用次数(默认:10)
|
| 532 |
+
- `RETRY_429_ENABLED`: 启用 429 错误自动重试(默认:true)
|
| 533 |
+
- `RETRY_429_MAX_RETRIES`: 429 错误最大重试次数(默认:3)
|
| 534 |
+
- `RETRY_429_INTERVAL`: 429 错误重试间隔,秒(默认:1.0)
|
| 535 |
+
- `ANTI_TRUNCATION_MAX_ATTEMPTS`: 抗截断最大重试次数(默认:3)
|
| 536 |
+
|
| 537 |
+
**网络和代理配置**
|
| 538 |
+
- `PROXY`: HTTP/HTTPS 代理地址(格式:`http://host:port`)
|
| 539 |
+
- `OAUTH_PROXY_URL`: OAuth 认证代理端点
|
| 540 |
+
- `GOOGLEAPIS_PROXY_URL`: Google APIs 代理端点
|
| 541 |
+
- `METADATA_SERVICE_URL`: 元数据服务代理端点
|
| 542 |
+
|
| 543 |
+
**自动化配置**
|
| 544 |
+
- `AUTO_BAN`: 启用凭证自动封禁(默认:true)
|
| 545 |
+
- `AUTO_LOAD_ENV_CREDS`: 启动时自动加载环境变量凭证(默认:false)
|
| 546 |
+
|
| 547 |
+
**兼容性配置**
|
| 548 |
+
- `COMPATIBILITY_MODE`: 启用兼容性模式,将 system 消息转为 user 消息(默认:false)
|
| 549 |
+
|
| 550 |
+
**日志配置**
|
| 551 |
+
- `LOG_LEVEL`: 日志级别(DEBUG/INFO/WARNING/ERROR,默认:INFO)
|
| 552 |
+
- `LOG_FILE`: 日志文件路径(默认:gcli2api.log)
|
| 553 |
+
|
| 554 |
+
**存储配置(按优先级)**
|
| 555 |
+
|
| 556 |
+
**Redis 配置(最高优先级)**
|
| 557 |
+
- `REDIS_URI`: Redis 连接字符串(设置后启用 Redis 模式)
|
| 558 |
+
- 本地:`redis://localhost:6379`
|
| 559 |
+
- 带密码:`redis://:password@host:6379`
|
| 560 |
+
- SSL:`rediss://default:password@host:6380`
|
| 561 |
+
- `REDIS_DATABASE`: Redis 数据库索引(0-15,默认:0)
|
| 562 |
+
|
| 563 |
+
**MongoDB 配置(第二优先级)**
|
| 564 |
+
- `MONGODB_URI`: MongoDB 连接字符串(设置后启用 MongoDB 模式)
|
| 565 |
+
- `MONGODB_DATABASE`: MongoDB 数据库名称(默认:gcli2api)
|
| 566 |
+
|
| 567 |
+
**凭证配置**
|
| 568 |
+
|
| 569 |
+
支持使用 `GCLI_CREDS_*` 环境变量导入多个凭证:
|
| 570 |
+
|
| 571 |
+
#### 凭证环境变量使用示例
|
| 572 |
+
|
| 573 |
+
**方式 1:编号格式**
|
| 574 |
+
```bash
|
| 575 |
+
export GCLI_CREDS_1='{"client_id":"your-client-id","client_secret":"your-secret","refresh_token":"your-token","token_uri":"https://oauth2.googleapis.com/token","project_id":"your-project"}'
|
| 576 |
+
export GCLI_CREDS_2='{"client_id":"...","project_id":"..."}'
|
| 577 |
+
```
|
| 578 |
+
|
| 579 |
+
**方式 2:项目名格式**
|
| 580 |
+
```bash
|
| 581 |
+
export GCLI_CREDS_myproject='{"client_id":"...","project_id":"myproject",...}'
|
| 582 |
+
export GCLI_CREDS_project2='{"client_id":"...","project_id":"project2",...}'
|
| 583 |
+
```
|
| 584 |
+
|
| 585 |
+
**启用自动加载**
|
| 586 |
+
```bash
|
| 587 |
+
export AUTO_LOAD_ENV_CREDS=true # 程序启动时自动导入环境变量凭证
|
| 588 |
+
```
|
| 589 |
+
|
| 590 |
+
**Docker 使用示例**
|
| 591 |
+
```bash
|
| 592 |
+
# 使用通用密码
|
| 593 |
+
docker run -d --name gcli2api \
|
| 594 |
+
-e PASSWORD=mypassword \
|
| 595 |
+
-e PORT=8080 \
|
| 596 |
+
-e GOOGLE_CREDENTIALS="$(cat credential.json | base64 -w 0)" \
|
| 597 |
+
ghcr.io/su-kaka/gcli2api:latest
|
| 598 |
+
|
| 599 |
+
# 使用分离密码
|
| 600 |
+
docker run -d --name gcli2api \
|
| 601 |
+
-e API_PASSWORD=my_api_password \
|
| 602 |
+
-e PANEL_PASSWORD=my_panel_password \
|
| 603 |
+
-e PORT=8080 \
|
| 604 |
+
-e GOOGLE_CREDENTIALS="$(cat credential.json | base64 -w 0)" \
|
| 605 |
+
ghcr.io/su-kaka/gcli2api:latest
|
| 606 |
+
```
|
| 607 |
+
|
| 608 |
+
注意:当设置了凭证环境变量时,系统将优先使用环境变量中的凭证,忽略 `creds` 目录中的文件。
|
| 609 |
+
|
| 610 |
+
### API 使用方式
|
| 611 |
+
|
| 612 |
+
本服务支持两套完整的 API 端点:
|
| 613 |
+
|
| 614 |
+
#### 1. OpenAI 兼容端点
|
| 615 |
+
|
| 616 |
+
**端点:** `/v1/chat/completions`
|
| 617 |
+
**认证:** `Authorization: Bearer your_api_password`
|
| 618 |
+
|
| 619 |
+
支持两种请求格式,会自动检测并处理:
|
| 620 |
+
|
| 621 |
+
**OpenAI 格式:**
|
| 622 |
+
```json
|
| 623 |
+
{
|
| 624 |
+
"model": "gemini-2.5-pro",
|
| 625 |
+
"messages": [
|
| 626 |
+
{"role": "system", "content": "You are a helpful assistant"},
|
| 627 |
+
{"role": "user", "content": "Hello"}
|
| 628 |
+
],
|
| 629 |
+
"temperature": 0.7,
|
| 630 |
+
"stream": true
|
| 631 |
+
}
|
| 632 |
+
```
|
| 633 |
+
|
| 634 |
+
**Gemini 原生格式:**
|
| 635 |
+
```json
|
| 636 |
+
{
|
| 637 |
+
"model": "gemini-2.5-pro",
|
| 638 |
+
"contents": [
|
| 639 |
+
{"role": "user", "parts": [{"text": "Hello"}]}
|
| 640 |
+
],
|
| 641 |
+
"systemInstruction": {"parts": [{"text": "You are a helpful assistant"}]},
|
| 642 |
+
"generationConfig": {
|
| 643 |
+
"temperature": 0.7
|
| 644 |
+
}
|
| 645 |
+
}
|
| 646 |
+
```
|
| 647 |
+
|
| 648 |
+
#### 2. Gemini 原生端点
|
| 649 |
+
|
| 650 |
+
**非流式端点:** `/v1/models/{model}:generateContent`
|
| 651 |
+
**流式端点:** `/v1/models/{model}:streamGenerateContent`
|
| 652 |
+
**模型列表:** `/v1/models`
|
| 653 |
+
|
| 654 |
+
**认证方式(任选一种):**
|
| 655 |
+
- `Authorization: Bearer your_api_password`
|
| 656 |
+
- `x-goog-api-key: your_api_password`
|
| 657 |
+
- URL 参数:`?key=your_api_password`
|
| 658 |
+
|
| 659 |
+
**请求示例:**
|
| 660 |
+
```bash
|
| 661 |
+
# 使用 x-goog-api-key 头部
|
| 662 |
+
curl -X POST "http://127.0.0.1:7861/v1/models/gemini-2.5-pro:generateContent" \
|
| 663 |
+
-H "x-goog-api-key: your_api_password" \
|
| 664 |
+
-H "Content-Type: application/json" \
|
| 665 |
+
-d '{
|
| 666 |
+
"contents": [
|
| 667 |
+
{"role": "user", "parts": [{"text": "Hello"}]}
|
| 668 |
+
]
|
| 669 |
+
}'
|
| 670 |
+
|
| 671 |
+
# 使用 URL 参数
|
| 672 |
+
curl -X POST "http://127.0.0.1:7861/v1/models/gemini-2.5-pro:streamGenerateContent?key=your_api_password" \
|
| 673 |
+
-H "Content-Type: application/json" \
|
| 674 |
+
-d '{
|
| 675 |
+
"contents": [
|
| 676 |
+
{"role": "user", "parts": [{"text": "Hello"}]}
|
| 677 |
+
]
|
| 678 |
+
}'
|
| 679 |
+
```
|
| 680 |
+
|
| 681 |
+
**说明:**
|
| 682 |
+
- OpenAI 端点返回 OpenAI 兼容格式
|
| 683 |
+
- Gemini 端点返��� Gemini 原生格式
|
| 684 |
+
- 两种端点使用相同的 API 密码
|
| 685 |
+
|
| 686 |
+
## 📋 完整 API 参考
|
| 687 |
+
|
| 688 |
+
### Web 控制台 API
|
| 689 |
+
|
| 690 |
+
**认证端点**
|
| 691 |
+
- `POST /auth/login` - 用户登录
|
| 692 |
+
- `POST /auth/start` - 开始 OAuth 认证
|
| 693 |
+
- `POST /auth/callback` - 处理 OAuth 回调
|
| 694 |
+
- `GET /auth/status/{project_id}` - 检查认证状态
|
| 695 |
+
|
| 696 |
+
**凭证管理端点**
|
| 697 |
+
- `GET /creds/status` - 获取所有凭证状态
|
| 698 |
+
- `POST /creds/action` - 单个凭证操作(启用/禁用/删除)
|
| 699 |
+
- `POST /creds/batch-action` - 批量凭证操作
|
| 700 |
+
- `POST /auth/upload` - 批量上传凭证文件(支持 ZIP)
|
| 701 |
+
- `GET /creds/download/{filename}` - 下载凭证文件
|
| 702 |
+
- `GET /creds/download-all` - 打包下载所有凭证
|
| 703 |
+
- `POST /creds/fetch-email/{filename}` - 获取用户邮箱
|
| 704 |
+
- `POST /creds/refresh-all-emails` - 批量刷新用户邮箱
|
| 705 |
+
|
| 706 |
+
**配置管理端点**
|
| 707 |
+
- `GET /config/get` - 获取当前配置
|
| 708 |
+
- `POST /config/save` - 保存配置
|
| 709 |
+
|
| 710 |
+
**环境变量凭证端点**
|
| 711 |
+
- `POST /auth/load-env-creds` - 加载环境变量凭证
|
| 712 |
+
- `DELETE /auth/env-creds` - 清除环境变量凭证
|
| 713 |
+
- `GET /auth/env-creds-status` - 获取环境变量凭证状态
|
| 714 |
+
|
| 715 |
+
**日志管理端点**
|
| 716 |
+
- `POST /auth/logs/clear` - 清空日志
|
| 717 |
+
- `GET /auth/logs/download` - 下载日志文件
|
| 718 |
+
- `WebSocket /auth/logs/stream` - 实时日志流
|
| 719 |
+
|
| 720 |
+
**使用统计端点**
|
| 721 |
+
- `GET /usage/stats` - 获取使用统计
|
| 722 |
+
- `GET /usage/aggregated` - 获取聚合统计
|
| 723 |
+
- `POST /usage/update-limits` - 更新使用限制
|
| 724 |
+
- `POST /usage/reset` - 重置使用统计
|
| 725 |
+
|
| 726 |
+
### 聊天 API 功能特性
|
| 727 |
+
|
| 728 |
+
**多模态支持**
|
| 729 |
+
```json
|
| 730 |
+
{
|
| 731 |
+
"model": "gemini-2.5-pro",
|
| 732 |
+
"messages": [
|
| 733 |
+
{
|
| 734 |
+
"role": "user",
|
| 735 |
+
"content": [
|
| 736 |
+
{"type": "text", "text": "描述这张图片"},
|
| 737 |
+
{
|
| 738 |
+
"type": "image_url",
|
| 739 |
+
"image_url": {
|
| 740 |
+
"url": "data:image/jpeg;base64,/9j/4AAQSkZJRgABA..."
|
| 741 |
+
}
|
| 742 |
+
}
|
| 743 |
+
]
|
| 744 |
+
}
|
| 745 |
+
]
|
| 746 |
+
}
|
| 747 |
+
```
|
| 748 |
+
|
| 749 |
+
**思维模式支持**
|
| 750 |
+
```json
|
| 751 |
+
{
|
| 752 |
+
"model": "gemini-2.5-pro-maxthinking",
|
| 753 |
+
"messages": [
|
| 754 |
+
{"role": "user", "content": "复杂数学问题"}
|
| 755 |
+
]
|
| 756 |
+
}
|
| 757 |
+
```
|
| 758 |
+
|
| 759 |
+
响应将包含分离的思维内容:
|
| 760 |
+
```json
|
| 761 |
+
{
|
| 762 |
+
"choices": [{
|
| 763 |
+
"message": {
|
| 764 |
+
"role": "assistant",
|
| 765 |
+
"content": "最终答案",
|
| 766 |
+
"reasoning_content": "详细的思考过程..."
|
| 767 |
+
}
|
| 768 |
+
}]
|
| 769 |
+
}
|
| 770 |
+
```
|
| 771 |
+
|
| 772 |
+
**流式抗截断使用**
|
| 773 |
+
```json
|
| 774 |
+
{
|
| 775 |
+
"model": "流式抗截断/gemini-2.5-pro",
|
| 776 |
+
"messages": [
|
| 777 |
+
{"role": "user", "content": "写一篇长文章"}
|
| 778 |
+
],
|
| 779 |
+
"stream": true
|
| 780 |
+
}
|
| 781 |
+
```
|
| 782 |
+
|
| 783 |
+
**兼容性模式**
|
| 784 |
+
```bash
|
| 785 |
+
# 启用兼容性模式
|
| 786 |
+
export COMPATIBILITY_MODE=true
|
| 787 |
+
```
|
| 788 |
+
此模式下,所有 `system` 消息会转换为 `user` 消息,提高与某些客户端的兼容性。
|
| 789 |
+
|
| 790 |
+
---
|
| 791 |
+
|
| 792 |
+
## 支持项目
|
| 793 |
+
|
| 794 |
+
如果这个项目对您有帮助,欢迎支持项目的持续发展!
|
| 795 |
+
|
| 796 |
+
详细捐赠信息请查看:[📖 捐赠说明文档](docs/DONATE.md)
|
| 797 |
+
|
| 798 |
+
---
|
| 799 |
+
|
| 800 |
+
## 许可证与免责声明
|
| 801 |
+
|
| 802 |
+
本项目仅供学习和研究用途。使用本项目表示您同意:
|
| 803 |
+
- 不将本项目用于任何商业用途
|
| 804 |
+
- 承担使用本项目的所有风险和责任
|
| 805 |
+
- 遵守相关的服务条款和法律法规
|
| 806 |
+
|
| 807 |
+
项目作者对因使用本项目而产生的任何直接或间接损失不承担责任。
|
app.py
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Hugging Face Spaces Entry Point for GCLI2API Lightspeed
|
| 4 |
+
HF Spaces 部署入口文件
|
| 5 |
+
|
| 6 |
+
This file serves as the entry point for Hugging Face Spaces deployment.
|
| 7 |
+
It imports and runs the main application from web.py with appropriate configurations.
|
| 8 |
+
"""
|
| 9 |
+
|
| 10 |
+
import os
|
| 11 |
+
import sys
|
| 12 |
+
import asyncio
|
| 13 |
+
import signal
|
| 14 |
+
import logging
|
| 15 |
+
from pathlib import Path
|
| 16 |
+
|
| 17 |
+
# 确保项目根目录在 Python 路径中
|
| 18 |
+
project_root = Path(__file__).parent
|
| 19 |
+
if str(project_root) not in sys.path:
|
| 20 |
+
sys.path.insert(0, str(project_root))
|
| 21 |
+
|
| 22 |
+
# 设置基础环境变量(HF Spaces 特定)
|
| 23 |
+
os.environ.setdefault('HOST', '0.0.0.0')
|
| 24 |
+
os.environ.setdefault('PORT', '7860') # HF Spaces 默认端口
|
| 25 |
+
|
| 26 |
+
# 如果没有设置密码,使用默认值(HF Spaces 用户需要在环境变量中设置)
|
| 27 |
+
if not os.environ.get('PASSWORD') and not os.environ.get('API_PASSWORD'):
|
| 28 |
+
print("⚠️ 警告: 未设置密码环境变量!")
|
| 29 |
+
print(" 请在 HF Spaces Settings 中设置 API_PASSWORD 和 PANEL_PASSWORD")
|
| 30 |
+
print(" 或者设置通用 PASSWORD 环境变量")
|
| 31 |
+
|
| 32 |
+
# 为了演示目的,设置默认密码
|
| 33 |
+
os.environ.setdefault('PASSWORD', 'hf_demo_password_please_change')
|
| 34 |
+
|
| 35 |
+
# 设置日志级别
|
| 36 |
+
os.environ.setdefault('LOG_LEVEL', 'INFO')
|
| 37 |
+
|
| 38 |
+
# HF Spaces 优化配置
|
| 39 |
+
os.environ.setdefault('CALLS_PER_ROTATION', '5') # 较少的轮换次数适合 HF Spaces
|
| 40 |
+
os.environ.setdefault('RETRY_429_ENABLED', 'true')
|
| 41 |
+
os.environ.setdefault('AUTO_BAN', 'true')
|
| 42 |
+
os.environ.setdefault('COMPATIBILITY_MODE', 'true') # 增强兼容性
|
| 43 |
+
|
| 44 |
+
# 确保 creds 目录存在
|
| 45 |
+
creds_dir = project_root / "creds"
|
| 46 |
+
creds_dir.mkdir(exist_ok=True)
|
| 47 |
+
|
| 48 |
+
def signal_handler(signum, frame):
|
| 49 |
+
"""处理系统信号,优雅关闭"""
|
| 50 |
+
print(f"\n收到信号 {signum},正在优雅关闭服务...")
|
| 51 |
+
sys.exit(0)
|
| 52 |
+
|
| 53 |
+
def setup_logging():
|
| 54 |
+
"""设置日志配置"""
|
| 55 |
+
logging.basicConfig(
|
| 56 |
+
level=getattr(logging, os.environ.get('LOG_LEVEL', 'INFO')),
|
| 57 |
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
| 58 |
+
datefmt='%Y-%m-%d %H:%M:%S'
|
| 59 |
+
)
|
| 60 |
+
|
| 61 |
+
def print_startup_info():
|
| 62 |
+
"""打印启动信息"""
|
| 63 |
+
port = os.environ.get('PORT', '7860')
|
| 64 |
+
host = os.environ.get('HOST', '0.0.0.0')
|
| 65 |
+
|
| 66 |
+
print("=" * 80)
|
| 67 |
+
print("🚀 GCLI2API Lightspeed - Hugging Face Spaces Edition")
|
| 68 |
+
print("=" * 80)
|
| 69 |
+
print(f"🌐 服务地址: http://{host}:{port}")
|
| 70 |
+
print(f"🎛️ 控制面板: http://{host}:{port}/auth")
|
| 71 |
+
print(f"📡 OpenAI API: http://{host}:{port}/v1")
|
| 72 |
+
print(f"🔧 Gemini API: http://{host}:{port}")
|
| 73 |
+
print("=" * 80)
|
| 74 |
+
|
| 75 |
+
# 检查关键环境变量
|
| 76 |
+
if os.environ.get('API_PASSWORD') or os.environ.get('PASSWORD'):
|
| 77 |
+
print("✅ API 密码已配置")
|
| 78 |
+
else:
|
| 79 |
+
print("⚠️ API 密码未配置,将使用默认密码")
|
| 80 |
+
|
| 81 |
+
if os.environ.get('PANEL_PASSWORD') or os.environ.get('PASSWORD'):
|
| 82 |
+
print("✅ 控制面板密码已配置")
|
| 83 |
+
else:
|
| 84 |
+
print("⚠️ 控制面板密码未配置,将使用默认密码")
|
| 85 |
+
|
| 86 |
+
# 检查凭证配置
|
| 87 |
+
gcli_creds = [k for k in os.environ.keys() if k.startswith('GCLI_CREDS_')]
|
| 88 |
+
if gcli_creds:
|
| 89 |
+
print(f"✅ 检测到 {len(gcli_creds)} 个环境变量凭证")
|
| 90 |
+
elif os.environ.get('AUTO_LOAD_ENV_CREDS') == 'true':
|
| 91 |
+
print("⚠️ 启用了环境变量凭证加载,但未检测到 GCLI_CREDS_* 变量")
|
| 92 |
+
else:
|
| 93 |
+
print("📁 将使用 creds 目录中的凭证文件")
|
| 94 |
+
|
| 95 |
+
print("=" * 80)
|
| 96 |
+
print()
|
| 97 |
+
|
| 98 |
+
async def main():
|
| 99 |
+
"""主函数"""
|
| 100 |
+
# 注册信号处理器
|
| 101 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 102 |
+
signal.signal(signal.SIGTERM, signal_handler)
|
| 103 |
+
|
| 104 |
+
# 设置日志
|
| 105 |
+
setup_logging()
|
| 106 |
+
|
| 107 |
+
# 打印启动信息
|
| 108 |
+
print_startup_info()
|
| 109 |
+
|
| 110 |
+
try:
|
| 111 |
+
# 导入主应用(延迟导入以确保环境变量已设置)
|
| 112 |
+
from web import main as web_main
|
| 113 |
+
|
| 114 |
+
print("🔄 正在启动 GCLI2API 服务...")
|
| 115 |
+
await web_main()
|
| 116 |
+
|
| 117 |
+
except KeyboardInterrupt:
|
| 118 |
+
print("\n👋 收到中断信号,正在关闭服务...")
|
| 119 |
+
except Exception as e:
|
| 120 |
+
print(f"❌ 启动失败: {e}")
|
| 121 |
+
logging.exception("启动过程中发生错误")
|
| 122 |
+
sys.exit(1)
|
| 123 |
+
|
| 124 |
+
def run_app():
|
| 125 |
+
"""运行应用(同步入口)"""
|
| 126 |
+
try:
|
| 127 |
+
asyncio.run(main())
|
| 128 |
+
except KeyboardInterrupt:
|
| 129 |
+
print("\n👋 服务已停止")
|
| 130 |
+
except Exception as e:
|
| 131 |
+
print(f"❌ 运行错误: {e}")
|
| 132 |
+
sys.exit(1)
|
| 133 |
+
|
| 134 |
+
if __name__ == "__main__":
|
| 135 |
+
run_app()
|
| 136 |
+
|
| 137 |
+
# HF Spaces 兼容性:提供 Gradio 接口(可选)
|
| 138 |
+
try:
|
| 139 |
+
import gradio as gr
|
| 140 |
+
|
| 141 |
+
def create_gradio_interface():
|
| 142 |
+
"""创建简单的 Gradio 界面用于 HF Spaces 展示"""
|
| 143 |
+
|
| 144 |
+
def show_info():
|
| 145 |
+
port = os.environ.get('PORT', '7860')
|
| 146 |
+
api_password = os.environ.get('API_PASSWORD') or os.environ.get('PASSWORD', 'hf_demo_password_please_change')
|
| 147 |
+
|
| 148 |
+
info = f"""
|
| 149 |
+
# 🚀 GCLI2API Lightspeed 已启动
|
| 150 |
+
|
| 151 |
+
## 🔗 访问链接
|
| 152 |
+
- **控制面板**: [点击访问管理界面](/auth) (密码: `{api_password}`)
|
| 153 |
+
- **API 文档**: [OpenAI 兼容端点](/v1/models)
|
| 154 |
+
|
| 155 |
+
## 📡 API 端点
|
| 156 |
+
- **OpenAI 格式**: `POST /v1/chat/completions`
|
| 157 |
+
- **Gemini 格式**: `POST /v1/models/{{model}}:generateContent`
|
| 158 |
+
|
| 159 |
+
## 🔑 认证信息
|
| 160 |
+
- **API 密钥**: `{api_password}`
|
| 161 |
+
- **使用方法**: 在请求头中添加 `Authorization: Bearer {api_password}`
|
| 162 |
+
|
| 163 |
+
## 💡 使用提示
|
| 164 |
+
1. 首次使用请先访问控制面板上传 Google OAuth 凭证文件
|
| 165 |
+
2. 支持多种模型变体,包括思维模型和搜索增强模型
|
| 166 |
+
3. 完整文档请查看项目 README
|
| 167 |
+
|
| 168 |
+
---
|
| 169 |
+
**注意**: 这是一个功能性的 API 服务,主要通过 HTTP 接口使用。
|
| 170 |
+
"""
|
| 171 |
+
return info
|
| 172 |
+
|
| 173 |
+
with gr.Blocks(title="GCLI2API Lightspeed", theme=gr.themes.Soft()) as demo:
|
| 174 |
+
gr.Markdown(show_info())
|
| 175 |
+
|
| 176 |
+
gr.Markdown("## 🔧 快速测试")
|
| 177 |
+
with gr.Row():
|
| 178 |
+
test_input = gr.Textbox(
|
| 179 |
+
label="测试消息",
|
| 180 |
+
placeholder="输入测试消息...",
|
| 181 |
+
value="Hello, how are you?"
|
| 182 |
+
)
|
| 183 |
+
test_btn = gr.Button("发送测试", variant="primary")
|
| 184 |
+
|
| 185 |
+
test_output = gr.Textbox(
|
| 186 |
+
label="API 响应",
|
| 187 |
+
lines=10,
|
| 188 |
+
interactive=False
|
| 189 |
+
)
|
| 190 |
+
|
| 191 |
+
def test_api(message):
|
| 192 |
+
import requests
|
| 193 |
+
import json
|
| 194 |
+
|
| 195 |
+
try:
|
| 196 |
+
port = os.environ.get('PORT', '7860')
|
| 197 |
+
api_password = os.environ.get('API_PASSWORD') or os.environ.get('PASSWORD', 'hf_demo_password_please_change')
|
| 198 |
+
|
| 199 |
+
response = requests.post(
|
| 200 |
+
f"http://127.0.0.1:{port}/v1/chat/completions",
|
| 201 |
+
headers={
|
| 202 |
+
"Authorization": f"Bearer {api_password}",
|
| 203 |
+
"Content-Type": "application/json"
|
| 204 |
+
},
|
| 205 |
+
json={
|
| 206 |
+
"model": "gemini-2.5-pro",
|
| 207 |
+
"messages": [
|
| 208 |
+
{"role": "user", "content": message}
|
| 209 |
+
],
|
| 210 |
+
"temperature": 0.7
|
| 211 |
+
},
|
| 212 |
+
timeout=30
|
| 213 |
+
)
|
| 214 |
+
|
| 215 |
+
if response.status_code == 200:
|
| 216 |
+
result = response.json()
|
| 217 |
+
return json.dumps(result, indent=2, ensure_ascii=False)
|
| 218 |
+
else:
|
| 219 |
+
return f"错误 {response.status_code}: {response.text}"
|
| 220 |
+
|
| 221 |
+
except Exception as e:
|
| 222 |
+
return f"请求失败: {str(e)}\n\n请确保:\n1. 已配置有效的 Google OAuth 凭证\n2. API 服务正在运行"
|
| 223 |
+
|
| 224 |
+
test_btn.click(
|
| 225 |
+
test_api,
|
| 226 |
+
inputs=[test_input],
|
| 227 |
+
outputs=[test_output]
|
| 228 |
+
)
|
| 229 |
+
|
| 230 |
+
return demo
|
| 231 |
+
|
| 232 |
+
# 如果在 HF Spaces 环境中,启动 Gradio 界面
|
| 233 |
+
if os.environ.get('SPACE_ID'):
|
| 234 |
+
demo = create_gradio_interface()
|
| 235 |
+
|
| 236 |
+
# 在后台启动主应用
|
| 237 |
+
import threading
|
| 238 |
+
app_thread = threading.Thread(target=run_app, daemon=True)
|
| 239 |
+
app_thread.start()
|
| 240 |
+
|
| 241 |
+
# 启动 Gradio 界面
|
| 242 |
+
if __name__ == "__main__":
|
| 243 |
+
demo.launch(
|
| 244 |
+
server_name="0.0.0.0",
|
| 245 |
+
server_port=7860,
|
| 246 |
+
show_error=True,
|
| 247 |
+
share=False
|
| 248 |
+
)
|
| 249 |
+
|
| 250 |
+
except ImportError:
|
| 251 |
+
# 如果没有 Gradio,直接运行主应用
|
| 252 |
+
if __name__ == "__main__":
|
| 253 |
+
run_app()
|
requirements.txt
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
fastapi
|
| 2 |
+
httpx[socks]
|
| 3 |
+
pydantic
|
| 4 |
+
python-dotenv
|
| 5 |
+
hypercorn
|
| 6 |
+
aiofiles
|
| 7 |
+
python-multipart
|
| 8 |
+
toml
|
| 9 |
+
PyJWT
|
| 10 |
+
oauthlib
|
| 11 |
+
motor
|
| 12 |
+
redis
|
| 13 |
+
asyncpg
|
| 14 |
+
gradio
|
| 15 |
+
requests
|