亚马逊AWS官方博客
化繁为简:一键部署多模型网关,助力 Role-play 最佳实践
引言
随着生成式 AI 技术的兴起,Role-play 应用正在成为业界关注的热点。Role-play 应用是指基于大语言模型(LLM)构建的具有个性化特征的 AI 助手或虚拟人物,能够在客服、教育、娱乐等领域提供智能化的人机交互服务。为提升 Role-play 应用体验,多模型成为必然的趋势,然而多模型也带来了模型路由、多模型并发、弹性扩缩等挑战,这就需要一套灵活、高效、经济的流量调度机制。本文将探讨如何利用 Amazon ECS(Elastic Container Service)以及 Amazon Graviton 配合 LiteLLM 实现这一目标。
挑战
Role-play 模型网关在线提供服务,访问时面临以下挑战:
- 多模型:不同 Role-play 角色需要使用多样化的 LLM 模型,在知识领域、语言风格、交互方式上各有侧重,因此流量网关需要支持不同模型实例的路由。
- 多区域/账号:流量调度网关需要在多个区域或者多账号间实现负载均衡,将请求合理分发,避免过载,同时还要具备一定的容错能力,规避单区域故障,提升可用性。
- 高可用:大模型推理是关键路径,计算资源消耗大,单个网关实例无法支撑高流量请求。需要能够根据流量压力调整到多个实例配置,在高峰期自动扩容,闲时缩容,以平衡性能和成本。
- 安全:为了模型调用的可靠,避免模型 API 的直接暴露,我们还需要实现 API 调用的鉴权机制。
解决方案
针对上述挑战,我们提出了基于容器化方案和开源 LiteLLM 来构建大模型流量调度网关的解决方案。整体架构如下图所示:
将流量动态路由到 Claude、Mistral 等不同的大语言模型上,或者负载到不同的账号上, 实现大模型的负载均衡和智能调度。
关键特性
- 容器化封装:每个 AI Character 对应的 LLM 模型分配和调度策略被封装为 Docker 容器镜像,内置推理运行时环境和模型参数文件。利用 ECS 的任务定义(Task Definition)描述容器的资源需求和配置属性。
- 服务化部署:通过服务描述文件指定使用的任务定义、期望运行的任务数量等配置 Auto Scaling 策略,根据 CPU 利用率等指标自动调整任务数,实现服务的弹性伸缩。ECS 将确保运行中的任务数量符合期望值,发生故障时自动替换。
- 分层负载均衡:引入 Application Load Balancer(ALB)作为流量网关的入口。ALB 支持基于内容的路由规则,可根据请求的特征(如路径、查询参数等)将流量分发到不同的目标组(Target Group)。每个 ECS 服务注册为一个目标组,ALB 将请求动态转发到服务内的多个任务实例,实现负载均衡。同时在 ECS 服务内部,每个任务实例运行一个 LiteLLM 容器,使用 Round-Robin 策略处理分发到本实例的请求,避免单个容器过载。
部署方式
基于 ECS 的部署
步骤:
1. 根据账号和模型使用情况编写 Proxy Config 文件:
- 为相同的 model_name 配置不同的区域或者账号信息,实现相同模型的流量分配。
- 为不同的模型,包括 Bedrock 托管模型和在 SageMaker 上部署的模型,配置不同的 model_name,实现为不同用户、角色和任务的灵活选择。
## proxy_config.yaml
model_list:
- model_name: bedrock-claude-v3-sonnet
litellm_params:
model: bedrock/anthropic.claude-3-sonnet-20240229-v1:0
aws_region_name: "us-west-2"
aws_access_key_id: "<replace_with_your_access_key>"
aws_secret_access_key: "<replace_with_your_secret_key>"
- model_name: bedrock-claude-v3-sonnet
litellm_params:
model: bedrock/anthropic.claude-3-sonnet-20240229-v1:0
aws_region_name: "us-east-1"
aws_access_key_id: "<replace_with_your_access_key>"
aws_secret_access_key: "<replace_with_your_secret_key>"
- model_name: bedrock-claude-v3-haiku
litellm_params:
model: bedrock/anthropic.claude-3-haiku-20240307-v1:0
aws_region_name: "us-west-2"
aws_access_key_id: "<replace_with_your_access_key>"
aws_secret_access_key: "<replace_with_your_secret_key>"
- model_name: sagemaker-llama2-7b
litellm_params:
model: sagemaker/jumpstart-dft-meta-textgeneration-l-2024xxxx-0642 # replace with your endpoint
aws_region_name: "us-west-2"
aws_access_key_id: "<replace_with_your_access_key>"
aws_secret_access_key: "<replace_with_your_secret_key>"
- model_name: sagemaker-Yi-1.5-9b
litellm_params:
model: sagemaker/jumpstart-dft-hf-llm-yi-1-5-9b-chat-2024xxxx-070517 # replace with your endpoint
aws_region_name: "us-west-2"
aws_access_key_id: "<replace_with_your_access_key>"
aws_secret_access_key: "<replace_with_your_secret_key>"
general_settings:
master_key: "<replace_with_your_master_key>"
2. 在方案部署账号中准备一个 S3 桶,上传上述 yaml 文件到 s3://<bucket_name>/litellm/proxy_config.yaml
3. 一键部署 CloudFormation 模版,需要输入上一步的 S3 桶名 bucket_name。该方案会部署的资源包括:
- 新的 VPC、公有和私有 Subnets、安全组、Internet Gateway。方案默认为实现 Virtual Key 和用户资源使用管理部署 PostgreSQL,为实现负载均衡的路由规则管理部署 Redis。
- ECS 集群和 Litellm ECS Service,该服务支持根据 CPU utilization 使用量自动扩缩,日志会进入 CloudWatch LogGroup。
- Application Load Balancer,Litellm Service 通过 ALB 暴露在 80 端口。
部署完成后,CloudFormation 的 Output 会显示 ALB 的 DNS。
即可开始使用模型网关,以下为 Postman 示例:
除了适用于生产环境的基于 ECS 的高可用弹性部署,此方案也提供基于 EC2 和 docker-compose 的快速部署方案,方便进行功能快速验证。
基于 EC2 的部署
步骤:
1. 准备 proxy_config.yaml 并将文件到 s3://<bucket_name>/litellm/proxy_config.yaml
2. 上传 docker-compose.yml 和 prometheus.yml 到同一路径 s3://<bucket_name>/litellm/
下
services:
litellm:
image: ghcr.io/berriai/litellm:main-stable
ports:
- "80:4000"
...
redis:
image: redis:6.2-alpine
ports:
- '6379:6379'
...
db:
image: postgres
ports:
- '5432:5432'
...
prometheus:
image: prom/prometheus
ports:
- '9090:9090'
基于 docker-compose 的部署默认添加了 Prometheus 组件,因只有 LiteLLM 企业版提供譬如根据 user,key,model,team 等维度指标来跟踪 spend 和 token 的使用情况,开源版本中默认的 prometheus 组件仅上报基础的 python 和 process 资源使用指标。可根据实际需要选择使用企业版或移除 prometheus 组件。
3. 一键部署 CloudFormation 模版 ,需要输入上一步的 S3 桶名 bucket_name。该方案会部署的资源包括:
- 新的 VPC、公有和私有 Subnets、安全组、Internet Gateway
- EC2 MultiLLM server,服务端点为 http:// <MultiLLM_Server_PublicIP>:80
此方案的部署基于 LiteLLM 项目,以上两种方式都可通过 admin 面板 http://<MultiLLM_DNS_or_IP>/ui
进行后续管理,登录信息为 admin/<master_key>
。
基础功能测试
1. OpenAPI 兼容性
- rest call 调用(支持 streaming 功能)
curl -i http://$litellm_ip:80/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer <master_key>" \ -d '{ "model": "bedrock-claude-v3-haiku", "messages": [ { "role": "user", "content": "Hello" } ], "stream": True }'
- SDK 集成
import openai client = openai.OpenAI( api_key="<your_master_key or virtual_key>", base_url="http://$litellm_ip:80" ) # request sent to model set on litellm proxy, `litellm --model` response = client.chat.completions.create(model="bedrock-claude-v3-haiku", messages = [ { "role": "user", "content": "this is a test request, write a short poem" } ]) print(response)
2. Virtual key 使用
- 为 user 生成 key,配置可以调用的模型
curl http://$litellm_ip:80/key/generate \ --header 'Authorization: Bearer <master_key>' \ --header 'Content-Type: application/json' \ --data-raw '{ "models": [ "bedrock-claude-v3-sonnet", "bedrock-claude-v3-haiku" ], "metadata": { "user": "<user_mail>" } }'
结果返回的 JSON 中含有类似 sk-pyHgYR8Iacc4CLHwjeKu4Q 的 virtual key。
- 查询 key 的使用情况
curl http://$litellm_ip:80/key/info?key=sk-pyHgYR8Iacc4CLHwjeKu4Q \ -X GET \ -H 'Authorization: Bearer <master_key>'
结果返回的 JSON 内容包含对应 Key 的 spend 使用情况。
3. Routing 功能
- 在 yaml 文件中将路由策略配置为 simple shuffle
model_list: - model_name: bedrock-claude-v3-sonnet litellm_params: model: bedrock/anthropic.claude-3-sonnet-20240229-v1:0 aws_region_name: "us-west-2" ... - model_name: bedrock-claude-v3-sonnet litellm_params: model: bedrock/anthropic.claude-3-sonnet-20240229-v1:0 aws_region_name: "us-east-1" ... router_settings: routing_strategy: simple-shuffle
当多次调用 bedrock-claude-v3-sonnet 时,返回的结果标头会显示不同的 model id ,证明不同的 LLM 实例被调用了。
#第一次调用 bedrock-claude-v3-sonnet 返回结果标头 HTTP/1.1 200 OK ... server: uvicorn x-litellm-call-id: ac125673-85ef-466e-ba3f-f26fab463041 x-litellm-model-id: 2a281c00b23a45934cb6a5cb3929249fb55627923ece219cdbcc2331a7b1855f ... #第二次调用 bedrock-claude-v3-sonnet 返回结果标头 HTTP/1.1 200 OK ... server: uvicorn x-litellm-call-id: c24f6b5c-385a-4105-af2f-b4ad2b801371 x-litellm-model-id: ab933985853f13d8760ccd08d89e500574fd52724a211b24e082936b8d5eb382 ...
- 在 proxy_config.yaml 文件中将路由策略按以下配置为 rate limit aware 方式
YAML model_list: - model_name: bedrock-claude-v3-sonnet litellm_params: model: bedrock/anthropic.claude-3-sonnet-20240229-v1:0 aws_region_name: "us-west-2" rpm: 10 ... - model_name: bedrock-claude-v3-sonnet litellm_params: model: bedrock/anthropic.claude-3-sonnet-20240229-v1:0 aws_region_name: "us-east-1" rpm: 10 ... router_settings: routing_strategy: usage-based-routing
当调用 bedrock-claude-v3-sonnet 的 rpm 超过 20 时,返回的结果为 “HTTPError(‘429 Client Error: Too Many Requests for url: /v1/chat/completions’)” 。
更多详细功能可参考 LiteLLM 项目。
Locust 压测
运行 locust 脚本,以下是配置 peak users = 100, ramp up = 20 对 haiku 模型进行的压测结果截图:
结论
借助容器化和自动扩缩容特性,以及 LiteLLM 的轻量化优势,我们可以构建一个灵活、高效、经济的大模型调度机制。这不仅能够显著降低应用的运营成本,还能以更敏捷的方式满足不断变化的需求。
代码链接:
https://github.com/chenxqdu/multillm-proxy-on-aws