执行摘要
- 一句话:共享 base-URL 解析并修复 IPv6 格式化
- 推荐动作:推荐阅读,尤其是
resolve_base_url 的设计和 _BACKEND_API_PATHS 的引入方式。该 PR 展示了如何通过提取通用函数消除重复代码并修复一致性问题,是良好的工程实践。
功能与动机
每个 HTTP bench 客户端都重复实现了“使用 --base-url,否则从 --host/--port 构建”的逻辑,且部分构建使用了原始 f-string,未对 IPv6 地址加括号(如 bench_serving 的 embedding 路径),导致 IPv6 环境下 URL 格式错误。集中解析逻辑可避免重复并统一 IPv6 兼容格式化。
实现拆解
按照 PR 描述,分为以下步骤:
- 在
sglang/srt/utils/network.py 中添加 resolve_base_url(base_url, host, port) 函数,该函数如果 base_url 非空则直接返回,否则通过 NetworkAddress(host, port).to_url() 生成 IPv6 安全的 URL。
- 修改
bench_serving.py:导入 resolve_base_url;移除原有的 if/elif 后端 URL 构建链,替换为 _BACKEND_API_PATHS 字典映射;调用 resolve_base_url 生成 base_url,然后与 API 路径拼接;修复 embedding 路径中缺少 IPv6 括号的问题。
- 修改
send_one.py:导入 resolve_base_url;在 BenchArgs 中添加 base_url 字段,新增 --base-url 命令行参数;在 send_one_prompt() 中使用 resolve_base_url 替换原有的 f-string 构造。
- 修改
endpoint.py:导入 resolve_base_url;在 launch_or_reuse_server() 中使用 resolve_base_url('', server_args.host, server_args.port) 替换原有的 f-string 构造。
关键文件:
python/sglang/bench_serving.py(模块 基准测试;类别 source;类型 dependency-wiring): 核心变更文件:引入 _BACKEND_API_PATHS 字典替换冗长的 if/elif 链,简化 URL 构建逻辑,并修复 embedding 路径 IPv6 问题。
python/sglang/srt/utils/network.py(模块 网络工具;类别 source;类型 core-logic;符号 resolve_base_url): 新增 resolve_base_url 函数,作为统一的 URL 解析入口,优先使用 base_url 参数,否则使用 NetworkAddress 构造 IPv6 兼容 URL。
python/sglang/benchmark/endpoint.py(模块 基准启动;类别 source;类型 dependency-wiring): 使用 resolve_base_url 替换硬编码的 f-string,确保 IPv6 兼容。
python/sglang/test/send_one.py(模块 测试工具;类别 test;类型 test-coverage): 新增 --base-url 选项,与 bench 脚本保持一致;使用 resolve_base_url 解析 URL。
关键符号:resolve_base_url, launch_or_reuse_server, send_one_prompt, run_benchmark
关键源码片段
python/sglang/bench_serving.py
核心变更文件:引入 _BACKEND_API_PATHS 字典替换冗长的 if/elif 链,简化 URL 构建逻辑,并修复 embedding 路径 IPv6 问题。
# bench_serving.py - 后端 API 路径映射表
_BACKEND_API_PATHS = {
"sglang": "/generate",
"sglang-native": "/generate",
"sglang-oai": "/v1/completions",
"sglang-oai-chat": "/v1/chat/completions",
"sglang-embedding": "/v1/embeddings",
"vllm": "/v1/completions",
"vllm-chat": "/v1/chat/completions",
"lmdeploy": "/v1/completions",
"lmdeploy-chat": "/v1/chat/completions",
"trt": "/v2/models/ensemble/generate_stream",
"truss": "/v1/models/model:predict",
}
# 使用
base_url = resolve_base_url(args.base_url, args.host, args.port)
if args.backend == "gserver":
api_url = args.base_url if args.base_url else _na.to_host_port_str()
else:
api_url = f"{base_url}{_BACKEND_API_PATHS[args.backend]}"
评论区精华
该 PR 没有展开 review 讨论(GitHub Review 评论数 0)。PR body 已清晰说明变更动机和实现细节,未引发争议。
风险与影响
- 风险:主要风险是回归:虽然作者声称对于 IPv4/hostname 输出 byte-identical,但
endpoint.py 中原使用 f'http://{host}:{port}' 现在变为 NetworkAddress(host, port).to_url(),若 NetworkAddress.to_url() 内部行为有变化(例如对非 IPv6 的 host 添加括号?)可能导致 URL 不同。但检查 NetworkAddress 实现可知 to_url() 仅对 IPv6 地址加括号,对 IPv4/hostname 返回 http://host:port 格式,因此无差异。另外,bench_serving 中 gserver 后端特殊处理(bare host:port)未受影响。总体风险较低,但应确认测试覆盖(特别是 IPv6 场景)。
- 影响:影响限于 bench 和测试客户端。用户:bench 脚本在 IPv6 网络下正确工作;
send_one 新增 --base-url 选项,与 bench 脚本一致。系统:无性能影响。团队:URL 解析逻辑集中,后续维护更简单。
- 风险标记:兼容性回归风险(IPv6 括号添加), 缺少 IPv6 集成测试
关联脉络
- PR #28592 [misc] Centralize bench launch-vs-connect into a reusable acquire_endpoint: 同样修改了 endpoint.py,进一步集中 bench 启动逻辑。
- PR #28576 [misc] Unify bench seed default to 42 and rename --profile-filename-prefix to --profile-prefix: 统一 bench 参数风格,与本 PR 的 --base-url 标准化方向一致。
参与讨论