【Bug已解决】[Bug] Crash input dump leaks structured-output schema at ERROR level 解决方案

发布时间:2026/7/26 21:24:58

【Bug已解决】[Bug] Crash input dump leaks structured-output schema at ERROR level 解决方案
【Bug已解决】[Bug] Crash input dump leaks structured-output schema at ERROR level 解决方案一、现象长什么样vLLM 在请求处理中崩溃时默认会把出问题的那条请求输入整个 dump 到 ERROR 日志方便排障。但当这条请求用了**结构化输出guided / JSON schema 约束解码**时dump 出来的内容会包含那段 JSON schemaERROR 01-15 11:02:33 engine.py:233] Request crashed, dumping input: { model: qwen-7b, messages: [{role: user, content: 把这张发票解析成结构化数据}], guided_json: { type: object, properties: { invoice_no: {type: string}, buyer_tax_id: {type: string}, amount: {type: number}, items: {type: array, items: {type: object, ...}} }, required: [invoice_no, buyer_tax_id, amount] } }问题schema 属于业务敏感元数据它描述了系统能产出哪些结构化字段发票号、税号、金额项…泄露到日志等于把内部数据模型暴露给能看日志的人日志平台、运维、第三方托管。ERROR 级别被广收ERROR 日志通常接入集中式日志/告警转发范围广比 DEBUG 更容易外泄。dump 没有脱敏prompt 内容 schema 一起明文落盘既可能含用户隐私发票内容也可能含业务 schema。这不是功能 bug而是崩溃转储缺乏脱敏策略把本不该出现在 ERROR 日志里的结构化输出 schema 明文泄露了。下面给出一套崩溃输入脱敏方案。二、背景vLLM 的结构化输出guided decoding要求调用方传一个 schemaJSON schema / regex / grammar来约束模型输出。这个 schema 在请求对象里是一个字段如guided_json/guided_grammar。当请求在 engine 内崩溃排查逻辑会把整个request对象序列化后打到 ERROR。矛盾在于排障确实需要看是哪条请求、什么参数导致崩溃但schema 字段和 prompt 内容都属于不该广泛传播的数据。正确做法是崩溃转储默认脱敏——只保留定位所需的元信息request_id、模型名、错误阶段、是否用了 structured output、schema 的字段名而非完整定义把完整 schema / prompt 内容替换成占位或降级到 DEBUG。下面用可运行代码给出一套ScrubbedCrashDump实现。三、根因拆成三条根因崩溃转储无字段级脱敏转储逻辑直接json.dumps(request)全量打印没有区分定位需要和敏感不该泄露的字段。根因是转储缺少一个字段分类表。敏感字段被印到 ERROR 而非 DEBUG即便要保留 schema 用于排障也应只在 DEBUG / 受限日志里出现而不是 ERROR 这种广收级别。根因是日志级别选择不当。schema 完整定义被当普通字段处理guided_json是个可能很大的嵌套结构既含字段名也含约束细节正则、枚举取值。排障其实只需要知道用了哪种 structured output 顶层字段名完整定义没必要进 ERROR。根因是没有对 schema 做只留骨架、去掉细节的提炼。修复方向定义敏感字段表 转储时脱敏schema 只留顶层 key 名、prompt 截断/哈希 ERROR 只打脱敏摘要、完整内容走 DEBUG。四、最小可运行复现下面复现崩溃转储明文泄露 schema的现状问题import json def naive_crash_dump(request: dict): 现状整个请求对象明文打到 ERROR。 return json.dumps(request, ensure_asciiFalse) req { request_id: req-001, model: qwen-7b, messages: [{role: user, content: 解析这张发票}], guided_json: { type: object, properties: {invoice_no: {type: string}, buyer_tax_id: {type: string}}, required: [invoice_no, buyer_tax_id], }, } print(现状 ERROR 日志:, naive_crash_dump(req)) # 输出里完整 schema 明文暴露现状 ERROR 日志: {... guided_json 完整定义 ...}即复现schema 明文进了 ERROR。下面重做成脱敏转储。五、解决方案第一层最小直接修复最小修复定义敏感字段表转储时把guided_json提炼为只留顶层字段名把messages内容截断/哈希ERROR 只印脱敏摘要。import json import hashlib from typing import Any, Dict # 需要脱敏的请求字段 SENSITIVE {guided_json, guided_grammar, guided_regex, messages, prompt, messages} def schema_skeleton(schema: Any) - Dict[str, Any]: 只保留 schema 的顶层字段名与类型去掉约束细节。 if not isinstance(schema, dict): return {_type: type(schema).__name__} props schema.get(properties, {}) return { type: schema.get(type), top_level_keys: sorted(props.keys()), required: schema.get(required, []), } def redact_messages(messages: list) - list: 消息内容只留长度哈希不印明文。 out [] for m in messages: content m.get(content, ) out.append({ role: m.get(role), content_sha256: hashlib.sha256( str(content).encode()).hexdigest()[:12], content_len: len(str(content)), }) return out def scrub_request(req: dict) - dict: 生成脱敏后的崩溃摘要用于 ERROR 级别。 summary { request_id: req.get(request_id), model: req.get(model), has_structured_output: any(k in req for k in (guided_json, guided_grammar, guided_regex)), } for k in (guided_json, guided_grammar, guided_regex): if k in req: summary[structured_output_skeleton] schema_skeleton(req[k]) summary[messages_scrubbed] redact_messages(req.get(messages, [])) return summary # 用法 print(脱敏 ERROR 摘要:, json.dumps(scrub_request(req), ensure_asciiFalse))这一层改动让 ERROR 日志只含request_id / model / 是否用了结构化输出 / schema 顶层字段名 / 消息长度哈希完整 schema 与 prompt 不再明文出现。六、解决方案第二层结构化改进把脱敏转储做成结构化组件区分 ERROR 摘要脱敏与 DEBUG 全文受限并用配置控制是否允许在 DEBUG 下保留 schema。import logging from dataclasses import dataclass from typing import Optional dataclass class DumpPolicy: redact_structured_output: bool True # ERROR 下是否提炼 schema redact_messages: bool True # ERROR 下是否脱敏 prompt allow_full_at_debug: bool True # DEBUG 级是否允许完整内容 class CrashDumper: def __init__(self, policy: DumpPolicy, error_log: logging.Logger, debug_log: logging.Logger): self.policy policy self.error_log error_log self.debug_log debug_log def dump(self, req: dict, error: Exception): # ERROR永远脱敏 summary scrub_request(req) if (self.policy.redact_structured_output or self.policy.redact_messages) \ else {k: v for k, v in req.items() if k not in SENSITIVE} summary[error] repr(error) self.error_log.error(请求崩溃(已脱敏): %s, json.dumps(summary, ensure_asciiFalse)) # DEBUG受限环境下才打完整内容 if self.policy.allow_full_at_debug: self.debug_log.debug(请求崩溃(完整, DEBUG only): %s, json.dumps(req, ensure_asciiFalse)) # 用法 err logging.getLogger(vllm.error) dbg logging.getLogger(vllm.debug) dumper CrashDumper(DumpPolicy(), err, dbg) dumper.dump(req, RuntimeError(boom))CrashDumper保证 ERROR 永远是脱敏摘要完整内容只在 DEBUG 且仅当策略允许时出现杜绝了schema 随 ERROR 广收外泄。七、解决方案第三层断言 / CI 守护脱敏最怕有人又把完整 schema 印回 ERROR。用断言守两条不变量def check_dump_invariants(req: dict): summary scrub_request(req) msg json.dumps(summary, ensure_asciiFalse) # 不变量 1ERROR 摘要里不得出现完整 schema 的敏感细节如正则/枚举取值 full_schema json.dumps(req.get(guided_json, {}), ensure_asciiFalse) # 若完整 schema 字符串是摘要字符串的子串说明脱敏失败 assert full_schema not in msg, 完整 schema 泄露进 ERROR 摘要 # 不变量 2不得出现明文 prompt 内容 for m in req.get(messages, []): content str(m.get(content, )) if content: assert content not in msg, 明文 prompt 泄露进 ERROR 摘要 # 不变量 3必须保留定位所需的元信息 assert request_id in summary and model in summary, 缺少定位元信息 return True def test_crash_dump_redaction(): assert check_dump_invariants(req) print(OK: 崩溃转储脱敏不变量通过) if __name__ __main__: test_crash_dump_redaction()把test_crash_dump_redaction接进 CI任何把完整 schema / 明文 prompt 写回 ERROR的改动都会立即红。八、排查清单崩溃输入转储泄露 schema按序查先确认 ERROR 日志里有没有完整guided_json/grammar/regexgrep 日志中guided_关键字。若有完整定义说明转储没脱敏按第五节scrub_request改。schema 只留骨架排障只需要用了哪种 structured output 顶层字段名 required 列表完整约束正则、枚举、嵌套细节不该进 ERROR用schema_skeleton提炼。prompt / messages 脱敏ERROR 里只用content_sha256 长度绝不印明文用户隐私内容发票、身份证号尤其敏感。日志级别分离ERROR 只打脱敏摘要完整请求只在 DEBUG 且策略允许时出现。集中式日志/告警通常只接 ERROR 及以上这样就天然把敏感内容挡在广收通道之外。配置开关DumpPolicy.allow_full_at_debug在生产默认关只在排障会话临时开避免长期留完整内容。结构化输出 schema 当资产看待schema 本质是系统能产出什么字段的契约属于内部资产按敏感数据处理不要在广收日志里明文。CI 接test_crash_dump_redaction用完整 schema 串不是摘要子串的断言锁死任何回退到明文转储的改动。九、小结崩溃输入转储把结构化输出 schema 明文打到 ERROR本质是转储缺乏字段级脱敏 日志级别选错。三层修复第一层SENSITIVE字段表 schema_skeleton只留顶层字段名/requiredredact_messages只留哈希/长度ERROR 只印脱敏摘要第二层CrashDumperDumpPolicy把 ERROR永远脱敏与 DEBUG受限全文分离完整内容绝不进广收通道第三层CI 断言守住完整 schema / 明文 prompt 不出现在 ERROR 摘要任何回退立即红。落实后vLLM 崩溃时 ERROR 日志只含request_id / model / 是否结构化输出 / schema 骨架 / 消息长度哈希既能定位又不泄露敏感 schema 与用户内容。

