# 770 Readme Cn De79e993

> uni-api

- Skill: `tools-only/770-readme-cn-de79e993` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add tools-only/770-readme-cn-de79e993`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tools-only/770-readme-cn-de79e993/raw
- Safety review: pending (external: skill-scanner PASS, skillspector FAIL)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: tools-only (https://skillmd.com/u/tools-only)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/tools-only/770-readme-cn-de79e993

---

# uni-api

<p align="center">
  <a href="https://t.me/uni_api">
    <img src="https://img.shields.io/badge/Join Telegram Group-blue?&logo=telegram">
  </a>
   <a href="https://hub.docker.com/repository/docker/yym68686/uni-api">
    <img src="https://img.shields.io/docker/pulls/yym68686/uni-api?color=blue" alt="docker pull">
  </a>
</p>

[英文](./README.md) | [中文](./README_CN.md)

## 介绍

如果个人使用的话，one/new-api 过于复杂，有很多个人不需要使用的商用功能，如果你不想要复杂的前端界面，又想要支持的模型多一点，可以试试 uni-api。这是一个统一管理大模型 API 的项目，可以通过一个统一的API 接口调用多种不同提供商的服务，统一转换为 OpenAI 格式，支持负载均衡。目前支持的后端服务有：OpenAI、Anthropic、Gemini、Vertex、Azure、AWS、xai、Cohere、Groq、Cloudflare、OpenRouter、[0-0.pro](https://0-0.pro) 等。

## ✨ 特性

- 无前端，纯配置文件配置 API 渠道。只要写一个文件就能运行起一个属于自己的 API 站，文档有详细的配置指南，小白友好。
- 统一管理多个后端服务，支持 OpenAI、Deepseek、OpenRouter 等其他 API 是 OpenAI 格式的提供商。支持 OpenAI Dalle-3 图像生成。
- 同时支持 Anthropic、Gemini、Vertex AI、Azure、AWS、xai、Cohere、Groq、Cloudflare、[0-0.pro](https://0-0.pro)。Vertex 同时支持 Claude 和 Gemini API。
- 支持 OpenAI、 Anthropic、Gemini、Vertex、Azure、AWS、xai 原生 tool use 函数调用。
- 支持 OpenAI、Anthropic、Gemini、Vertex、Azure、AWS、xai 原生识图 API。
- 支持四种负载均衡。
  1. 支持渠道级加权负载均衡，可以根据不同的渠道权重分配请求。默认不开启，需要配置渠道权重。
  2. 支持 Vertex 区域级负载均衡，支持 Vertex 高并发，最高可将 Gemini，Claude 并发提高 （API数量 * 区域数量） 倍。自动开启不需要额外配置。
  3. 除了 Vertex 区域级负载均衡，所有 API 均支持渠道级顺序负载均衡，提高沉浸式翻译体验。默认不开启，需要配置 `SCHEDULING_ALGORITHM` 为 `round_robin`。
  4. 支持单个渠道多个 API Key 自动开启 API key 级别的轮训负载均衡。
- 支持自动重试，当一个 API 渠道响应失败时，自动重试下一个 API 渠道。
- 支持渠道冷却，当一个 API 渠道响应失败时，会自动将该渠道排除冷却一段时间，不再请求该渠道，冷却时间结束后，会自动将该模型恢复，直到再次请求失败，会重新冷却。
- 支持细粒度的模型超时时间设置，可以为每个模型设置不同的超时时间。
- 支持细粒度的权限控制。支持使用通配符设置 API key 可用渠道的特定模型。
- 支持限流，可以设置每分钟最多请求次数，可以设置为整数，如 2/min，2 次每分钟、5/hour，5 次每小时、10/day，10 次每天，10/month，10 次每月，10/year，10 次每年。默认60/min。
- 支持多个标准 OpenAI 格式的接口：`/v1/chat/completions`，`/v1/responses`，`/v1/images/generations`，`/v1/embeddings`，`/v1/audio/transcriptions`，`/v1/audio/speech`，`/v1/moderations`，`/v1/models`。
- 支持 OpenAI moderation 道德审查，可以对用户的消息进行道德审查，如果发现不当的消息，会返回错误信息。降低后台 API 被提供商封禁的风险。

## 使用方法

启动 uni-api 必须使用配置文件，有两种方式可以启动配置文件：

1. 第一种是使用 `CONFIG_URL` 环境变量填写配置文件 URL，uni-api启动时会自动下载。
2. 第二种就是挂载名为 `api.yaml` 的配置文件到容器内。

### 方法一：挂载 `api.yaml` 配置文件启动 uni-api

必须事先填写完成配置文件才能启动 `uni-api`，必须使用名为 `api.yaml` 的配置文件才能启动 `uni-api`，可以配置多个模型，每个模型可以配置多个后端服务，支持负载均衡。下面是最小可运行的 `api.yaml` 配置文件的示例：

```yaml
providers:
  - provider: provider_name # 服务提供商名称, 如 openai、anthropic、gemini、openrouter，随便取名字，必填
    base_url: https://api.your.com/v1/chat/completions # 后端服务的API地址，必填
    api: sk-YgS6GTi0b4bEabc4C # 提供商的API Key，必填，自动使用 base_url 和 api 通过 /v1/models 端点获取可用的所有模型。
  # 这里可以配置多个提供商，每个提供商可以配置多个 API Key，每个提供商可以配置多个模型。
api_keys:
  - api: sk-Pkj60Yf8JFWxfgRmXQFWyGtWUddGZnmi3KlvowmRWpWpQxx # API Key，用户请求 uni-api 需要 API key，必填
  # 该 API Key 可以使用所有模型，即可以使用 providers 下面设置的所有渠道里面的所有模型，不需要一个个添加可用渠道。
