突发问题:模型崩掉了。查看后台记录,发现是新加的记忆功能和对话提示导致的。记忆功能把上一轮对话的全部信息,包括角色、提示、交互信息全塞到下一轮对话里,对话提示这个功能还要求模型给出3个最可能的问题,叠加起来导致模型崩掉。


新问题
NPU 使用率不高但推理一跑就崩——一次 Text-to-SQL 评估服务的排障记录
 

以下给出报错:
 

INFO 01-29 16:13:11 [loggers.py:122] Engine 000: Avg prompt throughput: 0.9 tokens/s, Avg generation throughput: 8.6 tokens/s, Running: 1 reqs, Waiting: 0 reqs, GPU KV cache usage: 1.8%, Prefix cache hit rate: 78.2%
INFO 01-29 16:13:14 [logger.py:41] Received request chatcmpl-477448aee9f246b6896b747dc85cf3e7: prompt: '<|im_start|>system\n你是 Text-to-SQL 的线上评估器(模拟真实使用场景)。\n\n你将得到:\n- 用户问题\n- 数据库表结构\n- 小模型生成的 SQL\n- 该 SQL 在数据库执行得到的“结构化摘要”(success/error/row_count/columns/rows_preview)\n\n重要约束:\n- 你不知道标准答案 SQL,也看不到标准 SQL 的执行结果。\n- 你要基于“问题 + 执行结果摘要”判断是否完成任务。\n\n你的输出必须是 JSON(不要 markdown 代码块),结构为:\n{\n  "is_correct": true/false,\n  "score": 0-100,\n  "error_tags": ["tag1", "tag2"],\n  "repair_task": "sql_correct" | "sql_fill" | "none",\n  "comment": "<=40字的短备注"\n}\n\n规则:\n- 如果 is_correct=true:error_tags 为空数组,repair_task 必须是 "none"。\n- 如果 SQL 执行失败(success=false):通常视为不正确,并给出合适的 error_tags。\n- error_tags 必须从给定允许集合中选择,最多 5 个;无法判断时用 "other"。\n- repair_task 用于指导下一轮:缺条件/缺列/缺 join 等“缺东西”优先用 sql_fill;其他更像改错则 sql_correct。\n<|im_end|>\n<|im_start|>user\n## 用户问题\n查询筛网制作胶水的领用情况\n\n## 数据库表结构\n- 表名:VIEW_PART_USER_HISTORY\n- 字段:CREATE_TIME, APPLY_NO, dict_label, APPLY_AMOUNT, ACT_APPLY_AMOUNT, BASE_PART_ID, PART_NO, PART_NAME_C, PRICE\n\n## 生成 SQL\nSELECT * FROM VIEW_PART_USER_HISTORY WHERE PART_NAME_C = N\'筛网制作胶水\' ORDER BY CREATE_TIME DESC\n\n## 生成 SQL 执行结果(摘要)\n{"success": true, "error": null, "row_count": 0, "columns": [], "rows_preview": [], "elapsed_ms": 13}\n\n## 允许的错误标签集合\nagg_no_groupby, ambiguous_col, col_missing, condition_type_mismatch, condition_wrong_col, duplicate_select, except_missing, extra_table, extra_values_selected, groupby_missing_col, hardcoded_value, having_incorrect, having_vs_where, having_without_groupby, incorrect_col, incorrect_foreign_key, intersect_missing, invalid_alias, join_missing, join_wrong_type, limit_missing, order_by_missing, other, sql_syntax_error, subquery_correlation_error, subquery_missing, table_missing, union_missing, unsupported_function, unused_subquery, value_format_wrong, where_missing\n\n请按要求输出 JSON。<|im_end|>\n<|im_start|>assistant\n', params: SamplingParams(n=1, presence_penalty=0.0, frequency_penalty=0.0, repetition_penalty=1.0, temperature=0.0, top_p=1.0, top_k=0, min_p=0.0, seed=None, stop=[], stop_token_ids=[], bad_words=[], include_stop_str_in_output=False, ignore_eos=False, max_tokens=21425, min_tokens=0, logprobs=None, prompt_logprobs=None, skip_special_tokens=True, spaces_between_special_tokens=True, truncate_prompt_tokens=None, guided_decoding=GuidedDecodingParams(json=None, regex=None, choice=None, grammar=None, json_object=True, backend=None, backend_was_auto=False, disable_fallback=False, disable_any_whitespace=False, disable_additional_properties=False, whitespace_pattern=None, structural_tag=None), extra_args=None), prompt_token_ids: None, prompt_embeds shape: None, lora_request: None.
INFO 01-29 16:13:14 [async_llm.py:269] Added request chatcmpl-477448aee9f246b6896b747dc85cf3e7.
[rank2]:[W129 16:13:15.056421750 compiler_depend.ts:57] Warning: EZ9999: Inner Error!
EZ9999: [PID: 3278431] 2026-01-29-16:13:15.628.193 The error from device(chipId:6, dieId:0), serial number is 35, there is an exception of aivec error, core id is 14, error code = 0, dump info: pc start: 0x12c200314000, current: 0x12c20031495c, vec error info: 0xd002b1415a, mte error info: 0xbc42ff7413, ifu error info: 0x20003fffeda00, ccu error info: 0xe24910300000000, cube error info: 0, biu error info: 0, aic error mask: 0x6500020bd00028c, para base: 0x12c240583000.[FUNC:ProcessStarsCoreErrorInfo][FILE:device_error_core_proc.cc][LINE:303]
        TraceBack (most recent call last):
       The extend info: errcode:(0, 0x8000, 0) errorStr: When the D-cache reads and writes data to the UB, the response value returned by the bus is a non-zero value. fixp_error0 info: 0x2ff7413, fixp_error1 info: 0xbc, fsmId:0, tslot:0, thread:0, ctxid:0, blk:1, sublk:0, subErrType:4.[FUNC:ProcessStarsCoreErrorInfo][FILE:device_error_core_proc.cc][LINE:322]
       Kernel task happen error, retCode=0x31, [vector core exception].[FUNC:PreCheckTaskErr][FILE:davinci_kernel_task.cc][LINE:1539]
       AIV Kernel happen error, retCode=0x31.[FUNC:GetError][FILE:stream.cc][LINE:1183]
       [AIC_INFO] after execute:args print end[FUNC:GetError][FILE:stream.cc][LINE:1183]
       Aicore kernel execute failed, device_id=6, stream_id=1834, report_stream_id=1834, task_id=38412, flip_num=305, fault kernel_name=ApplyTopKTopPWithSorted_fp32_high_performance_0, fault kernel info ext=none, program id=417, hash=15861197690901397285.[FUNC:GetError][FILE:stream.cc][LINE:1183]
       rtStreamSynchronize execute failed, reason=[vector core exception][FUNC:FuncErrorReason][FILE:error_message_manage.cc][LINE:53]
       synchronize stream failed, runtime result = 507035[FUNC:ReportCallError][FILE:log_inner.cpp][LINE:161]
 (function copy_between_host_and_device_opapi)
