mcpField
S
serving-llms-on-epyc

serving-llms-on-epyc

github.com/amd云与 DevOps470858 次安装2 天前更新
代码仓库

关于 serving-llms-on-epyc

该技能指导在 AMD EPYC CPU 上部署单实例 vLLM OpenAI 端点,面向需要 CPU 推理服务的用户。它按硬件检测、内存估算和单插槽资源绑定来规划启动,并要求失败时停止而不重试。

主要功能

  1. 01检测 EPYC 型号与指令集
  2. 02验证运行时及软件栈兼容性
  3. 03检查模型支持和主机内存
  4. 04按插槽配置 CPU 线程与内存
  5. 05启动并验证 vLLM 端点

适用场景

  1. 01在 EPYC 主机上提供 CPU 推理端点
  2. 02判断模型是否适合当前主机内存
  3. 03在双插槽主机上为实例选择单个插槽

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/amd/skills --skill serving-llms-on-epyc

安装后在 Claude Code 中输入/serving-llms-on-epyc确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

.federated.json
reference.md
skill-card.md
data/
epyc.json
evals/
evals.json
machine.yml
scripts/
check_model.py
cpu_tune.py
detect.py
estimate_memory.py
validate.py

详细介绍

在 AMD EPYC™ 上提供 LLM 服务(vLLM + zentorch,CPU)

在 AMD EPYC™ 主机上使用 zentorch CPU 后端启动单个 vLLM OpenAI 端点,并根据硬件配置容量。优先使用容器(Docker 或 Podman);conda/主机作为备用方案。即使主机已安装 AMD Instinct GPU,也不影响选择:当端点本身应运行在 EPYC CPU 上时,选择此技能。

这是单插槽服务:一个实例固定在一个插槽及其内存上(vLLM 跨插槽扩展效果不佳,因此不跨插槽运行)。在双插槽主机上,它会运行在单个插槽上;多插槽方案是多个实例(每个插槽一个),超出本单实例方案的范围。

此技能的硬性规则:任何失败时,都要报告原因和日志,然后停止。不要重试,也不要调试。(调试属于单独的工作流。)

Agent 自行执行服务流程——拉取、配置、启动、轮询——并使用运行时生成的 validate.py 报告。绝不要向用户提供逐项服务命令。与 serving-llms-on-instinct 类似,可访问的容器运行时是一次性的前置条件:如果 validate.py 未找到容器运行时,请报告一次性修复方法(使 Docker 可访问/安装 Podman/提供 conda 环境),然后停止。不要尝试使用 sudo 或提升权限。

数据文件

直接读取 data/epyc.json。其中包含容器镜像、必需的 CPU 运行标志、支持的精度、模型支持策略、默认模型,以及已验证的吞吐量标志注意事项。其 vllm_version 和镜像标签组成一组已验证的默认堆栈;保持两者一致,不要凭记忆硬编码其中任何一项。

步骤 1:检测 CPU

python3 scripts/detect.py            # add --host user@box for a remote host

返回 cpu_model、is_amd_epyc、epyc_generation (Naples/Rome/Milan/Genoa/Bergamo/Siena/Turin/Venice 或 EPYC 4004/4005)、 zen_arch、is_supported_epyc、avx512、logical_cores、physical_cores、 sockets、numa_nodes、memory_gb。

根据 detect.py 的结果选择服务路径:

  • is_amd_epyc 为 false -> 停止:此技能面向 AMD EPYC。(其他 x86 处理器可能可用,但不在此处的支持范围内。)
  • avx512 为 false -> 此 CPU 无法运行 zentorch(其 bf16 路径需要 AVX-512 BF16,即 avx512_bf16,该特性仅在 Zen4 及更新架构上提供)。这是 Zen4 之前的 EPYC(Naples / Rome / Milan,7000 系列)。不要就此结束——它仍然是 EPYC 主机:提供 stock vLLM CPU 路径(纯 vLLM,不使用 zentorch 加速——速度较慢,但已验证可在 EPYC 7763/Milan 上运行)。只有在用户明确同意后才继续,启动官方 stock vLLM CPU 镜像(步骤 6 的“Stock vLLM”变体);如果用户拒绝,则停止。
  • is_supported_epyc 为 false 且 avx512 为 true(例如 Bergamo / Siena / EPYC 4004/4005)-> zentorch 路径未针对该代处理器验证。请获得用户明确确认后再尝试未验证的 zentorch 路径,或者提供同样的 stock vLLM 方案。
  • 否则(9000 系列——Genoa/Turin/Venice——支持 AVX-512 BF16)-> 使用已验证的 zentorch 路径。继续。

