tbphp 2b23d8a62a feat(ui): 补齐权重、分组启停与日志路由入口 (#572)
* feat(ui): 补齐权重、分组启停与日志路由入口

订阅账号卡片支持调度权重(#535):徽章行只在手动权重时露出 chip,
点击一次完成展开并进入编辑;权重面板落在展开区代理面板之上,两块上下堆叠。
自动权重等同代理的继承态,不在折叠态制造视觉噪音。

代理模式改用分段控件,三个模式直接可见;表单不再折行,地址栏独自吸收
剩余宽度。分段控件新增 xs 尺寸,与同排输入框、按钮统一 26px,
顺带修掉密钥列表权重编辑器原本 30px 与 26px 不齐的问题。

分组列表支持快速启停(#554):开关并入状态列,与徽章相邻以区分
「我关的」和「凭据不可用」。集合项新增 enabled 字段——status 还叠加了
weight_manual 为 0 的历史数据,拿它当开关会出现点击后状态不变的假故障。
追加凭据改为纯图标,省下的宽度抵掉状态列扩宽,总表宽反而更窄。

模型列表展示归属分组(#555):上游行挂分组 chip,最多两枚、其余折叠为 +N,
数据本就随列表返回,此前未被消费。

请求日志路由拆成访问密钥与路由两列(#555):路由列首行渠道图标加分组名、
次行凭据编号,分组名可点击就地筛选。按各列实际内容重算宽度,
压出的空间正好装下新列,总宽与拆列前持平。

* fix(ui): 修正开关反馈延迟、按钮内边距与列举分隔符

分组开关此前绑查询数据,而 AppSwitch 是纯受控组件,点击后要等请求与
refetch 走完才翻转,看起来是个卡住的开关。改为本地乐观置位,请求结束
(成功交还 refetch 结果、失败回滚原值)后再交还查询数据。

代理指示器的按钮形态补上 padding/font 复位:容器是固定 22×22 的
border-box,UA 默认内边距会把 13px 图标挤变形。

模型分组折叠提示原先硬编码中文顿号,会漏进英文与日文界面,改用
Intl.ListFormat 按当前语言格式化。实测须用 conjunction + narrow:
narrow 去掉「和 / and」只留分隔符,而 unit 类型在中日文下根本不插
分隔符,会把名字连成一串。

* fix(monitor): 修正日志骨架屏列数

路由列拆成访问密钥与路由两列后,非访问密钥视图的列头与 grid 都是 9 列,
骨架屏仍按 8 列渲染,加载时与表头错位。两处 SkeletonSurface 一并修正。

* refactor(ui): 撤除分组集合 enabled 字段并精简注释

开关改由 status 派生:weight_manual 为 0 虽然也判定 disabled,但该值经
接口限定在 1~100,只有直接改库才能触发,为此新增响应字段与两个测试
超出了本次 UI 补齐的范围。后端与测试恢复原状,本 PR 回到纯前端改动。

同时精简全部新增注释,只保留解释非显然决策的部分,去掉代码本身已经
说清楚的描述。

* feat(monitor): 日志显示凭据掩码并补齐交互细节

日志响应新增 credential_name:按 ID 从凭据注册表取密文解密后算掩码,
订阅账号给邮箱掩码、API 密钥给密钥掩码。密文常驻内存,整个过程不读
数据库,一页内重复出现的凭据只解密一次;注册表里没有的凭据留空,
前端据此显示「已删除 · #id」,与访问密钥、分组共用同一套回退。

分组开关改走设置页同一条缓存失效链路,切换后进入详情页不再需要刷新。

日志中可点击就地筛选的值扩展到访问密钥、分组、凭据、模型四处,样式
提取为全局 filterable-value,此前两个组件各维护一套雷同规则。

订阅卡片的权重徽标与代理徽标统一改用 AppTooltip 并提示可点击编辑;
模型页的分组 chip 直达该分组的模型 tab;日志详情的凭据后增加复制按钮,
与 request_id 的复制控件同尺寸同图标。

* fix(models): 详情抽屉的分组链接直达模型 tab

与模型列表的分组 chip 保持一致,从模型上下文点进分组不再落到凭据 tab。

* fix: 修复样式

* fix: 访问密钥模型页面修复
2026-09-05 21:41:41 +08:00
2025-07-02 17:15:10 +08:00
2026-08-27 22:48:16 +08:00

GPT-Load

GPT-Load

A self-hosted AI gateway for multi-channel, multi-credential setups

API keys, subscription accounts, traffic scheduling, failure handling, request logs, and usage accounting — behind a single entry point.

English · 中文 · 日本語 | Official Website

Release Docker Go License

tbphp/gpt-load | Trendshift Featured|HelloGitHub


Sponsors

Become a sponsor

Sponsor details (collapsible)
AxisNow Protect and accelerate websites and APIs, serving users in mainland China and around the world, and extend acceleration and security capabilities to native/mobile apps through a client SDK — self-built private-deployment CDN | subscription-based high-protection CDN | an independently controllable, flexibly composable CDN network.
APIMart Thanks to APIMart for sponsoring this project! APIMart is a low-cost API platform for AI image & video generation — GPT-Image-2 from $0.006/image, 160+ images per dollar. One async API covers both image and video: submit a task, get an ID, fetch results via polling or callback. Batch tens of thousands of images without timeouts, switch models without changing code. Pay-as-you-go with no monthly fee — sign up here to get started.

Why GPT-Load

Your application only needs one base URL and one AccessKey. Providers, accounts, credentials, models, and routing policy are all configured in the management UI.

GPT-Load unified access and upstream routing architecture
  • One gateway, native protocols — Manage official APIs, cloud platforms, model services, and compatible relays together while clients keep their OpenAI, Anthropic, or Gemini native interfaces.
  • One mechanism for API keys and subscriptions — Codex, Claude, Antigravity, Grok, and API-key channels share credential management, scheduling, and health handling.
  • Scheduling and failure isolation built in — Multi-credential scheduling, automatic weighting, retries, cooldown, blacklisting, and session affinity reduce the impact of overloaded or failing credentials.
  • Observable, self-hosted, and simple to deploy — Inspect health, routes, logs, usage, and cost estimates in an embedded UI backed by SQLite, MySQL, or PostgreSQL with local credential encryption.

Quick start

Warning

If you are using 1.x, read Moving from 1.x first. 2.0 cannot open, import, or migrate 1.x data in place.

1. Start the service

Requires Docker and Docker Compose.

git clone --depth 1 https://github.com/tbphp/gpt-load.git
cd gpt-load

cp .env.example .env
docker compose up -d

Confirm the service is up:

curl --fail http://127.0.0.1:3001/health

The first start generates a management key. Read it and store it safely:

docker compose exec gpt-load sh -c 'cat /app/data/auth.key'

Open http://127.0.0.1:3001 and sign in to the console with that key.

You can also set AUTH_KEY explicitly in .env before starting. By default the service listens on the loopback address only and is not exposed to the internet.

2. Initial configuration

Initial setup takes three steps:

  1. Add a channel — Choose an upstream service and add one or more API keys. For subscription channels, complete the OAuth flow or import credentials as prompted.
  2. Create a group — Pick a channel, then configure available models and runtime policy.
  3. Create an AccessKey — Set the groups and client protocols it may use, then give the generated AccessKey to your application.
OAuth callback ports for subscription channels

The Codex, Claude, and Antigravity OAuth clients use fixed callback ports. Compose publishes them on the address configured by HOST, which defaults to 127.0.0.1; setting HOST=0.0.0.0 also publishes these callback ports on all host interfaces. Because the ports are fixed by the upstream clients, only one default Compose instance can run on a host at a time.

When working over SSH or from a remote browser, the browser's localhost may not reach GPT-Load — paste the full callback URL into the authorization dialog to finish the flow.

Screenshots

Groups — View channels, models, credential counts, and health in one place

GPT-Load groups overview

Subscription accounts — Track account availability, quota windows, reset times, and runtime diagnostics

GPT-Load subscription accounts and quota status

AccessKey read-only home — Sign in with an AccessKey to view only its own groups, models, requests, usage, and cost allowance

GPT-Load AccessKey read-only home

Usage and cost — Review request trends, cache hit rate, token categories, and cost estimates

GPT-Load usage and cost monitoring

Scope

Client protocols

Protocol Main entry
OpenAI Chat Completions POST /v1/chat/completions
OpenAI Responses /v1/responses and its resource paths
OpenAI Images POST /v1/images/...
OpenAI Embeddings POST /v1/embeddings
Anthropic Messages POST /v1/messages
Gemini /v1beta/models/...

Each channel declares exactly which protocols and capabilities it can execute. GPT-Load converts between supported capabilities, but it is not a general-purpose any-protocol, any-JSON translator.

Embeddings initially uses the native OpenAI-compatible wire only on the OpenAI, OpenRouter, and OpenAI Compatible API-key channels; subscription channels and protocol conversion are not supported. An AccessKey without a protocol filter keeps its existing “all enabled protocols” behavior and therefore gains Embeddings access after upgrade. Least-privilege deployments should configure an explicit protocol filter.

Built-in channels

  • Official and cloud — OpenAI, Anthropic, Gemini, xAI, Azure OpenAI, AWS Bedrock, Google Vertex AI
  • Model services — DeepSeek, Moonshot AI, SiliconFlow, Zhipu AI, Alibaba, Volcengine, OpenRouter, Groq
  • Subscription — Codex, Claude, Antigravity, Grok
  • Custom — OpenAI Compatible (any compatible relay)

Deployment and data

Docker Compose uses application-managed SQLite by default. Data lives in the gpt-load-data named volume and includes the database, auth.key, and encryption.key.

Important

encryption.key decrypts channel credentials. When backing up or migrating, the database and the key must be kept together. Once the key is lost or replaced, existing encrypted credentials cannot be recovered, and this version does not support master key rotation.

Using an external database

Use the unified DATABASE_DSN to connect SQLite, MySQL, or PostgreSQL:

mysql://user:password@db.example:3306/gpt_load?charset=utf8mb4&collation=utf8mb4_bin
postgres://user:password@db.example:5432/gpt_load?sslmode=require

Common operations:

docker compose logs -f      # view logs
docker compose pull && docker compose up -d   # update to the latest 2.x image
docker compose stop         # stop the service

The official Compose file uses ghcr.io/tbphp/gpt-load:2. Before GA, 2 tracks verified 2.0 Beta and RC releases; after GA, it tracks stable 2.x releases only. Exact image tags omit the Git tag's v prefix (for example, 2.0.0-beta.25), while 2.0-beta remains the 2.0 Beta channel. latest remains on 1.x.

Using a native binary

Download the build for your platform from GitHub Releases, and verify it against the bundled SHA256SUMS first:

chmod +x ./gpt-load-linux-amd64

HOST=127.0.0.1 DATA_DIR=./data ./gpt-load-linux-amd64

Then open http://127.0.0.1:3001. Portable builds are provided for five targets across Linux, macOS (amd64 / arm64), and Windows; gpt-load-windows-amd64.exe keeps running in the foreground as before.

Windows desktop users can instead download gpt-load-windows-setup.exe. After one administrator approval, Setup installs and starts a low-privilege Windows service, enables automatic startup, and creates desktop and Start Menu shortcuts to the GPT-Load management page. Setup displays the generated management key before it finishes; save it before closing the page. The protected copy remains at %ProgramData%\GPT-Load\data\auth.key. Service configuration and its .env live in %ProgramData%\GPT-Load, with persistent data in %ProgramData%\GPT-Load\data.

Installing a newer Setup stops the service gracefully before updating it. Windows uninstall removes the program and service but preserves data. Advanced users can still manage an installed service with gpt-load-windows-amd64.exe service start|stop|restart|status.

Environment configuration

At startup, the application reads .env in the current directory; existing process environment variables take precedence. Unless noted otherwise, changes require restarting the process or container; see .env.example for the common configuration template.

Show all environment variables
Variable Default Description
HOST 127.0.0.1 Native listening address, and the default host address for Compose's main port and OAuth callback ports; Compose always listens on 0.0.0.0 inside the container.
PORT 3001 HTTP service port, must be 1–65535; Compose also uses it for the container port, host publishing, and health check.
BIND_ADDRESS Empty, inherits HOST Compose only; overrides the host publishing address for the main service port without changing OAuth callback ports.
OAUTH_CALLBACK_BIND_ADDRESS Empty, inherits HOST Compose only; overrides the host publishing address for the fixed OAuth callback ports 1455, 54545, and 51121.
GRACEFUL_SHUTDOWN_TIMEOUT 10 Maximum time to wait for requests after a stop signal, positive integer in seconds.
CONTAINER_STOP_GRACE_PERIOD 15s Docker duration to wait before Compose force-stops the container; should be longer than GRACEFUL_SHUTDOWN_TIMEOUT.
READ_TIMEOUT 60 HTTP request read timeout, positive integer in seconds.
IDLE_TIMEOUT 120 HTTP keep-alive idle connection timeout, positive integer in seconds.
DATA_DIR ./data Directory for the managed database, auth.key, encryption.key, and runtime state; official Compose uses /app/data, while the Windows Setup service uses %ProgramData%\GPT-Load\data.
DATABASE_DSN Empty, uses ${DATA_DIR}/gpt-load.db Empty uses application-managed SQLite; non-empty values support SQLite paths or URLs, MySQL URLs, and PostgreSQL URLs, and are treated as operator-managed external databases. Container file paths must be inside a mounted directory.
DATABASE_MAX_OPEN_CONNECTIONS 10 Maximum open connections for MySQL and PostgreSQL, positive integer. SQLite always uses one connection.
DATABASE_MAX_IDLE_CONNECTIONS 5 Maximum idle connections for MySQL and PostgreSQL, positive integer and no greater than DATABASE_MAX_OPEN_CONNECTIONS. SQLite always uses one connection.
AUTH_KEY Empty, reads or generates ${DATA_DIR}/auth.key Bearer key for the management UI and /api management API, not a data-plane AccessKey.
ENCRYPTION_KEY Empty, reads or generates ${DATA_DIR}/encryption.key Encrypts channel credentials; changing or losing it makes existing credentials undecryptable, so back it up with the database.
HTTP_PROXY Empty Environment proxy for HTTP upstream requests.
HTTPS_PROXY Empty Environment proxy for HTTPS upstream requests.
NO_PROXY Empty Comma-separated hosts, domains, or IPs that bypass the environment proxy.
LOG_LEVEL info Supports panic, fatal, error, warn, warning, info, debug, and trace; invalid values warn and fall back to info.
LOG_FORMAT text Supports text and json; any other value fails startup.
MODELS_DEV_AUTO_SYNC_ENABLED Unset, initial default true When unset, uses the persisted management UI setting; when set, forces Models.dev auto-sync on or off and makes the same UI option read-only.

Environment proxies apply only when no proxy is specified on the credential, group, or global settings.

Production considerations

  • The service listens on 127.0.0.1 only by default. For remote access, expose it through a controlled network or a TLS reverse proxy, and configure ACLs and firewall rules.
  • Manage AUTH_KEY and ENCRYPTION_KEY carefully. Never commit real keys to a repository, log, screenshot, or public issue.
  • 2.0 is designed for a single application instance. Instances do not share state, so horizontal scaling is not supported.
  • Usage and cost are estimates derived from upstream responses. They support operational analysis and capacity planning, and do not equal a provider invoice or a financial reconciliation.
  • Subscription channels depend on upstream OAuth and compatibility protocols and may change as upstreams change. Only connect accounts you are entitled to use, and follow each provider's terms.
  • In OpenAI Responses, stateful requests relying on previous_response_id, conversation, or an existing resource ID are only reliable with a single credential, or with an upstream that shares resources across credentials.

Moving from 1.x

Warning

GPT-Load 2.0 is a complete rewrite. It cannot open, import, or migrate 1.x data in place.

Deploy 2.0 with its own database, DATA_DIR, port, and Docker volume. Cut traffic over only after verification, and keep the original 1.x deployment until the rollback window closes. Documentation for the 1.4.x maintenance line is at the official docs.

Open-source dependencies

Some of GPT-Load's capabilities build on these projects, with thanks:

Project Role License
Bifrost Core Provider authentication, request/response conversion, streaming, usage normalization Apache-2.0
CLIProxyAPI OAuth and execution adapter for subscription channels MIT
Lobe Icons Channel brand icons in the management UI MIT

GPT-Load owns credential storage, account selection, scheduling, retry, health, affinity, logging, and usage policy. Third-party notices are in THIRD_PARTY_NOTICES.md, full license texts in LICENSES/, and each release ships a CycloneDX SBOM covering the Go dependency graph.

Channel icons identify their respective upstream providers. All trademarks belong to their owners; this project is not affiliated with or endorsed by them.

Project support

OpenAI
Platform support
LINUX DO
Community support
DigitalOcean
Infrastructure support

MIT License · Third-party notices · Security policy

S
Description
Self-hosted AI gateway for multi-channel, multi-credential setups — API keys and subscription accounts, scheduling, failover, request logs and usage. 自托管 AI 网关:多渠道多凭据统一接入,含密钥与订阅账号、调度容错、日志与用量。
https://www.gpt-load.com
Readme MPL-2.0 Apache-2.0 Inno-Setup MIT
27 MiB
0 Stars 1 Watchers 0 Forks
Languages
Go 65.9%
Vue 20.8%
TypeScript 12.1%
CSS 0.3%
Shell 0.3%
Other 0.5%