Skip to content

Repository files navigation

sub2api-pricing-api

sub2api模型定价分组配置只读导出为公开 JSON 接口, 供文档站 / 官网的「模型广场」直接消费。

一个单文件二进制,只做三件事:

  1. 只读连接 sub2api 的 Postgres,读出活跃分组(groups)、活跃渠道及其自定义定价(channels / channel_groups / channel_model_pricing)。
  2. 读取 sub2api 数据目录里的 model_pricing.json(LiteLLM 口径的官方参考价)。
  3. 合成快照并通过带 CORS 的 HTTP 接口暴露,后台定时刷新。

不写库、不读任何用户/密钥数据、不需要 sub2api 的管理员 token。

价格口径

每个模型给出四个价格,单位统一为 每百万 token

字段 币种 含义 来源
list_price USD 原价 model_pricing.json 里的官方参考价
base_price USD 计费基准 渠道自定义价(channel_model_pricing)优先,否则等于原价
actual_price USD 实际折扣价 base_price × 分组 rate_multiplier
actual_price_cny CNY 实际折扣价(人民币) actual_price × exchange.cny_per_usd
peak_price USD 高峰期价格 base_price × peak_rate_multiplier(仅当分组开启高峰计费)

人民币汇率

sub2api 的账户余额单位是「美元额度」,充值 N 元到账 N × BALANCE_RECHARGE_MULTIPLIER 美元额度, 实付还要加上 RECHARGE_FEE_RATE(百分比)的手续费。因此响应顶层的 exchange 给出:

cny_per_usd = (1 / balance_recharge_multiplier) × (1 + recharge_fee_rate / 100)
"exchange": {
  "cny_per_usd": 1,
  "balance_recharge_multiplier": 1,
  "recharge_fee_rate_percent": 0,
  "source": "sub2api settings: BALANCE_RECHARGE_MULTIPLIER, RECHARGE_FEE_RATE"
}

需要固定汇率时用 CNY_PER_USD 环境变量覆盖,此时 source 会变成 env: CNY_PER_USD

discount_vs_list = actual_price / list_price(例如 0.8 表示 8 折)。 分组层面另有 discount_percent(倍率 < 1 时给出,0.820)。

价格为 null 表示该项未配置:官方定价表里没有这个模型,或该项在表里是 0。

分组的模型清单从哪来

按顺序合并、大小写不敏感去重(先出现者胜,后出现者只补齐缺失的渠道价):

  1. groups.models_list_config.models —— 管理端维护的分组模型清单,标记为 source: "group_list"
  2. 该分组关联的活跃渠道的 channel_model_pricing.modelschannels.model_mapping 的 key,标记为 source: "channel"

* 的通配符条目会被跳过。非 composite 分组只收平台一致的条目(避免跨平台串台)。

接口

路径 说明
GET /api/v1/pricing 完整快照:分组配置 + 每个分组下所有模型的三档价格
GET /api/v1/groups 同上但去掉 models,只要分组配置
GET /api/v1/models 以模型为主视角的扁平视图:每个模型 + 其在各分组下的实际价与最低倍率
GET /healthz 存活与最近一次刷新状态

响应带 ETag / Cache-Control: public, max-age=60,支持 If-None-Match 与 gzip(响应体在刷新时预压缩)。

/api/v1/pricing 响应示例

