A Simple, Beautiful, and Elegant LLM API Aggregation & Load Balancing Service for Individuals
English | 简体中文
- 🔀 Multi-Channel Aggregation - Connect multiple LLM provider channels with unified management
- 🔑 Multi-Key Support - Support multiple API keys for a single channel
- ⚡ Smart Selection - Multiple endpoints per channel, smart selection of the endpoint with the shortest delay
- ⚖️ Load Balancing - Automatic request distribution for stable and efficient service
- 🔄 Protocol Conversion - Seamless conversion between OpenAI Chat / OpenAI Responses / Anthropic / Gemini / Antigravity API formats
- 💰 Price Sync - Automatic model pricing updates
- 🔃 Model Sync - Automatic synchronization of available model lists with channels
- 📊 Analytics - Comprehensive request statistics, token consumption, and cost tracking
- 🎨 Elegant UI - Clean and beautiful web management panel
- 🗄️ Multi-Database Support - Support for SQLite, MySQL, PostgreSQL
- 🏷️ Per-Channel Model Pricing - Independent model pricing configuration for each channel, supporting same model names across different channels with unique pricing
- 🔌 Dynamic Channel Types - Channel types are fetched from backend API, making it easy to add new provider support
Run directly:
docker run -d --name octopus -v /path/to/data:/app/data -p 8080:8080 bestrui/octopusOr use docker compose:
wget https://raw.githubusercontent.com/bestruirui/octopus/refs/heads/dev/docker-compose.yml
docker compose up -dDownload the binary for your platform from Releases, then run:
./octopus startRequirements:
- Go 1.24.4
- Node.js 18+
- pnpm
# Clone the repository
git clone https://github.com/ffflyZzz/octopus.git
cd octopus
# Build frontend
cd web && pnpm install && pnpm run build && cd ..
# Move frontend assets to static directory
mv web/out static/
# Start the backend service
go run main.go start 💡 Tip: The frontend build artifacts are embedded into the Go binary, so you must build the frontend before starting the backend.
Development Mode
cd web && pnpm install && NEXT_PUBLIC_API_BASE_URL="http://127.0.0.1:8080" pnpm run dev
## Open a new terminal, start the backend service
go run main.go start
## Access the frontend at
http://localhost:3000After first launch, visit http://localhost:8080 and log in to the management panel with:
- Username:
admin - Password:
admin
⚠️ Security Notice: Please change the default password immediately after first login.
The configuration file is located at data/config.json by default and is automatically generated on first startup.
Complete Configuration Example:
{
"server": {
"host": "0.0.0.0",
"port": 8080
},
"database": {
"type": "sqlite",
"path": "data/data.db"
},
"log": {
"level": "info"
}
}Configuration Options:
| Option | Description | Default |
|---|---|---|
server.host |
Listen address | 0.0.0.0 |
server.port |
Server port | 8080 |
database.type |
Database type | sqlite |
database.path |
Database connection string | data/data.db |
log.level |
Log level | info |
Database Configuration:
Three database types are supported:
| Type | database.type |
database.path Format |
|---|---|---|
| SQLite | sqlite |
data/data.db |
| MySQL | mysql |
user:password@tcp(host:port)/dbname |
| PostgreSQL | postgres |
postgresql://user:password@host:port/dbname?sslmode=disable |
MySQL Configuration Example:
{
"database": {
"type": "mysql",
"path": "root:password@tcp(127.0.0.1:3306)/octopus"
}
}PostgreSQL Configuration Example:
{
"database": {
"type": "postgres",
"path": "postgresql://user:password@localhost:5432/octopus?sslmode=disable"
}
}💡 Tip: MySQL and PostgreSQL require manual database creation. The application will automatically create the table structure.
All configuration options can be overridden via environment variables using the format OCTOPUS_ + configuration path (joined with _):
| Environment Variable | Configuration Option |
|---|---|
OCTOPUS_SERVER_PORT |
server.port |
OCTOPUS_SERVER_HOST |
server.host |
OCTOPUS_DATABASE_TYPE |
database.type |
OCTOPUS_DATABASE_PATH |
database.path |
OCTOPUS_LOG_LEVEL |
log.level |
OCTOPUS_GITHUB_PAT |
For rate limiting when getting the latest version (optional) |
OCTOPUS_RELAY_MAX_SSE_EVENT_SIZE |
Maximum SSE event size (optional) |
Octopus supports Amp CLI proxy integration, allowing you to use Octopus as a proxy for Amp CLI requests.
Configuration (in data/config.json):
{
"ampcode": {
"enabled": true,
"upstream_url": "https://ampcode.com",
"upstream_api_key": "your-api-key"
}
}| Field | Description | Default |
|---|---|---|
enabled |
Enable Amp CLI proxy | false |
upstream_url |
Amp upstream URL | https://ampcode.com |
upstream_api_key |
Amp API key (optional) | "" |
restrict_management_to_localhost |
Restrict management API to localhost | false |
API Key Priority:
The API key is resolved in the following order:
- Config file:
ampcode.upstream_api_keyin config.json - Environment variable:
AMP_API_KEY - Amp secrets file:
~/.local/share/amp/secrets.json
💡 Tip: If you have Amp CLI installed locally, Octopus can automatically use its stored credentials.
Channels are the basic configuration units for connecting to LLM providers.
Base URL Guide:
The program automatically appends API paths based on channel type. You only need to provide the base URL:
| Channel Type | Auto-appended Path | Base URL | Full Request URL Example |
|---|---|---|---|
| OpenAI Chat | /chat/completions |
https://api.openai.com/v1 |
https://api.openai.com/v1/chat/completions |
| OpenAI Responses | /responses |
https://api.openai.com/v1 |
https://api.openai.com/v1/responses |
| Anthropic | /messages |
https://api.anthropic.com/v1 |
https://api.anthropic.com/v1/messages |
| Gemini | /models/:model:generateContent |
https://generativelanguage.googleapis.com/v1beta |
https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent |
| Antigravity | /v1internal:streamGenerateContent or /v1internal:generateContent |
https://daily-cloudcode-pa.sandbox.googleapis.com |
https://daily-cloudcode-pa.sandbox.googleapis.com/v1internal:streamGenerateContent |
💡 Tip: No need to include specific API endpoint paths in the Base URL - the program handles this automatically.
Antigravity Channel:
Antigravity provides access to Google's Claude models through their internal API:
- Base URL:
https://daily-cloudcode-pa.sandbox.googleapis.com - API Key: Supports both Refresh Token (starting with
1//) and Access Token (starting withya29.) - Auto Token Refresh: When using Refresh Token, the system automatically refreshes access tokens before expiration
- Models: Supports Claude models like
claude-sonnet-4-5-20250929,claude-opus-4-5-20251101, etc.
💡 Tip: The system intelligently detects token type and handles refresh automatically. Refresh tokens are cached and refreshed 5 minutes before expiration.
Groups aggregate multiple channels into a unified external model name.
Core Concepts:
- Group name is the model name exposed by the program
- When calling the API, set the
modelparameter to the group name
Load Balancing Modes:
| Mode | Description |
|---|---|
| 🔄 Round Robin | Cycles through channels sequentially for each request |
| 🎲 Random | Randomly selects an available channel for each request |
| 🛡️ Failover | Prioritizes high-priority channels, switches to lower priority only on failure |
| ⚖️ Weighted | Distributes requests based on configured channel weights |
💡 Example: Create a group named
gpt-4o, add multiple providers' GPT-4o channels to it, then access all channels via a unifiedmodel: gpt-4o.
Manage model pricing information in the system with per-channel pricing support.
Architecture:
The system uses a one-to-many relationship architecture:
- Channel Type → Channels → Models
- Each channel can have independent model pricing
- Same model name can exist across different channels with different prices
Data Sources:
- The system periodically syncs model pricing data from models.dev
- When creating a channel, if the channel contains models not in models.dev, the system automatically creates pricing information for those models, allowing users to set prices manually
- Manual creation of models that exist in models.dev is also supported for custom pricing
Price Priority:
| Priority | Source | Description |
|---|---|---|
| 🥇 High | Channel-Specific Price | Prices configured for specific channel-model combinations |
| 🥈 Medium | Default Price | User-defined default prices in price management page |
| 🥉 Low | models.dev | Auto-synced upstream default prices |
Key Features:
- 🎯 Channel-Based Organization - View and manage models organized by channel tabs
- 💱 Independent Pricing - Set different prices for the same model across different channels
- 🔄 Automatic Cost Calculation - System automatically uses channel-specific prices when calculating request costs
- 📊 Per-Channel Statistics - Track token usage and costs separately for each channel
💡 Example: You can have
claude-sonnet-4at $3.00/$15.00 on Channel A and $2.50/$12.00 on Channel B, with accurate cost tracking for each.
💡 Tip: To override a model's default price for a specific channel, navigate to that channel's tab in the price management page and edit the model's pricing.
Global system configuration.
Statistics Save Interval (minutes):
Since the program handles numerous statistics, writing to the database on every request would impact read/write performance. The program uses this strategy:
- Statistics are first stored in memory
- Periodically batch-written to the database at the configured interval
⚠️ Important: When exiting the program, use proper shutdown methods (likeCtrl+Cor sendingSIGTERMsignal) to ensure in-memory statistics are correctly written to the database. Do NOT usekill -9or other forced termination methods, as this may result in statistics data loss.
from openai import OpenAI
import os
client = OpenAI(
base_url="http://127.0.0.1:8080/v1",
api_key="sk-octopus-P48ROljwJmWBYVARjwQM8Nkiezlg7WOrXXOWDYY8TI5p9Mzg",
)
completion = client.chat.completions.create(
model="octopus-openai", # Use the correct group name
messages = [
{"role": "user", "content": "Hello"},
],
)
print(completion.choices[0].message.content)Edit ~/.claude/settings.json
{
"env": {
"ANTHROPIC_BASE_URL": "http://127.0.0.1:8080",
"ANTHROPIC_AUTH_TOKEN": "sk-octopus-P48ROljwJmWBYVARjwQM8Nkiezlg7WOrXXOWDYY8TI5p9Mzg",
"API_TIMEOUT_MS": "3000000",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
"ANTHROPIC_MODEL": "octopus-sonnet-4-5",
"ANTHROPIC_SMALL_FAST_MODEL": "octopus-haiku-4-5",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "octopus-sonnet-4-5",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "octopus-sonnet-4-5",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "octopus-haiku-4-5"
}
}Edit ~/.codex/config.toml
model = "octopus-codex" # Use the correct group name
model_provider = "octopus"
[model_providers.octopus]
name = "octopus"
base_url = "http://127.0.0.1:8080/v1"Edit ~/.codex/auth.json
{
"OPENAI_API_KEY": "sk-octopus-P48ROljwJmWBYVARjwQM8Nkiezlg7WOrXXOWDYY8TI5p9Mzg"
}- 🐙 bestruirui/octopus - This project is forked from the original Octopus project
- 🙏 looplj/axonhub - The LLM API adaptation module in this project is directly derived from this repository
- 📊 sst/models.dev - AI model database providing model pricing data











