跳到主要内容
版本:最新版(main)

故障排查与常见问题

先看运行时对自身的报告。对于在 8100 端口独立运行的 vllm-srun worker:

curl -s localhost:8100/health
curl -s localhost:8100/v1/models

对于路由器托管的运行时,查看路由器的指标和日志:

curl -s localhost:9190/metrics | grep '^vsr_model_runtime'

vsr_model_runtime_ready{deployment="..."} 1 表示该 deployment 可以作答。 路由器日志会列出每个托管运行时进程以及它停止的原因。

使用 vllm-sr serve ARTIFACT --engine 时,应访问前端 listener 的 /v1/systemone/models。公网 /v1/models 列出 Chat 模型,不是私有 worker 清单;配置了 listener API key 时还需要携带相应凭据。

启动会等待模型​

只有当路由器为当前配置托管的每个模型都加载完成后,它才开始服务。在此之前,/ready 返回 503, vllm-sr serve 会一直等待,并打印路由器还在等待什么:

Waiting for Router-managed model deployments, 0 of 1 ready: decision-edge (vllm-sr/d3-edge) loading

/startup-status 报告 phase: loading_model_deployments,并在 model_deployments 中列出每个 deployment 及其状态:

curl -s localhost:8080/startup-status

离线的挂接运行时不会阻塞自定义 systemone 问题的准备;当前能力信息就绪且兼容之前,这些问题不可用。它作为决策模型回答的信号、或通过选择头的绑定回答的信号,仍可能需要在启动时读取模型元数据。见部署就绪规则。

首次启动要下载模型,因此比之后的启动更久。等待在 VLLM_SRUN_READY_TIMEOUT(默认 10 分钟)后结束, 并报告 did not become ready within 10m0s;再次启动即可从缓存继续下载,或在路由器的环境中调大该超时。 模型加载失败时,等待会立即结束并给出原因(见下文)。

信号从不匹配​

很可能是模型还没就绪,或者它的答案到得太晚。

  1. 查看该 deployment 的 vsr_model_runtime_ready。它为 0 时,使用它的每个信号都为未知,不会匹配。

  2. 按 reason 查看 vsr_model_runtime_unknown_answers_total。timeout 表示答案晚于信号的 timeout_ms:调大它,或改用更小的模型或 GPU。unavailable 表示运行时未就绪或不可达。 overloaded 表示它的队列已满。

  3. 打开调试并发送同样的文本,读取 x-vsr-trace 的 signals 成员;Router 只把它发给 global.router.headers.debug 允许的调用方:

    curl -s -D - -o /dev/null localhost:8899/v1/chat/completions \
    -H 'content-type: application/json' -H 'x-vsr-debug: true' \
    -d '{"model": "vllm-sr/auto", "messages": [{"role": "user", "content": "your text"}]}'
  4. 预览同一段文本的路由,而不生成回答。返回中的 signal_errors 列出未知的信号及原因, 例如 decision_timeout:

    curl -s 'localhost:8080/api/v1/routing/preview?trace=true' \
    -H 'content-type: application/json' \
    -d '{"model": "vllm-sr/auto", "text": "your text"}' \
    | jq '{decision: .decision_result.decision_name, matched: .decision_result.matched_signals, signal_errors}'