[rank3]:[W129 16:13:15.057030150 compiler_depend.ts:57] Warning: EZ9999: Inner Error!
EZ9999: [PID: 3278432] 2026-01-29-16:13:15.629.510 The error from device(chipId:7, dieId:0), serial number is 35, there is an exception of aivec error, core id is 36, error code = 0, dump info: pc start: 0x12c200314000, current: 0x12c20031495c, vec error info: 0xe303976fa8, mte error info: 0xe00add70b5, ifu error info: 0x20003fffeda00, ccu error info: 0xb034843400000000, cube error info: 0, biu error info: 0, aic error mask: 0x6500020bd00028c, para base: 0x12c240583000.[FUNC:ProcessStarsCoreErrorInfo][FILE:device_error_core_proc.cc][LINE:303]

1. 现象与结论
  • 现象:推理服务刚收到请求就报 NPU 内核异常并退出;监控里 NPU 使用率不高,但程序“秒崩”。
  • 结论:这类情况通常不是“负载不足”,而是请求参数触发了不稳定/不兼容的推理路径(例如 guided decoding + 大 max_tokens + 采样/贪婪路径冲突),导致 NPU kernel 直接异常,还没来得及把利用率拉高。

2. 关键日志特征(脱敏描述)

请求日志里出现类似信息:

  • guided_decoding ... json_object=True
  • temperature=0.0
  • top_p=1.0, top_k=0(或后端默认等价配置)
  • max_tokens 被设置成一个很大的值(例如 2×1042×104 量级)
  • NPU 报错栈指向采样相关 kernel(例如 TopK/TopP 相关算子),并伴随 “vector core exception / aicore execute failed” 一类错误

这些组合在部分 NPU 推理后端上属于高风险组合:一旦进入相关 kernel,直接报错退出


3. 触发逻辑复盘(为什么会走到“危险路径”)

本次问题的触发链路可以抽象为 3 个点:

3.1 KV cache / 内存压力被“隐性放大”
  • 请求由两段 token 构成:提示词 tokens + 最大生成 tokens
  • 如果客户端不限制 max_tokens,某些 OpenAI 兼容后端会把它自动放到“可用上下文的最大值”(可能达到数万 token)。
  • 大模型推理时 KV cache 的显存/显存等价内存占用近似与序列长度成正比(粗略理解即可),结果就是:
    • 序列长度被“默认 max_tokens”放大
    • KV cache 分配/访问压力骤增
    • 更容易触发后端实现的边界/异常情况(尤其在约束解码或特殊 kernel 上)
3.2 temperature=0 与采样器实现的冲突风险
  • 直觉上:temperature=0 应该是贪婪解码。
  • 但在一些服务端实现里,仍可能初始化/调用与 top_p/top_k 相关的采样路径(即使参数看似“等价不采样”)。
  • 在某些 NPU kernel/插件版本中,这会导致内部状态组合不被很好支持,从而触发 kernel 异常。
3.3 JSON 约束解码(guided decoding)让路径更复杂
  • 当客户端使用 response_format={"type":"json_object"} 这类参数时,服务端会启用 JSON 约束解码(guided decoding)。
  • 约束解码会改变解码流程(token 过滤/回退/结构约束),与采样/贪婪路径的组合更复杂。
  • 在部分 NPU 后端上,这条路径更容易踩到未覆盖的实现分支或不稳定 kernel。

4. 根因归纳(可直接放到“问题原因”章节)
  • 根因 1:max_tokens 未显式设置,服务端默认值过大,导致 KV cache 压力显著增大,风险上升。
  • 根因 2:temperature=0 与后端的 topk/topp 采样实现存在组合不稳定性(即使 top_p=1、top_k=0 看似“无采样”)。
  • 根因 3:启用了 JSON 约束解码(guided decoding),与上面两点叠加后更容易触发 NPU kernel 异常。

5. 解决方案(代码侧:把“危险组合”拆开并默认走稳路径)

思路是:限制输出长度、默认关掉约束解码、避免 0 温度落到问题分支,并通过环境变量保留“需要时再开”的开关。

已在 validate_sql.py 的 judge 调用处做了如下改动(脱敏描述,保留设计要点):

  • 显式设置 judge 的 max_tokens,默认 256,可配置

    • 环境变量:JUDGE_MAX_TOKENS(默认 256
    • 目标:避免服务端出现“自动给到 2w+ token 上限”
  • 默认不启用 response_format=json_object(即默认不走 guided decoding)

    • 环境变量:JUDGE_USE_RESPONSE_FORMAT=1 时才开启
    • 目标:规避 NPU 上更不稳定的约束解码路径
  • 对 judge 温度做“非零兜底”

    • 环境变量:JUDGE_MIN_TEMPERATURE(默认 0.01
    • 当请求温度 ≤0≤0 时,用一个很小的非零温度
    • 目标:绕开某些后端在 temperature=0 + topk/topp 组合上的异常分支
    • 如果确实需要严格 0:设置 JUDGE_MIN_TEMPERATURE=0

结果:按当前反馈,好像没崩了,说明规避策略对当前环境有效。


6. 推荐运行参数(博客可给读者的“实用配置”)

在不依赖具体硬件/后端实现细节的前提下,推荐默认策略是:

  • 对所有请求显式设置 max_tokens(尤其是评估/裁判类小输出场景)
    • judge 输出通常很短:128~256 足够
  • 优先不用 structured output 的强约束(能用“提示词 + JSON 解析容错”替代时)
  • 温度为 0 的场景,如遇到后端不稳定:
    • 尝试 temperature=0.01 或 0.05
    • 或在服务端明确切换到真正的 greedy 路径(这属于服务端范畴)

7. 为什么“使用率不高”反而更像后端 bug/不兼容
  • 利用率低并不代表“算力没跑起来”,也可能是:
    • 刚进入某个 kernel 就异常退出
    • 或在初始化/分配阶段直接失败
  • 因此看到“低利用率 + 秒崩”,排查方向应优先放在:
    • 解码路径(greedy / sampling / guided)
    • max_tokens 与上下文长度
    • dtype / kernel 实现兼容性
    • 驱动/运行时/推理框架版本匹配

8. 一句话经验总结
  • 大模型推理稳定性 = 模型参数 + 解码策略 + 输出上限 + 后端实现 的组合问题。
  • 工程上最有效的第一步往往不是“换卡/加卡”,而是:把 max_tokens 限住、把 guided decoding 关掉、避免 0 温度触发奇怪分支
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