MultimodalFlow
← 返回博客

Thor 上验证 vLLM:Qwen3-0.6B 的 8/9 项检查与三个 API Demo

Jetson ThorQwen3vLLMthortestDemo工具调用JSON Schema

2026 年 11 月 9 日,我用自研 thortest 的 quick 档验证 Thor 上的推理服务。实际完成的是 vLLM × Qwen3-0.6B 的功能与性能子测试:9 项功能检查通过 8 项,JSON Schema 输出检查失败;整轮矩阵尚未完成。

计划中的 SGLang、8B Dense 和 30B-A3B MoE 没有完成结果。quick 档另一个 Granite 小 MoE 的权重下载失败,也不能当成引擎不兼容。

现场条件与结果来源

设备为 128 GB Jetson AGX Thor,sm_110、L4T R39.2、宿主机 CUDA 驱动 API 13.2、MAXN。vLLM 使用固定 digest 的 nightly-aarch64 镜像,版本 0.33.0rc1.dev806+ga2bcb5657;Qwen3-0.6B 使用 BF16,最大上下文 8,192 tokens、最多四个活动序列。

本次有一个明显限制:Flash-Next 大模型仍然驻留,可用内存开始时只有约 18.3 GB。因此结果反映共存环境,不能当成清空设备后的最佳性能。保存的 results.json 将该组合标为 partial。

文章根据 thortest/reports/20261109-051803/results.json、lib/bench.py 和 lib/probes.py 核对。可下载原报告字段摘录,其中保留检查详情与六组吞吐数据,去除了机器地址和无关服务信息。大模型部署背景见122B 与 Flash-Next 实测。

功能检查:8 项通过,一项需要继续定位

检查本次结果
/v1/models通过,返回正确服务模型名
基础算术通过,17 × 23 返回 391
中文对话通过,回答中国首都是北京
SSE 流式输出通过,收到 35 个内容 chunk
JSON Schema失败,数字重复,JSON 未闭合
Function Calling通过,解析出 get_weather({"city":"Paris"})
思考内容分离通过,返回独立 reasoning 与最终回答
长上下文检索通过,5,769 输入 tokens 中找到 7429
四路并发通过,四个请求均有非空回答

这里的“通过”是脚本中对应探针的判定。工具调用没有连接真实天气服务,并发检查也只确认有返回;它们不能直接代表完整 Agent 工作流或生产可靠性。

JSON 失败发生在 population_million 字段,报告中的输出不断追加 5,在 128-token 输出预算下没有完成对象。还需要检查输出预算、约束解码和模型行为,现有记录不能把责任唯一归到 vLLM 或模型。单次探针也不足以给出结构化输出的成功率。

性能口径:输出吞吐与逐路解码分开看

每组先生成近似目标长度的输入,短场景约 512→256 tokens,长输入场景约 4096→256;实际平均输入长度保存在摘录里。每档请求数为 3、4、8,输出采用 ignore_eos 以维持预算,属于合成压测。

输入场景并发请求数聚合输出 tok/s平均 TTFT
约 512 tokens13142.2543.3 ms
约 512 tokens24269.7760.5 ms
约 512 tokens48493.7689.9 ms
约 4096 tokens13111.85147.6 ms
约 4096 tokens24176.48247.4 ms
约 4096 tokens48243.24450.2 ms

聚合输出吞吐为“本轮输出 token 总数 ÷ 整轮墙钟”。四路约 494 tok/s 是合计值,不是每个用户各有 494 tok/s。报告还给出按 TPOT 中位数倒数计算的逐路速度:短场景单并发约 147.78 tok/s,四并发约 128.63 tok/s,它和表中的整轮吞吐分母不同。

prefill 子测试在实际平均 2,034 / 6,084 输入 tokens 下,报告约 29,790 / 25,441 tok/s。脚本使用 输入 tokens ÷ TTFT 估算,包含 API 与首 token 路径开销,不能当作独立 GPU prefill kernel 的计时。每个长度只有两次请求;这些数值与表中 3–8 次样本均不足以支持稳定的 P99 或长期容量结论。

三个可下载、可复跑的 API Demo

下载 demos.py。只依赖 Python 标准库,--dry-run 可以查看请求体。以下是根据已验证 API 形态整理的新示例,未在本文发布过程中重新启动模型验证,因此不作为新增 Thor 测试数据。

服务必须已就绪。在 Thor 本机用 127.0.0.1;从其他机器测试时,可先建立 SSH 本地端口转发,再把 --base-url 指到转发端口。模型名以 /v1/models 的实际返回为准。

Demo 1:流式回答与思考分离

python3 demos.py chat --model qwen38-flash-next
python3 demos.py chat --model qwen38-flash-next --thinking --max-tokens 2048

问题是“用三句话解释 MoE”。脚本把最终回答写到标准输出,思考内容与计时写到标准错误,并分别报告首个输出时间、首个最终回答时间和总耗时。这样能看清“正在思考”和“最终答案还没开始”的区别。finish_reason=length 会提示输出预算耗尽,不会把截断内容算作正常完成。

Demo 2:解析工具调用

python3 demos.py tool --model qwen3-0.6b \
  --base-url http://127.0.0.1:8100/v1

示例要求模型调用 get_weather,脚本检查函数名、参数 JSON 和城市 Paris,不执行外部工具,也不返回虚构的实时天气。历史功能探针在 0.6B 上通过;完整工具执行、回传与最终回答仍应作为下一阶段测试。

Demo 3:重放 JSON Schema 检查

python3 demos.py schema --model qwen3-0.6b \
  --base-url http://127.0.0.1:8100/v1 --max-tokens 128

示例请求 Tokyo 的 city、country、population_million,检查完整 JSON、字段集合、基础类型和正常结束状态,不校验人口事实。历史运行在这一请求形态上失败,复跑时应该同时记录模型 revision、结束原因与完整返回,而不是假定它一定成功。

三个 Demo 默认关闭 thinking;服务需要支持 chat_template_kwargs.enable_thinking 和相应 parser。大模型启动脚本可以从部署文章下载。0.6B 的 8100 服务属于历史测试实例,目前需要另行启动,网页也没有连接现场设备的公开推理入口。

中断记录与下一轮

本轮在拉取 SGLang 镜像阶段发生设备失联。报告能证明当时 Flash-Next 共存、内存余量较小,但不能仅凭时间先后确定失联根因,也不能把镜像拉取停滞认定为 SGLang 推理失败。

下一轮应在独占环境下分别验证 vLLM 与 SGLang,先完成模型下载与镜像准备,再启动标准档。现场框架提供:

cd ~/thorllmtest/thortest
./run.sh --profile standard --stop-running

该选项会停止框架识别到的已有模型容器,按框架设计在测试结束后尝试恢复,适合维护窗口使用。需要补齐的是 8B / 30B-A3B 的实测、结构化输出复现、更多请求和稳定性数据;现有结果只覆盖本文列出的 0.6B 组合。