ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

vLLM Engine-Core Rust 客户端冒烟测试实战:utility 调用与 logprobs 解码的端到端验证

vLLM Engine-Core Rust 客户端冒烟测试实战:utility 调用与 logprobs 解码的端到端验证 vLLM Engine-Core Rust 客户端冒烟测试实战utility 调用与 logprobs 解码的端到端验证【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllm本文基于仓库中的 Engine-Core Smoke Tests 文档讲解如何启动 headless 模式的 vLLM 引擎并通过 Rust 侧vllm-engine-core-client的两个示例程序完成端到端冒烟验证一个走 utility 调用路径sleep/wake_up、cache 重置等控制面操作另一个走原始 engine-core 请求路径带 sample logprobs 与 prompt logprobs 的解码。读完后你可以独立完成 Rust 前端与 Python 引擎之间 ZMQ/MessagePack 协议的连通性验证理解握手地址、传输模式与 utility 线上契约等底层机制。背景vllm-engine-core-client 是什么vLLM 仓库中的rust/目录实现了实验性的 Rust 前端vllm-frontend-rs用 Rust 重建北向服务层同时继续通过 ZMQ 走既有引擎边界与 Python 引擎进程通信。按 rust/README.md 的分层架构vllm-engine-core-client是最底层的一块负责 headless vLLM 引擎的ZMQ 传输 MessagePack 协议。从 rust/src/engine-core-client/Cargo.toml 的依赖可以看到它的技术底座zeromq、tokio、rmp-serde/rmpvMessagePack、bytes、bytemuck等。该 crate 在 rust/Cargo.toml 中注册为 workspace 成员vllm-engine-core-client { path src/engine-core-client }对外暴露的核心 API 见 rust/src/engine-core-client/src/lib.rsEngineCoreClient/EngineCoreClientConfig/TransportMode连接与传输模式配置EngineCoreOutputStream/EngineCoreStreamOutput每个请求的原始输出流protocol模块logprobs、request、sampling、utility 等线上协议类型。冒烟测试的意义在于不依赖 Rust 前端服务栈vllm-server、vllm-chat等上层 crate直接用最小的 Rust 客户端连上真实 Python 引擎验证握手、请求提交、utility 往返、logprobs 张量解码这几条关键链路是否正常工作。第一步启动 headless vLLM 引擎按原文档先在仓库根目录rust/目录下按相对路径激活准备好虚拟环境然后以 headless 模式启动一个小型模型服务source ../vllm/.venv/bin/activate HF_HUB_OFFLINE1 \ VLLM_LOGGING_LEVELDEBUG \ VLLM_CPU_KVCACHE_SPACE2 \ VLLM_HOST_IP127.0.0.1 \ VLLM_LOOPBACK_IP127.0.0.1 \ python3 -m vllm.entrypoints.cli.main serve Qwen/Qwen3-0.6B \ --headless \ --enable-sleep-mode \ --data-parallel-address 127.0.0.1 \ --data-parallel-rpc-port 62100 \ --data-parallel-size-local 1 \ --max-model-len 512 \ --dtype float16各参数的作用均可在当前仓库中验证环境变量 / 参数说明HF_HUB_OFFLINE1离线模式要求模型已在本地缓存避免启动时访问模型仓库VLLM_LOGGING_LEVELDEBUG提高日志级别便于排查冒烟测试中的连接/解码问题VLLM_CPU_KVCACHE_SPACE2CPU KV cache 空间GB冒烟场景下给一个很小的值即可VLLM_HOST_IP/VLLM_LOOPBACK_IP固定本机通信地址为 127.0.0.1保证单进程单机回环--headless只启动引擎进程不启动前端 API 服务--enable-sleep-mode启用 sleep mode供冒烟测试调用sleep/wake_uputility--data-parallel-address 127.0.0.1数据并行握手地址所在主机--data-parallel-rpc-port 62100握手 RPC 端口Rust 客户端的--handshake-address必须与其一致。该参数在 vllm/config/parallel.py 中默认为29550在 vllm/engine/arg_utils.py 中解析--data-parallel-size-local 1本节点本地引擎数为 1即单引擎拓扑--max-model-len 512限制最大序列长度与 logprobs 冒烟的 prompt 长度设计480 token匹配--dtype float16权重精度float16 下模型显存占用小适合冒烟从 vllm/entrypoints/cli/serve.py 可以看到serve命令读取parallel_config.data_parallel_rpc_port来监听握手端口这正是 Rust 侧握手地址tcp://127.0.0.1:62100的监听方。第二步utility 调用冒烟测试external_engine_utility_call在rust/目录下通过 workspace 运行示例cargo run -p vllm-engine-core-client --example external_engine_utility_call -- \ --handshake-address tcp://127.0.0.1:62100 \ --host 127.0.0.1该命令经由EngineCoreClient的 utility 接口对引擎发起一串控制面调用。完整示例源码见 external_engine_utility_call.rs。连接与参数示例通过 clap 解析命令行参数--handshake-address必填其余均有默认值参数默认值说明--handshake-address必填引擎启动时拨入的共享握手端点如tcp://127.0.0.1:62100--engine-count1期望加入传输的引擎总数--modelQwen/Qwen3-0.6B模型名用于前端侧 metrics 标签--host127.0.0.1引擎回连前端传输 socket 时使用的 advertised host--client-index0盖在每个请求上的前端客户端索引--ready-timeout-secs30每个启动阶段的最大等待时间--expected-is-sleepingfalse执行各冒烟步骤前is_sleeping()的期望初始值--reset-running-requestsfalsereset_prefix_cache是否同时重置进行中的请求--reset-externalfalsereset_prefix_cache是否重置外部连接器缓存--sleep-level1sleep 级别--sleep-modeabort暂停模式取值abort/wait/keep--skip-sleep-wakefalse引擎未开启 sleep mode 时跳过 sleep/wake_up 步骤连接配置对应 rust/src/engine-core-client/src/client.rs 中的TransportMode::HandshakeOwnerRust 进程拥有启动握手自行分配/绑定前端传输地址再回复引擎的HELLO消息TransportMode::HandshakeOwner { handshake_address: args.handshake_address.clone(), advertised_host: args.host.clone(), engine_count: args.engine_count, ready_timeout: Duration::from_secs(args.ready_timeout_secs), local_input_address: None, local_output_address: None, },连接成功后示例会打印input_address、output_address与engine_identities可用于确认传输地址分配与引擎身份注册是否符合预期。冒烟执行序列连接成功后的调用顺序见示例main函数client.is_sleeping()— 通过 utility 共识调用查询初始 sleep 状态与--expected-is-sleeping比对不一致则失败退出client.reset_prefix_cache(reset_running_requests, reset_external)— 重置前缀缓存返回布尔值数据并行下要求所有引擎确认client.reset_mm_cache()与client.reset_encoder_cache()— 重置多模态缓存与 encoder 缓存若未指定--skip-sleep-wakeclient.sleep(sleep_level, sleep_mode)再次is_sleeping()断言结果为trueclient.wake_up(None)再次is_sleeping()断言结果回到falseclient.shutdown()— 关闭本地客户端任务与传输状态有序终止输出、分发、abort 三类后台任务。引擎不支持 sleep mode 时的变体如果当前引擎没有以--enable-sleep-mode启动加上--skip-sleep-wake跳过 sleep/wake_up 部分cargo run -p vllm-engine-core-client --example external_engine_utility_call -- \ --handshake-address tcp://127.0.0.1:62100 \ --host 127.0.0.1 \ --skip-sleep-wake源码纵深utility 调用的线上契约sleep、wake_up、is_sleeping这些便捷方法最终都落到 client.rs 的call_utility它对每个已连接引擎分配一个 utilitycall_id按 Python 侧约定的(client_index, call_id, method_name, args)契约构造EngineCoreUtilityRequest然后并行发送并等待每个引擎的应答。call_utility_consensusis_sleeping使用它则要求所有引擎返回一致结果否则报InconsistentUtilityResults错误。PauseMode定义在 rust/src/engine-core-client/src/protocol/utility.rs其序列化刻意保持 Python 字面量字符串abort/wait/keep而不是 serde 枚举元组保证与 Python 引擎侧的 MessagePack 载荷兼容模式语义abort默认立即中止所有进行中的请求wait等待进行中的请求完成keep冻结队列中的请求以便之后恢复utility 调用还有健壮性设计call_utility内部用UtilityCallGuard在 future 被取消时反注册 waiter并等待所有引擎的结果后才返回错误以便调用方对部分生效的变更做补偿。第三步logprobs 冒烟测试external_engine_logprobs第二个示例走的是原始 engine-core 请求路径而不是 utility 接口cargo run -p vllm-engine-core-client --example external_engine_logprobs -- \ --handshake-address tcp://127.0.0.1:62100 \ --host 127.0.0.1它请求一小份生成 token 的logprobs载荷同时在长 prompt 上请求 prompt logprobs从而对真实引擎同时演练 inline 解码路径与 aux-frame 解码路径。如原文档所述Rust 客户端把这些载荷解码为按位置组织的语义化记录而不是直接暴露原始 ndarray/张量线上形状。完整实现见 external_engine_logprobs.rs。参数与 prompt 设计参数默认值说明--max-tokens1只生成 1 个 token得到一份小 logprobs 载荷--logprobs2每个生成位置返回 top-2 logprobs--prompt-logprobs1每个 prompt 位置返回 top-1 prompt logprobs--prompt-repeats96基础 prompt 重复次数--output-timeout-secs120等待最终输出的超时prompt 由 5 个基础 token[20841, 448, 6896, 25, 23811]重复prompt_repeats次构成默认 96 次共 480 个 token——刻意比生成部分长得多且正好落在第一步配置的--max-model-len 512之内。请求构造与断言请求构造build_request将prompt_token_ids与EngineCoreSamplingParams { max_tokens, logprobs, prompt_logprobs, .. }填入EngineCoreRequest然后通过client.call(request)获得EngineCoreOutputStream消费到终态输出为止。示例最后做四组断言任何一项不满足即报错退出finish_reason必须是Length因为max_tokens1生成被长度上限截断是预期行为new_token_ids非空解码后的new_logprobssample logprobs非空new_prompt_logprobs_tensors非空且行数满足prompt_logprobs.len() 1 prompt_len验证 prompt logprobs 的按位置记录覆盖了完整 prompt。logprobs 的线上/解码类型位于 rust/src/engine-core-client/src/protocol/logprobs.rs 及其logprobs/子模块array.rs、wire.rs、tests.rs其中as_direct()用于取出已解码的直连direct表示而非 raw tensor 形状。关键注意事项每次冒烟必须重启 vLLM原文档特别强调每次运行冒烟测试前必须重启vllm实例。原因是 vLLM 引擎目前无法处理前端断开后重新连接的情况cannot manage frontend closures and subsequent reconnects。即同一个 headless 引擎实例不能被多个 Rust 客户端先后连接复用——utility 冒烟跑完尤其涉及 sleep/wake_up 与 shutdown引擎侧的连接状态就不可再用于下一轮握手。这与 Rust 客户端的连接语义一致EngineCoreClient::connect在HandshakeOwner模式下驱动完整的启动握手每个引擎通过HELLO帧注册客户端拿到EngineCoreReadyResponse含dtype、max_model_len、num_gpu_blocks等引擎上报信息后即建立该引擎专属的传输状态。排障与延伸阅读连接失败时优先核对两点headless 引擎的--data-parallel-rpc-port与 Rust 侧--handshake-address的端口/主机是否一致ready_timeout内引擎是否完成启动可结合VLLM_LOGGING_LEVELDEBUG日志观察。客户端的健康与能力查询 API 可在 client.rs 中查阅model_dtype()、max_model_len()注意这是 KV cache profiling 后自动适配的值可能与配置值不同、vllm_version()、is_healthy()等可作为自定义冒烟脚本的断言素材。该 crate 的单元测试cargo test -p vllm-engine-core-client基于 mock_engine.rs 与 tests/ 在进程内模拟引擎行为不依赖真实 Python 引擎而本文两个示例是与之互补的真引擎集成验证。如需了解 Rust 前端的完整启动路径VLLM_USE_RUST_FRONTEND1 vllm serve ...、外部引擎模式、engine-free render 模式参见 rust/README.md。小结这两个示例覆盖了vllm-engine-core-client与 Python 引擎之间两类最重要的交互面控制面utility 路径is_sleeping/reset_prefix_cache/reset_mm_cache/reset_encoder_cache/sleep/wake_up的往返与时序断言验证 MessagePack utility 契约和 consensus 聚合逻辑数据面raw request 路径EngineCoreRequest提交 输出流消费验证 sample logprobs 与 prompt logprobs 两条解码路径的语义化还原。按启动 headless 引擎 → 跑 utility 冒烟 → 重启引擎 → 跑 logprobs 冒烟的流程操作即可完成 Rust 引擎核心客户端与真实 vLLM 引擎的端到端连通性验证。【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表