跳到正文

5 分钟从 LiteLLM 迁移。换一个基础 URL 和密钥,把应用从 LiteLLM 代理迁到 Kaeso,再把 config.yaml 的其余部分逐项搬过来。

发布日期
作者
Kaeso Team
阅读时间
3 分钟
  • 指南
  • 迁移
  • litellm
明亮的蓝色与青色渐变,沿对角线向上折叠,一角透着暖光

如果您的应用现在调用的是 LiteLLM 代理,它们已经在说 OpenAI 或 Anthropic 的 API。Kaeso 两种都说。所以迁移一个应用,主要就是换个地址:新的基础 URL,新的密钥。代码、SDK 和流式接收回复的方式都不用变。

这 5 分钟指的就是这次切换:启动 Kaeso,连接一个服务商,把一个应用指向它。一份很长的 config.yaml 需要更久才能搬完,所以本指南的后半部分逐项讲解:模型、回退、密钥、预算、缓存和日志,也包括哪些地方做法不同,以及 Kaeso 不做的少数几件事。

迁移期间请让 LiteLLM 继续运行。这里的任何步骤都不会改动它,任何应用只要把基础 URL 改回去就能回退。

开始之前

  • 一台服务器。 装有 Docker Engine 和 Docker Compose 2.24 或更新版本的 Linux,2 个 vCPU、4 GB 内存和 20 GB 磁盘。想先在自己的电脑上试用,把域名设为 localhost 即可。
  • 一个域名,其 DNS 记录指向这台服务器,并开放 80 和 443 端口,以便自带的 Caddy 获取证书。
  • 您的服务商密钥。 也就是 LiteLLM 现在用的那些;config.yaml 里写作 os.environ/OPENAI_API_KEY 之类。
  • 一台 SMTP 服务器,用于发送登录链接和邀请。试用时可以先不配。

切换

启动 Kaeso

每个版本都会发布一份 compose.yaml,用来运行网关、控制台、PostgreSQL、存放请求日志的 ClickHouse、Valkey 和 Caddy。下载它,写好设置,然后全部启动:

mkdir -m 700 kaeso && cd kaesocurl -fsSLO https://github.com/logicplanes/kaeso/releases/latest/download/compose.yaml umask 077cat > .env <<EOFKAESO_DOMAIN=kaeso.example.comPOSTGRES_PASSWORD=$(openssl rand -hex 24)POSTGRES_SUPERUSER_PASSWORD=$(openssl rand -hex 24)CLICKHOUSE_PASSWORD=$(openssl rand -hex 24)VALKEY_PASSWORD=$(openssl rand -hex 24)KAESO_MAIL_TRANSPORT=logEOF docker run --rm ghcr.io/logicplanes/kaeso-gateway:latest master-key generate > master-keyssudo chown 65532:65532 master-keys && sudo chmod 0400 master-keys docker compose up -d --waitdocker compose exec gateway kaeso setup-link

首次启动需要一两分钟来下载镜像。在 Docker Desktop 或 Colima 上,只运行 chmod 0400 master-keys,不运行 chown 那一行。

KAESO_MAIL_TRANSPORT=log 会把邮件写进网关的日志,而不是发出去,一个人试用时足够了。邀请他人之前,请换成您的 SMTP 服务器(邮件设置(在新标签页中打开))。

这里有个名字指的是两回事。Kaeso 的主密钥用来加密它存储的服务商密钥;它不是 LiteLLM 的 master_key,也不能用来调用模型。请把 master-keys 的副本妥善保存,并与数据库备份分开存放。

最后一条命令会打印一个设置链接。打开它,填写您的姓名、邮箱、密码和组织名称,然后选择设置 Kaeso。现在您就是实例管理员,也是该组织的所有者。

连接服务商

打开服务商,选择添加服务商密钥,选好服务商并粘贴它的密钥。一个服务商的第一个密钥会成为它的默认密钥,所有项目都会使用它。

Kaeso 加密存储这个密钥,之后不再显示。应用永远看不到它:它们用自己的密钥调用 Kaeso。

添加模型

请求只能指定项目目录中的模型,这和 LiteLLM 基本只服务 model_list 里列出的模型类似。在项目中选择创建项目,用应用的名字命名。然后打开模型,选择添加模型,搜索应用要调用的模型,例如 claude-sonnet-5-5 或 gpt-6-sol,把它们添加进来。

价格和上下文窗口不用自己填。它们来自 KPMR(在新标签页中打开),即 Kaeso Provider & Model Registry,实例会自动保持更新。

创建密钥

在项目中选择 API 密钥,再选择创建密钥。用应用的名字命名,访问权限保持模型调用,并选择有效期。关闭对话框之前复制密钥 sk-kso-…:Kaeso 只保留它的哈希。

把应用指向 Kaeso

改基础 URL 和密钥,别的都不用动:

 import os from openai import OpenAI  client = OpenAI(-    base_url="http://litellm.internal:4000",-    api_key=os.environ["LITELLM_API_KEY"],+    base_url="https://kaeso.example.com/v1",+    api_key=os.environ["KAESO_API_KEY"], )

如果应用从环境变量读取设置,就改这些变量:

OPENAI_BASE_URL=https://kaeso.example.com/v1OPENAI_API_KEY=sk-kso-… ANTHROPIC_BASE_URL=https://kaeso.example.comANTHROPIC_API_KEY=sk-kso-…

注意 /v1。LiteLLM 在 /chat/completions 和 /v1/chat/completions 上都会应答,所以很多应用让 OpenAI SDK 直接指向主机地址。Kaeso 只在 /v1 下提供模型 API,域名下的其余路径都是控制台。Anthropic SDK 正好相反:它会自己加上 /v1,所以它的基础 URL 就是域名本身。

SDK基础 URL密钥的发送方式
OpenAIhttps://kaeso.example.com/v1Authorization: Bearer
Anthropichttps://kaeso.example.comx-api-key 或 Authorization: Bearer

发送一个请求。每个应答都带有 kaeso-request-id 请求头,几秒后,项目的请求日志就会显示这个请求的状态、Token、费用和耗时。切换就完成了。

和 LiteLLM 一样,任何 SDK 都能调用任何聊天模型,所以 OpenAI SDK 也能调用 Claude。如果应用发送了模型的服务商不接受的字段,Kaeso 不会悄悄丢掉它,而是拒绝请求,并在错误中指出这个字段,这样任何设置都不会在您不知情时丢失。

Claude Code 和 Codex

编程工具和其他应用一样。对 Claude Code,在 ~/.claude/settings.json 中改两个值:

{  "env": {    "ANTHROPIC_BASE_URL": "https://kaeso.example.com",    "ANTHROPIC_AUTH_TOKEN": "sk-kso-…"  }}

Claude Code 会调用一个 Opus、一个 Sonnet 和一个 Haiku 模型,最后一个用于后台任务,所以这三个都需要在项目目录中。ANTHROPIC_DEFAULT_OPUS_MODEL、ANTHROPIC_DEFAULT_SONNET_MODEL 和 ANTHROPIC_DEFAULT_HAIKU_MODEL 决定具体用哪几个,也可以填别名。对 Codex,把 Kaeso 添加为模型服务商,设置 base_url = "https://kaeso.example.com/v1" 和 wire_api = "responses"。编程工具(在新标签页中打开) 里有两份文件的完整内容。

逐行解读 config.yaml

下面是一份很多团队都在用的那类 LiteLLM 配置:三个模型,其中一个用了自定义名称,外加回退、重试、Redis 缓存,以及存放密钥和支出的数据库。

model_list:  - model_name: claude-sonnet-5-5    litellm_params:      model: anthropic/claude-sonnet-5-5      api_key: os.environ/ANTHROPIC_API_KEY  - model_name: gpt-6-sol    litellm_params:      model: openai/gpt-6-sol      api_key: os.environ/OPENAI_API_KEY  - model_name: fast    litellm_params:      model: openai/gpt-5.4-mini      api_key: os.environ/OPENAI_API_KEY litellm_settings:  num_retries: 2  fallbacks: [{"claude-sonnet-5-5": ["gpt-6-sol"]}]  context_window_fallbacks: [{"fast": ["claude-sonnet-5-5"]}]  cache: true  cache_params: {type: redis} general_settings:  master_key: os.environ/LITELLM_MASTER_KEY  database_url: os.environ/DATABASE_URL

在 Kaeso 中,这些都不放在文件里。您在控制台中设置,或者用脚本通过 Platform API 设置,审计日志会记录每一次更改。