相关新闻

【Bug已解决】[Feature]: Improve DCP error messages 解决方案

【Bug已解决】[Feature]: Improve DCP error messages 解决方案

2026/7/26 21:24:58

【Bug已解决】[Feature]: Improve DCP error messages 解决方案 一、现象长什么样 PyTorch 的 DCP(Distributed Checkpoint,分布式检查点)在保存/加载大模型分片时,报错极其不友好: RuntimeError: Missing keys in sta…

基于Java的学生管理系统的设计与实现开题报告

基于Java的学生管理系统的设计与实现开题报告

2026/7/26 21:24:58

一、项目研究背景与意义 随着我国教育信息化建设的全面深化,各类中小学及高校的办学规模持续扩大,在校学生数量不断增加,学生日常信息、学业成绩、考勤纪律、奖惩信息、班级信息等管理数据呈指数级增长。传统校园学生管理模式以人工纸质登记、…

【Bug已解决】[Bug]: vllm start with TieringOffloadingSpec mmap_obj error 解决方案

【Bug已解决】[Bug]: vllm start with TieringOffloadingSpec mmap_obj error 解决方案

2026/7/26 21:24:58

【Bug已解决】[Bug]: vllm start with TieringOffloadingSpec mmap_obj error 解决方案 一、现象长什么样 vLLM 的 TieringOffloadingSpec(分级卸载规格)用来把 KV cache / 权重按冷热分层,把冷数据 mmap 到文件或共享内存作为慢速层。启动带…