validate.py(步骤 2)会报告 zentorch_capable,并为 stock/未验证路径设置 requires_confirmation,因此它也会强制执行此路由。

在后续阶段保留 epyc_generation / avx512——例如,Venice 每个插槽最多可容纳 256 个核心,步骤 5 的线程绑定配置会根据此信息进行调整。

步骤 2:验证运行时和环境

python3 scripts/validate.py --image <image from data/epyc.json> --generation <epyc_generation from detect> --avx512 <avx512 from detect>

这也会强制执行 AVX-512 门槛:如果 CPU 不支持 AVX-512,validate.py 会返回阻断性 error(ready: false),因此无论步骤 1 中如何描述,流程都会在此处停止——不拉取镜像,也不启动。(如果省略 --avx512,它会自行读取本地 CPU 信息,因此即使没有传入该值,也会执行此门槛。)

返回 ready、requires_confirmation、zentorch_capable(false 表示 zentorch 无法运行;请在步骤 6 中使用标准 vLLM 版本)、runtime(docker、podman 或 null)、runtime_detail、conda_path_available、stack、compatibility、hf_cache (解析后的 HF 缓存挂载路径——启动时使用 hf_cache.mount)、ram_gb,以及 errors/warnings/advisories。如果设置了 requires_confirmation(标准/未经验证的 路径),请告知用户并在启动前征得用户同意。选择路径:

  • runtime 为 docker 或 podman -> 容器路径(步骤 6),按原样使用。
  • runtime 为 null,但 conda_path_available: true -> conda/主机路径。
  • runtime 为 null 且没有 conda -> ready 为 false。报告一次性入门设置的 fix(使 docker 可用/安装 podman/设置 conda 环境),然后停止。

如果 ready 为 false,请勿继续。

堆栈兼容性门槛。 validate.py 会探测所选运行时的确切 vllm/zentorch/torch 版本和当前启用的 vLLM 平台,然后设置 compatibility.status:

  • proceed -> 堆栈是经过验证的默认版本(或 Zen 平台上经过验证的版本系列);继续。
  • blocked -> 当前启用的是标准 CPU 平台,因此 zentorch 加速未启用(错误)。报告 compatibility.message 并停止。
  • confirmation_required(requires_confirmation: true)-> Venice 使用的 vLLM 不是固定的默认版本。此配方尚未在该版本的 Venice 上经过验证。告知用户 compatibility.message,建议使用 data/epyc.json 中固定 vllm_version 的镜像,并在启动前 停止以等待用户明确确认是否继续。使用固定的默认 vLLM 版本时,Venice 可继续运行,且不会发出警告。

只有在镜像已存在于本地时才会运行该门槛。如果 validate.py 报告镜像尚未拉取,请先拉取镜像(或让步骤 6 拉取),然后重新运行 validate.py,以便门槛探测实际堆栈,而不只是镜像标签。

步骤 3:解析并验证模型

如果用户没有指定模型,请使用 data/epyc.json 中的 default_model (Qwen/Qwen3-0.6B——无需权限门槛、小巧、快速获得首次成功)。否则使用用户指定的模型。

检查 vLLM 是否确实支持该模型(不要一概禁止多模态模型)。 传入模型实际运行所用的 vLLM 版本:如果 validate.py 已探测到该版本,请使用 stack.vllm(conda 环境中的版本可能与固定版本不同);否则使用 data/epyc.json 中的 vllm_version。

python3 scripts/check_model.py --model-id <model> --revision <rev or main> --vllm-version <stack.vllm from validate, else vllm_version from data/epyc.json>
  • 退出码为 0 = vLLM 将其作为生成端点提供服务,或无法确定是否支持(需要权限/离线)——继续;启动时会确认。
  • 退出码为 1 = 停止:架构不在 vLLM 的注册表中、属于 pooling/嵌入/重排序模型(不是聊天/补全端点),或是没有可用聊天模板的多模态模型(launchable: false)。报告打印出的 message 并停止。