config.yaml 中Kaeso 中
api_key: os.environ/…服务商页面上的服务商密钥,加密存储
model_list模型页面上的项目目录
model_name: claude-sonnet-5-5模型本身:应用继续发送同一个名称
model_name: fast名为 fast 的别名
fallbacks、context_window_fallbacks别名的路由,带回退
num_retriesSDK 自带的重试
cache: true项目的响应缓存
master_key给人用的控制台账户,给脚本用的平台密钥
database_url、Rediscompose.yaml 中的 PostgreSQL、ClickHouse 和 Valkey
虚拟密钥API 密钥 sk-kso-…,每个应用一个
团队项目
max_budget、tpm_limit、rpm_limit项目、成员或密钥上的限额

下面各节逐一说明。

模型和服务商

应用已经在发送的名称

如果 model_name 就是服务商自己的模型 ID,例如 claude-sonnet-5-5,只需把这个模型加入目录。应用照常发送它。

自己起的名称,例如 fast,就成为一个别名。在模型中打开别名,选择创建别名,命名为 fast 并选择 gpt-5.4-mini。应用发送 fast,以后您可以把它换到另一个模型上,不用改动应用。

Kaeso 也认 provider/model 的写法,所以像 anthropic/claude-sonnet-5-5 这样的名称可以原样使用。不过别名不能包含 /,所以像 prod/claude 这样的 LiteLLM 名称需要在应用中修改。

服务商前缀

litellm_params.model 中的 LiteLLM 前缀告诉您要添加哪个服务商密钥。大多数在 Kaeso 中名称相同,少数拼写不同:

LiteLLMKaeso
openai/、anthropic/、groq/、mistral/、deepseek/、xai/、cerebras/、openrouter/相同的 ID
together_ai/togetherai
cohere/、cohere_chat/cohere
moonshot/moonshotai
dashscope/alibaba,即 QwenCloud
vercel_ai_gateway/vercel

