用 LiteLLM 搭建自助式模型网关
方案在 AWS Fargate 上部署 LiteLLM,将 Bedrock 模型封装为兼容 OpenAI 的 API,开发者通过单个 API 密钥接入。平台侧统一提供按用户计费控制、配额隔离和可观测性。
AI 深度解读
团队接入 AI 编程助手,难点往往从「能调用模型」之后才开始:谁用了多少钱、限流后怎么办、长时间推理为什么断连。AWS 这篇文章给出的方案,是用 LiteLLM 和 Amazon Bedrock 搭一个统一入口,让开发者自行领 key,让平台集中管理模型、预算和观测。
作者在新 AWS 账号验证过示例,并称自家部署服务了数百名开发者。最值得读的,是那些会让预算悄悄失效、请求运行到一半才报错的配置细节。但它提供的是架构和片段,还不是可直接部署的完整工程。
统一入口解决了什么,又增加了什么
开发者把工具指向一个 OpenAI-compatible API,填写 base URL、个人 API key 和模型名,例如 claude-sonnet-4-20250514。LiteLLM 再把模型名映射到 Bedrock 的 Application Inference Profile,由 Fargate task 的 IAM role 调用模型。
开发者因此不用管理 AWS 凭证。平台也可以在入口调整模型映射,而不必逐个修改客户端配置。不过,协议兼容不等于工具功能完全兼容。原文列举了 Claude Code、Continue、Cursor,却没有给出各工具的实际配置验证,不能把示意配置当成通用配置文件。
网关后面也不只有一个容器。请求经过 Route 53、CloudFront 和 Application Load Balancer(ALB),进入运行在 AWS Fargate 上的 LiteLLM。PostgreSQL 保存虚拟 key 和消费记录;ElastiCache for Valkey 保存非持久缓存,并协调多个任务之间的限流;Secrets Manager 提供密钥。Fargate 按 CPU 使用率自动扩缩容。
这里有个采购前提。按原文的许可说明,AI Gateway 免费支持最多 5 名用户,超过需要许可证;免费层虽然支持 virtual keys,但文章所描述的自助发 key,需要 Enterprise。SSO、审计日志和委派管理角色也属于 Enterprise 能力。
因此,这套方案的价值是统一治理,而不是单纯少写几行 SDK 调用。
为什么配了预算,账单仍可能不受控
作者在早期试点中观察到,extended thinking 会带来意外费用。他们采用的策略是每个 API key 设置 max_budget: 250,配合 budget_duration: 7d,按文中描述执行滚动 7 天预算;达到上限后返回 HTTP 429。
但预算生效有个容易漏掉的条件:必须先算对钱。
下面的配置同时完成模型映射、费用计算和缓存接入,是全文最值得保留的一段:
model_list:
- model_name: claude-sonnet-4-20250514
litellm_params:
model: bedrock/arn:aws:bedrock:us-east-1:111122223333:application-inference-profile/sonnet-profile-id
aws_region_name: us-east-1
max_retries: 3
timeout: 900 # 为扩展思考预留 15 分钟
# 使用原始 inference-profile ARN 时,必须明确设置 token 单价。
# LiteLLM 无法从内置价格表识别该 ARN,否则费用会按 $0 记录,
# 每个 key 的 spend 将保持为 0,预算也就不会触发。
model_info:
input_cost_per_token: 0.000003 # 示例价格
output_cost_per_token: 0.000015 # 示例价格
- model_name: claude-haiku-4-5
litellm_params:
model: bedrock/arn:aws:bedrock:us-east-1:111122223333:application-inference-profile/haiku-profile-id
aws_region_name: us-east-1
timeout: 120
model_info:
input_cost_per_token: 0.000001 # 示例价格
output_cost_per_token: 0.000005 # 示例价格
litellm_settings:
max_budget: 250 # 每个 key 的示例预算
budget_duration: 7d # 滚动 7 天窗口
max_parallel_requests: 10
set_verbose: false
cache: true
cache_params:
type: redis # Valkey 兼容该协议,因此仍填写 "redis"
host: elasticache-endpoint
port: 6379
master_key: os.environ/LITELLM_MASTER_KEY
database_url: os.environ/DATABASE_URL
重点看 model_info。使用 inference-profile ARN 后,LiteLLM 无法从内置价格表匹配费用,会按 $0 记录。有预算配置,不代表预算真的在执行。 上述单价都是示例,不能直接当成当前报价;原文还提到可使用 input_cost_per_million_tokens。
database_url 必须指向 PostgreSQL,不能拿 Valkey 替代。/key/generate、store_model_in_db 和消费追踪依赖数据库。LITELLM_MASTER_KEY、DATABASE_URL 则通过 Secrets Manager 注入环境变量,不应硬编码。
查账也有现成接口:GET /user/daily/activity 接受 start_date、end_date,返回每日费用、token 和请求量;GET /user/info?user_id=… 查看用户及关联 key 的消费;/global/spend/report 可供定时任务生成报表。开发者还能在 /ui 的 Usage 页面查看记录,本地测试入口为 http://localhost:4000/ui。
金额预算和调用限额要分开理解。/chat/completions 返回的 x-litellm-key-remaining-requests-{model}、x-litellm-key-remaining-tokens-{model},表示 RPM、TPM 余量,不是剩余金额。
长推理、跨区路由和监控,要一起设计
作者最初使用 Geographic(US)跨区域推理,遇到区域配额限制后迁移到 Global CRIS。前者把处理范围限制在指定地理区域,后者可使用全球受支持 AWS 商业区域的容量,前提是组织允许数据跨这些区域处理。
下面这段 CDK 代码解决 Global CRIS 的模型来源和调用权限问题:
import * as cdk from 'aws-cdk-lib';
import * as bedrock from 'aws-cdk-lib/aws-bedrock';
import * as iam from 'aws-cdk-lib/aws-iam';
// 创建指向 Global CRIS 系统推理配置的应用推理配置,注意 global. 前缀。
const sonnetProfile = new bedrock.CfnApplicationInferenceProfile(this, 'SonnetProfile', {
inferenceProfileName: 'claude-sonnet-gateway',
modelSource: {
copyFrom: `arn:aws:bedrock:us-east-1:${this.account}:inference-profile/global.anthropic.claude-sonnet-4-20250514-v1:0`,
},
description: 'Claude Sonnet for developer coding assistants (Global CRIS)',
});
// 授予任务角色调用权限,覆盖应用推理配置和底层模型资源。
litellmTaskRole.addToPolicy(new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['bedrock:InvokeModel', 'bedrock:InvokeModelWithResponseStream'],
resources: [
sonnetProfile.attrInferenceProfileArn,
'arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-sonnet-4-20250514-v1:0',
'arn:aws:bedrock:*::foundation-model/anthropic.claude-sonnet-4-20250514-v1:0',
],
}));
要盯住 copyFrom 和 resources:前者必须引用带 global. 前缀的系统 inference profile,直接引用 foundation-model ARN 会得到单区域配置;后者必须覆盖实际路由涉及的底层模型,仅授权应用 profile 会在调用时被拒绝。
长推理还会暴露链路超时问题。作者遇到过 ALB 的 60 秒 idle timeout 导致请求失败,建议至少设为 900 秒,同时配置 LiteLLM 的 timeout: 900。Haiku 示例则为 timeout: 120。
限流后的处理也有取舍。作者曾尝试从 Sonnet 降级到 Haiku,后来改为同模型指数退避,配置 max_retries: 3;重试耗尽就明确报错。他们认为编程助手需要稳定的行为,不能只追求请求返回成功。
观测上,他们重点关注 RPM 和 TPM,并在配额使用到 60–70% 时提前告警。示例告警使用 LiteLLM/Gateway 下的 TokensPerMinute,按 1 分钟 Sum 聚合,阈值 600000、evaluationPeriods: 3。阈值必须结合实际账号配额调整。
这个指标不会自动出现,需要自定义 logger 调用 CloudWatch PutMetricData。原文在这里存在冲突:正文要求通过可叠加的 litellm_settings.success_callback 注册,警告 callbacks 会替换内部 logger、破坏消费追踪,但随后的 Python 示例却写了 litellm.callbacks = [TPMEmitter()]。这段不能直接照抄上线。
Langfuse 则负责提示词级排查,通过 success_callback、failure_callback 接入,并用 LANGFUSE_PUBLIC_KEY、LANGFUSE_SECRET_KEY、LANGFUSE_HOST 配置。启用前需要确定脱敏、保留期限和访问权限,因为日志可能包含代码、提示词与响应。
我的判断
这篇最有价值的经验,是把费用计算、长请求超时和模型行为稳定性连起来看。相比每个人直接接 Bedrock,统一网关更适合需要身份管理、成本归属和统一策略的团队。
但作者没有提供延迟、吞吐、运维成本的对照数据。「服务数百人」是部署经验,不能直接换算成你需要的容量。原文对 profile 配额隔离的表述也不能理解成每建一个 profile 就有独立容量池,实际配额边界仍需核实。
对小团队,Fargate、RDS、Valkey、ALB 加上 Enterprise 许可可能偏重。先由管理员发 key 做试点,也能验证部分需求。Global CRIS 同样有数据处理地域前提,不能仅凭容量优势决定。
此外,原文没有给出 LiteLLM 版本、完整部署栈,也未展开 Bedrock Guardrails。它适合作为方案检查清单,距离可交付工程仍有一段实现和验证工作。
能拿来做什么
- 给团队统一接入 AI 编程工具时,先验证客户端的流式响应、工具调用和错误处理,再用个人 key 接入预算管理;不要只测一次文本问答。
- 验证预算时,检查实际请求是否产生非零消费,再测试触顶后的 HTTP 429,并确认新增观测回调后消费仍持续累计。
- 将 CI/CD、自动代码审查与交互式开发流量分开。作者建议自动化直接使用 Bedrock,并配置各自的 inference profiles 和配额,减少延迟与费用归属上的相互干扰。
- 试点结束就清理资源。CDK 管理的栈可用
cdk destroy;手工拼装的方案需要逐项删除,尤其不要遗漏持续计费的 RDS、Valkey、Fargate 和 ALB。