{
  "generated_at": "2026-07-29T01:23:45Z",
  "currency": "USD",
  "price_unit": "per_1m_tokens",
  "exchange": {
    "cny_per_usd": 1,
    "balance_recharge_multiplier": 1,
    "recharge_fee_rate_percent": 0,
    "source": "sub2api settings: BALANCE_RECHARGE_MULTIPLIER, RECHARGE_FEE_RATE"
  },
  "source": {
    "pricing_models": 218,
    "pricing_sha256": "",
    "pricing_origin": "file:/data/model_pricing.json",
    "group_count": 4,
    "channel_count": 1
  },
  "groups": [
    {
      "id": 2,
      "name": "GPT codex",
      "platform": "openai",
      "rate_multiplier": 0.5,
      "discount_percent": 50,
      "is_exclusive": false,
      "peak": { "enabled": false, "start": "", "end": "", "rate_multiplier": 1 },
      "image": { "rate_independent": false, "rate_multiplier": 1 },
      "video": { "rate_independent": false, "rate_multiplier": 1 },
      "web_search_price_per_call": null,
      "model_count": 13,
      "models": [
        {
          "name": "gpt-5.4",
          "platform": "openai",
          "source": "group_list",
          "pricing_key": "gpt-5.4",
          "list_price":       { "input": 1.25, "output": 10, "cache_write": null, "cache_read": 0.125 },
          "base_price":       { "input": 1.25, "output": 10, "cache_write": null, "cache_read": 0.125 },
          "actual_price":     { "input": 0.625, "output": 5, "cache_write": null, "cache_read": 0.0625 },
          "actual_price_cny": { "input": 0.625, "output": 5, "cache_write": null, "cache_read": 0.0625 },
          "rate_multiplier": 0.5,
          "discount_vs_list": 0.5,
          "channel_override": false,
          "meta": { "max_input_tokens": 400000, "mode": "chat", "provider": "openai" }
        }
      ]
    }
  ]
}

配置

环境变量 默认值 说明
LISTEN :8090 监听地址
DATABASE_URL 完整 DSN;给了就忽略下面的 DB_*
DB_HOST / DB_PORT postgres / 5432
DB_USER / DB_PASSWORD / DB_NAME sub2api / — / sub2api 建议用只读账号,见下
DB_SSLMODE disable
PRICING_FILE /data/model_pricing.json sub2api 数据目录里的官方定价表
PRICING_URL 文件不存在时的回落地址
REFRESH_INTERVAL 5m 快照刷新间隔
INCLUDE_EXCLUSIVE false 是否输出专属分组(is_exclusive
EXCLUDE_GROUPS 额外屏蔽的分组名,逗号分隔,大小写不敏感
CNY_PER_USD 固定人民币汇率;留空则从 sub2api 充值设置推导
CORS_ORIGIN * Access-Control-Allow-Origin
SITE_NAME / SITE_API_BASE_URL 原样放进响应的 site 字段;后者留空时取 sub2api 的 api_base_url 设置
DESCRIPTION 原样放进响应的 description

部署

推荐直接并入 sub2api 的 docker-compose.yml,复用同一个网络与数据目录:

  pricing-api:
    build: /home/ubuntu/sub2api-pricing-api   # 或 image: ghcr.io/…
    container_name: sub2api-pricing-api
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
    volumes:
      - ./data:/data:ro          # 只读挂载,拿 model_pricing.json
    environment:
      - LISTEN=:8090
      - DB_HOST=postgres
      - DB_USER=${PRICING_DB_USER:-sub2api_ro}
      - DB_PASSWORD=${PRICING_DB_PASSWORD:?required}
      - DB_NAME=${POSTGRES_DB:-sub2api}
      - PRICING_FILE=/data/model_pricing.json
      - REFRESH_INTERVAL=5m
      - TZ=${TZ:-Asia/Shanghai}
    ports:
      - "127.0.0.1:8090:8090"
    networks:
      - sub2api-network

建一个只读账号

CREATE ROLE sub2api_ro LOGIN PASSWORD '';
GRANT CONNECT ON DATABASE sub2api TO sub2api_ro;
GRANT USAGE ON SCHEMA public TO sub2api_ro;
GRANT SELECT ON groups, channels, channel_groups, channel_model_pricing, settings TO sub2api_ro;

通过 nginx 暴露到公网

location ^~ /pricing-api/ {
    proxy_pass http://127.0.0.1:8090/;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
}

开发

go test ./...
go run .            # 需要 DB_PASSWORD / PRICING_FILE
docker build -t sub2api-pricing-api .

License

MIT

About

把 sub2api 的模型定价与分组配置只读导出为公开 JSON 接口

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages