公司动态

基于LiteLLM构建高可用AI Gateway:统一多模型API调用与生产实践

📅 2026/8/12 10:40:21
基于LiteLLM构建高可用AI Gateway:统一多模型API调用与生产实践
1. 项目概述为什么我们需要一个AI Gateway如果你最近在折腾大模型应用开发大概率会跟我有一样的感受API调用太乱了。今天要调OpenAI的ChatGPT明天客户要求换成智谱的GLM后天内部测试又得切到本地的Ollama。每个模型的API地址、认证方式、参数格式、甚至错误码都五花八门。更别提计费、限流、日志和监控这些运维层面的头疼事了。这感觉就像家里电器插头型号不统一每次用新设备都得找个转换器麻烦不说还容易出错。这就是“AI Gateway”AI网关要解决的问题。它本质上是一个统一的代理层坐落在你的应用程序和背后五花八门的AI模型API之间。你的App只需要和这个网关对话由网关来负责把请求路由到正确的模型、转换格式、处理认证、收集日志。听起来是不是有点像微服务架构里的API网关没错核心思想一脉相承只是专门为AI模型API的特性做了优化。我最近在重构公司的一个智能客服项目接入了超过5家厂商的模型深刻体会到了没有统一网关的痛。比如Anthropic的Claude和DeepSeek的API同样一个“max_tokens”参数一个代表“最大生成token数”另一个却可能代表“最大上下文长度”直接传过去就报错。又比如所有厂商的计费方式都不一样有的按token有的按请求次数月底对账简直是一场噩梦。所以我决定动手搭建一个自己的AI Gateway把这些问题一次性解决掉。这篇文章就是我这次实践的完整记录从为什么需要到怎么设计再到一步步实现和踩坑希望能给有同样需求的你一份可落地的参考。2. AI Gateway的核心价值与设计思路拆解在动手写代码之前我们必须想清楚一个好的AI Gateway到底应该承担哪些职责仅仅是做个请求转发吗那用Nginx反向代理也能做。但AI模型的调用有它的特殊性我们需要一个更“聪明”的中间层。2.1 核心价值不止于统一接口首先最直观的价值是统一接口。对外Gateway暴露一套标准化的API比如统一的聊天补全端点/v1/chat/completions无论后端是GPT-4还是通义千问对前端应用来说调用方式完全一样。这极大地降低了客户端代码的复杂度和耦合性。其次是厂商无关的抽象。不同模型提供商的能力有差异。有的支持函数调用Function Calling有的支持JSON模式输出有的则没有。Gateway可以在这一层做能力调和与降级处理。例如当后端模型不支持JSON模式时Gateway可以通过Prompt工程技巧在请求中注入指令并解析返回的文本模拟出JSON格式的输出给前端实现透明的兼容。第三是关键的业务支撑功能这往往是自建Gateway的最大动力负载均衡与故障转移当你有多个相同模型的API密钥比如多个OpenAI账号或多个可用区端点时Gateway可以实现轮询、加权或基于延迟的负载均衡。更重要的是当某个端点超时或返回特定错误时能自动切换到备用端点保障服务的可用性。速率限制与配额管理防止单个用户或应用过度消耗资源。你可以基于API Key、IP或用户ID设置每秒/每分钟/每日的调用次数或Token消耗上限。这对于SaaS服务或多租户应用至关重要。成本控制与预算预警Gateway是所有流量的必经之路因此可以精确统计每个项目、每个用户、每个模型的Token消耗并根据厂商的定价模型实时计算成本。可以设置预算阈值当接近限额时发出告警或直接阻断请求。审计与日志集中记录每一次调用的详细信息谁、在什么时候、调用了什么模型、输入输出是什么、消耗了多少Token、耗时多久。这不仅是安全审计的需要也为后续的模型效果分析、性能优化提供了数据基础。缓存对于一些重复性或可预测的请求例如将固定产品描述翻译成多国语言可以将结果缓存起来后续相同请求直接返回缓存能显著降低成本和延迟。2.2 技术选型从零造轮子还是基于开源明确了需求接下来就是技术选型。你有几个主流选择完全自研用PythonFastAPI/Flask、GoGin或Node.js从头搭建。灵活性最高可以完全贴合业务定制。但所有功能都需要自己实现开发周期长容易重复造轮子。使用开源项目这是更高效的选择。目前社区有几个不错的开源AI Gateway项目它们已经实现了路由、鉴权、限流等核心功能。OpenAI的LiteLLM这可能是目前最流行、功能最全的选择。它不仅仅是一个网关更是一个强大的模型抽象库。它支持超过100种模型API的统一调用内置了缓存、故障转移、负载均衡、流式输出、成本计算等高级功能。它的Gateway模式可以独立部署。Portkey另一个功能丰富的开源网关特别强调可观测性和生产就绪提供了精细的监控面板。AI Proxy一些更轻量级的代理项目功能相对聚焦。经过对比我最终选择了LiteLLM作为基础。原因很简单它的模型支持列表最全社区活跃文档也比较完善并且它“Proxy Server”的模式开箱即用我们可以在其基础上进行二次开发增加我们需要的特定业务逻辑性价比最高。2.3 架构设计一个高可用的Gateway长什么样即使使用LiteLLM我们也需要规划部署架构。对于生产环境我们不能只运行一个单点服务。一个典型的高可用架构如下[客户端 App] - [负载均衡器 (如 Nginx/云LB)] - [AI Gateway 集群] - [各大模型厂商 API] |- [Redis (用于限流、缓存)] |- [数据库 (用于存储日志、配置)]Gateway集群部署多个Gateway实例通过负载均衡器对外提供服务避免单点故障。Redis用作分布式速率限制的存储后端确保集群内所有实例的限流计数是同步的。同时也可以作为缓存后端。数据库存储详细的调用日志、API Key信息、成本数据等用于查询和分析。可以选择PostgreSQL或MySQL。我们的目标就是基于LiteLLM搭建起这样一个具备生产可用性的服务。3. 基于LiteLLM搭建AI Gateway实操详解理论讲完我们进入实战环节。我会以LiteLLM为核心演示如何从零部署一个功能完备的AI Gateway。3.1 环境准备与依赖安装首先确保你的服务器环境是Python 3.8。我推荐使用虚拟环境来管理依赖避免污染系统环境。# 创建项目目录并进入 mkdir ai-gateway cd ai-gateway # 创建虚拟环境以venv为例 python -m venv venv # 激活虚拟环境 # Linux/macOS source venv/bin/activate # Windows venv\Scripts\activate # 安装核心依赖litellm pip install litellm[proxy] # [proxy] 额外安装了运行代理服务器所需的依赖除了LiteLLM我们可能还需要一些其他库比如用于连接Redis的redis用于连接数据库的sqlalchemy和psycopg2-binary以PostgreSQL为例以及用于配置管理的pydantic-settings。pip install redis sqlalchemy psycopg2-binary pydantic-settings3.2 基础配置与启动LiteLLM的代理服务器可以通过命令行快速启动也支持通过配置文件进行更精细的控制。我们先从简单的开始。创建一个名为config.yaml的配置文件model_list: - model_name: gpt-4-turbo # 你给这个模型组合起的别名 litellm_params: model: gpt-4-turbo # 实际的OpenAI模型名 api_key: ${OPENAI_API_KEY} # 从环境变量读取 api_base: https://api.openai.com/v1 - model_name: claude-3-sonnet litellm_params: model: claude-3-5-sonnet-20241022 api_key: ${ANTHROPIC_API_KEY} api_base: https://api.anthropic.com - model_name: deepseek-chat litellm_params: model: deepseek-chat api_key: ${DEEPSEEK_API_KEY} api_base: https://api.deepseek.com litellm_settings: drop_params: true # 自动丢弃后端不支持的参数 set_verbose: true # 开启详细日志调试时有用 general_settings: master_key: ${MASTER_KEY} # Gateway的管理员密钥用于创建用户API Key等 database_url: postgresql://user:passlocalhost/dbname # 可选用于持久化日志注意敏感信息如api_key和master_key务必通过环境变量传入不要直接写在配置文件中。可以使用${VAR_NAME}语法LiteLLM会自动从环境变量中读取。设置环境变量export OPENAI_API_KEYsk-xxx export ANTHROPIC_API_KEYsk-ant-xxx export DEEPSEEK_API_KEYsk-xxx export MASTER_KEYyour-super-secret-master-key-here现在使用配置文件启动代理服务器litellm --config ./config.yaml默认情况下服务会运行在http://localhost:4000。你可以用curl测试一下curl http://localhost:4000/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer your-master-key-or-generated-key \ -d { model: gpt-4-turbo, # 使用你在config里定义的model_name messages: [{role: user, content: Hello, world!}] }如果一切正常你将收到来自GPT-4的回复。至此一个最基础的、能统一调用多模型的Gateway就跑起来了。但它的功能还很基础我们接下来要为其注入灵魂。3.3 核心功能增强路由、限流与缓存1. 动态路由与负载均衡上面的配置是静态的一个model_name对应一个后端。但在生产环境中我们可能需要更灵活的路由策略。例如将“gpt-4”的请求根据负载或成本动态分发给Azure OpenAI和OpenAI官方API。这可以通过LiteLLM的router模式实现。我们需要编写一个Python脚本来启动更强大的路由服务。创建router_server.pyfrom litellm import Router import os # 定义多个相同模型的不同后端 model_list [ { model_name: gpt-4o, # 统一对外的模型名 litellm_params: { model: azure/gpt-4o, api_key: os.getenv(AZURE_API_KEY), api_base: os.getenv(AZURE_API_BASE), api_version: 2024-02-01 }, }, { model_name: gpt-4o, # 同一个对外模型名指向另一个提供商 litellm_params: { model: gpt-4o, api_key: os.getenv(OPENAI_API_KEY), }, }, ] # 创建路由器设置路由策略 router Router( model_listmodel_list, routing_strategylatency-based, # 策略负载均衡、最少请求、基于延迟 # fallbacks[...], # 可以设置降级模型列表 # num_retries2, # 失败重试次数 ) # 现在所有对“gpt-4o”的请求router会根据策略选择其中一个后端。 # 你可以将router集成到FastAPI应用中对外提供API。2. 速率限制限流是保护后端API不被刷爆的关键。LiteLLM支持基于用户ID或API Key的限流。我们需要一个Redis来存储计数。首先确保Redis服务已运行。然后在配置或代码中启用限流# 在config.yaml中追加 litellm_settings: # ... 其他设置 redis_url: redis://localhost:6379 # 指向你的Redis redis_cache: true general_settings: # ... 其他设置 rate_limit: user_based # 或 api_key_based更精细的限流规则需要在代码中设置。你可以通过LiteLLM的success_callback和async_success_callback钩子在请求成功后自定义计数逻辑或者直接使用其内置的get_model_list和update_model_listAPI来动态管理每个模型的每分钟调用次数TPM限制。3. 结果缓存对于内容确定的请求如固定文本的翻译、总结缓存可以极大提升响应速度并节省成本。启用缓存同样需要Redis。litellm_settings: caching: true caching_with_models: true # 将模型信息也作为缓存键的一部分避免不同模型结果混淆 redis_url: redis://localhost:6379缓存的行为是当收到一个请求时LiteLLM会生成一个哈希键基于模型、消息内容、参数等先检查Redis中是否存在。如果存在且未过期则直接返回缓存结果。你可以在请求中通过cachingTrue参数来显式启用本次调用的缓存。3.4 监控、日志与成本计算一个没有观测性的系统就是在“裸奔”。我们需要知道Gateway的运行状况。1. 日志持久化LiteLLM可以将详细的调用日志包括请求、响应、token用量、延迟发送到多个目的地。最常用的方式是写入数据库。我们在配置中已经指定了database_urlLiteLLM会自动创建表并写入日志。你也可以编写自定义的回调函数将日志推送到Elasticsearch、DataDog或你的内部监控系统。from litellm import completion import asyncio async def custom_callback( kwargs, # 请求参数 completion_response, # 响应对象 start_time, end_time ): # kwargs 包含 model, messages, api_key 等 # completion_response 包含 choices, usage 等 latency end_time - start_time print(f本次调用模型: {kwargs[model]}, 耗时: {latency}, 消耗token: {completion_response[usage]}) # 这里可以写入你的数据库或消息队列 # 将回调函数挂载到litellm import litellm litellm.success_callback [custom_callback]2. 成本计算成本计算依赖于准确的token计数。LiteLLM在completion_response.usage中提供了prompt_tokens和completion_tokens。你需要自己维护一个价格表。# 一个简单的价格表示例 (价格是假设的需查询厂商最新定价) MODEL_COST_PER_1K_TOKENS { “gpt-4-turbo”: {“input”: 0.01, “output”: 0.03}, # 美元/1K tokens “claude-3-sonnet”: {“input”: 0.003, “output”: 0.015}, “deepseek-chat”: {“input”: 0.00014, “output”: 0.00028}, # 人民币元/1K tokens } def calculate_cost(model_name, usage): cost_config MODEL_COST_PER_1K_TOKENS.get(model_name) if not cost_config: return 0.0 input_cost (usage.prompt_tokens / 1000) * cost_config[“input”] output_cost (usage.completion_tokens / 1000) * cost_config[“output”] return input_cost output_cost在你的自定义回调函数中调用calculate_cost并将成本与日志一起持久化就能实现按项目、按用户、按模型的成本分析了。4. 生产环境部署与运维要点让服务在本地跑起来只是第一步要上生产环境还有一系列问题需要解决。4.1 部署与高可用我推荐使用Docker容器化部署。这能保证环境一致性也便于编排。创建一个简单的DockerfileFROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . # 暴露端口 EXPOSE 4000 # 使用环境变量配置文件启动 CMD [litellm, --config, /app/config.yaml, --port, 4000, --host, 0.0.0.0]使用Docker Compose可以轻松管理Gateway、Redis和PostgreSQL服务# docker-compose.yml version: 3.8 services: ai-gateway: build: . ports: - “4000:4000” environment: - OPENAI_API_KEY${OPENAI_API_KEY} - ANTHROPIC_API_KEY${ANTHROPIC_API_KEY} - MASTER_KEY${MASTER_KEY} - REDIS_URLredis://redis:6379 - DATABASE_URLpostgresql://postgres:passworddb:5432/litellm_logs depends_on: - redis - db restart: unless-stopped redis: image: redis:7-alpine ports: - “6379:6379” volumes: - redis_data:/data restart: unless-stopped db: image: postgres:15-alpine environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: password POSTGRES_DB: litellm_logs volumes: - postgres_data:/var/lib/postgresql/data restart: unless-stopped volumes: redis_data: postgres_data:在云环境中你可以使用Kubernetes来部署这个Compose栈并配置Horizontal Pod Autoscaler (HPA) 根据CPU/内存或自定义指标如QPS自动伸缩Gateway的实例数量实现真正的高可用与弹性伸缩。4.2 安全加固Gateway掌握了所有模型的API密钥安全至关重要。网络隔离将Gateway部署在内网不直接对外暴露。通过一个前置的API网关如Kong, Tyk或负载均衡器进行反向代理并在该层配置WAF、DDoS防护和SSL终止。认证与鉴权不要长期使用master_key。应该通过Gateway提供的/key/generate端点LiteLLM支持为每个客户端应用或用户生成具有特定权限如只能访问某些模型、有调用限额的临时API Key。密钥管理所有API Key包括后端模型商的都应使用专业的密钥管理服务如HashiCorp Vault AWS Secrets Manager 或云原生的K8s Secrets来存储和动态注入而不是写在环境变量文件里。请求验证与过滤在Gateway层对输入进行基本的清洗和过滤防止Prompt注入攻击。可以检查输入长度过滤敏感词等。4.3 监控告警体系除了日志还需要建立监控仪表盘和告警。核心指标请求量QPS、成功率、错误率按模型、按用户细分平均响应延迟、P95/P99延迟Token消耗速率、成本消耗速率各后端模型API的健康状态可用性工具链可以使用Prometheus收集指标需要为LiteLLM编写一个简单的exporter或在其回调函数中推送指标用Grafana制作仪表盘。告警可以配置在Prometheus Alertmanager或Grafana自身。关键告警某个模型错误率连续超过5%平均响应延迟超过10秒单个用户Token消耗速率异常激增当日成本预算使用超过80%5. 常见问题与故障排查实录在实际搭建和运营过程中我遇到了不少坑。这里总结几个典型问题及其解决方案。5.1 连接性与超时问题问题现象客户端调用Gateway超时或Gateway调用后端模型API超时。排查思路检查网络连通性在Gateway容器内使用curl或ping测试是否能访问目标API基地址如api.openai.com。防火墙或安全组规则是常见原因。调整超时设置模型生成长文本时可能耗时很久。需要在Gateway层面增加超时配置。# 在config.yaml的litellm_settings下 litellm_settings: request_timeout: 600 # 全局请求超时设置为600秒 read_timeout: 600 # 读取超时同时确保你的反向代理如Nginx和客户端SDK的超时设置也足够长。并发限制检查是否为同一个API Key配置了过高的并发请求。某些厂商对单个Key的并发数有限制超出会返回429错误。需要在Gateway中配置合理的速率限制。5.2 流式响应Server-Sent Events中断问题现象当请求流式输出streamTrue时连接经常中途断开客户端收不全数据。排查与解决网关超时这是最常见的原因。流式响应是一个长连接如果网关或负载均衡器设置了较短的读写超时会主动切断连接。需要在Nginx等代理中调整相关参数。# Nginx 配置示例 location /v1/chat/completions { proxy_pass http://ai-gateway:4000; proxy_set_header Host $host; proxy_buffering off; # 关键禁用缓冲让数据立即转发 proxy_read_timeout 300s; # 设置长的读超时 proxy_connect_timeout 75s; }客户端处理确保客户端代码能正确处理SSE流及时从socket中读取数据。网络波动也可能导致中断需要客户端有重连机制。5.3 计费数据不准问题问题现象Gateway统计的Token消耗和成本与模型厂商后台的数据有出入。排查思路Tokenizer差异不同库的tokenizer如OpenAI的tiktoken和HuggingFace的tokenizer对同一文本的token计数可能有细微差别。LiteLLM默认使用各模型对应的官方或推荐tokenizer但版本更新可能导致偏差。确保LiteLLM版本是最新的。缓存影响如果启用了缓存那么命中的请求不会真实调用后端API因此后端厂商那里不会有记录但Gateway的日志里可能仍然记录了一次“调用”虽然没消耗真实Token。需要在成本计算逻辑中区分缓存命中与否。日志丢失在高并发下如果日志是异步写入数据库可能因程序崩溃或队列积压导致部分日志丢失。考虑引入更可靠的消息队列如RabbitMQ, Kafka做日志缓冲或者定期与厂商的账单API做对账校准数据。5.4 特定模型参数兼容性问题问题现象使用统一参数调用某个模型时返回奇怪的错误比如400 ‘type‘ must be in [“enabled“, “disabled“, “auto“]或400 this model‘s maximum context length is ...。原因与解决 这是AI Gateway面临的核心挑战之一参数标准化。例如max_tokens参数在OpenAI代表“最大生成token数”但在Anthropic可能被映射为max_tokens_to_sample而在其他平台可能有不同含义。启用drop_params: true这是LiteLLM配置中的一个救命选项。它会自动剥离目标模型不支持的参数避免因传递了未知参数而报错。使用模型别名与参数映射对于行为差异巨大的模型更好的办法是为它们创建独立的模型别名并在Gateway层做参数转换。model_list: - model_name: “claude-3-sonnet-custom“ litellm_params: model: claude-3-5-sonnet-20241022 api_key: ${ANTHROPIC_API_KEY} # 在这里可以添加litellm特定的转换参数 # 但更复杂的转换可能需要自定义代码自定义回调进行参数预处理在请求发送前通过pre_call_callback钩子根据目标模型动态修改请求体。def param_adapter(kwargs): model kwargs[“model”] if “claude” in model: # 将通用的max_tokens映射为Anthropic的参数 if “max_tokens” in kwargs: kwargs[“max_tokens_to_sample”] kwargs.pop(“max_tokens”) return kwargs litellm.pre_call_rules [param_adapter]搭建和维护一个成熟的AI Gateway绝非一蹴而就它随着接入模型的增多和业务复杂度的提升而不断演进。从我自己的经验来看起步阶段可以先用LiteLLM的默认配置快速搭建原型解决多模型调用的燃眉之急。随着业务发展再逐步引入更精细的路由策略、更完善的监控告警和更强大的安全管控。这个过程中清晰的日志和可观测性是你最好的排错伙伴。每当遇到诡异的问题回头去分析请求/响应的完整日志流总能找到线索。