结果还包含该模型支持的客户端端点:

  • primary_endpoint: "chat_completions"——存在可用聊天模板(chat_template.status: present);提供服务并移交 /v1/chat/completions。
  • primary_endpoint: "completions"——没有可用/可自动选择的模板(absent/ambiguous/unknown);提供服务并移交 /v1/completions,使用原始 prompt。也可以通过传入 --chat-template <file> 启用聊天(或者对于 ambiguous,从 chat_template.names 中选择一个);切勿自行编造模板。
  • 将 primary_endpoint、supported_endpoints 和 chat_template 传递到验证(步骤 7)和移交环节(步骤 8)。
  • 允许使用多模态模型;vLLM 支持的多模态架构在 CPU 上仍可能触发仅适用于 GPU 的内核问题,该问题会在加载时显现(届时遵循不重试规则)。

精度/数据类型:原生 CPU 数据类型为 bf16(默认)、fp16、fp32。除非用户另有要求,否则使用 bfloat16。

对于受限模型(Llama、Gemma),必须设置 HF_TOKEN 并在 HuggingFace 上接受许可;否则停止并说明原因。

步骤 4:检查主机 RAM 是否足够

CPU 上的 RAM 是上限(权重和 KV 缓存都占用 RAM)。在同一行运行:

python3 scripts/estimate_memory.py --model-id <model> --revision <rev or main> --ram-gb <memory_gb from detect> --max-model-len <4096 or user value> --num-prompts <1 or desired concurrency>

退出码为 0 = 足够,退出码为 1 = 不足。如果 fit.fits 为 false:不要启动。 告知用户 required_gb 与 ram_gb 的数值,以及打印出的 fit.action——将 --max-model-len 降至 fit.suggested_max_model_len 后重试,或改用更小的模型。--max-model-len 和 --num-prompts 是影响 KV 缓存的两个参数。 额外标志:如果模型没有 HF 元数据(少见),可使用 --weight-gb N 覆盖权重大小。在 zentorch CPU 上,KV 缓存仅支持 bf16(不支持 fp8 KV)。

步骤 5:根据硬件配置 CPU 运行时

eval "$(python3 scripts/cpu_tune.py)"      # or --format json to inspect

单个实例在一个插槽及其内存上运行(vLLM 跨插槽扩展效果不佳)。cpu_tune.py 会导出 VLLM_CPU_OMP_THREADS_BIND(所选插槽的物理核心)和 VLLM_CPU_KVCACHE_SPACE(根据该插槽的本地 RAM而非整个系统的内存配置,确保 KV 池位于同一插槽)。它不会设置 OMP_NUM_THREADS(由 vLLM 推导)或 VLLM_CPU_NUM_OF_RESERVED_CPU(使用 vLLM 自身的默认值)。

双插槽主机上的插槽选择(考虑负载):它会采样每个插槽的 CPU 忙碌率(约 0.5 秒),并优先选择空闲插槽——两个都空闲时选插槽 0;一个空闲时选该插槽;两个都繁忙(≥ --busy-threshold,默认 15%)时,会发出 warning,并选择最不繁忙的插槽继续运行。--socket N 可强制选择插槽。单插槽主机使用插槽 0。

对于选定的插槽,它还会输出受内存约束的绑定配置:容器路径使用 container_cpuset(--cpuset-cpus=<cores> --cpuset-mems=<nodes>);conda 使用 conda_launch_prefix(numactl --cpunodebind/--membind,若不可用则仅绑定 CPU 的 taskset;如果两者都不存在,则为空并附带说明)。如果设置了 warning,请告知用户。在 NPS2/NPS4 上,一个插槽跨越多个 NUMA 节点;内存会跨这些节点绑定,nps_note 会提示,更精细的绑定可能提升性能。

第 6 步:确认计划,然后启动(优先使用容器)

启动前,先呈现以下摘要并等待用户确认——未经提示不得启动。这是任何内容运行前必须经过的人工确认关卡:

字段值
模型 / 类型<model>——text 或 multimodal(来自 check_model.py)
后端zentorch 加速(Zen4+)或原版 vLLM CPU / 不使用 zentorch(zentorch_capable:false——未加速;已在 Milan 上验证)
路径容器(<runtime>,镜像来自 data/epyc.json)或 conda/主机
精度bfloat16(或用户选择的精度)
内存适配所需 <required_gb> GB,RAM 为 <ram_gb> GB
CPU 配置插槽 <chosen_socket>(<socket_choice_reason>),绑定 <VLLM_CPU_OMP_THREADS_BIND>,KV <VLLM_CPU_KVCACHE_SPACE> GB(插槽本地),内存绑定到 <numa_nodes_on_socket> 个节点
硬件EPYC <epyc_generation>(<zen_arch>),<physical_cores> 个核心,AVX-512 <avx512>
端口<port>

如果 cpu_tune.py 返回了 warning(例如所有插槽都繁忙),也要在此处列出,让用户在确认前看到。

只有用户明确表示“开始”后才继续。如果用户拒绝或想要更改(模型、--max-model-len、端口),请停止并调整——不得启动。

根据 data/epyc.json 构建启动命令。CLI 为 vllm serve <model>。 在 vLLM >= 0.20 中不要传入 --device cpu——zentorch 插件会自动选择 CPU 平台,而 vllm serve 会拒绝该标志。只有在 vllm serve --help 列出此选项时才添加(适用于较旧版本的 vLLM)。

先选择一个空闲端口。 使用 --network=host 时,端口会直接绑定到主机,因此端口被占用会导致硬性失败(不会重新映射)。选择一个空闲端口——例如 PORT=8000; while ss -ltn "sport = :$PORT" | grep -q LISTEN; do PORT=$((PORT+1)); done——并在启动、健康检查轮询和交接中使用 $PORT。

挂载 validate.py 解析出的 HF 缓存。 使用 validate.py 中的 hf_cache.mount(它会跟踪符号链接并标记 NFS/root-squash),而不是直接使用 ~/.cache/huggingface,否则在 NFS 主目录下,绑定挂载可能会在容器启动时失败。

容器路径(来自 validate.py 的 runtime)。Agent 会自行运行这些命令,包括拉取镜像。RT 是原样解析出的运行时:

RT="<runtime from validate.py: docker | podman>"
$RT rm -f vllm-epyc 2>/dev/null               # clear any leftover container from a prior run (name collision otherwise)
$RT pull <image from data/epyc.json>          # agent pulls; do not ask the user to
$RT run -d --name vllm-epyc \
  <run_flags from data/epyc.json>            # --ipc=host --network=host --cap-add=SYS_NICE (SYS_NICE = NUMA membind; NO --shm-size with --ipc=host)
  <hf_cache.mount from validate.py> \        # resolved real path, e.g. -v /scratch/you/hf:/root/.cache/huggingface
  <container_cpuset from cpu_tune>             # --cpuset-cpus=<cores> --cpuset-mems=<nodes>
  --env VLLM_CPU_OMP_THREADS_BIND="$VLLM_CPU_OMP_THREADS_BIND" \
  --env VLLM_CPU_KVCACHE_SPACE=$VLLM_CPU_KVCACHE_SPACE \
  --env HF_TOKEN=${HF_TOKEN} \
  <image from data/epyc.json> \
  vllm serve <model> --dtype bfloat16 --port <port> --max-model-len <len>

Conda/主机路径(无容器运行时,conda_path_available 为 true)。eval cpu_tune 已导出环境变量;在启动命令前加上来自 cpu_tune 的 conda_launch_prefix,以将内存绑定到选定的插槽(为空 → 不固定,并附带说明):

<conda_launch_prefix from cpu_tune> vllm serve <model> --dtype bfloat16 --port <port> --max-model-len <len> &
# e.g. numactl --cpunodebind=0 --membind=0 vllm serve ...

原版 vLLM 路径(不使用 zentorch)——仅当 validate.py 报告 zentorch_capable: false(Zen4 之前的 EPYC,例如 Milan)且用户已确认使用未加速的回退方案时采用。使用官方原版 vLLM CPU 镜像,不要使用 zentorch 镜像:vllm/vllm-openai-cpu:latest-x86_64(其 ENTRYPOINT 为 vllm serve,因此将 <model> --dtype ... --port ... 作为参数传入)。使用与上述容器启动方式相同的环境配置和标志(VLLM_CPU_OMP_THREADS_BIND、--cpuset-cpus/--cpuset-mems、--cap-add=SYS_NICE、--ipc=host --network=host、解析出的 HF 缓存挂载):

