本页面配置AI 服务如何连接到 LLM 提供商以及向客户端公开哪些模型。它位于数据层设置(必须先完成此设置)和JWT 身份验证(控制对此处配置的模型的用户访问)之间。下面记录的环境变量是在 AI 服务容器上设置的 - 在docker run命令、Kubernetes Deployment 清单或 ECS 任务定义中设置。

两个环境变量和一个 JWT 声明控制提供商和模型配置:

  • PROVIDERS:告诉 AI 服务如何与每个 LLM 提供商 API 进行身份验证。

  • MODELS:告诉服务向客户端公开哪些模型以及每个模型支持哪些功能。

  • auth.ai.permissions(JWT 声明):控制用户对单个模型的访问。

本页面记录了所有支持的提供商type、每个必需字段以及这两个变量的所有已知生产问题。

如果 AI 服务容器尚未运行,请先阅读入门指南。以下部分假设 ai-service 容器正在运行。

提供商和模型架构

AI 服务使用两个相关的环境变量:

变量类型功能

PROVIDERS

JSON 对象

提供商 ID 到提供商配置的映射。每个条目说明如何与一个 LLM 提供商 API 进行身份验证。

MODELS

JSON 数组

向客户端公开的模型列表。每个模型指向一个PROVIDERS条目,并声明它可以提供哪些功能。

JSON Web Token (JWT) auth.ai.permissions

字符串数组

按用户授权列表。包括ai:models:<provider-key>:<model-id>条目,以控制对单个模型的访问。

PROVIDERS键是任意标识符(例如"openai"、"my-bedrock"、"team-azure")。每个值对象都有一个type字段,用于选择实现:

type提供商

openai

OpenAI (api.openai.com)

anthropic

Anthropic (api.anthropic.com)

google

Google AI Studio / Gemini 直接连接

azure

Azure OpenAI Service

bedrock

AWS Bedrock

vertex

Google Cloud Vertex AI

openai-compatible

任何 OpenAI 兼容的 HTTP API(Ollama、vLLM、LM Studio、llama.cpp、LocalAI、OpenRouter、Together、Groq、Fireworks 等类似服务)

键(不是type)将被以下内容引用:

  • MODELS[].provider;将模型连接到提供商

  • JWT auth.ai.permissions;用于按提供商或按模型的访问控制(参见JWT 身份验证)

{
  "my-openai-key":   { "type": "openai",   "apiKeys": ["sk-proj-..."] },
  "my-bedrock":      { "type": "bedrock",  "region": "us-east-1", "credentials": { "accessKeyId": "...", "secretAccessKey": "..." } },
  "my-ollama":       { "type": "openai-compatible", "baseUrl": "http://host.docker.internal:11434/v1" }
}

GET /v1/models/1在每个模型的provider字段中报告提供商name,而不是提供商键。

各组件如何协同工作

PROVIDERS JSON 结构将提供商键映射到 OpenAI Anthropic Azure Bedrock Vertex 和自托管端点

该图反映了三个堆叠层:如何与每个上游提供商进行身份验证(PROVIDERS)、向客户端公开哪些内容(MODELS)以及谁可以使用哪个模型(JWT 权限)。相同的提供商键字符串将这三层联系在一起。

定义模型列表

默认模型行为(agent-1)

如果没有明确的MODELS变量,服务将公开一个名为agent-1的内置占位符。这仅适用于 OpenAI、Anthropic 和 Google 直接提供商(服务内置了针对这三个提供商的路由)。Azure、Bedrock、Vertex 和 openai-compatible 提供商在没有MODELS的情况下无法工作。

在生产环境中始终显式设置MODELS。如果没有它,编辑器模型选择器将只显示一个通用的agent-1条目,JWT 权限无法针对特定模型,非原生提供商将无法正常工作。
详细信息:agent-1行为和限制
  • /v1/models/1端点报告agent-1且allowed: false,除非 JWT 包含ai:models:agent权限。

  • TinyMCE 编辑器模型选择器不会显示真实的模型名称。

  • 显式设置 MODELS 可使编辑器显示有意义的名称、路由到正确的 provider,并启用按模型的 JWT 权限(ai:models:<provider>:<model-id>)。

  • 权限语法请参阅 JWT authentication。

当省略 MODELS 时,GET /v1/models/1 调用返回:

{
  "models": [
    { "id": "agent-1", "allowed": false, "features": [] }
  ]
}