运行时一直处于 loading 或 warming​

  • 首次启动: 模型正在下载,大模型需要几分钟。路由器日志和 GET /health 会显示当前阶段。

  • 没有网络: 运行时从 Hugging Face Hub 下载。离线时,先把模型复制到缓存中,或把 artifact 指向本地副本。 例如,把固定修订版的 Vela Omni Nano 下载到路由器镜像所管理的运行时的缓存(即模型卷)中, 然后以 HF_HUB_OFFLINE=1 启动:

    hf download vllm-sr/Vela-1.0-Omni-Nano \
    --revision 2ff2d66385dbdd661a560ec3e8bcb45a0527d92e \
    --cache-dir /app/models/model-runtime

    Mini 的修订版是 801bae3ad28df6891408f0e0441c676b30e132e3。路由器镜像不再内置预先导出的 Omni 包, 因此在离线集群中按图片路由的路由器需要先这样下载一次。

  • CPU 上长时间处于 warming: 自检会让模型跑几次请求。大型决策模型在 CPU 上很慢; 请使用 GPU 或 vllm-sr/Decision-2.0-Kai-0.6B。

  • loading 且原因中有 "retrying after ...": 模型因可能自行消失的原因加载失败,例如 GPU 被占用、可用内存不足或下载中断。运行时最多重试五次,首次等待 5 秒,之后每次加倍,期间同一进程中的其他模型照常服务(--load-attempts、--load-retry-seconds)。包损坏或自检失败会立即报告 failed。

运行时报告 failed​

GET /v1/models 会给出每个模型失败的原因。由路由器运行模型时,路由器日志会带有同样的原因,例如 model runtime is not ready: model vela-domain failed to load: ...,其中给出部署名。 路由器运行的某个运行时进程中所有模型都加载失败时,路由器会重启该进程(首次等待 1 秒,之后最长间隔 60 秒), 因此 GPU 被占用、磁盘已满这类暂时性原因消除后,模型会自行恢复。与仍在服务的模型同处一个进程的模型加载失败时,由运行时自己重试,该进程会继续运行。路由器托管的模型重试三次仍然失败时,路由器无法启动;配置重新加载时,新配置会被拒绝,上一份配置继续服务。常见原因:

原因提示处理方法
a file hash does not match下载已损坏或仓库发生了变化。从缓存中删除该模型后重新启动。
a revision is required非内置仓库需要用 40 位 commit 设置 revision。
access denied, gated or private用 hf auth login 登录,或为有访问权限的账号设置 HF_TOKEN。
does not fit, out of memory换用更小的模型、显存更大的 GPU,或把副本分配到不同 GPU。
device not available指定的 GPU 不存在,或已安装的 PyTorch 不支持它。使用 device: auto,或安装正确的 PyTorch 版本。
built without LAPACK该模型在 CPU 上需要 LAPACK,而当前的 PyTorch(ROCm 镜像中的版本)没有。把模型放到 GPU 上(device: rocm:0),或用 CPU 镜像运行 CPU 上的模型。运行时不会重试。
FP8 weights need an NVIDIA GPU of compute capability 8.9 or later or an AMD Instinct MI300 or MI350 series GPU该包的权重为 FP8,而当前设备没有 FP8 矩阵单元。请在这类 GPU 上运行,或改用该模型的 BF16 或 int4 包。运行时不会重试。
NVFP4 packages need FP4 tensor cores; serve NVFP4 packages on a Blackwell GPU该包的权重为 NVFP4,而当前设备无法进行这种乘法:它是 CPU、ROCm GPU 或没有 FP4 Tensor Core 的 NVIDIA GPU(计算能力不是 10.x 或 12.x),或者其 PyTorch 没有 FP4 张量、或未安装 Triton(报错信息会指出是哪一种)。请在装有较新 PyTorch 和 Triton 的 Blackwell GPU 上运行,或改用该模型的 BF16、FP8 或 int4 包。运行时不会重试。
no family recognizes the package不支持该模型的架构。见选择模型。
a licence must be accepted该模型的许可证限制了使用。确认你可以使用后,传入 --accept-licence <id>。

同一进程中一个模型失败时,该进程中的其他模型继续提供服务。

已就绪模型的自检显示 unverified​

