Deploy decision models with llama.cpp on Amazon SageMaker AI

TL;DR · AI 摘要
AWS展示如何在SageMaker AI部署llama.cpp决策模型,通过文本生成和结构化决策两种路径实现量化模型服务。
核心要点
- 使用AWS DLC打包模型并部署到SageMaker AI,支持CPU/GPU量化推理
- SemIf扩展可返回选项概率而不解码答案标记,适用于决策场景
- 两种部署路径分别对应OpenAI兼容API和结构化决策需求
结构提纲
按章节快速跳转。
- §引言
介绍在SageMaker AI部署决策模型的必要性和技术路径
展示文本生成和结构化决策两种部署路径的架构差异
详细说明模型打包、容器构建和环境变量配置流程
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- SageMaker AI部署决策模型
- 部署路径
- 文本生成
- 结构化决策
- 核心技术
- llama.cpp
- SemIf
- 输入模式
- OpenAI API
- 决策schema
金句 / Highlights
值得收藏与分享的关键句。
SemIf通过替换默认服务器实现选项概率返回,无需解码答案标记
结构化决策路径使用AWS CodeBuild构建子镜像并存储到ECR
llama-server HTTP API不暴露SemIf需要的最终位置logits和状态操作
使用 llama.cpp 在 Amazon SageMaker AI 上部署决策模型 | 人工智能
使用 llama.cpp 在 Amazon SageMaker AI 上部署决策模型
需要对固定选项集进行评分而非生成自由文本的应用场景(如请求路由、代理动作选择或策略结果分配)可通过 llama.cpp 在 SageMaker AI 上部署决策模型,实现基于 CPU 或 GPU 基础设施的量化模型服务化路径。
本文延续 AWS 专用深度学习容器(DLC)系列文章,聚焦生成式 AI 推理场景。此前文章已介绍 WhisperX 、vLLM-Omni – 第 1 部分 和 vLLM-Omni – 第 2 部分 。
本文首先演示如何使用 AWS DLC for llama.cpp 通过 SageMaker AI InvokeEndpoint 提供 OpenAI 兼容的聊天补全服务。随后将扩展相同运行时环境,集成 SemIf(原 OpenJev),该组件可直接返回声明选项的概率分布而无需解码答案标记。配套代码示例包含 CPU 和 GPU 部署方案。
解决方案概览
图 1 展示了从相同封装模型出发的两种部署路径。文本生成路径使用 AWS DLC for llama.cpp 通过 OpenAI 兼容 API 返回生成响应。结构化决策路径则构建子镜像,用 SemIf 适配器替换默认服务器,返回声明选项的概率分布。
图 1:根据工作负载的 API 和延迟需求,在 CPU 或 GPU 上运行 AWS DLC for llama.cpp 或 SemIf 子镜像
标准路径需将模型封装为 model.tar.gz 并上传至 Amazon S3,直接引用已发布的 DLC 镜像。容器会在 /opt/ml/model 下查找首个 .gguf 文件,将 POST /invocations 映射到 /v1/chat/completions 的 llama-server,并传递 SM_LLAMA_CPP_* 环境变量至 llama.cpp 参数。
llama-server HTTP API 未暴露 SemIf 所需的最终位置对数和状态操作。因此结构化决策路径使用 AWS CodeBuild 构建子镜像并存储至 Amazon ECR。该子镜像保留 DLC 的 CPU 或 CUDA 编译库,同时将入口点替换为 SageMaker 兼容适配器。
理解输入和输出模式
AWS DLC for llama.cpp 接受 OpenAI Chat Completions 模式。发送包含 role 和 content 的 messages 数组,以及 max_tokens 和 stream 等生成控制参数:
{
"messages": [
{
"role": "user",
"content": "客户无法接收密码重置邮件。请用最佳支持队列回复。"
}
],
"max_tokens": 64,
"stream": false
}响应使用 OpenAI 兼容的 choices 数组。从 choices[0].message.content 读取生成文本。
SemIf 使用约束决策模式而非聊天消息。请求包含调用者定义的 ID、非结构化状态、问题和有序允许选项列表:
{
"decision": {
"id": "support-route",
"state": "客户无法接收密码重置邮件。",
"question": "哪个队列应处理此请求?",
"options": [
{"id": "account_access", "description": "账户访问支持。"},
{"id": "billing", "description": "账单支持。"}
]
}
}响应返回的选项ID、概率和原始选项日志,顺序与请求中的一致,同时包含提示信息、时间戳和固定模型元数据。通过稳定的选项ID,您的应用可以在不解析生成文本的情况下应用阈值、回退机制和策略检查。
SemIf属于更广泛的决策模型类别,这类模型能够对非结构化状态进行应用定义的评分。其他实现包括Jev、TypeSafe的决策模型和/v1/systemone API;Kev,专为TypeSafe API兼容性设计的模型服务器;以及Strands Decider 2B,专为智能体工作流设计的校准输出模型。
选择合适的决策工作流
在应用在请求时定义允许选项且需要模型解释非结构化上下文时使用此模式。典型场景包括将案例路由到队列、从已知集合中提取单个值、分配事件优先级、检查策略结果或选择智能体操作。将授权和确定性业务规则保留在模型外部,并在将模型概率视为操作置信度之前进行验证。
当需要通过InvokeEndpoint获取OpenAI兼容的聊天补全时,请使用标准的SageMaker AI文本生成路径。SageMaker AI图像将POST /invocations映射到llama-server的/v1/chat/completions端点。仅在应用需要接口未提供的功能(如SemIf的直接日志和状态访问)时才构建子镜像。
移除答案标记生成不会影响模型推理。模型仍会在SemIf读取最终日志前处理完整的状态、问题和选项描述。保持提示简洁,并在生产使用前用应用的标记决策数据评估所选模型。
调整以满足您的延迟和质量目标
以下基准测试适用于SemIf扩展,而非文本生成端点。模型大小、量化方式、提示长度、运行时和CPU线程数会影响每个决策。为了量化这些权衡,我们将相同的231个公开JevBench任务依次发送到一个CPU端点和一个GPU端点。
配置
AWS DLC for llama.cpp
有效响应
准确性
客户端p50
客户端p95
Qwen3.5-4B
Q4_K_M,
ml.c6i.8xlarge, 32线程
llama-cpp:server-sagemaker-cpu-v1
231/231
179/231 (77.5%)
1.715秒
19.291秒
ml.g6e.xlarge, 全GPU卸载
llama-cpp:server-sagemaker-cuda-v1
180/231 (77.9%)
0.352秒
0.599秒
与CPU配置相比,GPU端点在p50时快4.9倍,在p95时快32.2倍。该示例使用SageMaker AI实例池功能按优先级列出兼容的GPU实例类型,因此SageMaker可在首选项不可用时选择替代方案。池的顺序为g6e、g6、g5,然后是g4dn。SageMaker选择了ml.g6e.xlarge,启动日志确认llama.cpp将所有34个模型层卸载到NVIDIA L40S。CPU和GPU镜像使用了不同的llama.cpp构建,在六个困难任务上产生了不同的预测。将单答案准确性差异视为运行时变化,而非GPU卸载提升模型质量的证据。
较小的模型降低了中位延迟,但2B和0.8B候选模型分别实现了66.7%和58.4%的准确率。因此该样本将4B Q4_K_M模型作为其以质量优先的默认选项。这些测量结果包含网络延迟,不代表服务保证。
请将完整模型和基础设施配置与您的决策需求进行基准测试。对于非延迟敏感型任务、需要数秒响应时间且可容忍延迟的后台/离线/低吞吐量工作负载,请使用CPU。对于交互式决策、长提示或尾部延迟要求严格的工作负载,请使用GPU。请保持状态和选项描述简洁,将共享相同状态的决策合并为单个请求,并根据并发需求扩展端点实例。共享状态评分会复用通用提示前缀,而适配器会返回可重试的HTTP 503响应,而非在其状态化llama.cpp上下文周围创建无限制队列。
先决条件
您需要:
- AWS账户及部署AWS区域内的S3存储桶
- Python 3.10或更高版本、Git和AWS命令行界面(AWS CLI)
- 用于可选SemIf扩展的专用CodeBuild服务角色
- SageMaker AI可承担的AWS身份和访问管理(IAM)角色
- SageMaker AI、Amazon ECR、Amazon S3、CodeBuild、IAM pass-role操作及Amazon CloudWatch Logs的权限
- 兼容x86 CPU或NVIDIA GPU的SageMaker实时端点配额
文本生成示例使用CPU DLC和固定CPU实例。SemIf扩展将CPU作为非延迟敏感型工作负载的默认选项,并提供可选的CUDA镜像与有序实例池。创建端点前请查看SageMaker AI定价。
部署决策模型并扩展SemIf
请按照以下步骤部署标准文本生成端点,然后在CPU或GPU上构建可选的SemIf扩展以进行结构化决策:
- 克隆代码示例并安装依赖项
git clone https://github.com/aws-samples/sagemaker-genai-hosting-examples.git
cd sagemaker-genai-hosting-examples/03-features/semif-decision-model
python3 -m venv .venv
. .venv/bin/activate
python3 -m pip install -r deploy/requirements.txt- 设置账户的部署参数
export AWS_REGION="<your-region>"
export ARTIFACT_BUCKET=amzn-s3-demo-semif-artifacts
export CODEBUILD_ROLE_ARN=arn:aws:iam::111122223333:role/semif-codebuild-role
export SAGEMAKER_ROLE_ARN=arn:aws:iam::111122223333:role/semif-sagemaker-role
export STANDARD_ENDPOINT_NAME=llamacpp-gguf
export SEMIF_ENDPOINT_NAME=semif-decision-workflows- 使用CodeBuild打包固定GGUF模型和分词器
python deploy/prepare_model_build.py \
--region "$AWS_REGION" \
--bucket "$ARTIFACT_BUCKET" \
--codebuild-role-arn "$CODEBUILD_ROLE_ARN" \
--model-s3-uri "s3://$ARTIFACT_BUCKET/semif-llamacpp/model.tar.gz"等待返回的构建ID状态变为SUCCEEDED。构建过程会在model-manifest.json中记录源代码修订版本和校验和,如果GGUF校验和与验证值不一致则会停止构建。
- 使用 AWS DLC for llama.cpp 部署 GGUF 模型。从 AWS DLC for llama.cpp 文档中解析固定摘要的 server-sagemaker-cpu-v1 镜像,然后创建 SageMaker AI 模型、端点配置和端点:
export STANDARD_IMAGE_URI="<published-llama-cpp-cpu-image>@sha256:<digest>"
python deploy/deploy_standard_endpoint.py \
--region "$AWS_REGION" \
--image-uri "$STANDARD_IMAGE_URI" \
--model-data-url "s3://$ARTIFACT_BUCKET/semif-llamacpp/model.tar.gz" \
--role-arn "$SAGEMAKER_ROLE_ARN" \
--instance-type ml.c6i.2xlarge \
--name "$STANDARD_ENDPOINT_NAME"选择 server-sagemaker-cpu-v1 或 server-sagemaker-cuda-v1 镜像,而不是对应的 EC2 镜像。SageMaker AI 镜像实现了 /ping 和 /invocations 容器接口,并将调用负载映射到聊天补全。本操作指南通过 Amazon S3 中的 SageMaker AI 模型构件提供 GGUF 模型。作为替代方案,可通过配置 SM_LLAMA_CPP_HF_REPO 和 SM_LLAMA_CPP_HF_FILE 在端点具备网络出口时从 Hugging Face 下载 GGUF 文件。此路径无需 Dockerfile 或 ECR 仓库。等待端点进入 InService 状态后,发送兼容 OpenAI 的聊天请求:
python deploy/invoke_standard_endpoint.py \
--region "$AWS_REGION" \
--endpoint-name "$STANDARD_ENDPOINT_NAME"- 构建可选的 SemIf 子镜像并解析其不可变摘要。对于 CPU:
python deploy/prepare_build.py \
--region "$AWS_REGION" \
--bucket "$ARTIFACT_BUCKET" \
--codebuild-role-arn "$CODEBUILD_ROLE_ARN"对于 GPU,构建 CUDA 子镜像:
python deploy/prepare_build.py \
--region "$AWS_REGION" \
--bucket "$ARTIFACT_BUCKET" \
--codebuild-role-arn "$CODEBUILD_ROLE_ARN" \
--dockerfile Dockerfile.gpu \
--image-tag "gpu-$(date +%Y%m%d%H%M%S)"构建成功后,构造不可变镜像 URI:
ECR_REPOSITORY_URI=$(aws ecr describe-repositories \
--region "$AWS_REGION" \
--repository-names semif-llamacpp-dlc \
--query 'repositories[0].repositoryUri' \
--output text)
IMAGE_DIGEST=$(aws ecr describe-images \
--region "$AWS_REGION" \
--repository-name semif-llamacpp-dlc \
--query 'sort_by(imageDetails,&imagePushedAt)[-1].imageDigest' \
--output text)
export IMAGE_URI="${ECR_REPOSITORY_URI}@${IMAGE_DIGEST}"部署脚本会拒绝可变镜像标签。
- 部署 SemIf 端点。CPU 配置使用固定实例类型:python deploy/deploy_endpoint.py \ --region "$AWS_REGION" \ --image-uri "$IMAGE_URI" \ --model-data-url "s3://$ARTIFACT_BUCKET/semif-llamacpp/model.tar.gz" \ --role-arn "$SAGEMAKER_ROLE_ARN" \ --instance-type ml.c6i.8xlarge \ --threads 32 \ --name "$SEMIF_ENDPOINT_NAME" 等待返回的端点名称进入 InService 状态。此配置路径设置 n_gpu_layers=0。由于适配器将评分序列化到一个状态化的 llama.cpp 上下文中,因此应通过测量工作负载后扩展端点实例,而不是假设容器内并行评分。对于 GPU 镜像,提供有序的实例池并请求完整模型卸载:python deploy/deploy_endpoint.py \ --region "$AWS_REGION" \ --image-uri "$IMAGE_URI" \ --model-data-url "s3://$ARTIFACT_BUCKET/semif-llamacpp/model.tar.gz" \ --role-arn "$SAGEMAKER_ROLE_ARN" \ --instance-pool ml.g6e.xlarge \ --instance-pool ml.g6.2xlarge \ --instance-pool ml.g5.2xlarge \ --instance-pool ml.g4dn.2xlarge \ --gpu-layers=-1 \ --provision-timeout 1200 \ --name "$SEMIF_ENDPOINT_NAME" 实例池是按顺序的放置回退选项,而非推理负载均衡。SageMaker 会为变体选择一种可用类型。创建端点可能需要更长时间,因为 SageMaker AI 需要遍历实例池。检查启动日志中选定的 GPU 以及确认所有模型层已卸载的消息。
- 使用示例决策调用 SemIf 端点。请求为每个允许选项声明稳定 ID:{ "decision": { "id": "support-route", "state": "客户要求重置遗忘的密码并表示重置邮件从未收到。", "question": "哪个队列应处理此请求?", "options": [ {"id": "account_access", "description": "账户访问和身份验证支持。"}, {"id": "billing", "description": "计费和支付支持。"}, {"id": "sales", "description": "销售和产品评估。"} ] } } python deploy/invoke_endpoint.py \ --region "$AWS_REGION" \ --endpoint-name "$SEMIF_ENDPOINT_NAME" 响应保留选项顺序,并包含条件概率、原始对数几率、标记和提示元数据以及固定模型标识:{ "result": { "id": "support-route", "option_ids": ["account_access", "billing", "sales"], "probabilities": [0.99996, 0.00003, 0.00001], "option_logits": [28.47, 17.92, 17.04], "prompt_sha256": "016267542103ab91422c425d2234ec7e1b9aef77f9d3e481b96db2de7cca470a", "readout": "量化后的最后位置对数几率限制在声明的答案插槽中;无生成标记" } } 应用应用级阈值和回退机制。不要将模型决策用作授权的替代方案。
清理
删除 SageMaker AI 端点、端点配置和模型:
python deploy/cleanup_endpoint.py \
--region "$AWS_REGION" \
--name "$STANDARD_ENDPOINT_NAME"
python deploy/cleanup_endpoint.py \
--region "$AWS_REGION" \
--name "$SEMIF_ENDPOINT_NAME"该脚本仅删除明确命名的 SageMaker AI 资源。当不再需要时,删除 CodeBuild 项目、ECR 仓库、Amazon S3 中的模型和源对象、日志以及特定用途的 IAM 角色。
结论
AWS DLC for llama.cpp 为在 SageMaker AI 的 CPU 和 GPU 实例上部署决策模型提供了托管基础。它可以从 SageMaker AI 模型工件或配置的 Hugging Face 仓库加载 GGUF 模型,然后通过 InvokeEndpoint 提供 OpenAI 兼容的聊天补全,无需使用自定义容器。当您的应用需要直接访问 logits 和模型状态时,可以通过添加 SemIf 适配器扩展 DLC 功能。对于非延迟敏感型工作负载请选择 CPU,当提示预填充和尾部延迟影响应用体验时请选择 GPU。
查看代码示例、AWS DLC for llama.cpp 文档和 SageMaker AI 自定义推理容器规范以根据您的工作负载调整部署。
关于作者
'"`