Unity游戏暂停功能:事件广播机制实现与最佳实践

Unity游戏暂停功能:事件广播机制实现与最佳实践

2026/7/26 22:45:01

1. 项目概述:为什么事件广播是暂停功能的最佳拍档?在Unity游戏开发里,实现游戏暂停(Pause)功能,几乎是每个项目都会遇到的“必修课”。新手最常见的做法,可能是在一个全局的GameManager脚本里&a…

Three.js 围栏着色器教程

Three.js 围栏着色器教程

2026/7/26 22:45:01

围栏着色器 Fence Shader ▶ 在线运行案例 案例合集: 三维可视化功能案例(threehub.cn)开源仓库github地址: https://github.com/z2586300277/three-cesium-examples400个案例代码: 网盘链接 你将学到什么 ShaderMaterial 自…

UE5像素流送技术:从原理到部署,实现云端实时渲染应用分发

UE5像素流送技术:从原理到部署,实现云端实时渲染应用分发

2026/7/26 22:45:01

1. 项目概述:为什么像素流送是UE5应用分发的新范式?最近在折腾一个UE5的演示项目,想把一个接近10个G、包含高精度模型和复杂交互的虚拟展厅,让客户在手机、平板甚至低配电脑上都能流畅体验。直接打包分发?光是下载安装…

3步拯救你的B站缓存视频:m4s-converter让珍贵内容永不消失