RT="<runtime>"
$RT rm -f vllm-epyc 2>/dev/null
$RT run -d --name vllm-epyc \
  --ipc=host --network=host --cap-add=SYS_NICE \
  <container_cpuset from cpu_tune> <hf_cache.mount from validate.py> \
  --env VLLM_CPU_OMP_THREADS_BIND="$VLLM_CPU_OMP_THREADS_BIND" \
  --env VLLM_CPU_KVCACHE_SPACE=$VLLM_CPU_KVCACHE_SPACE --env HF_TOKEN=${HF_TOKEN} \
  vllm/vllm-openai-cpu:latest-x86_64 \
  <model> --dtype bfloat16 --port <port> --max-model-len <len>

此路径未加速(不使用 zentorch),但已在 EPYC 7763(Milan/Zen3)上通过 --dtype bfloat16 验证可用——bf16 可在没有 AVX-512 的原版 vLLM CPU 上运行,因此无需使用 fp32。如果加载仍然失败,请遵循不重试规则(报告并停止)。

可选的吞吐量标志为选择启用,且必须一起启用(参见 Gotchas): TORCHINDUCTOR_FREEZING=1 + VLLM_USE_AOT_COMPILE=0(+ ZENTORCH_WEIGHT_PREPACK=1)。 基础启动命令不设置其中任何标志。

步骤 7:轮询直至服务启动并响应

加载期间出现 503 是正常现象。轮询 /health 直至服务响应,确认服务中的模型已列出,然后验证所选端点可用(来自步骤 3 中的 primary_endpoint)。CPU 首次编译可能需要一两分钟。 跟踪 healthy 标志,确保超时会被判定为失败,而不是继续执行。

# 1. container alive (conda: process alive) + /health, with a real timeout
healthy=""
for i in $(seq 1 120); do
  $RT inspect -f '{{.State.Running}}' vllm-epyc 2>/dev/null | grep -q true || { echo "FAILED: container exited"; $RT logs --tail 50 vllm-epyc; break; }
  curl -sf http://localhost:<port>/health >/dev/null 2>&1 && { healthy=1; echo "HEALTHY"; break; }
  sleep 3
done
[ -n "$healthy" ] || { echo "FAILED: not healthy before timeout"; $RT logs --tail 50 vllm-epyc; }

# 2. the served model is registered
curl -sf --max-time 30 http://localhost:<port>/v1/models

然后测试模型实际支持的端点。冒烟检查时使用确定性采样,并限制输出长度:

# primary_endpoint == chat_completions
curl -sf --max-time 180 http://localhost:<port>/v1/chat/completions -H 'Content-Type: application/json' \
  -d '{"model":"<served-model>","messages":[{"role":"user","content":"hi"}],"max_tokens":16,"temperature":0}'

# primary_endpoint == completions  (no chat template)
curl -sf --max-time 180 http://localhost:<port>/v1/completions -H 'Content-Type: application/json' \
  -d '{"model":"<served-model>","prompt":"Hello, world","max_tokens":16,"temperature":0}'

确认响应为 JSON,且 choices[0] 不包含错误(chat:message.content;completion:text)。HTTP 200 响应中若包含 error 负载,不算成功。 资源检查(验证清单):$RT stats --no-stream vllm-epyc。

如果服务始终未达到健康状态、/v1/models 未列出该模型,或端点返回错误/空的 choices:打印容器/进程日志,说明失败阶段,然后停止。不要重试。不要进入调试循环。

步骤 8:成功后,提供端点信息

向用户提供调用服务所需的一切信息。打印连接表:

字段值
基础 URLhttp://localhost:<port>/v1(末尾的 /v1 很重要)
服务中的模型<served-model>(/v1/models 中的 id)
端点/v1/chat/completions 或 /v1/completions(来自 primary_endpoint)
原因chat = 存在聊天模板;completions = 没有模板(原始提示词)
运行时/端口<runtime> / <port>
资源配置OMP 线程数、KV GB、--max-model-len、套接字/NUMA 绑定
停止$RT rm -f vllm-epyc(容器)或 kill <pid>(conda)

然后提供一个适用于所选端点且可直接运行的示例。

Chat 模型(primary_endpoint: chat_completions):

curl -s http://localhost:<port>/v1/chat/completions -H 'Content-Type: application/json' \
  -d '{"model":"<served-model>","messages":[{"role":"user","content":"Hello"}],"max_tokens":128,"temperature":0.7}'

