From 9cb8f5bb022580b4c63c079cc1d1cba754a0dc3a Mon Sep 17 00:00:00 2001 From: arch3rPro Date: Tue, 26 Aug 2025 15:24:38 +0000 Subject: [PATCH] feat: add app GPT-Load --- .gitignore | 5 +- README.md | 35 ++++--- apps/gpt-load/1.0.22.1/.env.sample | 43 +++++++++ apps/gpt-load/1.0.22.1/data.yml | 19 ++++ apps/gpt-load/1.0.22.1/docker-compose.yml | 18 ++++ apps/gpt-load/README.md | 32 +++++++ apps/gpt-load/README_en.md | 107 ++++++++++++++++++++++ apps/gpt-load/data.yml | 27 ++++++ apps/gpt-load/latest/.env.sample | 43 +++++++++ apps/gpt-load/latest/data.yml | 19 ++++ apps/gpt-load/latest/docker-compose.yml | 18 ++++ apps/gpt-load/logo.png | Bin 0 -> 8752 bytes 12 files changed, 352 insertions(+), 14 deletions(-) create mode 100644 apps/gpt-load/1.0.22.1/.env.sample create mode 100644 apps/gpt-load/1.0.22.1/data.yml create mode 100644 apps/gpt-load/1.0.22.1/docker-compose.yml create mode 100644 apps/gpt-load/README.md create mode 100644 apps/gpt-load/README_en.md create mode 100644 apps/gpt-load/data.yml create mode 100644 apps/gpt-load/latest/.env.sample create mode 100644 apps/gpt-load/latest/data.yml create mode 100644 apps/gpt-load/latest/docker-compose.yml create mode 100644 apps/gpt-load/logo.png diff --git a/.gitignore b/.gitignore index 0acbc46..6e9255b 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,7 @@ .cursor # CodeBuddy -.codebuddy \ No newline at end of file +.codebuddy + +# Qoder +.qoder \ No newline at end of file diff --git a/README.md b/README.md index 333a5a6..791a1d1 100644 --- a/README.md +++ b/README.md @@ -523,14 +523,14 @@ AI驱动的开源代码知识库与文档协作平台,支持多模型、多数 - -Flowise -
Flowise +
+GPT-Load +
GPT-Load
-🔮 开源可视化AI工作流构建平台,拖拽式设计LLM应用 +🚀 智能密钥轮询的多渠道AI代理,高性能企业级AI接口透明代理服务 -3.0.5s • [官网链接](https://github.com/FlowiseAI/Flowise) +1.0.22.1 • [官网链接](https://github.com/tbphp/gpt-load) @@ -540,6 +540,18 @@ AI驱动的开源代码知识库与文档协作平台,支持多模型、多数 + +Flowise +
Flowise +
+ +🔮 开源可视化AI工作流构建平台,拖拽式设计LLM应用 + +3.0.5 • [官网链接](https://github.com/FlowiseAI/Flowise) + + + + MCP Inspector
MCP Inspector @@ -562,6 +574,11 @@ AI驱动的开源代码知识库与文档协作平台,支持多模型、多数 2.4.10 • [官网链接](https://github.com/metatool-ai/metamcp) + + + + + - -
@@ -574,11 +591,6 @@ AI驱动的开源代码知识库与文档协作平台,支持多模型、多数 latest • [官网链接](https://github.com/alibaba/higress)
- - - -
@@ -593,9 +605,6 @@ AI驱动的开源代码知识库与文档协作平台,支持多模型、多数 - -
diff --git a/apps/gpt-load/1.0.22.1/.env.sample b/apps/gpt-load/1.0.22.1/.env.sample new file mode 100644 index 0000000..26189ee --- /dev/null +++ b/apps/gpt-load/1.0.22.1/.env.sample @@ -0,0 +1,43 @@ +# 服务器配置 +PORT=3001 +HOST=0.0.0.0 + +# 服务器读取、写入和空闲连接的超时时间(秒) +SERVER_READ_TIMEOUT=60 +SERVER_WRITE_TIMEOUT=600 +SERVER_IDLE_TIMEOUT=120 +SERVER_GRACEFUL_SHUTDOWN_TIMEOUT=10 + +# 从节点标识 +IS_SLAVE=false + +# 时区 +TZ=Asia/Shanghai + +# 认证配置 是必需的,用于保护管理 API 和 UI 界面 +AUTH_KEY=sk-123456 + +# 数据库配置 默认不填写,使用./data/gpt-load.db的SQLite +# MySQL 示例: +# DATABASE_DSN=root:123456@tcp(mysql:3306)/gpt-load?charset=utf8mb4&parseTime=True&loc=Local +# PostgreSQL 示例: +# DATABASE_DSN=postgres://postgres:123456@postgres:5432/gpt-load?sslmode=disable + +# Redis配置 默认不填写,使用内存存储 +# REDIS_DSN=redis://redis:6379/0 + +# 并发数量 +MAX_CONCURRENT_REQUESTS=100 + +# CORS配置 +ENABLE_CORS=true +ALLOWED_ORIGINS=* +ALLOWED_METHODS=GET,POST,PUT,DELETE,OPTIONS +ALLOWED_HEADERS=* +ALLOW_CREDENTIALS=false + +# 日志配置 +LOG_LEVEL=info +LOG_FORMAT=text +LOG_ENABLE_FILE=true +LOG_FILE_PATH=./data/logs/app.log diff --git a/apps/gpt-load/1.0.22.1/data.yml b/apps/gpt-load/1.0.22.1/data.yml new file mode 100644 index 0000000..bd572cf --- /dev/null +++ b/apps/gpt-load/1.0.22.1/data.yml @@ -0,0 +1,19 @@ +additionalProperties: + formFields: + - default: 3001 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Port + labelZh: 端口 + required: true + rule: paramPort + type: number + - default: "gpt-load-sk" + edit: true + envKey: AUTH_KEY + labelEn: API Authentication Key + labelZh: API认证密钥 + random: true + required: true + rule: paramComplexity + type: password diff --git a/apps/gpt-load/1.0.22.1/docker-compose.yml b/apps/gpt-load/1.0.22.1/docker-compose.yml new file mode 100644 index 0000000..181d5b7 --- /dev/null +++ b/apps/gpt-load/1.0.22.1/docker-compose.yml @@ -0,0 +1,18 @@ +services: + gpt-load: + image: ghcr.io/tbphp/gpt-load:v1.0.22.1 + container_name: ${CONTAINER_NAME} + restart: always + ports: + - ${PANEL_APP_PORT_HTTP}:3001 + networks: + - 1panel-network + volumes: + - ./data:/app/data + environment: + - AUTH_KEY=${AUTH_KEY} + labels: + createdBy: "Apps" +networks: + 1panel-network: + external: true diff --git a/apps/gpt-load/README.md b/apps/gpt-load/README.md new file mode 100644 index 0000000..035dbe7 --- /dev/null +++ b/apps/gpt-load/README.md @@ -0,0 +1,32 @@ +# GPT-Load + +一个高性能、企业级的 AI 接口透明代理服务,专门为需要集成多种 AI 服务的企业和开发者设计。采用 Go 语言开发,具备智能密钥管理、负载均衡和完善的监控功能,专为高并发生产环境而设计。 + +![](https://cdn.jsdelivr.net/gh/xiaoY233/PicList@main/public/assets/GPT-Load.png) + +![](https://img.shields.io/badge/Copyright-arch3rPro-ff9800?style=flat&logo=github&logoColor=white) + +详细请查看[官方文档](https://www.gpt-load.com/docs) + + +## 功能特性 + +- **透明代理**: 完全保留原生 API 格式,支持 OpenAI、Google Gemini 和 Anthropic Claude 等多种格式 +- **智能密钥管理**: 高性能密钥池,支持分组管理、自动轮换和故障恢复 +- **负载均衡**: 支持多上游端点的加权负载均衡,提升服务可用性 +- **智能故障处理**: 自动密钥黑名单管理和恢复机制,确保服务连续性 +- **动态配置**: 系统设置和分组配置支持热重载,无需重启即可生效 +- **企业级架构**: 分布式主从部署,支持水平扩展和高可用 +- **现代化管理**: 基于 Vue 3 的 Web 管理界面,直观易用 +- **全面监控**: 实时统计、健康检查、详细请求日志 +- **高性能设计**: 零拷贝流式传输、连接池复用、原子操作 +- **生产就绪**: 优雅关闭、错误恢复、完善的安全机制 +- **双重认证体系**: 管理端与代理端认证分离,代理认证支持全局和分组级别密钥 + +## 支持的 AI 服务 + +GPT-Load 作为透明代理服务,完整保留各 AI 服务商的原生 API 格式: + +- **OpenAI 格式**: 官方 OpenAI API、Azure OpenAI、以及其他 OpenAI 兼容服务 +- **Google Gemini 格式**: Gemini Pro、Gemini Pro Vision 等模型的原生 API +- **Anthropic Claude 格式**: Claude 系列模型,支持高质量的对话和文本生成 diff --git a/apps/gpt-load/README_en.md b/apps/gpt-load/README_en.md new file mode 100644 index 0000000..7477599 --- /dev/null +++ b/apps/gpt-load/README_en.md @@ -0,0 +1,107 @@ +# GPT-Load + +A high-performance, enterprise-grade AI API transparent proxy service designed specifically for enterprises and developers who need to integrate multiple AI services. Built with Go, featuring intelligent key management, load balancing, and comprehensive monitoring capabilities, designed for high-concurrency production environments. + +![](https://cdn.jsdelivr.net/gh/xiaoY233/PicList@main/public/assets/GPT-Load.png) + +![](https://img.shields.io/badge/Copyright-arch3rPro-ff9800?style=flat&logo=github&logoColor=white) + +For detailed information, please check the [Official Documentation](https://www.gpt-load.com/docs) + +## Features + +- **Transparent Proxy**: Fully preserves native API formats, supporting OpenAI, Google Gemini, Anthropic Claude, and other formats +- **Intelligent Key Management**: High-performance key pool with group management, automatic rotation, and fault recovery +- **Load Balancing**: Supports weighted load balancing across multiple upstream endpoints to improve service availability +- **Smart Fault Handling**: Automatic key blacklist management and recovery mechanism to ensure service continuity +- **Dynamic Configuration**: System settings and group configurations support hot reload, taking effect without restart +- **Enterprise Architecture**: Distributed master-slave deployment with horizontal scaling and high availability support +- **Modern Management**: Vue 3-based web management interface, intuitive and user-friendly +- **Comprehensive Monitoring**: Real-time statistics, health checks, detailed request logging +- **High-Performance Design**: Zero-copy streaming, connection pool reuse, atomic operations +- **Production Ready**: Graceful shutdown, error recovery, comprehensive security mechanisms +- **Dual Authentication System**: Separation of management and proxy authentication, proxy authentication supports global and group-level keys + +## Supported AI Services + +GPT-Load serves as a transparent proxy service, fully preserving the native API formats of various AI service providers: + +- **OpenAI Format**: Official OpenAI API, Azure OpenAI, and other OpenAI-compatible services +- **Google Gemini Format**: Native API for Gemini Pro, Gemini Pro Vision, and other models +- **Anthropic Claude Format**: Claude series models, supporting high-quality conversation and text generation + +## Quick Start + +### Default Configuration + +After deployment, access the service through your web browser to begin setup. For first-time use, it's recommended to: + +1. Configure API keys for different AI service providers +2. Set up load balancing and failover policies +3. Configure monitoring and logging preferences +4. Test the proxy endpoints with your applications + +### API Integration + +GPT-Load maintains full compatibility with original AI service APIs, allowing seamless integration: + +- Use your existing OpenAI SDK/libraries +- Simply change the base URL to your GPT-Load instance +- All request/response formats remain unchanged +- Authentication handled transparently + +## Core Capabilities + +### Intelligent Key Management + +- **Key Pool**: Centralized management of API keys across multiple providers +- **Auto Rotation**: Intelligent key switching based on usage quotas and rate limits +- **Fault Recovery**: Automatic detection and recovery of failed keys +- **Group Management**: Organize keys by project, team, or usage patterns + +### Load Balancing & High Availability + +- **Multi-Upstream Support**: Distribute requests across multiple AI service endpoints +- **Weighted Routing**: Configure traffic distribution based on endpoint capacity +- **Health Monitoring**: Continuous endpoint health checks and automatic failover +- **Circuit Breaker**: Prevent cascade failures with intelligent request routing + +### Monitoring & Analytics + +- **Real-time Metrics**: Request rates, response times, error rates, and usage statistics +- **Detailed Logging**: Comprehensive request/response logging for debugging and audit +- **Health Dashboard**: Visual monitoring of system status and performance metrics +- **Alert System**: Configurable alerts for system anomalies and threshold breaches + +### Security & Compliance + +- **Authentication**: Dual-level authentication for management and API access +- **Rate Limiting**: Configurable rate limits per key, user, or endpoint +- **Access Control**: Fine-grained permissions and access policies +- **Data Privacy**: No request content logging, ensuring data privacy compliance + +## Architecture + +### Distributed Deployment + +- **Master-Slave Architecture**: Scalable deployment with automatic failover +- **Horizontal Scaling**: Add instances dynamically based on load requirements +- **State Synchronization**: Consistent configuration and state across instances +- **Zero-Downtime Updates**: Rolling updates without service interruption + +### Performance Optimization + +- **Connection Pooling**: Efficient connection reuse for upstream services +- **Streaming Support**: Zero-copy streaming for large responses +- **Caching**: Intelligent response caching where appropriate +- **Async Processing**: Non-blocking request handling for maximum throughput + +## Related Links + +- **Official Website**: [https://www.gpt-load.com](https://www.gpt-load.com) +- **GitHub Repository**: [https://github.com/tbphp/gpt-load](https://github.com/tbphp/gpt-load) +- **Official Documentation**: [https://www.gpt-load.com/docs](https://www.gpt-load.com/docs) +- **API Reference**: [https://www.gpt-load.com/docs/api](https://www.gpt-load.com/docs/api) + +--- +For detailed configuration and usage instructions, please refer to [GPT-Load Official Documentation](https://www.gpt-load.com/docs). \ No newline at end of file diff --git a/apps/gpt-load/data.yml b/apps/gpt-load/data.yml new file mode 100644 index 0000000..7cd5ed2 --- /dev/null +++ b/apps/gpt-load/data.yml @@ -0,0 +1,27 @@ +name: GPT-Load +tags: + - AI / 大模型 +title: 智能密钥轮询的多渠道 AI 代理 +description: GPT-Load 是一个高性能、企业级的 AI 接口透明代理服务,专门为需要集成多种 AI 服务的企业和开发者设计。采用 Go 语言开发,具备智能密钥管理、负载均衡和完善的监控功能。 +additionalProperties: + key: gpt-load + name: GPT-Load + tags: + - AI + shortDescZh: 智能密钥轮询的多渠道 AI 代理 + shortDescEn: Intelligent key rotation multi-channel AI proxy + description: + en: A high-performance, enterprise-grade AI API transparent proxy service designed specifically for enterprises and developers who need to integrate multiple AI services. Built with Go, featuring intelligent key management, load balancing, and comprehensive monitoring capabilities. + zh: 一个高性能、企业级的 AI 接口透明代理服务,专门为需要集成多种 AI 服务的企业和开发者设计。采用 Go 语言开发,具备智能密钥管理、负载均衡和完善的监控功能。 + zh-Hant: 一個高性能、企業級的 AI 接口透明代理服務,專門為需要集成多種 AI 服務的企業和開發者設計。採用 Go 語言開發,具備智能密鑰管理、負載均衡和完善的監控功能。 + type: website + crossVersionUpdate: true + limit: 0 + recommend: 0 + website: https://www.gpt-load.com + github: https://github.com/tbphp/gpt-load + document: https://www.gpt-load.com/docs + memoryRequired: 1024 + architectures: + - amd64 + - arm64 diff --git a/apps/gpt-load/latest/.env.sample b/apps/gpt-load/latest/.env.sample new file mode 100644 index 0000000..26189ee --- /dev/null +++ b/apps/gpt-load/latest/.env.sample @@ -0,0 +1,43 @@ +# 服务器配置 +PORT=3001 +HOST=0.0.0.0 + +# 服务器读取、写入和空闲连接的超时时间(秒) +SERVER_READ_TIMEOUT=60 +SERVER_WRITE_TIMEOUT=600 +SERVER_IDLE_TIMEOUT=120 +SERVER_GRACEFUL_SHUTDOWN_TIMEOUT=10 + +# 从节点标识 +IS_SLAVE=false + +# 时区 +TZ=Asia/Shanghai + +# 认证配置 是必需的,用于保护管理 API 和 UI 界面 +AUTH_KEY=sk-123456 + +# 数据库配置 默认不填写,使用./data/gpt-load.db的SQLite +# MySQL 示例: +# DATABASE_DSN=root:123456@tcp(mysql:3306)/gpt-load?charset=utf8mb4&parseTime=True&loc=Local +# PostgreSQL 示例: +# DATABASE_DSN=postgres://postgres:123456@postgres:5432/gpt-load?sslmode=disable + +# Redis配置 默认不填写,使用内存存储 +# REDIS_DSN=redis://redis:6379/0 + +# 并发数量 +MAX_CONCURRENT_REQUESTS=100 + +# CORS配置 +ENABLE_CORS=true +ALLOWED_ORIGINS=* +ALLOWED_METHODS=GET,POST,PUT,DELETE,OPTIONS +ALLOWED_HEADERS=* +ALLOW_CREDENTIALS=false + +# 日志配置 +LOG_LEVEL=info +LOG_FORMAT=text +LOG_ENABLE_FILE=true +LOG_FILE_PATH=./data/logs/app.log diff --git a/apps/gpt-load/latest/data.yml b/apps/gpt-load/latest/data.yml new file mode 100644 index 0000000..bd572cf --- /dev/null +++ b/apps/gpt-load/latest/data.yml @@ -0,0 +1,19 @@ +additionalProperties: + formFields: + - default: 3001 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Port + labelZh: 端口 + required: true + rule: paramPort + type: number + - default: "gpt-load-sk" + edit: true + envKey: AUTH_KEY + labelEn: API Authentication Key + labelZh: API认证密钥 + random: true + required: true + rule: paramComplexity + type: password diff --git a/apps/gpt-load/latest/docker-compose.yml b/apps/gpt-load/latest/docker-compose.yml new file mode 100644 index 0000000..357f8cd --- /dev/null +++ b/apps/gpt-load/latest/docker-compose.yml @@ -0,0 +1,18 @@ +services: + gpt-load: + image: ghcr.io/tbphp/gpt-load:latest + container_name: ${CONTAINER_NAME} + restart: always + ports: + - ${PANEL_APP_PORT_HTTP}:3001 + networks: + - 1panel-network + volumes: + - ./data:/app/data + environment: + - AUTH_KEY=${AUTH_KEY} + labels: + createdBy: "Apps" +networks: + 1panel-network: + external: true diff --git a/apps/gpt-load/logo.png b/apps/gpt-load/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..18022d62041d369b576f99503872a4c201839efd GIT binary patch literal 8752 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 S*scFnPnZ~3=)c!>j{ZNe_y)!R literal 0 HcmV?d00001