```

`api.yaml` 详细的高级配置：

```yaml
providers:
  - provider: provider_name # 服务提供商名称, 如 openai、anthropic、gemini、openrouter，随便取名字，必填
    base_url: https://api.your.com/v1/chat/completions # 后端服务的API地址，必填
    api: sk-YgS6GTi0b4bEabc4C # 提供商的API Key，必填
    model: # 选填，如果不配置 model，会自动通过 base_url 和 api 通过 /v1/models 端点获取可用的所有模型。
      - gpt-5.2 # 可以使用的模型名称，必填
      - claude-sonnet-4-5-20250929: claude-sonnet-4-5 # 重命名模型，claude-sonnet-4-5-20250929 是服务商的模型名称，claude-3-5-sonnet 是重命名后的名字，可以使用简洁的名字代替原来复杂的名称，选填
      - dall-e-3

  - provider: anthropic
    base_url: https://api.anthropic.com/v1/messages
    api: # 支持多个 API Key，多个 key 自动开启轮训负载均衡，至少一个 key，必填
      - sk-ant-api03-bNnAOJyA-xQw_twAA
      - sk-ant-api02-bNnxxxx
    model:
      - claude-sonnet-4-5-20250929: claude-sonnet-4-5 # 重命名模型，claude-sonnet-4-5-20250929 是服务商的模型名称，claude-sonnet-4-5 是重命名后的名字，可以使用简洁的名字代替原来复杂的名称，选填
      - claude-sonnet-4-5-20250929: claude-sonnet-4-5-think # 重命名模型，claude-sonnet-4-5-20250929 是服务商的模型名称，claude-sonnet-4-5-think 是重命名后的名字，可以使用简洁的名字代替原来复杂的名称，如果重命名后的名字里面有think，则自动转换为 claude 思考模型，默认思考 token 限制为 4096。选填
    tools: true # 是否支持工具，如生成代码、生成文档等，默认是 true，选填
    preferences:
      post_body_parameter_overrides: # 支持自定义请求体参数
        claude-sonnet-4-5-think: # 给模型 claude-sonnet-4-5-think 添加自定义请求体参数
          tools:
            - type: code_execution_20250522 # 给模型 claude-sonnet-4-5-think 添加 code_execution 工具
              name: code_execution
            - type: web_search_20250305 # 给模型 claude-sonnet-4-5-think 添加 web_search 工具，max_uses 表示最多使用 5 次
              name: web_search
              max_uses: 5

  - provider: gemini
    base_url: https://generativelanguage.googleapis.com/v1beta # base_url 支持 v1beta/v1, 仅供 Gemini 模型使用，必填
    api: # 支持多个 API Key，多个 key 自动开启轮训负载均衡，至少一个 key，必填
      - AIzaSyAN2k6IRdgw123
      - AIzaSyAN2k6IRdgw456
      - AIzaSyAN2k6IRdgw789
    model:
      - gemini-3-pro-preview: gemini-3-pro
      - gemini-2.5-flash: gemini-2.5-flash # 重命名后，原来的模型名字 gemini-2.5-flash 无法使用，如果要使用原来的名字，可以在 model 中添加原来的名字，只要加上下面一行就可以使用原来的名字了
      - gemini-2.5-flash
      - gemini-pro-latest: gemini-2.5-pro-search # 可以以 -search 后缀重命名模型，同时在 post_body_parameter_overrides 设置针对此模型的自定义请求体参数即可启用搜索。
      - gemini-2.5-flash: gemini-2.5-flash-think-24576-search # 可以以 -search 后缀重命名模型，同时在 post_body_parameter_overrides 设置针对此模型的自定义请求体参数即可启用搜索，同时支持使用 `-think-数字` 自定义推理预算，可以同时开启也可以单独开启。
      - gemini-2.5-flash: gemini-2.5-flash-think-0 # 支持以 -think-数字 自定义推理预算，当数字为 0 时，表示关闭推理。
      - gemini-embedding-001
      - text-embedding-004
    tools: true
    preferences:
      api_key_rate_limit: 15/min # 每个 API Key 每分钟最多请求次数，选填。默认为 999999/min。支持多个频率约束条件：15/min,10/day
      # api_key_rate_limit: # 可以为每个模型设置不同的频率限制
      #   gemini-2.5-flash: 10/min,500/day
      #   gemini-2.5-pro: 5/min,25/day,1048576/tpr # 1048576/tpr 表示每次请求的 tokens 数量限制为 1048576 个 tokens
      #   default: 4/min # 如果模型没有设置频率限制，使用 default 的频率限制
      api_key_cooldown_period: 60 # 每个 API Key 遭遇 429 错误后的冷却时间，单位为秒，选填。默认为 0 秒, 当设置为 0 秒时，不启用冷却机制。当存在多个 API key 时才会生效。
      api_key_schedule_algorithm: round_robin # 设置多个 API Key 的请求顺序，选填。默认为 round_robin，可选值有：round_robin，random，fixed_priority，smart_round_robin。当存在多个 API key 时才会生效。round_robin 是轮询负载均衡，random 是随机负载均衡，fixed_priority 是固定优先级调度，永远使用第一个可用的 API key。smart_round_robin 是一个基于历史成功率的智能调度算法，详见 FAQ 部分。
      model_timeout: # 模型超时时间，单位为秒，默认 100 秒，选填
        gemini-2.5-pro: 500 # 模型 gemini-2.5-pro 的超时时间为 500 秒
        gemini-2.5-flash: 500 # 模型 gemini-2.5-flash 的超时时间为 500 秒
        default: 10 # 模型没有设置超时时间，使用默认的超时时间 10 秒，当请求的不在 model_timeout 里面的模型时，超时时间默认是 10 秒，不设置 default，uni-api 会使用全局配置的模型超时时间。
      keepalive_interval: # 心跳间隔，单位为秒，默认 99999 秒，选填。适合当 uni-api 域名托管在 cloudflare 并使用推理模型时使用。优先级高于全局配置的 keepalive_interval。
        gemini-2.5-pro: 50 # 模型 gemini-2.5-pro 的心跳间隔为 50 秒，此数值必须小于 model_timeout 设置的超时时间，否则忽略此设置。
      proxy: socks5://[用户名]:[密码]@[IP地址]:[端口] # 代理地址，选填。支持 socks5 和 http 代理，默认不使用代理。
      headers:  # 额外附加自定义HTTP请求头，选填。
        Custom-Header-1: Value-1
        Custom-Header-2: Value-2
      post_body_parameter_overrides: # 支持自定义请求体参数
        gemini-2.5-pro-search: # 给模型 gemini-2.5-pro-search 添加自定义请求体参数
          tools:
            - google_search: {} # 给模型 gemini-2.5-pro-search 添加 google_search 工具
            - url_context: {} # 给模型 gemini-2.5-pro-search 添加 url_context 工具

  - provider: vertex
    project_id: gen-lang-client-xxxxxxxxxxxxxx #    描述： 您的Google Cloud项目ID。格式： 字符串，通常由小写字母、数字和连字符组成。获取方式： 在Google Cloud Console的项目选择器中可以找到您的项目ID。
    private_key: "-----BEGIN PRIVATE KEY-----\nxxxxx\n-----END PRIVATE" # 描述： Google Cloud Vertex AI服务账号的私钥。格式： 一个 JSON 格式的字符串，包含服务账号的私钥信息。获取方式： 在 Google Cloud Console 中创建服务账号，生成JSON格式的密钥文件，然后将其内容设置为此环境变量的值。
    client_email: xxxxxxxxxx@xxxxxxx.gserviceaccount.com # 描述： Google Cloud Vertex AI 服务账号的电子邮件地址。格式： 通常是形如 "service-account-name@project-id.iam.gserviceaccount.com" 的字符串。获取方式： 在创建服务账号时生成，也可以在 Google Cloud Console 的"IAM与管理"部分查看服务账号详情获得。
    model:
      - gemini-2.5-flash
      - gemini-3-pro-preview: gemini-3-pro
      - gemini-pro-latest: gemini-2.5-pro-search # 可以以 -search 后缀重命名模型，同时在 post_body_parameter_overrides 设置针对此模型的自定义请求体参数即可启用搜索。不设置 post_body_parameter_overrides 参数，则无法启用搜索。
      - claude-sonnet-4-5@20250929: claude-sonnet-4-5
      - claude-opus-4-5@20251101: claude-opus-4-5
      - claude-haiku-4-5@20251001: claude-haiku-4-5
      - gemini-embedding-001
      - text-embedding-004
    tools: true
    notes: https://xxxxx.com/ # 可以放服务商的网址，备注信息，官方文档，选填
    preferences:
      post_body_parameter_overrides: # 支持自定义请求体参数
        gemini-2.5-pro-search: # 给模型 gemini-2.5-pro-search 添加自定义请求体参数
          tools:
            - google_search: {} # 给模型 gemini-2.5-pro-search 添加 google_search 工具
        gemini-2.5-flash:
          generationConfig:
            thinkingConfig:
              includeThoughts: True
              thinkingBudget: 24576
            maxOutputTokens: 65535
        gemini-2.5-flash-search:
          tools:
            - google_search: {}
            - url_context: {}

  - provider: cloudflare
    api: f42b3xxxxxxxxxxq4aoGAh # Cloudflare API Key，必填
    cf_account_id: 8ec0xxxxxxxxxxxxe721 # Cloudflare Account ID，必填
    model:
      - '@cf/meta/llama-3.1-8b-instruct': llama-3.1-8b # 重命名模型，@cf/meta/llama-3.1-8b-instruct 是服务商的原始的模型名称，必须使用引号包裹模型名，否则yaml语法错误，llama-3.1-8b 是重命名后的名字，可以使用简洁的名字代替原来复杂的名称，选填
      - '@cf/meta/llama-3.1-8b-instruct' # 必须使用引号包裹模型名，否则yaml语法错误

  - provider: azure
    base_url: https://your-endpoint.openai.azure.com
    api: your-api-key
    model:
      - gpt-5.2
    preferences:
      post_body_parameter_overrides: # 支持自定义请求体参数
        key1: value1 # 强制在请求中添加 "key1": "value1" 参数
        key2: value2 # 强制在请求中添加 "key2": "value2" 参数
        stream_options:
          include_usage: true # 强制在请求中添加 "stream_options": {"include_usage": true} 参数
      cooldown_period: 0 # 当 cooldown_period 设置为 0 时，表示该渠道不启用冷却机制，优先级高于全局配置的 cooldown_period。

  - provider: databricks
    base_url: https://xxx.azuredatabricks.net
    api:
      - xxx
    model:
      - databricks-claude-sonnet-4: claude-sonnet-4
      - databricks-claude-opus-4: claude-opus-4
      - databricks-claude-sonnet-4-5: claude-sonnet-4-5

  - provider: aws
    base_url: https://bedrock-runtime.us-east-1.amazonaws.com
    aws_access_key: xxxxxxxx
    aws_secret_key: xxxxxxxx
    model:
      - anthropic.claude-sonnet-4-5-20250929-v1:0: claude-sonnet-4-5

  - provider: vertex-express
    base_url: https://aiplatform.googleapis.com/
    project_id:
      - xxx # key1 的 project_id
      - xxx # key2 的 project_id
    api:
      - xx.xxx # key1 的 api
      - xx.xxx # key2 的 api
    model:
      - gemini-3-pro-preview

  - provider: other-provider
    base_url: https://api.xxx.com/v1/messages
    api: sk-bNnAOJyA-xQw_twAA
    model:
      - causallm-35b-beta2ep-q6k: causallm-35b
      - anthropic/claude-sonnet-4-5
    tools: false
    engine: openrouter # 强制使用某个消息格式，目前支持 gpt，claude，gemini，openrouter 原生格式，选填

  # 豆包火山引擎翻译（Ark /api/v3/responses）
  - provider: doubao-translate
    base_url: https://ark.cn-beijing.volces.com/api/v3/responses
    api: xxxxxxxxxxxxxxxxxxxxxxxx
    model:
      - doubao-seed-translation
    preferences:
      post_body_parameter_overrides:
        doubao-seed-translation:
          translation_options:
            target_language: zh # 默认目标语言，可选
            # source_language: en # 可选