GET /v1/models 在 golden 下给出每个模型的自检结果。matched 表示它的回答与该类设备上发布版的回答一致。 unverified 表示模型可以提供服务,但运行时无法担保这一点:

  • 没有 reason,且 golden.reference 为空: 该设备没有发布版的回答,例如非内置模型,或没有验证记录的 GPU(CUDA)。 运行时只检查了回答格式正确,且每次运行都相同。
  • reason 以 kernel choices not applied 开头: 在 AMD Instinct MI300X 和 MI325X GPU 上,Decision 2.0 和 Vela 2.0 使用发布时用 FLA 0.5.2 记录的内核配置运行,因此每个进程给出相同的回答。这些配置无法在当前环境运行时,模型仍会加载, 日志会写 ... runs without its recorded kernel choices: ...,它的回答可能与发布版不同。
reason 提示处理方法
FLA is not installed安装 fla-core==0.5.2,或使用自带它的路由器 ROCm 镜像。
they were recorded with FLA 0.5.2, not ...安装 fla-core==0.5.2。
failed to import修复 FLA 安装;消息中给出了具体错误。
has no autotuned kernel ...安装 fla-core==0.5.2。

--autotune-cache 会在重启之间保留已编译的内核,但不能代替记录的配置。

路由器拒绝配置​

消息提到处理方法
removed model execution fields、candle、ort、openvino、precision、variant、use_mmbert_32k、use_nli、polarity_guard运行 vllm-sr config migrate。见迁移。
profile was removed,而你的 config.yaml 里没有 profile这是 CLI 写入的:路由器镜像比 CLI 新。从同一渠道重新安装 CLI,或用 --image 指定与你的 CLI 一起构建的镜像;较早的开发版 CLI 拉取 :latest,而不是它们自己的镜像。
a binding does not match the model模型的标签、头、维度与该功能所需不同,或输入上限更小。绑定为该功能训练的模型,或修改 input。
artifact must be a Hub repository ID or an absolute package pathHub 模型用 owner/name,本地副本用绝对路径。
revision must be a 40-hex commit使用完整的 commit 哈希,而不是分支或标签。

长输入被拒绝​

任务 deployment 会拒绝超过 input.max_tokens 的输入,而不是悄悄截断。 把 max_tokens 调大到模型上限,或选择其他策略:

global:
model_catalog:
deployments:
vela-pii:
provider: model_runtime
artifact: vllm-sr/Vela-1.0-Encoder-307M-PII
input:
max_tokens: 32768
overflow: window

truncate 保留文本开头。window 用相互重叠的窗口读取全文并合并结果,PII 和安全扫描应使用它,以免漏检。

window 最多读取 max_tokens:更长的输入以 scan_budget_exceeded 失败。 通过 Vela 2.0 时,路由类问题只读取长请求的前若干 token(Vela 2.0 0.3B 在 CPU 上为 8,192 个), 安全类问题则在模型的扫描预算内读取全文(CPU 上为四个输入)。要让安全类问题读取更多, 请给 deployment 设置扫描预算:

global:
model_catalog:
deployments:
vela2:
provider: model_runtime
artifact: vllm-sr/Vela-2.0-0.3B
input:
max_tokens: 131072
overflow: window

安全问题(jailbreak、safety、PII、hallucination,以及带 coverage: full 的 systemone 规则)会整读输入,上限是模型的扫描预算或部署的 input.max_tokens(带 overflow: window)。 超出部分就是没读到的内容,jailbreak 或 pii 规则会把它算作匹配。 直接调用 /v1/decisions 时,仍遵循模型本身的输入长度限制。

模型没有完整读取的内容会让越狱或 PII 规则匹配:在 reject 下超过模型 max_tokens 的输入、超过其上限的输入,或被截断的输入。匹配的类型是 unscanned,并给出原因(input_limit 或 scan_budget),因此填充提示词无法让攻击或个人数据绕过检查。 带 coverage: full 的 systemone 规则用 on_unscanned 决定这类内容的含义;其他信号报告原因,并按失败的信号处理 (参考)。

请求在等待慢模型​

