执行摘要
- 一句话:降低 diffusion 每请求日志噪音,关键消息降级为 debug
- 推荐动作:此 PR 简单明确,值得快速 review,可作为日志管理的良好实践参考。
功能与动机
PR body 指出:'Several recently added diffusion logs run once per request or batch at info level, duplicating outcomes or reporting request-level implementation detail to operators.' 目的是减少每请求日志噪音,避免向运营人员重复报告结果或请求级实现细节。
实现拆解
- 降级 LongCat 提示重写日志:在
longcat_image.py 的 forward 方法中,将提示重写启用的 info 日志改为 debug,以减少每个请求的高频日志。
- 降级 attention 后端选择日志:在
denoising.py 的 _maybe_override_attention_backend 中,将每批切换 attention 后端的 info 日志改为 debug。
- 降级 LTX-2 自动时长日志:在
ltx_2/duration.py 的 forward 中,将每请求的自动时长 info 日志改为 debug。
- 移除重复成功日志:在
ltx_2_duration_head.py 的 predict_num_frames 中,删除成功预测时长的 info 日志,保留边界警告。
- 未涉及测试、配置或部署变更:由于仅为日志级别调整,PR 声明无需单元测试和文档。
关键文件:
python/sglang/multimodal_gen/runtime/models/adapter/ltx_2_duration_head.py(模块 模型适配器;类别 source;类型 data-contract): 删除成功时长预测的 info 日志,保留边界警告,减少冗余输出。
python/sglang/multimodal_gen/runtime/pipelines_core/stages/denoising.py(模块 流水线阶段;类别 source;类型 core-logic): 将每批 attention 后端切换的 info 日志降为 debug,减少每请求噪音。
python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/longcat_image.py(模块 模型阶段;类别 source;类型 data-contract): 将 LongCat 提示重写启用的 info 日志降为 debug,避免每请求输出。
python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/ltx_2/duration.py(模块 模型阶段;类别 source;类型 data-contract): 将每请求自动时长的 info 日志降为 debug,减少每请求噪音。
关键符号:predict_num_frames, _maybe_override_attention_backend, forward (longcat_image), forward (ltx_2/duration)
关键源码片段
python/sglang/multimodal_gen/runtime/models/adapter/ltx_2_duration_head.py
删除成功时长预测的 info 日志,保留边界警告,减少冗余输出。
# python/sglang/multimodal_gen/runtime/models/adapter/ltx_2_duration_head.py
# 移除成功预测的 info 日志,仅保留边界警告。
def predict_num_frames(self, ...):
if num_frames < min_frames:
# 向上取网格点
snapped_up = num_frames + temporal_compression_ratio
if snapped_up <= max_frames:
num_frames = snapped_up
else:
# 无网格点满足边界,接近比拒绝生成更好
if abs(snapped_up - clamped_frames) < abs(num_frames - clamped_frames):
num_frames = snapped_up
logger.warning(
"Duration bounds [%.2fs, %.2fs] at %.2f fps admit no frame count "
"on the VAE temporal grid (k * %d + 1); using nearest: %d frames",
min_seconds, max_seconds, frame_rate, temporal_compression_ratio, num_frames,
)
if seconds < min_seconds or seconds > max_seconds:
logger.warning(
"Duration prediction clamped: raw %.2fs outside [%.2fs, %.2fs], "
"using %.2fs (%d frames) @ %.2f fps",
seconds, min_seconds, max_seconds, num_frames / frame_rate, num_frames, frame_rate,
)
return num_frames
python/sglang/multimodal_gen/runtime/pipelines_core/stages/denoising.py
将每批 attention 后端切换的 info 日志降为 debug,减少每请求噪音。
# python/sglang/multimodal_gen/runtime/pipelines_core/stages/denoising.py
# 每批切换 attention 后端时,仅 debug 级别记录,减少每请求日志。
def _maybe_override_attention_backend(self, batch: Req) -> None:
"""Two-phase per-request backend switch: prepare all layers (may
raise, mutates nothing), then flip all — a rejected request leaves the
transformers untouched."""
target = self._parse_attention_backend_override(batch.sampling_params.attention_backend_override)
if target == self._attention_backend_active_override:
return
layers = self._request_switchable_attention_layers()
stage_backend = self._attn_backend_default
if target is not None:
stage_backend = self._validate_attention_backend_override(target, layers)
for layer in layers:
prepare_attention_backend_override(layer, target)
for layer in layers:
apply_attention_backend_override(layer, target)
self.attn_backend = stage_backend
self._attention_backend_active_override = target
logger.debug(
"Attention backend for this batch: %s (%d layers switched)",
target.name.lower() if target else "server default", len(layers),
)
python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/longcat_image.py
将 LongCat 提示重写启用的 info 日志降为 debug,避免每请求输出。
# python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/longcat_image.py
# 提示重写启用时,仅 debug 级别记录,避免每请求 info 日志。
@torch.no_grad()
def forward(self, batch: Req, server_args: ServerArgs) -> Req:
device = get_local_torch_device()
enable_prompt_rewrite = getattr(batch, "enable_prompt_rewrite", True)
with self.use_declared_component(component_name="text_encoder", module=self.text_encoder) as text_encoder:
assert text_encoder is not None
self.text_encoder = text_encoder
if enable_prompt_rewrite:
logger.debug(
"Prompt rewriting is enabled (enable_prompt_rewrite=True). "
"This runs autoregressive decoding on the Qwen2.5-VL text encoder (up to %d tokens). "
"Pass --enable-prompt-rewrite false to skip.",
REWRITE_MAX_NEW_TOKENS,
)
prompt = batch.prompt
if isinstance(prompt, str):
prompt = [prompt]
batch.prompt = self._rewire_prompt(prompt, device)
batch.generator = torch.Generator(device="cpu").manual_seed(batch.seed)
return batch
评论区精华
PR 无 review 讨论,仅 comment 为 CI 标签触发。
风险与影响
- 风险:低风险。仅调整日志级别和删除冗余日志,不影响推理逻辑。风险点是删除成功预测日志可能减少可观测性,但边界警告保留,足以诊断异常。对于依赖 info 日志进行监控的团队,需注意这些消息将不再出现在 info 级别。
- 影响:影响范围:扩散模型 pipeline 的日志输出。降低每请求 info 日志量,减少日志存储和 I/O 开销,对运营人员更友好,但可能降低信息可见度。对系统性能和功能无影响。
- 风险标记:日志可观测性下降
关联脉络
- PR #35615 [diffusion] ci: use canonical residency selector: 同为 diffusion 模块,关注配置和 CI 调整。
- PR #35182 [diffusion] fix: reject unsupported modelopt checkpoint algorithms: 同为 diffusion 模块,涉及模型配置和日志相关改动。
- PR #35538 [diffusion] fix: stop reserving NCCL device buffers for single-rank groups: 同为 diffusion 模块,优化运行时行为。
参与讨论