api_keys:
  - api: sk-KjjI60Yf0JFWxfgRmXqFWyGtWUd9GZnmi3KlvowmRWpWpQRo # API Key，用户使用本服务需要 API key，必填
    model: # 该 API Key 可以使用的模型，选填。默认开启渠道级轮询负载均衡，每次请求模型按照 model 配置的顺序依次请求。与 providers 里面原始的渠道顺序无关。因此你可以设置每个 API key 请求顺序不一样。
      - gpt-5.2 # 可以使用的模型名称，可以使用所有提供商提供的 gpt-5.2 模型
      - claude-sonnet-4-5 # 可以使用的模型名称，可以使用所有提供商提供的 claude-sonnet-4-5 模型
      - gemini/* # 可以使用的模型名称，仅可以使用名为 gemini 提供商提供的所有模型，其中 gemini 是 provider 名称，* 代表所有模型
    role: admin # 设置 API key 的别名，选填。请求日志会显示该 API key 的别名。如果 role 为 admin，则仅有此 API key 可以请求 v1/stats,/v1/generate-api-key 端点。如果所有 API key 都没有设置 role 为 admin，则默认第一个 API key 为 admin 拥有请求 v1/stats,/v1/generate-api-key 端点的权限。

  - api: sk-pkhf60Yf0JGyJxgRmXqFQyTgWUd9GZnmi3KlvowmRWpWqrhy
    model:
      - anthropic/claude-sonnet-4-5 # 可以使用的模型名称，仅可以使用名为 anthropic 提供商提供的 claude-sonnet-4-5 模型。其他提供商的 claude-sonnet-4-5 模型不可以使用。这种写法不会匹配到other-provider提供的名为anthropic/claude-3-5-sonnet的模型。
      - <anthropic/claude-sonnet-4-5> # 通过在模型名两侧加上尖括号，这样就不会去名为anthropic的渠道下去寻找claude-3-5-sonnet模型，而是将整个 anthropic/claude-sonnet-4-5 作为模型名称。这种写法可以匹配到other-provider提供的名为 anthropic/claude-sonnet-4-5 的模型。但不会匹配到anthropic下面的claude-3-5-sonnet模型。
      - openai-test/omni-moderation-latest # 当开启消息道德审查后，可以使用名为 openai-test 渠道下的 omni-moderation-latest 模型进行道德审查。
      - sk-KjjI60Yd0JFWtxxxxxxxxxxxxxxwmRWpWpQRo/* # 支持将其他 api key 当作渠道
    preferences:
      SCHEDULING_ALGORITHM: fixed_priority # 当 SCHEDULING_ALGORITHM 为 fixed_priority 时，使用固定优先级调度，永远执行第一个拥有请求的模型的渠道。默认开启，SCHEDULING_ALGORITHM 缺省值为 fixed_priority。SCHEDULING_ALGORITHM 可选值有：fixed_priority，round_robin，weighted_round_robin, lottery, random。
      # 当 SCHEDULING_ALGORITHM 为 random 时，使用随机轮训负载均衡，随机请求拥有请求的模型的渠道。
      # 当 SCHEDULING_ALGORITHM 为 round_robin 时，使用轮训负载均衡，按照顺序请求用户使用的模型的渠道。
      AUTO_RETRY: true # 是否自动重试，自动重试下一个提供商，true 为自动重试，false 为不自动重试，默认为 true。也可以设置为数字，表示重试次数。
      rate_limit: 15/min # 支持限流，每分钟最多请求次数，可以设置为整数，如 2/min，2 次每分钟、5/hour，5 次每小时、10/day，10 次每天，10/month，10 次每月，10/year，10 次每年。默认999999/min，选填。支持多个频率约束条件：15/min,10/day
      # rate_limit: # 可以为每个模型设置不同的频率限制
      #   gemini-2.5-flash: 10/min,500/day
      #   gemini-2.5-pro: 5/min,25/day
      #   default: 4/min # 如果模型没有设置频率限制，使用 default 的频率限制
      ENABLE_MODERATION: true # 是否开启消息道德审查，true 为开启，false 为不开启，默认为 false，当开启后，会对用户的消息进行道德审查，如果发现不当的消息，会返回错误信息。

  # 渠道级加权负载均衡配置示例
  - api: sk-KjjI60Yd0JFWtxxxxxxxxxxxxxxwmRWpWpQRo
    model:
      - gcp1/*: 5 # 冒号后面就是权重，权重仅支持正整数。
      - gcp2/*: 3 # 数字的大小代表权重，数字越大，请求的概率越大。
      - gcp3/*: 2 # 在该示例中，所有渠道加起来一共有 10 个权重，及 10 个请求里面有 5 个请求会请求 gcp1/* 模型，2 个请求会请求 gcp2/* 模型，3 个请求会请求 gcp3/* 模型。

    preferences:
      SCHEDULING_ALGORITHM: weighted_round_robin # 仅当 SCHEDULING_ALGORITHM 为 weighted_round_robin 并且上面的渠道如果有权重，会按照加权后的顺序请求。使用加权轮训负载均衡，按照权重顺序请求拥有请求的模型的渠道。当 SCHEDULING_ALGORITHM 为 lottery 时，使用抽奖轮训负载均衡，按照权重随机请求拥有请求的模型的渠道。没设置权重的渠道自动回退到 round_robin 轮训负载均衡。
      AUTO_RETRY: true
      credits: 10 # 支持设置余额，此时设置的数字表示该 API Key 的可以用 10 美元，选填。默认为无限余额，当设置为 0 时，该 key 不可使用。当用户使用完余额后，后续请求将会被阻止。
      created_at: 2024-01-01T00:00:00+08:00 # 当设置好余额后，必须设置 created_at 参数，表示使用费用从 created_at 设定的时间开始计算。选填。默认从当前时间的第 30 天前开始计算。

preferences: # 全局配置
  model_timeout: # 模型超时时间，单位为秒，默认 100 秒，选填
    gpt-5.2: 10 # 模型 gpt-5.2 的超时时间为 10 秒,gpt-5.2 是模型名称，当请求 gpt-5.2-2025-12-11 等模型时，超时时间也是 10 秒
    claude-sonnet-4-5: 10 # 模型 claude-sonnet-4-5 的超时时间为 10 秒，当请求 claude-sonnet-4-5-20250929 等模型时，超时时间也是 10 秒
    default: 10 # 模型没有设置超时时间，使用默认的超时时间 10 秒，当请求的不在 model_timeout 里面的模型时，超时时间默认是 10 秒，不设置 default，uni-api 会使用 环境变量 TIMEOUT 设置的默认超时时间，默认超时时间是 100 秒
    gemini-3-pro: 30 # 模型 gemini-3-pro 的超时时间为 30 秒，当请求名字是 gemini-3-pro 开头的模型时，超时时间是 30 秒
    gemini-3-pro-image: 100 # 模型 gemini-3-pro-image 的超时时间为 100 秒，当请求名字是 gemini-3-pro-image 开头的模型时，超时时间是 100 秒
  cooldown_period: 300 # 渠道冷却时间，单位为秒，默认 300 秒，选填。当模型请求失败时，会自动将该渠道排除冷却一段时间，不再请求该渠道，冷却时间结束后，会自动将该模型恢复，直到再次请求失败，会重新冷却。当 cooldown_period 设置为 0 时，不启用冷却机制。
  rate_limit: 999999/min # uni-api 全局速率限制，单位为次数/分钟，支持多个频率约束条件，例如：15/min,10/day。默认 999999/min，选填。
  keepalive_interval: # 心跳间隔，单位为秒，默认 99999 秒，选填。适合当 uni-api 域名托管在 cloudflare 并使用推理模型时使用。
    gemini-2.5-pro: 50 # 模型 gemini-2.5-pro 的心跳间隔为 50 秒，此数值必须小于 model_timeout 设置的超时时间，否则忽略此设置。
  error_triggers: # 错误触发器，当模型返回的消息包含错误触发器中的任意一个字符串时，该渠道会自动返回报错。选填
    - The bot's usage is covered by the developer
    - process this request due to overload or policy
  proxy: socks5://[username]:[password]@[ip]:[port] # 全局代理地址，选填。
  model_price: # 模型价格，单位为美元/M tokens，选填。默认价格为 1,2，表示输入 1 美元/100 万 tokens，输出 2 美元/100 万 tokens。
    gpt-5.2: 1,2
    claude-sonnet-4-5: 0.12,0.48
    default: 1,2
```

挂载配置文件并启动 uni-api docker 容器：

```bash
docker run --user root -p 8001:8000 --name uni-api -dit \
-v ./api.yaml:/home/api.yaml \
yym68686/uni-api:latest
```

### 方法二：使用 `CONFIG_URL` 环境变量启动 uni-api

按照方法一写完配置文件后，上传到云端硬盘，获取文件的直链，然后使用 `CONFIG_URL` 环境变量启动 uni-api docker 容器：

```bash
docker run --user root -p 8001:8000 --name uni-api -dit \
-e CONFIG_URL=http://file_url/api.yaml \
yym68686/uni-api:latest
```

### Codex（`/v1/responses` + `engine: codex`）

如果你希望使用 Codex CLI / OpenAI Responses API 客户端直接请求 uni-api，请：

1. 客户端将 `base_url` 指向 uni-api，并携带 uni-api 的 `api_keys[].api`。
2. 在 uni-api 的 `providers` 中新增一个 `engine: codex` 的渠道，配置多个账号凭据（`api` 支持列表；使用 `account_id,refresh_token` 逗号格式，uni-api 会自动换取/刷新 `access_token`）。
3. 当某个账号额度耗尽时，uni-api 会对该 token 进行冷却并自动切换到下一个账号（默认冷却 6 小时，可用 `api_key_quota_cooldown_period` 覆盖）。

示例配置：

```yaml
providers:
  - provider: codex
    engine: codex
    # 支持填写为 https://chatgpt.com/backend-api/codex 或 https://chatgpt.com/backend-api/codex/responses
    base_url: https://chatgpt.com/backend-api/codex
    api:
      # 每个条目为 "account_id,refresh_token"（用于自动设置 Chatgpt-Account-Id，并自动换取 access_token 作为 Bearer）
      - <chatgpt_account_id_1>,<refresh_token_1>
      - <chatgpt_account_id_2>,<refresh_token_2>
    model:
      - gpt-5.2-codex
      - gpt-5.2-codex-mini
    preferences:
      api_key_schedule_algorithm: round_robin
      api_key_quota_cooldown_period: 21600 # 额度耗尽冷却时间(秒)，可选

api_keys:
  - api: sk-xxx
    model:
      - codex/*
```

> 提示：如果你的客户端只支持 `/v1/chat/completions`，也可以直接用同样的模型名走 `/v1/chat/completions`，uni-api 会按需对上游 Responses 流进行转换。
>
> 注意：Codex 上游会拒绝部分 Chat Completions 参数（如 `temperature`/`top_p`/`max_tokens` 等），uni-api 会在转发时自动过滤；如果你看到 `403 Forbidden`，也请先确认客户端携带的是 uni-api 的 `api_keys[].api`。

### 搜索渠道（`/v1/search`）

要启用 `/v1/search`，需要在 `providers` 中配置包含 `search` 模型的渠道，并在 `api_keys[].model` 中显式授权 `provider/search`。

示例（Jina + Tavily）：

```yaml
providers:
  - provider: jina
    base_url: https://api.jina.ai/v1/chat/completions
    api:
      - jina_xxx1
      - jina_xxx2
    model:
      - jina-embeddings-v3
      - search
    preferences:
      api_key_rate_limit:
        search: 100/min

  - provider: tavily
    base_url: https://api.tavily.com/search
    api:
      - tvly-dev-xxx
    model:
      - search
    preferences:
      api_key_rate_limit:
        search: 100/min

api_keys:
  - api: sk-xxx
    model:
      - jina/search
      - tavily/search
```

请求示例：

```bash
curl -X GET 'https://xxx.xxx/v1/search?q=Jina%2BAI' \
  --header 'Authorization: Bearer sk-xxx'
```

## 环境变量

- CONFIG_URL: 配置文件的下载地址，可以是本地文件，也可以是远程文件，选填。
- DEBUG: 是否开启调试模式，默认为 false，选填，开启后会打印更多日志，用于提交 issue 时使用。
- TIMEOUT: 请求超时时间，默认为 100 秒，超时时间可以控制当一个渠道没有响应时，切换下一个渠道需要的时间，选填。
- DISABLE_DATABASE: 是否禁用数据库，默认为 false，选填。
- DB_TYPE: 数据库类型，默认为 sqlite，选填。支持 sqlite 和 postgres。

当 DB_TYPE 为 postgres 时，需要设置以下环境变量：

- DB_USER: 数据库用户名，默认为 postgres，选填。
- DB_PASSWORD: 数据库密码，默认为 mysecretpassword，选填。
- DB_HOST: 数据库主机，默认为 localhost，选填。
- DB_PORT: 数据库端口，默认为 5432，选填。
- DB_NAME: 数据库名称，默为 postgres，选填。

## Koyeb 远程部署

点击下面的按钮可以自动使用构建好的 uni-api docker 镜像一键部署：

[![Deploy to Koyeb](https://www.koyeb.com/static/images/deploy/button.svg)](https://app.koyeb.com/deploy?name=uni-api&type=docker&image=docker.io%2Fyym68686%2Funi-api%3Alatest&instance_type=free&regions=was&instances_min=0&env%5BCONFIG_URL%5D=)

让 Koyeb 读取配置文件有两种方法，选一种即可：

1. 填写环境变量 `CONFIG_URL` 为配置文件的直链

2. 直接粘贴 api.yaml 文件内容，如果直接把 api.yaml 文件内容粘贴到 Koyeb 环境变量设置的 file 里面，其中粘贴到文本框后，在下方 path 输入 api.yaml 路径为 `/home/api.yaml`。

最后点击 Deploy 部署按钮。

## Ubuntu 部署

在仓库 Releases 找到对应的二进制文件最新版本，例如名为 uni-api-linux-x86_64-0.0.99.pex 的文件。在服务器下载二进制文件并运行：

```bash
wget https://github.com/yym68686/uni-api/releases/download/v0.0.99/uni-api-linux-x86_64-0.0.99.pex
chmod +x uni-api-linux-x86_64-0.0.99.pex
./uni-api-linux-x86_64-0.0.99.pex
```

## serv00 远程部署（FreeBSD 14.0）

首先登录面板，Additional services 里面点击选项卡 Run your own applications 开启允许运行自己的程序，然后到面板 Port reservation 去随便开一个端口。

如果没有自己的域名，去面板 WWW websites 删掉默认给的域名，再新建一个域名 Domain 为刚才删掉的域名，点击 Advanced settings 后设置 Website type 为 Proxy 域名，Proxy port 指向你刚才开的端口，不要选中 Use HTTPS。

ssh 登陆到 serv00 服务器，执行下面的命令：

```bash
git clone --depth 1 -b main --quiet https://github.com/yym68686/uni-api.git
cd uni-api
python -m venv uni-api
source uni-api/bin/activate
pip install --upgrade pip
cpuset -l 0 pip install -vv -r pyproject.toml
```

从开始安装到安装完成需要等待10分钟，安装完成后执行下面的命令：

```bash
tmux new -A -s uni-api
source uni-api/bin/activate
export CONFIG_URL=http://file_url/api.yaml
export DISABLE_DATABASE=true
# 修改端口，xxx 为端口，自行修改，对应刚刚在面板 Port reservation 开的端口
sed -i '' 's/port=8000/port=xxx/' main.py
sed -i '' 's/reload=True/reload=False/' main.py
python main.py
```

使用 ctrl+b d 退出 tmux，即可让程序后台运行。此时就可以在其他聊天客户端使用 uni-api 了。curl 测试脚本：

```bash
curl -X POST https://xxx.serv00.net/v1/chat/completions \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer sk-xxx' \
-d '{"model": "gpt-5.2","messages": [{"role": "user","content": "你好"}]}'
```

参考文档：

https://docs.serv00.com/Python/

https://linux.do/t/topic/201181

https://linux.do/t/topic/218738

## Docker 本地部署

Start the container

```bash
docker run --user root -p 8001:8000 --name uni-api -dit \
-e CONFIG_URL=http://file_url/api.yaml \ # 如果已经挂载了本地配置文件，不需要设置 CONFIG_URL
-v ./api.yaml:/home/api.yaml \ # 如果已经设置 CONFIG_URL，不需要挂载配置文件
-v ./uniapi_db:/home/data \ # 如果不想保存统计数据，不需要挂载该文件夹
yym68686/uni-api:latest
```

Or if you want to use Docker Compose, here is a docker-compose.yml example:

```yaml
services:
  uni-api:
    container_name: uni-api
    image: yym68686/uni-api:latest
    environment:
      - CONFIG_URL=http://file_url/api.yaml # 如果已经挂载了本地配置文件，不需要设置 CONFIG_URL
    ports:
      - 8001:8000
    volumes:
      - ./api.yaml:/home/api.yaml # 如果已经设置 CONFIG_URL，不需要挂载配置文件
      - ./uniapi_db:/home/data # 如果不想保存统计数据，不需要挂载该文件夹
```

CONFIG_URL 就是可以自动下载远程的配置文件。比如你在某个平台不方便修改配置文件，可以把配置文件传到某个托管服务，可以提供直链给 uni-api 下载，CONFIG_URL 就是这个直链。如果使用本地挂载的配置文件，不需要设置 CONFIG_URL。CONFIG_URL 是在不方便挂载配置文件的情况下使用。

### api.yaml 热重启（最小修改）+ 前端同步读取

`uni-api` 默认启动时读取一次 `api.yaml`。如果你希望“在前端修改 api.yaml 后，uni-api 立即生效”，最小修改的做法是：

- `api.yaml` 同时挂载给后端 `uni-api` 和前端（`uni-api-status`）
- 额外加一个 `config-watcher` 监听 `api.yaml` 变更，并自动 `docker restart uni-api`

下面是一个可直接使用的 `docker-compose.yml` 示例（把 `./api.yaml` 放在同目录）：

```yaml
services:
  uni-api:
    image: yym68686/uni-api:latest
    container_name: uni-api
    restart: unless-stopped
    ports:
      - "8001:8000"
    environment:
      - WATCHFILES_FORCE_POLLING=true
    volumes:
      - ./api.yaml:/home/api.yaml
      - ./uniapi_db:/home/data

  uniapi-frontend:
    image: ghcr.io/melosbot/uni-api-status:latest
    container_name: uni-api-frontend
    restart: unless-stopped
    ports:
      - "3700:3000"
    environment:
      - NODE_ENV=production
      - PORT=3000
      - API_YAML_PATH=/app/config/api.yaml
      - STATS_DB_PATH=/app/data/stats.db
    volumes:
      - ./api.yaml:/app/config/api.yaml
      - ./uniapi_db:/app/data:ro
    depends_on:
      - uni-api

  config-watcher:
    image: alpine:latest
    container_name: uni-api-config-watcher
    restart: unless-stopped
    volumes:
      - ./api.yaml:/watch/api.yaml:ro
      - /var/run/docker.sock:/var/run/docker.sock
    command: >
      sh -c "
      apk add --no-cache inotify-tools docker-cli &&
      while true; do
        inotifywait -e modify,close_write /watch/api.yaml &&
        echo 'api.yaml changed, restarting uni-api...' &&
        docker restart uni-api
      done
      "
```

注意：`config-watcher` 通过挂载 `/var/run/docker.sock` 来重启容器，仅建议在可信机器/环境中使用。

如需用域名同时访问前端和 API，可用 Caddy 反代（`Caddyfile` 示例）：

```caddyfile
yourdomain.com {
  encode gzip
  tls a@bc.com

  route /v1* {
    reverse_proxy localhost:8001 {
      header_up Host {host}
      header_up X-Real-IP {remote}
    }
  }

  route * {
    reverse_proxy localhost:3700 {
      header_up Host {host}
      header_up X-Real-IP {remote}
    }
  }
}
```

这样就可以通过 `yourdomain.com` 在前端修改 `api.yaml`，保存后会触发重启 `uni-api`，随后 `uni-api` 会读取最新配置。

Run Docker Compose container in the background

```bash
docker-compose pull
docker-compose up -d
```

Docker build

```bash
docker buildx build --platform linux/amd64,linux/arm64 -t yym68686/uni-api:latest --push .
docker pull yym68686/uni-api:latest

# test image
docker buildx build --platform linux/amd64,linux/arm64 -t yym68686/uni-api:test -f Dockerfile.debug --push .
docker pull yym68686/uni-api:test
```

One-Click Restart Docker Image

```bash
set -eu
docker pull yym68686/uni-api:latest
docker rm -f uni-api
docker run --user root -p 8001:8000 -dit --name uni-api \
-e CONFIG_URL=http://file_url/api.yaml \
-v ./api.yaml:/home/api.yaml \
-v ./uniapi_db:/home/data \
yym68686/uni-api:latest
docker logs -f uni-api
```

RESTful curl test

```bash
curl -X POST http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${API}" \
-d '{"model": "gpt-5.2","messages": [{"role": "user", "content": "Hello"}],"stream": true}'
```

音频输入（/v1/chat/completions）示例：

```bash
curl -X POST 'https://xxx.xxx/v1/chat/completions' \
  --header 'Content-Type: application/json' \
  --header "Authorization: Bearer ${API}" \
  --data '{
  "model": "gemini-2.5-flash",
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "Generate a transcript of the speech."
        },
        {
          "type": "input_audio",
          "input_audio": {
            "data": "<base64 bytes here>",
            "format": "wav"
          }
        }
      ]
    }
  ]
}'
```

使用 URL 作为音频输入：

```bash
curl -X POST 'https://xxx.xxx/v1/chat/completions' \
  --header 'Content-Type: application/json' \
  --header "Authorization: Bearer ${API}" \
  --data '{
  "model": "gemini-2.5-flash",
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "Generate a transcript of the speech."
        },
        {
          "type": "input_audio",
          "input_audio": {
            "data": "https://www.youtube.com/watch?v=ku-N-eS1lgM",
            "format": "mp4"
          }
        }
      ]
    }
  ]
}'
```

pex linux 打包：

```bash
VERSION=$(cat VERSION)
pex -D . -r pyproject.toml \
    -c uvicorn \
    --inject-args 'main:app --host 0.0.0.0 --port 8000' \
    --platform linux_x86_64-cp-3.10.12-cp310 \
    --interpreter-constraint '==3.10.*' \
    --no-strip-pex-env \
    -o uni-api-linux-x86_64-${VERSION}.pex
```

macos 打包：

```bash
VERSION=$(cat VERSION)
pex -r pyproject.toml \
    -c uvicorn \
    --inject-args 'main:app --host 0.0.0.0 --port 8000' \
    -o uni-api-macos-arm64-${VERSION}.pex
```

## HuggingFace Space 远程部署

WARN: 请注意远程部署的密钥泄露风险，请勿滥用服务以避免封号
Space 仓库需要提供三个文件  `Dockerfile`、`README.md`、`entrypoint.sh`
运行程序还需要 api.yaml（我以全量放在机密中为例，也可以HTTP下载的方式实现），访问匹配、模型和渠道配置等均在配置文件中
操作步骤
1. 访问 https://huggingface.co/new-space 新建一个sapce，要public库，开源协议/名字/描述等随便
2. 访问你的space的file，URL是 https://huggingface.co/spaces/your-name/your-space-name/tree/main,把下面三个文件上传（`Dockerfile`、`README.md`、`entrypoint.sh`）
3. 访问你的space的setting，URL是 https://huggingface.co/spaces/your-name/your-space-name/settings 找到 Secrets 新建机密 `API_YAML_CONTENT`（注意大写），把你的api.yaml在本地写好后直接复制进去，UTF-8编码
4. 继续在设置中，找到 Factory rebuild 让它重新构建，如果你修改机密或者文件或者手动重启Sapce等情况均有可能导致卡住无log，此时就用这个方法解决
5. 在设置最右上角有三个点的按钮，找到 Embed this Space 获取Space的公网链接，格式 https://(your-name)-(your-space-name).hf.space 去掉括号

相关的文件代码如下
```Dockerfile
# Dockerfile,记得删除本行
# 使用uni-api官方镜像
FROM yym68686/uni-api:latest

# 创建数据目录并设置权限
RUN mkdir -p /data && chown -R 1000:1000 /data

# 设置用户和工作目录
RUN useradd -m -u 1000 user
USER user
ENV HOME=/home/user \
    PATH=/home/user/.local/bin:$PATH \
    DISABLE_DATABASE=true

# 复制入口点脚本
COPY --chown=user entrypoint.sh /home/user/entrypoint.sh
RUN chmod +x /home/user/entrypoint.sh

# 确保/home目录可写（这很重要！）
USER root
RUN chmod 777 /home
USER user

# 设置工作目录
WORKDIR /home/user

# 入口点
ENTRYPOINT ["/home/user/entrypoint.sh"]
```

```markdown
# README.md,覆盖掉默认的,记得删除本行
---
title: Uni API
emoji: 🌍
colorFrom: gray
colorTo: yellow
sdk: docker
app_port: 8000
pinned: false
license: gpl-3.0
---
```
```shell
# entrypoint.sh,记得删除本行
#!/bin/sh
set -e
CONFIG_FILE_PATH="/home/api.yaml"  # 注意这里改成/home/api.yaml

echo "DEBUG: Entrypoint script started."

# 检查Secret是否存在
if [ -z "$API_YAML_CONTENT" ]; then
  echo "ERROR: Secret 'API_YAML_CONTENT' is不存在或为空。退出。"
  exit 1
else
  echo "DEBUG: API_YAML_CONTENT secret found. Preparing to write..."
  printf '%s\n' "$API_YAML_CONTENT" > "$CONFIG_FILE_PATH"
  echo "DEBUG: Attempted to write to $CONFIG_FILE_PATH."

  if [ -f "$CONFIG_FILE_PATH" ]; then
    echo "DEBUG: File $CONFIG_FILE_PATH created successfully. Size: $(wc -c < "$CONFIG_FILE_PATH") bytes."
    # 显示文件的前几行进行调试（注意不要显示敏感信息）
    echo "DEBUG: First few lines (without sensitive info):"
    head -n 3 "$CONFIG_FILE_PATH" | grep -v "api:" | grep -v "password"
  else
    echo "ERROR: File $CONFIG_FILE_PATH was NOT created."
    exit 1
  fi
fi

echo "DEBUG: About to execute python main.py..."
# 不需要使用--config参数，因为程序有默认路径
cd /home
exec python main.py "$@"
```

## uni-api 前端部署

uni-api 的 web 前端可以自行部署，地址：https://github.com/yym68686/uni-api-web

也可以使用我提前部署好的前端，地址：https://uni-api-web.pages.dev/

说明：`uni-api-web` 是独立的前后端项目，而 `uni-api` 目前仅提供后端能力。`uni-api-web` 不负责自动重试/故障转移等能力，这些能力仍由 `uni-api` 负责；你只需要在 `uni-api-web` 配置 `uni-api` 的 base url 即可（同时 `uni-api-web` 也可以对接其他兼容的 API）。`uni-api-web` 主要提供用户管理、计费、日志、权限控制等功能；`uni-api` 会一直保持“仅后端”的设计。

前端相关环境变量的解释请参考 `uni-api-web` 的 README：https://github.com/yym68686/uni-api-web

下面是一个 `docker-compose.yml` 示例：

```yaml
services:
  web:
    image: yym68686/uni-api-frontend:main
    container_name: uni-api-frontend
    restart: unless-stopped
    depends_on:
      - api
    environment:
      # Inside Docker, use service-to-service networking (NOT localhost).
      API_BASE_URL: ${API_BASE_URL:-http://api:8000/v1}
      NEXT_TELEMETRY_DISABLED: ${NEXT_TELEMETRY_DISABLED:-1}
      NODE_ENV: ${NODE_ENV:-production}
      APP_NAME: ${APP_NAME:-UniAPI}
      GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-}
      GOOGLE_REDIRECT_URI: ${GOOGLE_REDIRECT_URI:-}
    ports:
      - "8003:3000"

  db:
    image: postgres:17.6-alpine
    container_name: uni-api-db
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${DB_POSTGRES_USER:-uniapi}
      POSTGRES_PASSWORD: ${DB_POSTGRES_PASSWORD:-}
      POSTGRES_DB: ${DB_POSTGRES_DB:-uniapi}
    ports:
      - "5433:5432"
    volumes:
      - uniapi_pg_data:/var/lib/postgresql/data

  api:
    image: yym68686/uni-api-backend:main
    container_name: uni-api-backend
    restart: unless-stopped
    depends_on:
      - db
    environment:
      DATABASE_URL: ${DATABASE_URL:-}
      APP_ENV: ${APP_ENV:-dev}
      APP_NAME: ${BACKEND_APP_NAME:-Uni API Backend}
      API_PREFIX: ${API_PREFIX:-/v1}
      SESSION_TTL_DAYS: ${SESSION_TTL_DAYS:-7}
      GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-}
      GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-}
      GOOGLE_REDIRECT_URI: ${GOOGLE_REDIRECT_URI:-}
      ADMIN_BOOTSTRAP_TOKEN: ${ADMIN_BOOTSTRAP_TOKEN:-}
      RESEND_API_KEY: ${RESEND_API_KEY:-}
      RESEND_FROM_EMAIL: ${RESEND_FROM_EMAIL:-}
      EMAIL_VERIFICATION_REQUIRED: ${EMAIL_VERIFICATION_REQUIRED:-true}
    ports:
      - "8002:8000"

  postgres:
    container_name: postgres
    image: postgres:17.6
    restart: always
    environment:
      POSTGRES_USER: ${UNIAPI_POSTGRES_USER:-root}
      POSTGRES_PASSWORD: ${UNIAPI_POSTGRES_PASSWORD:-}
      POSTGRES_DB: ${UNIAPI_POSTGRES_DB:-uniapi}
    ports:
      - "5432:5432"
    volumes:
      - ./postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${UNIAPI_POSTGRES_USER:-root} -d ${UNIAPI_POSTGRES_DB:-uniapi}"]
      interval: 5s
      timeout: 5s
      retries: 5

  uni-api:
    container_name: uni-api
    image: yym68686/uni-api:latest
    environment:
      # CONFIG_URL: ${CONFIG_URL:-}
      TIMEOUT: ${TIMEOUT:-200}
      DB_TYPE: ${DB_TYPE:-postgres}
      DB_HOST: ${DB_HOST:-postgres}
      DB_PORT: ${DB_PORT:-5432}
      DB_USER: ${DB_USER:-root}
      DB_PASSWORD: ${DB_PASSWORD:-}
      DB_NAME: ${DB_NAME:-uniapi}
    depends_on:
      postgres:
        condition: service_healthy
    ports:
      - "8001:8000"
    volumes:
      - ./api-copy.yaml:/home/api.yaml
      - ./uniapi_db:/home/data
      - /etc/localtime:/etc/localtime:ro
    restart: unless-stopped

volumes:
  uniapi_pg_data:
```

## 赞助商

我们感谢以下赞助商的支持：
<!-- ¥2050 -->
- @PowerHunter：¥2000
- @IM4O4: ¥100
- @ioi：¥50

## 如何赞助我们

如果您想支持我们的项目，您可以通过以下方式赞助我们：

1. [PayPal](https://www.paypal.me/yym68686)

2. [USDT-TRC20](https://pb.yym68686.top/~USDT-TRC20)，USDT-TRC20 钱包地址：`TLFbqSv5pDu5he43mVmK1dNx7yBMFeN7d8`

3. [微信](https://pb.yym68686.top/~wechat)

4. [支付宝](https://pb.yym68686.top/~alipay)

感谢您的支持！

## 常见问题

- 为什么总是出现 `Error processing request or performing moral check: 404: No matching model found` 错误？

将 ENABLE_MODERATION 设置为 false 将修复这个问题。当 ENABLE_MODERATION 为 true 时，API 必须能够使用 omni-moderation-latest 模型，如果你没有在提供商模型设置里面提供 omni-moderation-latest，将会报错找不到模型。

- 怎么优先请求某个渠道，怎么设置渠道的优先级？

直接在api_keys里面通过设置渠道顺序即可。不需要做其他设置，示例配置文件：

```yaml
providers:
  - provider: ai1
    base_url: https://xxx/v1/chat/completions
    api: sk-xxx

  - provider: ai2
    base_url: https://xxx/v1/chat/completions
    api: sk-xxx

api_keys:
  - api: sk-1234
    model:
      - ai2/*
      - ai1/*
```

这样设置则先请求 ai2，失败后请求 ai1。

- 各种调度算法背后的行为是怎样的？比如 fixed_priority，weighted_round_robin，lottery，random，round_robin, smart_round_robin？

所有调度算法需要通过在配置文件的 api_keys.(api).preferences.SCHEDULING_ALGORITHM 设置为 fixed_priority，weighted_round_robin，lottery，random，round_robin, smart_round_robin 中的任意值来开启。

1. fixed_priority：固定优先级调度。所有请求永远执行第一个拥有用户请求的模型的渠道。报错时，会切换下一个渠道。这是默认的调度算法。

2. weighted_round_robin：加权轮训负载均衡，按照配置文件 api_keys.(api).model 设定的权重顺序请求拥有用户请求的模型的渠道。

3. lottery：抽奖轮训负载均衡，按照配置文件 api_keys.(api).model 设置的权重随机请求拥有用户请求的模型的渠道。

4. round_robin：轮训负载均衡，按照配置文件 api_keys.(api).model 的配置顺序请求拥有用户请求的模型的渠道。可以查看上一个问题，如何设置渠道的优先级。

5. smart_round_robin: 智能成功率调度。这是一个专为拥有大量 API Key（成百上千甚至数万个）的渠道设计的先进调度算法。它的核心机制是：
    - **基于历史成功率排序**：算法会根据过去72小时内每个 API Key 的实际请求成功率进行动态排序。
    - **智能分组与负载均衡**：为了避免流量永远只集中在少数几个“最优” Key 上，该算法会将所有 Key（包括从未用过的 Key）智能地分成若干组。它会将成功率最高的 Key 分布到每个组的开头，次高的分布到第二位，以此类推。这确保了负载能被均匀地分配给不同梯队的 Key，同时也保证了新 Key 或历史表现不佳的 Key 也有机会被尝试（探索）。
    - **周期性自动更新**：当一个渠道的所有 Key 都被轮询过一遍之后，系统会自动触发一次重排序，从数据库中拉取最新的成功率数据，生成一个全新的、更优的 Key 序列。这个更新频率是自适应的：Key 池越大、请求量越小，更新周期就越长；反之则越短。
    - **适用场景**：强烈建议拥有大量 API Key 的用户启用此算法，以最大化 Key 池的利用率和请求成功率。

- 应该怎么正确填写 base_url？

除了高级配置里面所展示的一些特殊的渠道，所有 OpenAI 格式的提供商需要把 base_url 填完整，也就是说 base_url 必须以 /v1/chat/completions 结尾或者 /v1/responses 结尾。如果你使用的 GitHub models，base_url 应该填写为 https://models.inference.ai.azure.com/chat/completions，而不是 Azure 的 URL。

对于 Azure 渠道，base_url 兼容以下几种写法：https://your-endpoint.services.ai.azure.com/models/chat/completions?api-version=2024-05-01-preview 和 https://your-endpoint.services.ai.azure.com/models/chat/completions，https://your-endpoint.openai.azure.com，推荐使用第一种写法。如果不显式指定 api-version，默认使用 2024-10-21 版本。

- 模型超时时间是如何确认的？渠道级别的超时设置和全局模型超时设置的优先级是什么？

渠道级别的超时设置优先级高于全局模型超时设置。优先级顺序：渠道级别模型超时设置 > 渠道级别默认超时设置 > 全局模型超时设置 > 全局默认超时设置 > 环境变量 TIMEOUT。

更细一点，`model_timeout` 和 `keepalive_interval` 的匹配规则是一样的（同时适用于全局 `preferences.model_timeout` / `preferences.keepalive_interval` 和单个渠道 `providers.(provider).preferences.model_timeout` / `providers.(provider).preferences.keepalive_interval`）：

1. 先定义两个名字：
   - 「请求模型名」：你在请求体 `model` 字段里写的，例如 `gpt-5.2`、`claude-sonnet-4-5`。
   - 「真实上游模型名」：在 `providers.(provider).model` 左边配置的原始 ID，例如：
     ```yaml
     providers:
       - provider: openai
         model:
           - gpt-5.2-2025-12-11: gpt-5.2   # 左边是真实上游模型名，右边是请求里使用的别名
     ```
     在这个例子里，请求模型名是 `gpt-5.2`，真实上游模型名是 `gpt-5.2-2025-12-11`。

2. 在某个具体渠道下（单个 provider 的 `preferences.model_timeout`）确定超时时间时，会按下面 6 层回退顺序依次尝试（前一步命中就不会再往后走）：

   1) 使用「请求模型名」在该渠道的 `model_timeout` 中做精确匹配（大小写不敏感）。

   2) 如果没有精确命中，再用「请求模型名」做模糊匹配：检查 `model_timeout` 下面是否有某个 key 是请求模型名的一部分。
      比如你只配置了：
      ```yaml
      model_timeout:
        gpt-5.2: 20
      ```
      那么 `gpt-5.2-2025-12-11`、`gpt-5-mini` 等模型都会命中 20 秒。

   3) 如果请求模型名在这个渠道里完全匹配不到任何 key，再换成「真实上游模型名」在该渠道的 `model_timeout` 中做精确匹配。
      例如只给上游 ID `gpt-5.2-2025-12-11` 配了超时，也能在这一步被命中。

   4) 如果真实上游模型名的精确匹配失败，再用「真实上游模型名」做模糊匹配：检查 `model_timeout` 下面的某个 key 是否是真实上游模型名的一部分。

   5) 如果前四步都没有命中，并且该渠道的 `model_timeout` 里配置了 `default`，则使用该渠道的 `default` 超时时间。

   6) 如果这个渠道完全没有命中（包括没有渠道级 `default`），则回退到全局 `preferences.model_timeout`：
      - 先用「请求模型名」按「精确匹配 → 模糊匹配 → 全局 `default`」的顺序尝试一遍；
      - 如果没有命中，再用「真实上游模型名」按「精确匹配 → 模糊匹配 → 全局 `default`」的顺序尝试一遍；
      - 如果全局也没有任何匹配，最后才会退回到环境变量 `TIMEOUT` 的值（默认 100 秒）。

实际配置时，`model_timeout` 下面的模型名可以这样写：

- 写成你请求时用的别名（例如 `gpt-5.2`、`claude-sonnet-4-5`），方便按「请求模型名」直接命中；
- 写成真实上游模型名（例如 `gpt-5.2-2025-12-11`），适合只想精确控制某个供应商的某个版本；
- 或者写一段稳定的公共前缀 / 关键子串（例如只写 `gpt-5.2`），用来同时覆盖一批以该前缀开头的模型。

通过合理配置 `model_timeout`，可以避免出现某些渠道请求超时报错的情况。如果你遇到 `{'error': '500', 'details': 'fetch_response_stream Read Response Timeout'}` 错误，请尝试增加对应模型的超时时间。

- api_key_rate_limit 是怎么工作的？我如何给多个模型设置相同的频率限制？

如果你想同时给 gemini-1.5-pro-latest，gemini-1.5-pro，gemini-1.5-pro-001，gemini-1.5-pro-002 这四个模型设置相同的频率限制，可以这样设置：

```yaml
api_key_rate_limit:
  gemini-1.5-pro: 1000/min
```

这会匹配所有含有 gemini-1.5-pro 字符串的模型。gemini-1.5-pro-latest，gemini-1.5-pro，gemini-1.5-pro-001，gemini-1.5-pro-002 这四个模型频率限制都会设置为 1000/min。api_key_rate_limit 字段配置的逻辑如下，这是一个示例配置文件：

```yaml
api_key_rate_limit:
  gemini-1.5-pro: 1000/min
  gemini-1.5-pro-002: 500/min
```

此时如果有一个使用模型 gemini-1.5-pro-002 的请求。

首先，uni-api 会尝试精确匹配 api_key_rate_limit 的模型。如果刚好设置了 gemini-1.5-pro-002 的频率限制，则 gemini-1.5-pro-002 的频率限制则为 500/min，如果此时请求的模型不是 gemini-1.5-pro-002，而是 gemini-1.5-pro-latest，由于 api_key_rate_limit 没有设置 gemini-1.5-pro-latest 的频率限制，因此会寻找有没有前缀和 gemini-1.5-pro-latest 相同的模型被设置了，因此 gemini-1.5-pro-latest 的频率限制会被设置为 1000/min。

- 我想设置渠道1和渠道2为随机轮训，uni-api 在渠道1和渠道2请求失败后才自动重试渠道3，怎么设置？

uni-api 支持将 api key 本身作为渠道，可以通过这一特性对渠道进行分组管理。

```yaml
api_keys:
  - api: sk-xxx1
    model:
      - sk-xxx2/* # 渠道 1 2 采用随机轮训，失败后请求渠道3
      - aws/* # 渠道3
    preferences:
      SCHEDULING_ALGORITHM: fixed_priority # 表示始终优先请求 api key：sk-xxx2 里面的渠道 1 2，失败后自动请求渠道 3

  - api: sk-xxx2
    model:
      - anthropic/claude-sonnet-4-5 # 渠道1
      - openrouter/claude-sonnet-4-5 # 渠道2
    preferences:
      SCHEDULING_ALGORITHM: random # 渠道 1 2 采用随机轮训
```

- 我想使用 Cloudflare AI Gateway，怎么填写 base_url？

对于 gemini 渠道，Cloudflare AI Gateway 的 base_url 需要填写为 https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_name}/google-ai-studio/v1beta/openai/chat/completions ，{account_id} 和 {gateway_name} 需要替换为你的 Cloudflare 账户 ID 和 Gateway 名称。

对于 Vertex 渠道，Cloudflare AI Gateway 的 base_url 需要填写为 https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_name}/google-vertex-ai ，{account_id} 和 {gateway_name} 需要替换为你的 Cloudflare 账户 ID 和 Gateway 名称。

- 什么时候 api key 的具有管理权限？

1. 当只有一个 key 时，说明是自用，唯一的 key 获得管理权限，可以通过前端看到所有渠道敏感信息。
2. 当存在两个以上的 key 时，必须指定其中一个或多个 key 的 role 字段为 admin，只有 role 为 admin 的 key 才有权限访问敏感信息。这样设计的原因是为了防止另外一个 key 的用户也能访问敏感信息。因此添加了 强制给 key 设置 role 为 admin 的设计。

- 配置文件使用 koyeb 文件方式部署后，如果配置文件渠道没有写 model 字段，启动会报错，怎么解决？

koyeb 部署 uni-api 的 api.yaml 默认是 0644 权限，uni-api 没有写权限。当 uni-api 尝试获取 model 字段时，会修改配置文件，此时会报错。控制台输入 chmod 0777 api.yaml 赋予 uni-api 写权限即可。

- nginx代理后无法获取用户真实IP？

nginx添加
```xml
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;

```

## 压测

压测工具：[locust](https://locust.io/)

压测脚本：[test/locustfile.py](test/locustfile.py)

mock_server：[test/mock_server.go](test/mock_server.go)

启动压测：

```bash
go run test/mock_server.go
# 100 10 120s
locust -f test/locustfile.py
python main.py
```

压测结果：

| Type | Name | 50% | 66% | 75% | 80% | 90% | 95% | 98% | 99% | 99.9% | 99.99% | 100% | # reqs |
|------|------|-----|-----|-----|-----|-----|-----|-----|-----|--------|---------|------|--------|
| POST | /v1/chat/completions (stream) | 18 | 23 | 29 | 35 | 83 | 120 | 140 | 160 | 220 | 270 | 270 | 6948 |
| | Aggregated | 18 | 23 | 29 | 35 | 83 | 120 | 140 | 160 | 220 | 270 | 270 | 6948 |

## 安全

我们非常重视项目的安全性。如果您发现任何安全漏洞，请通过 [yym68686@outlook.com](mailto:yym68686@outlook.com) 与我们联系。

**致谢 (Acknowledgments):**

*   我们特别感谢 **@ryougishiki214** 报告了一个安全问题，该问题已在 [v1.5.1](https://github.com/yym68686/uni-api/releases/tag/v1.5.1) 版本中得到解决。

## ⭐ Star

…(truncated)