配置很大时,有两个捷径。添加所有当前 OpenAI 模型,以及其他每个服务商对应的同类按钮,可以代替 openai/* 这样的通配符;它添加服务商现有的模型,不会添加以后出现的模型。另外,当两个服务商提供相同的模型 ID 时,写明您要的那个,例如 groq/openai/gpt-oss-120b。

自己设定的价格

LiteLLM 的 input_cost_per_token 和 output_cost_per_token 以每 Token 美元计。Kaeso 的价格以每百万 Token 美元计,所以乘以一百万:0.000003 就是 3。打开模型的侧滑面板,选择编辑覆盖值并填入价格。它只对当前项目生效,恢复为 KPMR 的值可以撤销。

自托管的服务器

带有 api_base 的条目,例如 vLLM、Ollama 或 LM Studio 服务器,会成为自定义服务商。在服务商中打开自定义服务商,选择添加自定义服务商,填入基础 URL 和密钥,再选择检测设置。Kaeso 会询问服务器该如何调用它,并在您把模型添加到项目时列出它的模型。

Kaeso 无从知道您的服务器成本,所以每个模型的价格需要您来填;不按 Token 付费的硬件填 0 即可。如果服务器位于私有地址,请在 compose.yaml 旁边的 compose.override.yaml 中允许它所在的网络,再用 docker compose up -d --wait 应用:

services:  gateway:    environment:      KAESO_CUSTOM_PROVIDERS_ALLOWED_NETWORKS: 10.0.0.0/8

Kaeso 没有的服务商

Kaeso 内置了 14 个服务商:Anthropic、Cerebras、Cohere、DeepSeek、Groq、Mistral、Moonshot、Ollama Cloud、OpenAI、OpenRouter、QwenCloud、SpaceX、Together AI 和 Vercel AI Gateway。Azure OpenAI、Amazon Bedrock、Google Vertex AI 和 Gemini API 不在其中。如果您的配置用到了 azure/、bedrock/、vertex_ai/ 或 gemini/,有两条路。Gemini 模型也可以通过 OpenRouter 和 Vercel AI Gateway 调用,例如 openrouter/google/gemini-2.5-pro。其余的,可以把 LiteLLM 留在 Kaeso 后面,做法见本指南末尾。

回退、重试和负载均衡

回退

在 LiteLLM 中,回退是一个按模型名称组织的列表。在 Kaeso 中,回退属于别名:别名的路由先尝试一个模型,再尝试下一个。路由随 Kaeso 0.6.0 推出,撰写本文时它还处于候选版本阶段;在 0.5.6 中,一个别名只指向一个模型。

要让应用继续发送原来的名称,就给别名起这个名字。别名优先于同名模型,列表中会标记为遮蔽同名模型。对上面的配置:

  1. 创建一个名为 claude-sonnet-5-5 的别名。
  2. 在从模板开始中选择回退链。
  3. 把 claude-sonnet-5-5 设为第一步,gpt-6-sol 设为它的回退,然后选择保存。

当一步的模型不可用、触发速率限制,或无法处理请求中的某些内容(例如图片)时,这一步就会回退。对应的原因是 unavailable、limited 和 unsupported,也就是默认值。第四个原因 rejected 覆盖了 context_window_fallbacks 和 content_policy_fallbacks 的作用:服务商因为上下文过长或内容本身而拒绝了请求。只有当回退模型能接受第一个模型拒绝的内容时,才加上它。

对于长提示词,有比等待报错更好的办法。从模板开始还提供长提示词另走:根据请求的输入 Token 数设置条件,让长提示词直接发往上下文更大的模型。

对别名的每个应答都带有 kaeso-route 请求头,列出请求尝试过的每一步及其状态。请求日志在先尝试的模型下记录同样的步骤,测试标签页则能在保存之前显示请求会去往哪里。

重试

Kaeso 每个请求只发送一次。OpenAI 和 Anthropic 的 SDK 在错误允许时会自行重试,默认两次。如果您过去依靠 num_retries 在代理上重试,请改为调高客户端的 max_retries(TypeScript 中为 maxRetries)。

负载均衡

同一个 model_name 下的多个条目,例如同一模型配两个密钥,没有直接对应的做法。一个项目对每个服务商只用一个密钥,Kaeso 不会合并多个密钥,也不会按延迟或用量挑选部署。要把负载分散到多个服务商账户,可以用分配给项目把某个服务商密钥分配给部分项目。要在模型之间分配流量,可以在路由中使用分流:它按权重把每个请求送往其中一个分支,可以按请求、按调用方或按某个请求头的值来分。

密钥、团队和预算

每个应用都换新密钥

LiteLLM 的虚拟密钥不会迁移过来:Kaeso 签发自己的密钥,并且只保留它们的哈希。每个应用都会拿到一个新密钥,反正这也是您要对它做的唯一改动。

团队对应项目。每个项目有自己的目录、密钥、限额和日志,成员以某个角色加入:管理员、开发者或查看者。给软件用服务账号,而不是某个人的密钥,这样那个人离开后,它的密钥仍然有效。

虚拟密钥的设置对应什么

/key/generateKaeso
key_alias密钥的名称
models密钥的模型
duration有效期:1、7、30 或 90 天,某个日期,或永不过期
max_budget 加 budget_duration按天、按月或总计的支出预算
tpm_limitToken 速率
rpm_limit请求速率
team_id项目
user_id拥有该密钥的成员或服务账号

Kaeso 的天和月指 UTC 的自然日和自然月,所以 budget_duration 为 30d 时对应月度预算,1d 对应每日预算。预算默认是硬性的,用完后会拒绝请求;关掉这一项,它就只发提醒,默认在 50%、80% 和 100% 时发送。Kaeso 没有并发请求数限额,所以 max_parallel_requests 没有对应项,密钥的 metadata 也没有:请求日志和用量中显示的是密钥的名称。

限额是逐层嵌套的。密钥的预算不能高于其所有者的预算,所有者的预算不能高于项目的预算,所以 LiteLLM 中的团队预算对应项目上的限额。

批量创建密钥

有几十个密钥时,请用 Platform API。在组织设置 › 平台密钥中创建一个平台密钥,然后为每个应用创建一个服务账号,以及一个带限额的密钥:

ORG_URL=https://kaeso.example.com/platform/v1/orgs/org_…PROJECT=proj_… ACCOUNT=$(curl -s "$ORG_URL/projects/$PROJECT/service-accounts" \  -H "Authorization: Bearer $KAESO_PLATFORM_KEY" \  -H "content-type: application/json" \  -d '{"name": "support-bot", "role": "developer"}' | jq -r .id) curl -s "$ORG_URL/projects/$PROJECT/service-accounts/$ACCOUNT/keys" \  -H "Authorization: Bearer $KAESO_PLATFORM_KEY" \  -H "content-type: application/json" \  -d '{    "name": "support-bot",    "expires_in_days": 90,    "limits": [      {"kind": "spend_budget", "period": "month", "amount": "50"},      {"kind": "request_rate", "period": "minute", "amount": 600}    ]  }' | jq -r .secret

最后一条命令会打印一次新密钥。把它存到应用读取的位置。用 Platform API 自动化(在新标签页中打开) 涵盖其余内容,从添加模型到轮换密钥。

缓存

cache: true 变成每个项目的一个开关。打开项目的设置,在响应缓存下开启缓存回复,再选择回复保留多久,从 5 分钟到 7 天。

只有当请求与之前的某个请求完全相同时,缓存才会应答;比较发生在格式转换之后,所以 OpenAI 应用和 Anthropic 应用可以共用同一条缓存。它只存储非流式回复,并且只在项目内部共享。没有语义缓存。应用可以用标准的 Cache-Control 请求头逐个控制请求:no-cache 重新询问服务商,no-store 跳过缓存。每个应答都会在 kaeso-cache 中说明缓存做了什么,命中缓存不会消耗预算。

日志和支出

Kaeso 自己记录每个请求:模型、服务商、状态、Token、费用、耗时、密钥和发送者,默认还包括发送和返回的内容。保留多久由组织决定:如果不改,元数据保留 90 天,内容保留 30 天。要像 turn_off_message_logging 那样完全不保留提示词,请在组织设置 › 日志记录中关闭记录请求内容,也可以只对单个项目关闭。

用量可以按天、模型、密钥或成员查看,在控制台中或通过 Platform API 都行,请求日志可以导出为 CSV 或 JSON Lines。网关在单独的端口上提供 Prometheus 指标,供您的仪表盘使用。

Kaeso 不会把日志转发给外部工具,所以 Langfuse、Datadog 这类回调没有对应项;请改为读取 Platform API 的日志或导出文件。历史支出也不会迁移过来。Kaeso 从它处理的第一个请求开始计数,所以如果需要历史记录,请保留一份 LiteLLM 数据库的转储。

Kaeso 不做的,交给 LiteLLM

Kaeso 的模型 API 涵盖 Chat Completions、Responses、Messages、Embeddings、Token 计数和模型列表。它没有图片、音频、重排序、内容审核、文件或批处理的端点,没有透传路由,也没有防护栏,而且不为您的应用代理 MCP 服务器。它还会拒绝要求服务商存储或续接回复的 Responses 请求,例如带 previous_response_id 的请求;请每次都发送完整的对话。

这些端点请继续直接调用 LiteLLM;一个应用同时使用两者完全没问题。对于 Kaeso 没有的服务商,您还可以更进一步,把 LiteLLM 作为自定义服务商放在 Kaeso 后面:

  1. 在 LiteLLM 中创建一个虚拟密钥,只允许访问 Kaeso 需要用到的模型,例如您的 Bedrock 和 Azure 条目。
  2. 如果 LiteLLM 位于私有地址,在 compose.override.yaml 中允许它所在的网络,做法与自托管服务器相同。
  3. 在 Kaeso 中选择添加自定义服务商,填入 LiteLLM 的地址,例如 http://10.0.0.12:4000/v1,以及这个密钥。检测设置会识别出 Chat Completions。把 ID 设为 litellm。
  4. 把它的模型添加到项目并填入价格。Kaeso 按这些价格计费,并据此执行预算。

之后,应用在 LiteLLM 的 model_name 前加上这个 ID 来调用,例如 litellm/bedrock-claude,也可以调用以它命名的别名,使用的密钥和基础 URL 与其他模型相同。Kaeso 的密钥、限额和日志对这些请求同样适用。

切回去,以及关掉 LiteLLM

在停掉 LiteLLM 之前,回退就是反向做同样的改动:旧的基础 URL 和旧的密钥。一次迁移一个应用,看着它的请求出现在 Kaeso 的请求日志中。

当每个应用的流量都出现在 Kaeso 中、LiteLLM 的日志也安静下来,就为它的数据库做最后一次转储,然后停掉它。如果您的配置里有哪部分在上面各节中都找不到对应,请告诉我们(在新标签页中打开)。这能帮助决定 Kaeso 下一步做什么。

查看所有文章