客户端(包括 TinyMCE 编辑器)会回退到已禁用的 agent,每个 AI 请求都会失败,且 UI 中不会有有用的错误提示。模型列表端点也只接受字面版本 1:

# Works
curl http://localhost:8000/v1/models/1

# All 500
curl http://localhost:8000/v1/models/v1
curl http://localhost:8000/v1/models/v2
curl http://localhost:8000/v1/models/latest

使模型可用的最低 MODELS 条目:

[
  {
    "id": "gpt-4o-mini",
    "provider": "my-openai-key",
    "description": "OpenAI GPT-4o mini",
    "features": ["conversations", "reviews", "actions"]
  }
]

要使模型能够被某功能选用,features 数组必须至少包含 conversations、reviews 或 actions 之一。没有任何重叠功能的模型在该 UI 区域中不可见。

MODELS 的完整字段参考在本页末尾。

OpenAI

API key 来自 platform.openai.com。内置路由可在未显式定义 MODELS 的情况下处理 OpenAI 模型,但建议在生产环境中定义 MODELS(参见 Defining the model list)。

配置详情

JSON 结构:

{
  "openai": {
    "type": "openai",
    "apiKeys": ["sk-proj-YOUR_KEY_HERE"]
  }
}

字段:

字段必填说明

type

是

字面值 "openai"

apiKeys

是

一个或多个 API key 的数组。多个 key 支持零停机轮换。

baseUrl

否

仅在通过私有 OpenAI gateway 代理时需要覆盖。

完整 docker run 示例:

docker run --init -d -p 8000:8000 \
  --name ai-service \
  -e LICENSE_KEY="$LICENSE_KEY" \
  -e ENVIRONMENTS_MANAGEMENT_SECRET_KEY="$MANAGEMENT_SECRET" \
  -e DATABASE_DRIVER='mysql' \
  -e DATABASE_HOST='mysql' \
  -e DATABASE_USER='root' \
  -e DATABASE_PASSWORD="$DB_PASSWORD" \
  -e DATABASE_DATABASE='ai_service' \
  -e REDIS_HOST='redis' \
  -e STORAGE_DRIVER='database' \
  -e PROVIDERS='{"openai":{"type":"openai","apiKeys":["sk-proj-YOUR_KEY_HERE"]}}' \
  registry.containers.tiny.cloud/ai-service-tiny:latest

验证:

curl -s -H "Authorization: Bearer sk-proj-YOUR_KEY_HERE" \
  https://api.openai.com/v1/models | head -20

当该 curl 调用在主机上成功时,相同的 key 在容器内的 PROVIDERS 中也可用。

项目范围的 key(sk-proj-…​)仅对项目已获访问权限的模型有效。在 gpt-4o 上出现 404 通常意味着该 key 的项目受限。组织级 key 需要组织 header,而本服务不会发送该 header;请改用项目 key。

Anthropic

API key 来自 console.anthropic.com。结构与 OpenAI 相同。

配置详情

JSON 结构:

{
  "anthropic": {
    "type": "anthropic",
    "apiKeys": ["sk-ant-YOUR_KEY_HERE"]
  }
}

字段:

字段必填说明

type

是

字面值 "anthropic"

apiKeys

是

数组。轮换行为与 OpenAI 一致。

推理模型:

Claude 4.x 模型(Sonnet 4、Opus 4)支持 extended thinking。要在 TinyMCE UI 中显示推理开关,请在 MODELS 的模型条目中添加 capabilities.reasoning: true:

{
  "id": "claude-sonnet-4-5",
  "provider": "anthropic",
  "description": "Anthropic Claude Sonnet 4.5 with extended thinking",
  "capabilities": { "reasoning": true },
  "features": ["conversations", "reviews", "actions"]
}

最小示例:

-e PROVIDERS='{"anthropic":{"type":"anthropic","apiKeys":["sk-ant-YOUR_KEY_HERE"]}}'

验证:

curl -s https://api.anthropic.com/v1/models \
  -H "x-api-key: sk-ant-YOUR_KEY_HERE" \
  -H "anthropic-version: 2023-06-01"

Google(直接使用 Gemini)

通过 Google AI Studio 直接访问 Gemini。与 Vertex AI 不同:不同的 key、不同的端点、不同的计费路径。

配置详情

JSON 结构:

{
  "google": {
    "type": "google",
    "apiKeys": ["AIza-YOUR_KEY_HERE"]
  }
}

字段:

字段必填说明

type

是

固定字符串 "google"

apiKeys

是

来自 AI Studio 的 AIza…​ 密钥数组。

最小示例:

-e PROVIDERS='{"google":{"type":"google","apiKeys":["AIza-YOUR_KEY_HERE"]}}'

验证:

curl -s "https://generativelanguage.googleapis.com/v1beta/models?key=AIza-YOUR_KEY_HERE"
AI Studio 的 AIza 密钥不能用于 Vertex 端点。如需使用 Vertex,请参阅 Google Vertex AI 部分。
免费层的密钥速率限制严格,在中等负载下会返回 429 响应。在进行负载测试或生产流量之前,请升级到付费层。

Azure OpenAI

由 Azure 托管的 OpenAI 模型。需要 Azure 订阅、Azure OpenAI 资源以及至少一个部署。MODELS[].id 必须与 Azure 部署名称完全匹配。

配置详情

Azure 门户中的先决条件:

  1. 创建 Azure OpenAI 资源。记下资源名称;这是 https://<RESOURCE_NAME>.openai.azure.com 中的子域前缀。

  2. 如果区域要求,申请模型访问权限。

  3. 在 Azure AI Studio 中,为每个要暴露的模型创建部署。部署名称可任意(例如 prod-gpt4o、cheap-mini)。

  4. 从资源概览中的密钥和端点复制两个 API 密钥之一。

JSON 结构:

{
  "azure": {
    "type": "azure",
    "resourceName": "YOUR_RESOURCE_NAME",
    "apiKeys": ["YOUR_AZURE_KEY_HERE"],
    "apiVersion": "2024-10-21"
  }
}

字段:

字段必填说明

type

是

固定字符串 "azure"

resourceName

是

仅 *.openai.azure.com 前缀,而非完整 URL。

apiKeys

是

数组。Azure 为每个资源颁发两个密钥,用于零停机密钥轮换。

apiVersion

是

始终显式设置。省略会导致 SDK 报错,提示缺少查询字符串参数。请参阅Microsoft 的 API 版本矩阵获取当前稳定值。

MODELS[].id 值必须与 Azure 部署名称完全匹配。不匹配会导致 DeploymentNotFound 错误。请使用易读的部署名称,因为该 ID 也会出现在 JWT 权限字符串和编辑器模型选择器中。

双部署示例:

-e PROVIDERS='{
  "azure": {
    "type": "azure",
    "resourceName": "tinymce-ai",
    "apiKeys": ["YOUR_AZURE_KEY_HERE"],
    "apiVersion": "2024-10-21"
  }
}'

-e MODELS='[
  {
    "id": "prod-gpt4o",
    "provider": "azure",
    "name": "GPT-4o (production)",
    "description": "Azure deployment of GPT-4o for production traffic",
    "recommended": true,
    "features": ["conversations", "reviews", "actions"]
  },
  {
    "id": "cheap-mini",
    "provider": "azure",
    "name": "GPT-4o mini (low cost)",
    "description": "Azure deployment of GPT-4o mini for cheap actions",
    "features": ["reviews", "actions"]
  }
]'

验证:

curl -s -H "api-key: YOUR_AZURE_KEY_HERE" \
  "https://YOUR_RESOURCE_NAME.openai.azure.com/openai/deployments?api-version=2024-10-21"

预期会返回包含 MODELS 中部署 ID 的 JSON 列表。

错误的区域配额:每个 Azure 区域都有独立配额。突发工作负载可能会在中等 QPS 下受到限制;如有需要,可将流量拆分到不同区域的资源上。内容过滤器误报:Azure 的安全过滤器比直接使用 OpenAI 更严格。对某些技术内容的审查可能会返回 content_filter 错误。请在 Azure AI Studio 中配置自定义内容过滤策略。

AWS Bedrock

Amazon 的托管模型市场(Anthropic、Meta、Mistral、Cohere、Amazon Titan)。凭据必须内联;不会使用 AWS SDK 的默认凭据链。

配置详情
AI 服务不会使用 AWS SDK 的默认凭据链。AWS_PROFILE、~/.aws/credentials、IAM Roles for Service Accounts (IRSA)、EC2 实例配置文件、ECS 任务角色和 Web 身份令牌都会被忽略。请将凭据内联到 PROVIDERS JSON 中。