在信号截止时间前没有返回的模型运行时信号会按其策略处理,因此一个慢模型不会让整个请求失败: 越狱或 PII 规则按没有答案处理,除非规则设置了 on_unknown: no_match,否则匹配;其他信号都按失败的信号处理(设置了 rules.on_unknown 时为 Unknown;否则不匹配,或遵循 systemone 条件的 on_error)。截止时间是请求的截止时间减去剩余时间的十分之一, 已部署服务的请求没有路由器可见的截止时间,则为 45 秒;设置 global.model_catalog.signal_timeout_ms 可以缩短它。在 CPU 上,Vela 2.0 0.3B 用四个核每秒约读取 1,000 个 token,因此长请求可能无法在截止时间内完成安全扫描。

路由器无法访问挂载的运行时​

  • 除非用 --host 0.0.0.0 启动,运行时只监听 127.0.0.1。
  • 在容器内部,localhost 指容器自身。请使用宿主机地址、Docker 网络名或 Kubernetes Service。
  • 从路由器所在的机器执行 curl <endpoint>/health 必须有响应。

请求比预期慢​

  • 对于路由器托管的运行时,对比路由器上较慢 deployment 的 vsr_model_runtime_server_seconds(按 phase) 和 vsr_model_runtime_transport_seconds(见参考)。时间大多在 forward 说明模型本身在该设备上就慢。时间在 queue 说明模型已饱和:增加 GPU、改用更小的模型或另起一个进程。 传输占比大则指向宿主机(CPU 争用、远程 endpoint)。
  • 对于你自己启动的运行时,查看它 /metrics 上的 vllm_srun_request_duration_seconds 和 vllm_srun_queue_duration_seconds,或其响应的 Server-Timing 头。
  • 托管 CPU worker 默认使用路由器可用 CPU 预算的一半,向下取整,最少 1 个、最多 16 个线程。 在 vllm-sr serve 启动前设置正整数 VLLM_SRUN_CPU_THREADS,即可指定每个 worker 的线程数,上限为完整 CPU 预算。 用实际输入长度和并发量比较效果:多个模型同时忙碌时,减少线程可能降低争用;有专用核心时,长输入可能受益于更多线程。 参见 CPU 线程。自行启动并通过 endpoint 挂载的运行时使用自己的 --threads 设置,同一进程中的模型共享这些线程。
  • 当其他工作占用了部分核心时,CPU 模型会明显变慢,因为每个线程都要等最慢的那个。使用 ROCm GPU 的进程即使空闲也可能让一个 CPU 核心一直忙碌,同一主机上的 LLM 服务也一样:给 CPU 模型留出专用核心。
  • 并发请求本来就共用前向。对同一输入问很多问题时,在默认关闭的地方打开 enable_shared_context;想用吞吐换延迟,就调低 batch_window_ms 或 max_num_seqs。见引擎参数。

常见问题​

需要 GPU 吗? 不需要。所有内置任务模型以及较小的决策模型都能在 CPU 上运行。

运行时会把我的数据发到别处吗? 不会。它只从 Hugging Face Hub 下载模型文件,从不把请求文本发出去。 它不记录请求文本,指标中也不包含请求内容。

可以使用非内置的模型吗? 可以,只要架构受支持:提供带 revision 的 Hub 仓库,或本地绝对路径。 对于它不认识的模型,运行时会计算并报告其身份。

从 Hub 加载模型安全吗? 运行时从不执行模型仓库中附带的代码,并会在加载前对照固定的哈希校验内置模型的每个文件。

多个路由器可以共享一个运行时吗? 可以。启动一次,并给每个路由器配置同一个 endpoint。

一个运行时可以提供多个模型吗? 可以。给 vllm-srun serve 传入多个模型,再通过 endpoint 挂载各个 deployment。 路由器托管的 deployment 和 replica 各自使用独立的 worker。

更换 embedding 模型后,我缓存和存储的向量会怎样? 它们与新向量隔离,不会被复用。 见更换 embedding 模型时重新向量化。

模型存放在哪里? 你自己启动的运行时存放在 Hugging Face 缓存(HF_HUB_CACHE)中, 托管运行时存放在路由器的模型目录下;见参考。