基础/提示词模型(primary_endpoint: completions):

curl -s http://localhost:<port>/v1/completions -H 'Content-Type: application/json' \
  -d '{"model":"<served-model>","prompt":"Hello, world","max_tokens":128,"temperature":0.7}'

OpenAI Python 客户端(将 base_url 指向本地服务;SDK 要求密钥非空,因此服务未启用身份验证时可使用任意占位符):

from openai import OpenAI

client = OpenAI(base_url="http://localhost:<port>/v1", api_key="EMPTY")
model = client.models.list().data[0].id

# chat model:
r = client.chat.completions.create(
    model=model,
    messages=[{"role": "user", "content": "Hello"}],
    max_tokens=128, temperature=0.7,
)
print(r.choices[0].message.content)

# base/prompt model:
r = client.completions.create(model=model, prompt="Hello, world", max_tokens=128)
print(r.choices[0].text)

需要一并提供的参数说明(完整列表见 reference.md):

  • max_tokens 限制输出;prompt_tokens + max_tokens 必须 <= --max-model-len。
  • temperature(0 = 确定性/贪心,高值 = 更随机);调整 top_p 或 temperature,不要同时调整两者。
  • stream: true 会以流式方式(SSE)传输令牌,而不是等待后一次性返回响应。
  • 模型的 generation_config.json 可以设置采样默认值;请传入明确的值以确保设置生效。

离线(单实例批处理)

如果要进行一次性离线运行而不是启动服务,请将步骤 6-8 替换为一次 vllm bench throughput(或离线 LLM.generate),使用相同的资源配置环境,等待运行完成,并报告指标。仍然遵守不重试/不调试的规则。

注意事项

完整列表请参阅 reference.md。以下是关键事项:

  • vllm serve 中已移除 --device cpu,适用于 vLLM >= 0.20。zentorch 插件会自动选择 CPU。传入此参数会导致 vllm serve 报错,提示 "unrecognized arguments: --device cpu"。
  • 仅设置 TORCHINDUCTOR_FREEZING=1 会导致 engine-core 初始化崩溃,适用于 vLLM 0.23 / zentorch 2.11(AssertionError: expected OutputCode, got function)。只有同时设置 VLLM_USE_AOT_COMPILE=0 才能正常工作。切勿只设置其中一个。
  • /dev/shm:使用 --ipc=host,不要使用 --shm-size。 vLLM 需要较大的 /dev/shm(容器默认的 64MB 太小)。基础配置使用 --ipc=host,以共享主机的大容量共享内存。也不要传入 --shm-size:podman 会报错 "cannot set shmsize when running in the host IPC Namespace",而且在 docker 中这是多余的。如果改为隔离 IPC(移除 --ipc=host),则添加 --shm-size=16g——二选一,不能同时使用。
  • NUMA / socket:单个实例固定在一个 socket 及其内存上——使用 CPU 绑定和 --cpuset-mems(容器)/ numactl --membind(conda),并根据该 socket 的本地 RAM 设置 KV 大小。在双 socket 主机上,cpu_tune.py 会根据负载选择空闲 socket;如果两个 socket 都繁忙,则会发出 warning。对于 NPS2/NPS4(多节点 socket),会提供 nps_note,指出更精细的逐节点绑定可能带来额外收益。
  • 无 root 的 podman + --cpuset-cpus/--cpuset-mems:这些是 cgroup 限制,在未委派 cpuset cgroup 的无 root podman 中可能会被忽略或拒绝(cgroup v1,或未委派该控制器的 v2)。这不会导致致命错误:容器内仍会通过 VLLM_CPU_OMP_THREADS_BIND 绑定 CPU 线程;只是容器级内存固定会失效(NUMA 局部性降低)。如果运行明确因 cpuset 标志而报错,请移除这些标志后继续——不要将其视为启动失败。
  • HF 缓存挂载:默认挂载 ~/.cache/huggingface。如果 HF_HOME 指向其他位置(共享主机上很常见,例如 /proj/.../vllm),请改为将该路径挂载到 /root/.cache/huggingface,否则模型会在容器内重新下载。
  • 重复使用容器名称:如果上次运行留下了 vllm-epyc,run 会报错,提示 "name already in use"——步骤 6 会先通过 $RT rm -f vllm-epyc 清除它。

评论

支持 Markdown