JSON 结构:

{
  "bedrock": {
    "type": "bedrock",
    "region": "us-east-1",
    "credentials": {
      "accessKeyId": "AKIA_YOUR_KEY_HERE",
      "secretAccessKey": "YOUR_SECRET_HERE",
      "sessionToken": "OPTIONAL_FOR_STS"
    }
  }
}

sessionToken 字段是可选的,但对于 STS 签发的短期凭证是必需的。在使用临时凭证时,请规划轮换流程。

Bedrock 提供商可以设置 apiKeys 为在 AWS 控制台中签发的 Bedrock API 密钥,而不是使用 credentials。

Bedrock 控制台签发的 API 密钥有单独的计费权限检查,在 IAM 凭证路径正常工作的账户上可能会返回 INVALID_PAYMENT_INSTRUMENT。对于生产环境,建议使用 credentials 块(包含 accessKeyId / secretAccessKey 的 IAM 用户)。

前提条件检查清单:

  1. 启用模型访问。 Bedrock 控制台 → Model access → Manage model access。每个模型必须按区域批准。

  2. 通过 AWS Marketplace 订阅 非 Amazon 模型。Bedrock 上的 Anthropic Claude 需要一次性 Marketplace 订阅。

  3. 创建具有以下权限的 IAM 用户或角色。

  4. 选择有该模型的区域。 并非每个模型在每个区域都有。在假设之前,请检查 Bedrock 控制台 > Model catalog。

所需 IAM 权限:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "BedrockInvoke",
      "Effect": "Allow",
      "Action": [
        "bedrock:InvokeModel",
        "bedrock:InvokeModelWithResponseStream",
        "bedrock:Converse",
        "bedrock:ConverseStream"
      ],
      "Resource": "*"
    }
  ]
}

该服务根据模型系列使用 InvokeModel 和 Converse 路径,因此两者都要包含。

Claude 4.x 跨区域推理配置文件:

Bedrock 上的 Claude 4.x 使用 跨区域推理配置文件 而不是按区域的模型 ID。MODELS[].id 必须是推理配置文件 ID,并带有区域组前缀:

区域组示例配置文件 ID

US

us.anthropic.claude-sonnet-4-5-20250929-v1:0

EU

eu.anthropic.claude-sonnet-4-5-20250929-v1:0

APAC

apac.anthropic.claude-sonnet-4-5-20250929-v1:0

使用裸模型 ID(anthropic.claude-sonnet-4-5-…​)会返回 ValidationException。

最小示例:

-e PROVIDERS='{
  "bedrock": {
    "type": "bedrock",
    "region": "us-east-1",
    "credentials": {
      "accessKeyId": "AKIA_YOUR_KEY_HERE",
      "secretAccessKey": "YOUR_SECRET_HERE"
    }
  }
}'

-e MODELS='[
  {
    "id": "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
    "provider": "bedrock",
    "name": "Claude Sonnet 4.5 (Bedrock)",
    "description": "Anthropic Claude Sonnet 4.5 through AWS Bedrock cross-region inference",
    "recommended": true,
    "capabilities": { "reasoning": true },
    "features": ["conversations", "reviews", "actions"]
  }
]'

在运行 AI 服务之前进行验证:

aws bedrock list-foundation-models --region us-east-1 \
  --query 'modelSummaries[?contains(modelId,`claude`)].[modelId,modelLifecycle.status]' \
  --output table
aws bedrock-runtime converse \
  --region us-east-1 \
  --model-id us.anthropic.claude-sonnet-4-5-20250929-v1:0 \
  --messages '[{"role":"user","content":[{"text":"Say hello in five words."}]}]'

如果任一操作失败,AI 服务将以相同的根本原因失败;在继续之前修复 IAM 和模型访问权限。

AccessDeniedException 几乎总是意味着在 Bedrock 控制台中缺少模型访问权限。首次调用时的 ThrottlingException 表示默认配额较低;通过 Service Quotas 请求增加配额。ValidationException 意味着区域模型 ID 和跨区域推理配置文件之间不匹配。INVALID_PAYMENT_INSTRUMENT 表示缺少 AWS Marketplace 订阅。

Google Vertex AI

Google 的企业模型接口。项目范围,由 IAM 驱动,由 GCP 计费。凭证必须内联(与 Bedrock 的限制相同)。