3步拯救你的B站缓存视频:m4s-converter让珍贵内容永不消失

2026/7/26 22:45:01

3步拯救你的B站缓存视频:m4s-converter让珍贵内容永不消失 【免费下载链接】m4s-converter 一个跨平台小工具,将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否曾经遇到过这样的情…

P1530 分数化小数 Fractions to Decimals【洛谷算法习题】

P1530 分数化小数 Fractions to Decimals【洛谷算法习题】

2026/7/26 22:45:01

P1530 分数化小数 Fractions to Decimals 网页链接 P1530 分数化小数 Fractions to Decimals 题目描述 写一个程序,输入一个形如 ND\dfrac{N}{D}DN​ 的分数,输出它的小数形式。如果小数有循环节的话,把循环节放在一对圆括号中。 例如&…

41-DataviewJS-JavaScript高级查询

41-DataviewJS-JavaScript高级查询

2026/7/26 22:35:00

41 DataviewJS:JavaScript高级查询 从一个看板说起 去年夏天,前端开发者小林接手了一个内部工具项目——团队需要用Obsidian管理多个并行开发任务的进度。最初他用Dataview的DQL查询做了几个表格,但很快发现需求越来越复杂:需要根据任务状态自动变色、需要点击按钮快速变…

[具身智能-649]:个人电脑搭建 RTSP 服务完整方案(Windows / Ubuntu 双平台,适配 RDK X5 rtsp2display 调试)

[具身智能-649]:个人电脑搭建 RTSP 服务完整方案(Windows / Ubuntu 双平台,适配 RDK X5 rtsp2display 调试)

2026/7/26 0:04:02

目标:电脑作为RTSP 服务端,循环推送 H264/H265 视频流; RDK X5 通过 rtsp2display 拉流预览,完全不需要在开发板编译 live555。 提供两套成熟方案: ✅ 方案 A:FFmpeg(最简单,优先推…

PDF合并与动态水印的工程化方案:2026国内免费工具实测对比

PDF合并与动态水印的工程化方案:2026国内免费工具实测对比

2026/7/26 0:04:02

一、背景与测试方案 在实际项目交付中,PDF文件合并与版权保护水印的叠加是一个高频但容易被低估的技术需求。典型的处理链路涉及:多源PDF的文件流合并、页面级水印渲染(含透明度混合与图层叠加)、输出文件体积控制。看似简单的操作…

PDF拆分压完图糊了?2026国内免费实测,档案员都在用的组合方案

PDF拆分压完图糊了?2026国内免费实测,档案员都在用的组合方案

2026/7/26 0:04:02

说实话,提到PDF拆分再压缩,我真是被折腾得够呛。 上个月公司年度合同归档,一份300多页的PDF总合同,需要按年份拆分成三个独立文件,再分别压缩到10MB以内方便邮件发送各部门确认。我心想这还不简单?先找个海…

[具身智能-649]:个人电脑搭建 RTSP 服务完整方案(Windows / Ubuntu 双平台,适配 RDK X5 rtsp2display 调试)

[具身智能-649]:个人电脑搭建 RTSP 服务完整方案(Windows / Ubuntu 双平台,适配 RDK X5 rtsp2display 调试)

2026/7/26 0:04:02

目标:电脑作为RTSP 服务端,循环推送 H264/H265 视频流; RDK X5 通过 rtsp2display 拉流预览,完全不需要在开发板编译 live555。 提供两套成熟方案: ✅ 方案 A:FFmpeg(最简单,优先推…

PDF合并与动态水印的工程化方案:2026国内免费工具实测对比

PDF合并与动态水印的工程化方案:2026国内免费工具实测对比

2026/7/26 0:04:02

一、背景与测试方案 在实际项目交付中,PDF文件合并与版权保护水印的叠加是一个高频但容易被低估的技术需求。典型的处理链路涉及:多源PDF的文件流合并、页面级水印渲染(含透明度混合与图层叠加)、输出文件体积控制。看似简单的操作…

PDF拆分压完图糊了?2026国内免费实测,档案员都在用的组合方案

PDF拆分压完图糊了?2026国内免费实测,档案员都在用的组合方案

2026/7/26 0:04:02

说实话,提到PDF拆分再压缩,我真是被折腾得够呛。 上个月公司年度合同归档,一份300多页的PDF总合同,需要按年份拆分成三个独立文件,再分别压缩到10MB以内方便邮件发送各部门确认。我心想这还不简单?先找个海…