配置详细信息
Vertex 适配器忽略 Application Default Credentials (ADC)、GOOGLE_APPLICATION_CREDENTIALS、GKE Workload Identity 和 Compute Engine 元数据服务器凭证。在 PROVIDERS JSON 中内联服务账户密钥或账户绑定的 API 密钥。

JSON 结构(服务账户):

{
  "vertex": {
    "type": "vertex",
    "project": "YOUR_GCP_PROJECT_ID",
    "location": "us-central1",
    "credentials": {
      "clientEmail": "ai-service@YOUR_GCP_PROJECT_ID.iam.gserviceaccount.com",
      "privateKey": "-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----\n"
    }
  }
}

JSON 结构(账户绑定的 API 密钥):

{
  "vertex": {
    "type": "vertex",
    "project": "YOUR_GCP_PROJECT_ID",
    "location": "us-central1",
    "apiKeys": ["YOUR_VERTEX_API_KEY"]
  }
}

字段:

字段必需说明

type

是

字面值 "vertex"

project

是

GCP 项目 ID,而不是项目编号。

location

是

区域,例如 us-central1、europe-west4。必须支持该模型系列。

credentials.clientEmail

如果使用服务账号

来自服务账号 JSON 密钥的 client_email 字段。

credentials.privateKey

如果使用服务账号

来自服务账号 JSON 密钥的 private_key 字段。请参见下文关于换行符转义的说明。

apiKeys

如果使用账户绑定密钥

一个或多个 Vertex 绑定 API 密钥的数组。

private_key 换行符转义:

当从 GCP 服务账号 JSON 密钥中复制 private_key 到 .env 文件,然后使用 set -a && source .env 进行扩展时,shell 会将 \n 序列压缩,导致密钥无效(Vertex 返回 invalid_grant)。可靠的做法是使用 JSON 序列化器构建整个 PROVIDERS 值:

python3 - <<'EOF' > providers.json
import json
sa = json.load(open("/path/to/service-account.json"))
providers = {
    "vertex": {
        "type": "vertex",
        "project": sa["project_id"],
        "location": "us-central1",
        "credentials": {
            "clientEmail": sa["client_email"],
            "privateKey": sa["private_key"]
        }
    }
}
print(json.dumps(providers))
EOF

export PROVIDERS="$(cat providers.json)"

账户绑定 API 密钥仍需要服务账号:

Vertex 的“账户绑定 API 密钥”绑定到 Google Cloud 项目以及该项目中的一个服务账号。必须存在一个服务账号并授予 roles/aiplatform.user 角色;API 密钥仅避免分发私钥。

阻止设置的 GCP 组织策略:

组织策略阻止操作

iam.disableServiceAccountCreation

创建服务账号。症状:403 Permission iam.serviceAccounts.create denied。

iam.disableServiceAccountKeyCreation

下载 JSON 密钥。症状:创建密钥按钮变灰,或 FAILED_PRECONDITION。

iam.allow.disabled

创建账户绑定 API 密钥。症状:API_KEY_INVALID。

当 GCP 组织强制执行其中任何一项时,安全或云团队必须授予项目级例外或预先配置凭据。

最小示例:

-e PROVIDERS='{
  "vertex": {
    "type": "vertex",
    "project": "tinymce-ai",
    "location": "us-central1",
    "credentials": {
      "clientEmail": "ai-service@tinymce-ai.iam.gserviceaccount.com",
      "privateKey": "-----BEGIN PRIVATE KEY-----\nMIIEv...\n-----END PRIVATE KEY-----\n"
    }
  }
}'

-e MODELS='[
  {
    "id": "gemini-2.0-flash-001",
    "provider": "vertex",
    "name": "Gemini 2.0 Flash (Vertex)",
    "description": "通过 Vertex AI 的 Google Gemini 2.0 Flash",
    "features": ["conversations", "reviews", "actions"]
  }
]'

服务账号需要 roles/aiplatform.user(或具有 aiplatform.endpoints.predict 和 aiplatform.endpoints.streamGenerateContent 权限的自定义角色)。

验证:

gcloud auth activate-service-account \
  --key-file=/path/to/service-account.json

gcloud ai models list \
  --region=us-central1 \
  --project=YOUR_GCP_PROJECT_ID
区域不匹配:将 location 设置为托管模型的区域。SERVICE_DISABLED 表示未启用 Vertex AI API;请运行 gcloud services enable aiplatform.googleapis.com。配额:新项目默认为 5 QPS;在生产流量之前请求增加配额。

OpenAI 兼容(Ollama、vLLM、LM Studio 及类似工具)

对于任何未在上方列为原生提供商但暴露 OpenAI 兼容 /v1/chat/completions 端点的运行时或聚合器,请使用此提供商类型 — 包括 Ollama、vLLM、LM Studio、OpenRouter、Together、Groq 和 Fireworks。

baseUrl 必须包含 /v1 后缀。

配置

{
  "local-llm": {
    "type": "openai-compatible",
    "baseUrl": "http://host.docker.internal:11434/v1",
    "apiKeys": ["optional-bearer-token"],
    "headers": { "X-Custom-Header": "value" }
  }
}
字段必填备注

type

是

字面值 "openai-compatible"

baseUrl

是

必须包含 /v1 后缀。否则,每个请求都会因误导性的“未找到”服务器发送事件(SSE)错误而失败。

apiKeys

否

作为 Authorization: Bearer <key> 发送。大多数本地运行时会忽略它。

headers

否

其他标头,如身份验证令牌或租户 ID。

通过此适配器上传文件仅限于 image/* MIME 类型。PDF 和 Office 文档不会转发。要处理非图像文件,请通过 OpenAI、Anthropic 或 Bedrock 提供商进行路由。

Ollama 网络

Ollama 默认监听 127.0.0.1:11434,在 Docker 容器内部无法访问。请绑定到所有网络接口:

OLLAMA_HOST=0.0.0.0:11434 ollama serve

在 Linux 系统使用 systemd 时,请创建一个覆盖文件:

# /etc/systemd/system/ollama.service.d/override.conf
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"

然后重新加载并重启服务:sudo systemctl daemon-reload && sudo systemctl restart ollama。

在 Linux 上,添加 host gateway 以便 host.docker.internal 可以解析:

services:
  ai-service:
    image: registry.containers.tiny.cloud/ai-service-tiny:latest
    extra_hosts:
      - "host.docker.internal:host-gateway"

如果 Ollama 返回 "does not support tools",说明该模型是基于原始 GGUF 构建的,没有聊天模板。请使用 ollama pull 获取包含完整 Modelfile 的 Library 模型,或者编写一个自定义的 Modelfile。

自定义 Modelfile 示例
FROM /path/to/your-model.gguf

TEMPLATE """{{ if .System }}<|im_start|>system
{{ .System }}<|im_end|>
{{ end }}{{ range .Messages }}<|im_start|>{{ .Role }}
{{ .Content }}<|im_end|>
{{ end }}<|im_start|>assistant
"""

PARAMETER stop "<|im_end|>"
PARAMETER stop "<|im_start|>"

具体的模板取决于基础模型。请查看模型卡片以获取推荐的聊天模板。在连接到 AI 服务之前,请使用 ollama show <model> 验证工具支持情况。

推理开关 (capabilities.reasoning: true) 对于由 Ollama 支持的模型来说只是形式上的;openai-compatible adapter 不会将其转换为原生的 Ollama API。

超时设置

在消费级硬件上运行的大型自托管模型可能会超过默认的 180 秒超时时间。可以通过以下方式覆盖:

-e LLM_TIMEOUT_MS='600000'

示例 — Ollama

-e PROVIDERS='{
  "ollama": {
    "type": "openai-compatible",
    "baseUrl": "http://host.docker.internal:11434/v1"
  }
}'

-e MODELS='[
  {
    "id": "qwen3:0.6b",
    "provider": "ollama",
    "name": "Qwen3 0.6B (local)",
    "description": "Local Ollama model for fast actions",
    "features": ["conversations", "reviews", "actions"]
  }
]'

示例 — vLLM 和 LM Studio

配置模式与 Ollama 完全相同 — 只有 baseUrl、provider key 和 model ID 不同。

RuntimePROVIDERS entryMODELS entry

vLLM

{
  "vllm": {
    "type": "openai-compatible",
    "baseUrl": "http://vllm-host.internal:8001/v1",
    "apiKeys": ["YOUR_VLLM_TOKEN"]
  }
}
{
  "id": "meta-llama/Llama-3.1-8B-Instruct",
  "provider": "vllm",
  "name": "Llama 3.1 8B (vLLM)",
  "features": ["conversations", "reviews", "actions"]
}

LM Studio

{
  "lmstudio": {
    "type": "openai-compatible",
    "baseUrl": "http://host.docker.internal:1234/v1"
  }
}
{
  "id": "lmstudio-community/Meta-Llama-3.1-8B-Instruct-GGUF",
  "provider": "lmstudio",
  "name": "Llama 3.1 8B (LM Studio)",
  "features": ["conversations", "reviews", "actions"]
}

验证

在启动配置了 openai-compatible provider 的 AI 服务后,确认其能够连接到运行时:

curl -s http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <your-jwt-token>" \
  -d '{
    "model": "qwen3:0.6b",
    "messages": [{"role":"user","content":"Say hello in five words."}],
    "stream": false
  }'

成功的响应表明 AI 服务可以将请求转发到本地运行时。

多 provider 共存

PROVIDERS 是一个单一的 JSON 对象,可以包含任意数量的条目。每个条目都是独立的;服务会为每个 provider 维护一个单独的客户端池。除了环境变量中 JSON 大小的限制外(许多 shell 允许单个变量超过 64 KB 或更多),没有其他限制。

MODELS 数组使用 provider 字段将单个模型路由到特定的 provider,该字段必须与 PROVIDERS 键完全匹配(区分大小写)。

示例:三个 provider,混合路由

点击展开:三 provider 的 PROVIDERS 和 MODELS 示例
-e PROVIDERS='{
  "openai":     { "type": "openai",    "apiKeys": ["sk-proj-YOUR_KEY_HERE"] },
  "bedrock-us": {
    "type": "bedrock",
    "region": "us-east-1",
    "credentials": {
      "accessKeyId": "AKIA_YOUR_KEY_HERE",
      "secretAccessKey": "YOUR_SECRET_HERE"
    }
  },
  "ollama":     { "type": "openai-compatible", "baseUrl": "http://host.docker.internal:11434/v1" }
}'

-e MODELS='[
  {
    "id": "gpt-4o",
    "provider": "openai",
    "name": "GPT-4o",
    "description": "OpenAI flagship model for conversations",
    "recommended": true,
    "features": ["conversations"]
  },
  {
    "id": "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
    "provider": "bedrock-us",
    "name": "Claude Sonnet 4.5 (Bedrock)",
    "description": "Claude on Bedrock for reviews",
    "capabilities": { "reasoning": true },
    "features": ["reviews"]
  },
  {
    "id": "qwen3:0.6b",
    "provider": "ollama",
    "name": "Qwen3 0.6B (local)",
    "description": "Local model for cheap quick actions",
    "features": ["actions"]
  }
]'

这将对话功能连接到 OpenAI,审查功能连接到托管在 Bedrock 上的 Claude,快捷操作功能连接到本地的 Ollama 模型。TinyMCE 编辑器会根据模型声明的 features 属性,为每个功能自动选择合适的服务提供方。

如果 MODELS 中的某个条目的 provider 值在 PROVIDERS 中不存在,服务将在启动时停止,并显示 [FATAL] Following models have invalid provider: 错误信息,后跟受影响的模型 ID。请对照 PROVIDERS 中的键检查每个 provider 字段的拼写(区分大小写)。更多调试步骤请参阅 故障排除。

MODELS 字段参考

顶级字段

字段必需类型默认值说明

id

是

string

-

发送给上游服务提供方的模型标识符。对于 Azure,此值必须与部署名称匹配。对于 Bedrock,此值必须与模型 ID 或推理配置文件匹配。

provider

是

string

-

必须与 PROVIDERS 中的某个键完全匹配。

description

是

string

-

显示在模型选择器的提示工具中。

name

否

string

id 的值

模型选择器中显示的名称。

recommended

否

boolean

false

如果设置为 true,则会在模型选择器中将此模型标记为推荐。每个环境应只标记一个推荐模型。

capabilities.webSearch

否

boolean

false

是否为此模型启用网页搜索切换功能。需要设置 WEBSEARCH_ENABLED。

capabilities.reasoning

否

boolean

false

是否显示推理/扩展思考切换开关。支持的服务提供方包括 Anthropic、Bedrock-Claude 和 OpenAI o-series。对于 Ollama,此选项仅为界面装饰用途(参见 openai-compatible 部分)。

contextLimits

否

object

见下文

每个模型的上下文限制。

features

是

string[]

-

模型可支持的功能列表。必须包含至少一个可用功能。

contextLimits 默认值

字段默认值单位

maxContextLength

256000

字符

maxFiles

100

数量

maxFileSize

5242880 (Anthropic) / 7340032 (其他所有)

字节

maxTotalFileSize

31457280

字节

maxTotalPdfFilePages

100

页

仅在必要时覆盖 contextLimits,例如当模型的实际上下文窗口小于默认的 256K 字符限制,或者部署策略限制了文件大小等情况。

可用的 features 字符串

服务识别的完整功能字符串集合:

conversations
conversations.titleGeneration
reviews
reviews.correctness
reviews.clarity
reviews.readability
reviews.make-longer
reviews.make-shorter
reviews.make-tone-casual
reviews.make-tone-direct
reviews.make-tone-friendly
reviews.make-tone-confident
reviews.make-tone-professional
reviews.translate
actions
actions.make-longer
actions.make-shorter
actions.continue
actions.make-tone-casual
actions.make-tone-direct
actions.make-tone-friendly
actions.make-tone-confident
actions.make-tone-professional
actions.translate
actions.fix-grammar
actions.improve-writing

三个总括性值 conversations、reviews 和 actions 可启用对应功能的所有子功能。仅在需要将模型限制为特定子集时才使用具体的子功能;例如,一个仅处理 actions.fix-grammar 的低成本模型。

如果模型没有 features 条目,或者仅包含编辑器不会请求的子功能,该模型将从选择器中隐藏。

无缝轮换 API 密钥

每个支持 API 密钥的服务提供方类型,其 apiKeys 字段均为一个数组。服务会将所有条目视为对传入请求均有效,从而允许在零停机的情况下轮换密钥:

  1. 将新密钥追加到数组中:

    "apiKeys": ["sk-proj-OLD_KEY", "sk-proj-NEW_KEY"]
  2. 重启 AI 服务容器,使其加载新的 PROVIDERS 值。

  3. 验证新密钥是否可用(通过服务运行一次聊天补全)。

  4. 在服务提供方控制台中撤销旧密钥。

  5. 从 apiKeys 中移除旧密钥:

    "apiKeys": ["sk-proj-NEW_KEY"]
  6. 再次重启 AI 服务容器。

相同的流程适用于 anthropic、google、azure 和 openai-compatible 提供商类型。对于 Bedrock 和 Vertex,请原子性地替换 credentials 对象;不存在凭据对象数组,因此需规划一个短暂的维护窗口,或者在负载均衡器后运行两个 AI 服务副本以实现无停机替换。

快速故障排除索引

症状最可能的原因章节

编辑器显示"model unavailable" / agent-1 allowed:false

未设置 MODELS

定义模型列表

GET /v1/models/v1 返回 500

兼容性版本错误

定义模型列表

Bedrock 返回 NoValidApiKeysFoundError

依赖 AWS 默认凭据链

Bedrock

Bedrock 返回 AccessDeniedException

控制台中未启用模型访问权限

Bedrock 前提条件

Claude 4 在 Bedrock 返回 ValidationException

使用了裸模型 ID 而非跨区域推理配置文件

Bedrock

Bedrock 返回 INVALID_PAYMENT_INSTRUMENT

缺少模型系列的 AWS Marketplace 订阅

Bedrock 前提条件

Vertex 返回 invalid_grant

private_key 换行符转义错误

Vertex

Vertex 返回 SERVICE_DISABLED

未启用 aiplatform.googleapis.com

Vertex

Azure 返回 DeploymentNotFound

MODELS[].id 与部署名称不匹配

Azure

Azure SDK 关于缺少 API 版本的错误

未设置 apiVersion

Azure

Ollama:SSE 中显示"Not Found"

baseUrl 缺少 /v1

OpenAI-compatible

Ollama:"does not support tools"(不支持工具)

无聊天模板的裸-GGUF Modelfile

OpenAI-compatible

Ollama:推理切换开关无效

不支持通过 openai-compatible 适配器实现

OpenAI-compatible

自托管模型在 180 秒后超时

默认 LLM_TIMEOUT_MS

OpenAI-compatible

AI 请求在浏览器中永久挂起

反向代理缓冲 SSE

参见生产部署的反向代理和 TLS 章节

更通用的故障排除(数据库、JWT、存储、网络)位于故障排除。

另请参阅